def fetch(self, key, _conn=None): """ Fetch data from sharedance :Parameters: - `key`: The key to fetch :Types: - `key`: ``str`` :Exceptions: - `KeyError`: The key does not exist - `SharedanceCommandError`: The result was not interpretable """ key, write = str(key), _conn.write write("F%s" % _struct.pack('!L', len(key))) write(key) _conn.flush() expected, flags = -1, 0 if self.magic: value = _stream.read_exact(_conn, len(self._MAGIC)) if not value: raise KeyError(key) elif value == self._MAGIC and _conn.read(1) == '\0': line = _conn.readline() try: flags = int(line.rstrip()) except (TypeError, ValueError): raise SharedanceFormatError("Invalid flags: %r" % line) if flags & NO_FLAGS: raise SharedanceFormatError( "Unrecognized flags: %s" % flags) line = _conn.readline() try: expected = int(line.rstrip()) except (TypeError, ValueError): raise SharedanceFormatError( "Invalid value length: %r" % line) data = _stream.read_exact(_conn, expected) if expected >= 0 and len(data) != expected: raise SharedanceCommandError("Fetch incomplete") if flags & FLAG_COMPRESSED: if _zlib is None: raise SharedanceCommandError( "Cannot uncompress fetched value (no zlib)") else: try: data = _zlib.decompress(data) except _zlib.error, e: raise SharedanceFormatError( "Decompression error: %s" % str(e))
def _read_data(self, size): """ Read actual chunk data :Parameters: - `size`: The maximum number of bytes to read (>0) :Types: - `size`: ``int`` :return: Bytes read (empty on EOF) :rtype: ``str`` :Exceptions: - `IncompleteChunk`: The stream ended unexpectedly in the middle of the chunk """ rsize = min(self._left, size) if rsize <= 0: self._state = self._read_suffix return self.read(size) result = _stream.read_exact(self._stream, rsize) if not result: raise IncompleteChunk("Missing at least %d bytes" % self._left) self._left -= len(result) if self._left <= 0: self._state = self._read_suffix return result
def read(self, size): """ Read (at max) `size` bytes :Parameters: - `size`: Maximum number of octets to read :Types: - `size`: ``int`` :return: The bytes read (empty on EOF) :rtype: ``str`` """ if self._left > 0: size = min(size, self._left) result = _stream.read_exact(self._stream, size) self._left -= len(result) return result return ""
def get(self, *keys): """ Get a list of key/value pairs from the cache (if applicable) The returned dict contains all pairs it could get. But keys maybe missing or the dict might be completely empty (of course). :Parameters: - `keys`: The keys to fetch :Types: - `keys`: ``tuple`` :return: The dict of key/value pairs :rtype: ``dict`` """ # pylint: disable = R0912, R0915 result = {} if not keys: return result keymap = dict((self._prepare_key(key), key) for key in keys) try: conns = self._get_conn(*keymap.keys()) if not conns: return result conns = conns.items() try: while conns: conn, keys = conns.pop() try: conn.write("get %s%s" % (" ".join(keys), CRLF)) conn.flush() while True: line = self._error(conn.readline()) if line == "END": break elif line.startswith("VALUE "): _, key, flags, length = line.split() flags, length = int(flags), int(length) value = _stream.read_exact(conn, length) if _stream.read_exact(conn, 2) != CRLF: # sync error? conn, _ = None, conn.destroy() return {} try: result[keymap[key]] = \ self._decode_value(flags, value) except (TypeError, ValueError): pass # wrong flags or something except KeyError: raise KeyError('%r, %s: %r' % ( line, key, keymap )) except (SystemExit, KeyboardInterrupt): raise except: import sys e = sys.exc_info() try: msg = "%s:: %r, %s, %r" % ( str(e[1]), line, flags, value ) e = (e[0], msg, e[2]) finally: try: raise e[0], e[1], e[2] finally: del e else: # something else we don't know. Better close # the connection. conn, _ = None, conn.destroy() return {} finally: if conn is not None: conn.close() finally: while conns: conns.pop()[0].close() except _socket.error: pass return result