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();
}
}