//------------------------------------------------------------------------------
// <copyright file="DurableSession.java" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>
//      The implementation of the Durable Session Class
// </summary>
//------------------------------------------------------------------------------

package com.microsoft.hpc.scheduler.session;

import com.microsoft.hpc.*;
import com.microsoft.hpc.sessionlauncher.*;
import com.microsoft.hpc.SOATrace.SOATraceSource;
import com.microsoft.hpc.exceptions.*;

/**
 * Creates a session whose requests and responses gets stored in MSMQ. 
 * <p>This allows a user to disconnect the client or use a different client altogether
 * to retrieve messages.</p>
 * <p>Constructors are called from <code>SessionBase</code> during <code>CreateSession</code></p>
 * @See {@link #createSession(SessionStartInfo)}
 */
public class DurableSession extends SessionBase
{   
    /**
     * Initializes a new instance of the DurableSession class
     * @param info Session info
     * @param headnode the head node machine name.
     * @param traceSource the trace source
     */
    DurableSession(SessionInfo info, String headnode, SOATraceSource traceSource)
    {
        super(info, headnode, traceSource);
    }
    
    /**
     * Creates a new instance of durable session
     * @param startInfo the session start info 
     * @return a durable session instance
     * @throws SessionException If an exception occurred during the setup of a session 
     * @throws TimeoutException If the setup of a session took too long
     */
    public static DurableSession createSession(SessionStartInfo startInfo)
    throws TimeoutException, SessionException
    {
        return createSession(startInfo, Timeout.Infinite);
    }
    
    /**
     * Creates an instance of durable session
     * @param startInfo the session start info 
     * @param timeout timeout for creating the session 
     * @return a durable session instance 
     * @throws SessionException If an exception occurred during the setup of a session
     * @throws TimeoutException  If the setup of a session takes too long
     */
    public static DurableSession createSession(SessionStartInfo startInfo, Timeout timeout) 
    throws TimeoutException, SessionException
    {
        if (!startInfo.getTransportScheme().contains(TransportScheme.Http.getName()))
            throw new ArgumentException("Non-Http transports are not allowed");
        return (DurableSession)createSessionInternal(startInfo, timeout, true);
    }
    
    /**
     * Create a durable session
     * @param startInfo the session start info 
     * @param timeoutMilliseconds timeout for creating the session
     * @return a durable session instance 
     * @throws SessionException If an exception occurred during the setup of a session
     * @throws TimeoutException If the setup of a session takes too long
     */
    public static DurableSession createSession(SessionStartInfo startInfo, int timeoutMilliseconds) 
    throws TimeoutException, SessionException
    {
        if (!startInfo.getTransportScheme().contains(TransportScheme.Http.getName()))
            throw new ArgumentException(SR.TransportSchemeNotSupport);
        return (DurableSession)createSessionInternal(startInfo, timeoutMilliseconds, true);
            
    }
    
    /**
     * Attach to an existing session with session id
     * @param attachInfo the attach info 
     * @param timeoutMilliseconds timeout for attaching to the session 
     * @return a durable session instance
     * @throws SessionException If an exception occurred while trying to connect to an existing session
     */
    public static DurableSession attachSession(SessionAttachInfo attachInfo, int timeoutMilliseconds)
    throws SessionException, TimeoutException
    {
        SOATraceSource traceSource = new SOATraceSource(Integer.toString(attachInfo.getId()), SessionBase.getTraceSourceName(), SessionBase.getEventSource());
        
        SessionInfo info = attachInternal(attachInfo, timeoutMilliseconds, traceSource);
        
        return new DurableSession(info, attachInfo.getHeadnode(), traceSource);        
    }
    
    /**
     * Attach to an existing session with session id
     * @param attachInfo the attach info
     * @return the durable session instance
     * @throws SessionException If an exception occurred while trying to connect to an existing session
     */
    public static DurableSession attachSession(SessionAttachInfo attachInfo)
    throws SessionException, Exception
    {
        return attachSession(attachInfo, Timeout.Infinite);
    }
    
    /**
     * Attach to an existing session with session id
     * @param attachInfo the attach info
     * @param timeout timeout for attaching to the session 
     * @return a durable session
     * @throws SessionException If an exception occurred while trying to connect to an existing session
     */
    public static DurableSession attachSession(SessionAttachInfo attachInfo, Timeout timeout)
    throws SessionException, Exception
    {        
        SOATraceSource traceSource = new SOATraceSource(Integer.toString(attachInfo.getId()), SessionBase.getTraceSourceName(), SessionBase.getEventSource());
        
        SessionInfo info = attachInternal(attachInfo, timeout, traceSource);
        
        return new DurableSession(info, attachInfo.getHeadnode(), traceSource);
    }

    //public static IAsyncResult BeginCreateSession(SessionStartInfo startInfo, AsyncCallback callback, object asyncState)
    //public static DurableSession EndCreateSession(IAsyncResult result)
    //      asynchronous not supported in java

    /**
     * the help function to check the sanity of SessionStartInfo before creating a session
     * @param startInfo
     */
    protected static void checkSessionStartInfo(SessionStartInfo startInfo)
    {
        SessionBase.checkSessionStartInfo(startInfo);
        if(TransportScheme.valueOf(startInfo.getTransportScheme().get(0)) != TransportScheme.Http)
        {
            throw new NotSupportedException(SR.TransportSchemeNotSupport);
        }
    }
}
