def addEventListener(self, service, listener): assert protocol.isDispatchThread() svc_name = str(service) listener.svc_name = svc_name list = self.event_listeners.get(svc_name) or [] list.append(listener) self.event_listeners[svc_name] = list
def _processQueue(self): assert protocol.isDispatchThread() with self._lock: for cmd in self._queue: service, command, args, kwargs = cmd self._invoke(service, command, *args, **kwargs) del self._queue[:]
def sendCommand(self, service, name, args, listener): assert protocol.isDispatchThread() if self.state == STATE_OPENING: raise Exception("Channel is waiting for Hello message") if self.state == STATE_CLOSED: raise Exception("Channel is closed") msg = Message('C') msg.service = str(service) msg.name = name msg.data = args channel = self class CancelableToken(Token): def __init__(self, listener): super(CancelableToken, self).__init__(listener=listener) def cancel(self): assert protocol.isDispatchThread() if channel.state != STATE_OPEN: return False with channel.out_lock: if msg.is_sent: return False msg.is_canceled = True del channel.out_tokens[msg.token.getID()] return True token = CancelableToken(listener) msg.token = token self.out_tokens[token.getID()] = msg self.addToOutQueue(msg) return token
def wait(self, timeout=None): assert not protocol.isDispatchThread() with self._lock: while self._pending or self._queue: self._lock.wait(timeout) if timeout: break
def sendResult(self, token, results): assert protocol.isDispatchThread() if self.state != STATE_OPEN: raise Exception("Channel is closed") msg = Message('R') msg.data = results msg.token = token self.addToOutQueue(msg)
def __sendCongestionLevel(self): self.local_congestion_cnt += 1 if self.local_congestion_cnt < 8: return self.local_congestion_cnt = 0 if self.state != STATE_OPEN: return timeVal = int(time.time() * 1000) if timeVal - self.local_congestion_time < 500: return assert protocol.isDispatchThread() level = protocol.getCongestionLevel() if level == self.local_congestion_level: return i = (level - self.local_congestion_level) / 8 if i != 0: level = self.local_congestion_level + i self.local_congestion_time = timeVal with self.out_lock: msg = None if self.out_queue: msg = self.out_queue[0] if msg is None or msg.type != 'F': msg = Message('F') self.out_queue.insert(0, msg) self.out_lock.notify() data = "%i\0" % self.local_congestion_level msg.data = data msg.trace = self.trace_listeners self.local_congestion_level = level
def getRemoteService(self, cls_or_name): assert protocol.isDispatchThread() assert self.state != STATE_OPENING if type(cls_or_name) == types.StringType: return self.remote_service_by_name.get(cls_or_name) else: return self.remote_service_by_class.get(cls_or_name)
def getData(self): """ @return cached data object. Note: It is prohibited to call this method when cache is not valid. """ assert protocol.isDispatchThread() assert self.__valid return self.__data
def cancel(self): if not protocol.isDispatchThread(): protocol.invokeLater(self.cancel) return with self._lock: for cmd in self._pending.values(): cmd.token.cancel() del self._queue[:]
def dispose(self): assert protocol.isDispatchThread() id = self.getID() assert id peers = protocol.getLocator().getPeers() assert peers.get(id) == self del peers[id] self.sendPeerRemovedEvent()
def cancel(self): assert protocol.isDispatchThread() if channel.state != STATE_OPEN: return False with channel.out_lock: if msg.is_sent: return False msg.is_canceled = True del channel.out_tokens[msg.token.getID()] return True
def terminate(self, error): assert protocol.isDispatchThread() if self.state == STATE_CLOSED: return try: self.__sendEndOfStream(500) except Exception as x: if not error: error = x self._close(error)
def close(self): assert protocol.isDispatchThread() if self.state == STATE_CLOSED: return try: self.__sendEndOfStream(10000) self._close(None) except Exception as x: self._close(x)
def sendEvent(self, service, name, args): assert protocol.isDispatchThread() if not (self.state == STATE_OPEN or self.state == STATE_OPENING and isinstance(service, locator.LocatorService)): raise Exception("Channel is closed") msg = Message('E') msg.service = str(service) msg.name = name msg.data = args self.addToOutQueue(msg)
def cancel(self): assert protocol.isDispatchThread() with self._lock: if self.isDone(): return False self.__canceled = True self.__error = Exception("Canceled") if self.__channel: self.__channel.removeChannelListener(self.__channel_listener) self._lock.notifyAll() return True
def __init__(self, attrs): super(AbstractPeer, self).__init__(attrs) assert protocol.isDispatchThread() id = self.getID() assert id peers = protocol.getLocator().getPeers() if isinstance(peers.get(id), RemotePeer): peers.get(id).dispose() assert id not in peers peers[id] = self self.sendPeerAddedEvent()
def _waitForCommand(self, token, timeout=None): assert not protocol.isDispatchThread() with self._lock: while token.id in self._pending: self._lock.wait(timeout) if timeout: break else: if self._queue: self._lock.wait(timeout) while token.id in self._pending: self._lock.wait(timeout) if timeout: break
def removeEventListener(self, service, listener): assert protocol.isDispatchThread() svc_name = str(service) list = self.event_listeners.get(svc_name) if not list: return for i in range(len(list)): if list[i] is listener: if len(list) == 1: del self.event_listeners[svc_name] else: del list[i] return
def done(self, result): with self._lock: assert protocol.isDispatchThread() if self.__canceled: return assert not self.__is_done assert not self.__error assert self.__result is None self.__result = result self.__is_done = True if self.__channel: self.__channel.removeChannelListener(self.__channel_listener) self._lock.notifyAll()
def reset(self, data=None): """ Force cache to become valid, cancel pending data retrieval if data is provided. @param data - up-to-date data object (optional) """ assert protocol.isDispatchThread() if data is not None and self._command is not None: self._command.cancel() self._command = None if not self.__disposed: self.__data = data self.__error = None self.__valid = True self.post()
def invoke(self, service, command, *args, **kwargs): cmd = None if not protocol.isDispatchThread(): if not kwargs.get("async"): cmd = protocol.invokeAndWait(self._invoke, service, command, *args, **kwargs) if cmd and self._interactive: return cmd.getE() else: with self._lock: self._queue.append((service, command, args, kwargs)) if len(self._queue) == 1: protocol.invokeLater(self._processQueue) return return cmd
def wait(self, cb): """ Add a client call-back to cache wait list. Client call-backs are activated when cache state changes. Call-backs are removed from waiting list after that. It is responsibility of clients to check if the state change was one they are waiting for. @param cb - a call-back object """ assert protocol.isDispatchThread() assert not self.__disposed assert not self.__valid if cb and not self.isWaiting(cb): if self.__waiting_list is None: self.__waiting_list = [] self.__waiting_list.append(cb)
def __call__(self): """ Notify waiting clients about cache state change and remove them from wait list. It is responsibility of clients to check if the state change was one they are waiting for. Clients are not intended to call this method. """ assert protocol.isDispatchThread() self.__posted = False if self.__waiting_list: arr = self.__waiting_list self.__waiting_list = None for r in arr: if isinstance(r, DataCache) and r._DataCache__posted: continue r() if self.__waiting_list is None: self.__waiting_list = arr
def error(self, error): """ Set a error and notify all threads waiting for the task to complete. The method is supposed to be called in response to executing of run() method of this task. @param error - computation error. """ assert protocol.isDispatchThread() assert error with self._lock: if self.__canceled: return assert self.__error is None assert self.__result is None assert not self.__is_done self.__error = error if self.__channel: self.__channel.removeChannelListener(self.__channel_listener) self._lock.notifyAll()
def __validate(self): """ Initiate data retrieval if the cache is not valid. @return True if the cache is already valid """ assert protocol.isDispatchThread() if self.__disposed or self._channel.getState() != channel.STATE_OPEN: self._command = None self.__valid = True self.__error = None self.__data = None else: if self._command is not None: return False if not self.__valid and not self.startDataRetrieval(): return False assert self.__valid assert self._command is None self.post() return True
def get(self, timeout=None): """ Waits if necessary for the computation to complete, and then retrieves its result. @return the computed result @throws CancellationException if the computation was canceled @throws ExecutionException if the computation threw an exception @throws InterruptedException if the current thread was interrupted while waiting """ assert not protocol.isDispatchThread() with self._lock: while not self.isDone(): self._lock.wait(timeout) if timeout and not self.isDone(): raise TimeoutException("Timed out") if self.__error: raise Exception("TCF task aborted", self.__error) return self.__result
def set(self, token, error, data): """ End cache pending state and mark the cache as valid. If 'token' != None, the data represent results from a completed command. The data should be ignored if current cache pending command is not same as 'token'. It can happen if the cache was reset or canceled during data retrieval. @param token - pending command handle or None. @param error - data retrieval error or None @param data - up-to-date data object """ assert protocol.isDispatchThread() if token and self._command is not token: return self._command = None if not self.__disposed: assert not self.__valid if self._channel.getState() != channel.STATE_OPEN: self.__error = None self.__data = None self.__error = error self.__data = data self.__valid = True self.post()
def removeListener(self, listener): assert protocol.isDispatchThread() self.listeners.remove(listener)
def addListener(self, listener): assert listener is not None assert protocol.isDispatchThread() self.listeners.append(listener)
def getPeers(self): assert protocol.isDispatchThread() return self.peers