commit 7cfddc45953d6ad6f15c5f9aff46f45e125ab6da
parent 20185b4db2899d7ec71eb85e15f4b051f30b65af
Author: wmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Date: Wed, 3 Jan 2007 16:16:20 +0000
thread improvements (and back to sharing a connection)
git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@157 5c8cc53c-5e98-4d25-b20a-d8db53a31250
Diffstat:
1 file changed, 37 insertions(+), 21 deletions(-)
diff --git a/lib/sup/mbox/ssh-file.rb b/lib/sup/mbox/ssh-file.rb
@@ -66,6 +66,7 @@ class Buffer
x = @buf.index(what, start - @start)
x.nil? ? nil : x + @start
end
+
def rindex what, start=0
x = @buf.rindex(what, start - @start)
x.nil? ? nil : x + @start
@@ -91,6 +92,9 @@ class SSHFile
REASONABLE_TRANSFER_SIZE = 1024 * 32
SIZE_CHECK_INTERVAL = 60 * 1 # seconds
+ @@shells = {}
+ @@shells_mutex = Mutex.new
+
def initialize host, fn, ssh_opts={}
@buf = Buffer.new
@host = host
@@ -102,6 +106,7 @@ class SSHFile
@broken_msg = nil
@shell = nil
@shell_mutex = Mutex.new
+ @buf_mutex = Mutex.new
end
def to_s; "mbox+ssh://#@host/#@fn"; end ## TODO: remove thisis EVILness
@@ -113,28 +118,32 @@ class SSHFile
Redwood::log s
end
def shutup
- BufferManager.clear @say_id if BufferManager.instantiated?
+ BufferManager.clear @say_id if BufferManager.instantiated? && @say_id
@say_id = nil
end
private :say, :shutup
def connect
raise SSHFileError, @broken_msg if broken?
+ return if @shell
- @shell_mutex.synchronize do
- return if @shell
-
- begin
- say "Opening SSH connection to #{@host}..."
- #raise SSHFileError, "simulated SSH file error"
- session = Net::SSH.start @host, @ssh_opts
- say "Starting SSH shell..."
- @shell = session.shell.sync
- say "Checking for #@fn..."
- raise Errno::ENOENT, @fn unless @shell.test("-e #@fn").status == 0
- ensure
- shutup
+ @key = [@host, @ssh_opts[:username]]
+ begin
+ @shell = @@shells_mutex.synchronize do
+ unless @@shells.member? @key
+ say "Opening SSH connection to #{@host} for #@fn..."
+ #raise SSHFileError, "simulated SSH file error"
+ session = Net::SSH.start @host, @ssh_opts
+ say "Starting SSH shell..."
+ @@shells[@key] = session.shell.sync
+ end
+ @@shells[@key]
end
+
+ say "Checking for #@fn..."
+ @shell_mutex.synchronize { raise Errno::ENOENT, @fn unless @shell.test("-e #@fn").status == 0 }
+ ensure
+ shutup
end
end
@@ -154,15 +163,19 @@ class SSHFile
def gets
return nil if eof?
- make_buf_include @offset
- expand_buf_forward while @buf.index("\n", @offset).nil? && @buf.endd < size
- returning(@buf[@offset .. (@buf.index("\n", @offset) || -1)]) { |line| @offset += line.length }
+ @buf_mutex.synchronize do
+ make_buf_include @offset
+ expand_buf_forward while @buf.index("\n", @offset).nil? && @buf.endd < size
+ returning(@buf[@offset .. (@buf.index("\n", @offset) || -1)]) { |line| @offset += line.length }
+ end
end
def read n
return nil if eof?
- make_buf_include @offset, n
- @buf[@offset ... (@offset += n)]
+ @buf_mutex.synchronize do
+ make_buf_include @offset, n
+ @buf[@offset ... (@offset += n)]
+ end
end
private
@@ -173,14 +186,17 @@ private
connect
# MBox::debug "sending command: #{cmd.inspect}"
begin
- result = @shell.send_command cmd
+ result = @shell_mutex.synchronize { x = @shell.send_command cmd; sleep 0.25; x }
raise SSHFileError, "Failure during remote command #{cmd.inspect}: #{(result.stderr || result.stdout || "")[0 .. 100]}" unless result.status == 0
rescue Net::SSH::Exception # these happen occasionally for no apparent reason. gotta love that nondeterminism!
retry if (retries += 1) <= 3
raise
rescue Errno::EPIPE
if (retries += 1) <= e
- @shell = nil
+ @@shells_mutex.synchronize do
+ @shell = nil
+ @@shells[@key] = nil
+ end
connect
retry
end