serialize outgoing requests (duh) -- when prefetching multiple files, there may be several threads pumping out read requests
This commit is contained in:
Robey Pointer 2005-12-02 20:31:12 -08:00
parent 2d06308fd9
commit 62a83e7d03
1 changed files with 28 additions and 17 deletions

View File

@ -22,6 +22,7 @@ Client-mode SFTP support.
import errno import errno
import os import os
import threading
import weakref import weakref
from paramiko.sftp import * from paramiko.sftp import *
from paramiko.sftp_attr import SFTPAttributes from paramiko.sftp_attr import SFTPAttributes
@ -57,6 +58,8 @@ class SFTPClient (BaseSFTP):
self.sock = sock self.sock = sock
self.ultra_debug = False self.ultra_debug = False
self.request_number = 1 self.request_number = 1
# lock for request_number
self._lock = threading.Lock()
self._cwd = None self._cwd = None
# request # -> SFTPFile # request # -> SFTPFile
self._expecting = weakref.WeakValueDictionary() self._expecting = weakref.WeakValueDictionary()
@ -523,6 +526,9 @@ class SFTPClient (BaseSFTP):
return self._read_response(num) return self._read_response(num)
def _async_request(self, fileobj, t, *arg): def _async_request(self, fileobj, t, *arg):
# this method may be called from other threads (prefetch)
self._lock.acquire()
try:
msg = Message() msg = Message()
msg.add_int(self.request_number) msg.add_int(self.request_number)
for item in arg: for item in arg:
@ -536,10 +542,12 @@ class SFTPClient (BaseSFTP):
item._pack(msg) item._pack(msg)
else: else:
raise Exception('unknown type for %r type %r' % (item, type(item))) raise Exception('unknown type for %r type %r' % (item, type(item)))
self._send_packet(t, str(msg))
num = self.request_number num = self.request_number
self._expecting[num] = fileobj self._expecting[num] = fileobj
self._send_packet(t, str(msg))
self.request_number += 1 self.request_number += 1
finally:
self._lock.release()
return num return num
def _read_response(self, waitfor=None): def _read_response(self, waitfor=None):
@ -550,6 +558,9 @@ class SFTPClient (BaseSFTP):
if num not in self._expecting: if num not in self._expecting:
# might be response for a file that was closed before responses came back # might be response for a file that was closed before responses came back
self._log(DEBUG, 'Unexpected response #%d' % (num,)) self._log(DEBUG, 'Unexpected response #%d' % (num,))
if waitfor is None:
# just doing a single check
return
continue continue
fileobj = self._expecting[num] fileobj = self._expecting[num]
del self._expecting[num] del self._expecting[num]