2
\$\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\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.