1
\$\begingroup\$

In my application I need to perform several SSH commands from Windows to a Linux machine.

Since I need to reduce as much as possible the SSH calls overhead and also limit the number of concurrent SSH commands, I thought to keep some sessions open and create a session pool class to manage this.

The following code seems to work, but I'm not sure is deadlock safe :

// Class keeping a SSH session open
class SSHSession
{
    public SSHSession()
    {
        // create and open the SSH session
    }

    // run an SSH command synchronously
    public string RunCommand(string command, ManualResetEvent handle)
    {
        Thread.Sleep(3000); // simulate an SSH command of 3 seconds
        handle.Set();
        return "Result of " + command;
    }
}

// Class managing multiple concurrent ssh sessions
class SSHSessionPool
{
    private readonly object padLock;
    private readonly SSHSession[] sessions;
    private readonly ManualResetEvent[] waitHandles;

    public SSHSessionPool(int concurrentSessions)
    {
        this.padLock = new object();
        this.sessions = new SSHSession[concurrentSessions];
        this.waitHandles = new ManualResetEvent[concurrentSessions];
        for (int i = 0; i < concurrentSessions; i++)
        {
            this.sessions[i] = new SSHSession();
            this.waitHandles[i] = new ManualResetEvent(true);
        }
    }

    // run an SSH command synchronously
    public string RunCommand(string command)
    {
        SSHSession session;
        ManualResetEvent handle;
        lock (padLock)
        {
            int idx = WaitHandle.WaitAny(waitHandles);
            handle = waitHandles[idx];
            handle.Reset();
            session = sessions[idx];
        }
        return session.RunCommand(command, handle);
    }
}

Oversimplified application example :

class Program
{
    static void Main(string[] args)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();

        var sshPool = new SSHSessionPool(4);

        Parallel.For(0, 100,
        (i) =>
        {
            var start = DateTime.Now;
            Console.WriteLine("Task {0} started", i);
            sshPool.RunCommand(string.Format("{0}", i));
            Console.WriteLine("Task {0} completed in {1}", i, DateTime.Now - start);

        });

        sw.Stop();
        Console.WriteLine("Total elapsed: {0}", sw.Elapsed);

        Console.ReadLine();
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.