def fetch(self, client, blocking, val_index, metadata): #pylint: disable-msg=W0613 """Handle a fetch request on this variable. Arguments: client - client for whom to perform fetch blocking - is this a blocking fetch? val_index - index of value to fetch (unused here) """ fetch_location = max(val_index - self._index + 1, 0) if fetch_location > 0: raise WorkspaceFailure( 'ifetch* only supported at beginning of FIFO') try: value = remove_first(self._contents) var_metadata = remove_first(self._metadata) value.consumed() response = Response(var_metadata, value) response.iterstate = (self.vid, self._index) self._index += 1 return response except IndexError: if blocking: self.add_fetcher(client) return None else: raise WorkspaceFailure('no value available')
def send_long_response(self, response=None): """Send a response to a query which expects a "long" response.""" if response is None: response = Response(value=ERROR_VALUE) assert response.value is not None if response.iterstate is None: response.iterstate = ('', 0) # This operation is obviously no longer blocking self.__blocking_state.clear() # Coerce the response to a Value if not isinstance(response.value, Value): response.value = str(response.value) if isinstance(response.value, str): response.value = Value(DIRECT_STRING, response.value) # Coerce the status to a 4-digit string response.status = coerce_status(response.status) # Send the metadata if self.__metadata_send: self.__send_dictionary(response.metadata) # Send the reply itself self.__reply_long_preamble(response) if response.value.is_large(): if _DEBUG: log.msg("using long value protocol") producer = FileProducer(response.value, self.transport) self.transport.registerProducer(producer, None) else: self.transport.write(response.value.val())
def __handle_get(self, client, request): """Generic fetch/find implementation.""" try: value = self.get_handler(client, request) if value is not None: if not isinstance(value, Response): value = Response(value=value) if request.iterstate is not None: val_index = request.iterstate[1] + 1 value.iterstate = request.iterstate[0], val_index return value elif not request.blocking: raise OperationFailure('no value available.') else: thunk = lambda val: self.__value_callback(client, request, val) if request.remove: self.add_fetcher(client) else: self.add_finder(client) if not self.cb_handler(client, request, thunk): raise OperationFailure( 'Metavariable did not add callback.') else: return None except OperationFailure, fail: if fail.return_code == 0: fail.return_code = 1 raise WorkspaceFailure(fail.args[0], fail.return_code)
def __value_callback(self, client, request, value): """Callback to announce the unblocking of a fetch/find operation.""" if request.remove: try: self.fetchers.remove(client) except ValueError: log.msg('Blocking fetcher was not in the fetchers list for ' + self.name) return else: try: self.finders.remove(client) except ValueError: log.msg('Blocking finder was not in the finders list for ' + self.name) return if isinstance(value, OperationFailure): client.send_error(value.args[0], value.return_code, True) return if not isinstance(value, Response): data = str(value.value) metadata = value.metadata if request.iterstate is None: val_index = 0 else: val_index = request.iterstate[1] value = Response(metadata, data) value.iterstate = self.vid, val_index client.send_long_response(value)
def put_result(self, jid, resp, wrank): """Synthesize a result to the task currently claimed by the worker whose rank is wrank. """ if resp is None: resp = Response(value='', metadata={'nwsNull': '1'}) resp.metadata['nwsWorkerRank'] = str(wrank) self.__register_result(jid, resp.value, resp.metadata) self.__result_waiters.wake_one(jid)
def send_error(self, reason, status=1, long_reply=False): """Utility to send an error reply.""" metadata = {'nwsReason': reason} response = Response(metadata) response.status = status if long_reply: response.value = ERROR_VALUE self.send_long_response(response) else: self.send_short_response(response)
def send_short_response(self, response=None): """Send a response to a query which expects a "short" response.""" if response is None: response = Response() assert response.value is None assert response.iterstate is None # This operation is obviously no longer blocking self.__blocking_state.clear() # Coerce the status to a 4-digit string response.status = coerce_status(response.status) # Send the metadata if self.__metadata_send: self.__send_dictionary(response.metadata) # Send the reply self.transport.write(response.status)
def new_value(self, val_index, val, metadata): """Announce the appearance of a new value. If there are prior finders, the value will be distributed to them. If there are prior fetchers, the value will be distributed to the first of them in line, and False will be returned. Arguments: val_index - index of value being stored (for iterated finds, etc) val - newly stored value metadata - metadata stored with value """ # Not consumed unless there was a fetcher consumed = False # Build response resp = Response(metadata, val) resp.iterstate = (self.vid, val_index) # feed the finders for client in self.finders: if _DEBUG: log.msg('calling finder session %d with val_index %d' % (client.transport.sessionno, val_index)) client.send_long_response(resp) # clear the finders list del self.finders[:] # give it to a fetcher if there is one if self.fetchers: client = self.fetchers.pop(0) if _DEBUG: log.msg('calling fetcher session %d with val_index %d' % (client.transport.sessionno, val_index)) client.send_long_response(resp) consumed = True return consumed
def find(self, client, blocking, val_index, metadata): #pylint: disable-msg=W0613 """Handle a find request on this variable. Arguments: client - client for whom to perform find blocking - is this a blocking find? val_index - index of value to find (for iterated find) """ try: find_location = max(val_index - self._index + 1, 0) response = Response(self._metadata[find_location], self._contents[find_location]) response.iterstate = self.vid, self._index + find_location return response except IndexError: if blocking: self.add_finder(client) return None else: raise WorkspaceFailure('no value available')
def fetch(self, client, blocking, val_index, metadata): #pylint: disable-msg=W0613 """Handle a fetch request on this variable. Arguments: client -- client for whom to perform fetch blocking -- is this a blocking fetch? val_index -- index of value to fetch (unused here) """ try: fetch_location = max(val_index - self._index + 1, 0) value = self._contents.pop(fetch_location) value.consumed() response = Response(self._metadata, value) response.iterstate = (self.vid, self._index) self._metadata = None self._index += 1 return response except IndexError: if blocking: self.add_fetcher(client) return None else: raise WorkspaceFailure('no value available')