Ejemplo n.º 1
0
    def connect(self):
        self.log.log(logging.TRACE, "Connecting to Memcache %s", self._address)

        self._stream = BufferedStream(socket.create_connection(self._address))
Ejemplo n.º 2
0
class MemcacheConnection(object):
    log = logging.getLogger("MemcacheConnection")

    _read_timeout = 2
    _write_timeout = 2

    def __init__(self, address, protocol = "text", codec = "default"):

        self._address = address

        self._stream = None
        self._read_queue = DeferredQueue()
        self._write_queue = DeferredQueue()

        self._protocol = MemcacheProtocol.create(protocol)
        self._protocol.set_codec(MemcacheCodec.create(codec))

    def connect(self):
        self.log.log(logging.TRACE, "Connecting to Memcache %s", self._address)

        self._stream = BufferedStream(socket.create_connection(self._address))

    def disconnect(self):
        if self._stream is None:
            return
            
        try:
            self._stream.close()
        except:
            pass

        self._stream = None

    def is_connected(self):
        return self._stream is not None

    def flush(self):
        self._stream.flush()

    def _write_command(self, cmd, args, flush = True):
        with self._stream.get_writer() as writer:
            getattr(self._protocol, 'write_' + cmd)(writer, *args)
            if flush:
                writer.flush()

    def _read_result(self, cmd):
        with self._stream.get_reader() as reader:
            return getattr(self._protocol, 'read_' + cmd)(reader)

    def _defer_command(self, cmd, args, result_channel, error_value = None):
        def _read_result():

            timeout = Timeout(self._read_timeout, Timeout)
            timeout.start()
            try:
                result = self._read_result(cmd)
                result_channel.put(result)
            except Timeout:
                raise
            except:
                self.log.exception("read error in defer_command")
                result_channel.put((MemcacheResult.ERROR, error_value))

                self.log.warn("Error communicating with Memcache %s, disconnecting", self._address)
                self.disconnect()
            finally:
                timeout.cancel()

        def _write_command():

            timeout = Timeout(self._write_timeout, Timeout)
            timeout.start()
            try:
                if not self.is_connected():
                    self.connect()
                self._write_command(cmd, args, True)
                self._read_queue.defer(_read_result)
            except Timeout:
                raise
            except:
                result_channel.put((MemcacheResult.ERROR, error_value))

                self.log.warn("Error communicating with Memcache %s, disconnecting", self._address)
                self.disconnect()
            finally:
                timeout.cancel()

        self._write_queue.defer(_write_command)

    def _do_command(self, cmd, args, error_value = None):
        result_channel = ResultChannel()

        self._defer_command(cmd, args, result_channel, error_value)

        try:
            return result_channel.get()
        except TimeoutError:
            return MemcacheResult.TIMEOUT, error_value

    def close(self):
        if self.is_connected():
            self._stream.close()
            self._stream = None

    def delete(self, key, expiration = 0):
        return self._do_command("delete", (key, expiration))[0]

    def set(self, key, data, expiration = 0, flags = 0):
        return self._do_command("set", (key, data, expiration, flags))[0]

    def __setitem__(self, key, data):
        self.set(key, data)

    def add(self, key, data, expiration = 0, flags = 0):
        return self._do_command("add", (key, data, expiration, flags))[0]

    def replace(self, key, data, expiration = 0, flags = 0):
        return self._do_command("replace", (key, data, expiration, flags))[0]

    def append(self, key, data, expiration = 0, flags = 0):
        return self._do_command("append", (key, data, expiration, flags))[0]

    def prepend(self, key, data, expiration = 0, flags = 0):
        return self._do_command("prepend", (key, data, expiration, flags))[0]

    def cas(self, key, data, cas_unique, expiration = 0, flags = 0):
        return self._do_command("cas", (key, data, expiration, flags, cas_unique))[0]

    def incr(self, key, delta = 1):
        return self._do_command("incr", (key, delta))

    def decr(self, key, delta = 1):
        return self._do_command("decr", (key, delta))

    def get(self, key, default = None):
        _, values = self._do_command("get", ([key], ), {})
        return values.get(key, default)

    def __getitem__(self, key):
        return self.get(key)

    def getr(self, key, default = None):
        result, values = self._do_command("get", ([key], ), {})
        return result, values.get(key, default)

    def gets(self, key, default = None):
        result, values = self._do_command("gets", ([key], ), {})
        value, cas_unique = values.get(key, (default, None))
        return result, value, cas_unique

    def get_multi(self, keys):
        return self._do_command("get", (keys, ))

    def gets_multi(self, keys):
        return self._do_command("gets", (keys, ))

    def version(self):
        return self._do_command("version", ())

    def stats(self):
        return self._do_command("stats", ())