|
|
|
@ -754,8 +754,8 @@ class FileService(Service):
|
|
|
|
|
|
|
|
|
|
def __init__(self, router):
|
|
|
|
|
super(FileService, self).__init__(router)
|
|
|
|
|
#: Mapping of registered path -> file size.
|
|
|
|
|
self._metadata_by_path = {}
|
|
|
|
|
#: Set of registered paths.
|
|
|
|
|
self._paths = set()
|
|
|
|
|
#: Mapping of Stream->FileStreamState.
|
|
|
|
|
self._state_by_stream = {}
|
|
|
|
|
|
|
|
|
@ -777,15 +777,16 @@ class FileService(Service):
|
|
|
|
|
:param str path:
|
|
|
|
|
File path.
|
|
|
|
|
"""
|
|
|
|
|
if path in self._metadata_by_path:
|
|
|
|
|
return
|
|
|
|
|
if path not in self._paths:
|
|
|
|
|
LOG.debug('%r: registering %r', self, path)
|
|
|
|
|
self._paths.add(path)
|
|
|
|
|
|
|
|
|
|
def _generate_stat(self, path):
|
|
|
|
|
st = os.stat(path)
|
|
|
|
|
if not stat.S_ISREG(st.st_mode):
|
|
|
|
|
raise IOError('%r is not a regular file.' % (path,))
|
|
|
|
|
|
|
|
|
|
LOG.debug('%r: registering %r', self, path)
|
|
|
|
|
self._metadata_by_path[path] = {
|
|
|
|
|
return {
|
|
|
|
|
'size': st.st_size,
|
|
|
|
|
'mode': st.st_mode,
|
|
|
|
|
'owner': self._name_or_none(pwd.getpwuid, 0, 'pw_name'),
|
|
|
|
@ -869,26 +870,26 @@ class FileService(Service):
|
|
|
|
|
:raises Error:
|
|
|
|
|
Unregistered path, or Sender did not match requestee context.
|
|
|
|
|
"""
|
|
|
|
|
if path not in self._metadata_by_path:
|
|
|
|
|
if path not in self._paths:
|
|
|
|
|
raise Error(self.unregistered_msg)
|
|
|
|
|
if msg.src_id != sender.context.context_id:
|
|
|
|
|
raise Error(self.context_mismatch_msg)
|
|
|
|
|
|
|
|
|
|
LOG.debug('Serving %r', path)
|
|
|
|
|
|
|
|
|
|
# Response must arrive first so requestee can begin receive loop,
|
|
|
|
|
# otherwise first ack won't arrive until all pending chunks were
|
|
|
|
|
# delivered. In that case max BDP would always be 128KiB, aka. max
|
|
|
|
|
# ~10Mbit/sec over a 100ms link.
|
|
|
|
|
try:
|
|
|
|
|
fp = open(path, 'rb', self.IO_SIZE)
|
|
|
|
|
msg.reply(self._generate_stat(path))
|
|
|
|
|
except IOError:
|
|
|
|
|
msg.reply(mitogen.core.CallError(
|
|
|
|
|
sys.exc_info()[1]
|
|
|
|
|
))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Response must arrive first so requestee can begin receive loop,
|
|
|
|
|
# otherwise first ack won't arrive until all pending chunks were
|
|
|
|
|
# delivered. In that case max BDP would always be 128KiB, aka. max
|
|
|
|
|
# ~10Mbit/sec over a 100ms link.
|
|
|
|
|
msg.reply(self._metadata_by_path[path])
|
|
|
|
|
|
|
|
|
|
stream = self.router.stream_by_id(sender.context.context_id)
|
|
|
|
|
state = self._state_by_stream.setdefault(stream, FileStreamState())
|
|
|
|
|
state.lock.acquire()
|
|
|
|
|