def __recvCallback(self, msg): #DEALER response contains empty delimiter! if len(msg[0]) != 0: print >>sys.stderr, "Received malformed message: ", msg return msg = msg[1:] #Currently we don't check the response type YakDBConnectionBase._checkHeaderFrame(msg) #Struct unpack yields 1-element tuple! headerFrame = msg[0] assert(len(headerFrame) == 8) #4 bytes response + 4 bytes request ID requestId = struct.unpack("<I", YakDBConnectionBase._extractRequestId(headerFrame))[0] callback, params = self.requests[requestId] #Postprocess, depending on request type. responseType = headerFrame[2] dataFrames = msg[1:] if responseType == "\x13": #Scan if params["mapData"]: data = YakDBConnectionBase(dataFrames) else: data = YakDBConnectionBase._mapScanToTupleList(dataFrames) elif responseType == "\x10": #Read if params["mapKeys"]: data = YakDBConnectionBase._mapReadKeyValues(params["keys"], dataFrames) else: data = dataFrames else: raise YakDBProtocolException("Received correct response, but cannot handle response code %d" % ord(responseType)) #Cleanup del self.requests[requestId] #Call original callback callback(data)
def read(self, tableNo, keys, mapKeys=False, requestId=b""): """ Read one or multiples values, identified by their keys, from a table. @param tableNo The table number to read from @param keys A list, tuple or single value. Must only contain strings, ints or floats. integral types are automatically mapped to signed 32-bit little-endian binary, floating point types are mapped to signed little-endian 64-bit IEEE754 values. If you'd like to use another binary representation, use a binary string instead. @param mapKeys If this is set to true, a mapping from the original keys to values is performed, the return value is a dictionary key->value rather than a value list. Mapping keys introduces additional overhead. @return A list of values, correspondent to the key order (or a dict, depends on mapKeys parameter) """ #Check if this connection instance is setup correctly self._checkSingleConnection() self._checkRequestReply() #Check parameters and create binary-string only key list YakDBConnectionBase._checkParameterType(tableNo, int, "tableNo") convertedKeys = ZMQBinaryUtil.convertToBinaryList(keys) #Send header frame self.socket.send(b"\x31\x01\x10" + requestId, zmq.SNDMORE) #Send the table number frame self._sendBinary32(tableNo) #Send key list nextToSend = None #Needed because the last value shall be sent w/out SNDMORE for key in convertedKeys: #Send the value from the last loop iteration if nextToSend is not None: self.socket.send(nextToSend, zmq.SNDMORE) #Send the key and enqueue the value nextToSend = key #Send last key, without SNDMORE flag self.socket.send(nextToSend) #Wait for reply msgParts = self.socket.recv_multipart(copy=True) YakDBConnectionBase._checkHeaderFrame(msgParts, b'\x10') #Return data frames values = msgParts[1:] if mapKeys: values = YakDBConnectionBase._mapReadKeyValues(keys, values) return values
def read(self, tableNo, keys, mapKeys=False, requestId=b""): """ Read one or multiples values, identified by their keys, from a table. @param tableNo The table number to read from @param keys A list, tuple or single value. Must only contain strings/bytes, ints or floats. integral types are automatically mapped to signed 32-bit little-endian binary, floating point types are mapped to signed little-endian 64-bit IEEE754 values. If you'd like to use another binary representation, use a binary string instead. @param mapKeys If this is set to true, a mapping from the original keys to values is performed, the return value is a dictionary key->value rather than a value list. Mapping keys introduces additional overhead. @return A list of values, correspondent to the key order (or a dict, depends on mapKeys parameter) """ #Check if this connection instance is setup correctly self._checkSingleConnection() self._checkRequestReply() #Check parameters and create binary-string only key list YakDBConnectionBase._checkParameterType(tableNo, int, "tableNo") convertedKeys = ZMQBinaryUtil.convertToBinaryList(keys) #Send header frame self.socket.send(b"\x31\x01\x10" + requestId, zmq.SNDMORE) #Send the table number frame self._sendBinary32(tableNo) #Send key list nextToSend = None #Needed because the last value shall be sent w/out SNDMORE for key in convertedKeys: #Send the value from the last loop iteration if nextToSend is not None: self.socket.send(nextToSend, zmq.SNDMORE) #Send the key and enqueue the value nextToSend = key #Send last key, without SNDMORE flag self.socket.send(nextToSend) #Wait for reply msgParts = self.socket.recv_multipart(copy=True) YakDBConnectionBase._checkHeaderFrame(msgParts, b'\x10') #Return data frames values = msgParts[1:] if mapKeys: values = YakDBConnectionBase._mapReadKeyValues(keys, values) return values