def send(self, message, _sender=None): """Sends a message to the actor represented by this `Ref`.""" if not _sender: context = get_context() if context: _sender = context.ref if self._cell: if not self._cell.stopped: self._cell.receive(message, _sender) return else: self._cell = None if not self.is_local: if self.uri.node != self.node.nid: self.node.send_message(message, remote_ref=self, sender=_sender) else: self._cell = self.node.guardian.lookup_cell(self.uri) self.is_local = True self._cell.receive(message, _sender) else: if self.node and self.node.guardian: cell = self.node.guardian.lookup_cell(self.uri) if cell: cell.receive(message, _sender) # do NOT set self._cell--it will never be unset and will cause a memleak return if ('_watched', ANY) == message: message[1].send(('terminated', self), _sender=self) elif (message == ('terminated', ANY) or message == ('_unwatched', ANY) or message == ('_node_down', ANY) or message == '_stop' or message == '_kill' or message == '__done'): pass else: Events.log(DeadLetter(self, message, _sender))
def fetch(self, dst_path=None, on_progress=None): if dst_path is not None and os.path.isdir(dst_path): raise TransferFailed("%r is a directory" % (dst_path,)) if dst_path: mkdir_p(os.path.dirname(dst_path)) with lock_file(dst_path) if dst_path is not None else _NULL_CTX(): if (dst_path is not None and os.path.exists(dst_path) and reasonable_get_mtime(dst_path) == self.mtime and os.path.getsize(dst_path) == self.size): return dst_path ret = None # local if self.server.uri.node == get_context().ref.uri.node: _, src_path = self.server.ask(('request-local', self.file_id)) assert _ == 'local-file' # store to specific path if dst_path is not None: if src_path != dst_path: if os.path.exists(dst_path): os.unlink(dst_path) shutil.copy(src_path, dst_path) ret = dst_path # store to temp else: fd, tmppath = tempfile.mkstemp() os.close(fd) shutil.copy(src_path, tmppath) ret = tmppath if on_progress: on_progress(fileref=self, transferred_size=self.size, local=True) # remote else: fd, tmppath = tempfile.mkstemp() os.close(fd) with open(tmppath, 'wb') as tmpfile: transferred_size = self._transfer(tmpfile, on_progress) if transferred_size != self.size: os.unlink(tmppath) raise TransferFailed("fetched file size %db does not match remote size %db" % (transferred_size, self.size)) # store to specific path if dst_path: if os.path.exists(dst_path): os.unlink(dst_path) move_or_copy(tmppath, dst_path) ret = dst_path # store to temp else: ret = tmppath os.utime(ret, (self.mtime, self.mtime)) assert reasonable_get_mtime(ret) == self.mtime return ret
def serve_file(path, abstract_path=None, node=None): mtime = reasonable_get_mtime(path) size = os.path.getsize(path) file_id = uuid.uuid4().get_hex() node = node or get_context().node server = Server._instances.get(node) if not server: server = Server._instances[node] = node.spawn(Server) server << ('serve', path, file_id) if abstract_path is None: abstract_path = os.path.basename(path) return FileRef(file_id, server, abstract_path=abstract_path, mtime=mtime, size=size)
def _transfer(self, fh): request = get_context().spawn(Request.using(server=self.server, file_id=self.file_id, size=self.size, abstract_path=self.abstract_path)) more = True ret = 0 while more: msg = request.ask('next') if msg == 'stop': break elif msg == ('failure', ANY): _, cause = msg assert cause in ('response-died', 'inconsistent', 'timeout') raise TransferFailed("Other side died prematurely" if cause == 'response-died' else "Inconsistent stream" if cause == 'inconsistent' else "Timed out") _, chunk, more = msg assert _ == 'chunk' ret += len(chunk) fh.write(chunk) return ret
def send(self, message, _sender=None): if ('_child_terminated', ANY) == message: _, sender = message self._child_gone(sender) if not self._children and self.all_children_stopped: self.all_children_stopped.set(None) # # XXX: find a better way to avoid Terminated messages for TempActors, # # possibly by using a /tmp container for them # if not str(sender.uri).startswith('/tempactor'): # Events.log(Terminated(sender)) elif message == '_stop': return self._do_stop() elif message == '_kill': return self._do_stop(kill=True) else: if not _sender: context = get_context() if context: _sender = context.ref Events.log(UnhandledMessage(self, message, _sender))
def _transfer(self, fh, on_progress): request = get_context().spawn(Request.using(server=self.server, file_id=self.file_id, size=self.size, abstract_path=self.abstract_path)) more = True ret = 0 while more: msg = request.ask('next') if msg == 'stop': break elif msg == ('failure', ANY): _, cause = msg assert cause in ('response-died', 'inconsistent', 'timeout') raise TransferFailed("Other side died prematurely" if cause == 'response-died' else "Inconsistent stream" if cause == 'inconsistent' else "Timed out") _, chunk, more = msg assert _ == 'chunk' ret += len(chunk) fh.write(chunk) if on_progress: on_progress(fileref=self, transferred_size=ret, local=False) return ret
def send(self, message, _sender=None): """Sends a message to the actor represented by this `Ref`.""" if not _sender: context = get_context() if context: _sender = context.ref if self._cell: if not self._cell.stopped: self._cell.receive(message, _sender) return else: self._cell = None if not self.is_local: if self.uri.node != self.node.nid: self.node.send_message(message, remote_ref=self, sender=_sender) else: self._cell = self.node.guardian.lookup_cell(self.uri) self.is_local = True self._cell.receive(message, _sender) else: if self.node and self.node.guardian: cell = self.node.guardian.lookup_cell(self.uri) if cell: cell.receive( message, _sender ) # do NOT set self._cell--it will never be unset and will cause a memleak return if ('_watched', ANY) == message: message[1].send(('terminated', self), _sender=self) elif (message == ('terminated', ANY) or message == ('_unwatched', ANY) or message == ('_node_down', ANY) or message == '_stop' or message == '_kill' or message == '__done'): pass else: Events.log(DeadLetter(self, message, _sender))
def send_later(self, delay, message, _sender=None): spawn_later(delay, self.send, message, _sender=_sender or get_context().ref)
def forward(self, msg): sender = get_context().sender assert sender self.send(msg, _sender=sender)
def make(cls): # if not cls.pool: d = gevent.event.AsyncResult() ret = get_context().spawn(cls.using(d, cls.pool)) return ret, d