def test_servers(self): """Test that memcached servers are servicing requests. Returns: set: URIs of servers that are responding. """ responders = set() for server in self.servers: client = Client_([server]) key = uuid4().hex client.set(key, 1) if client.get(key) == 1: responders.add(server) return responders
def client(self): """Get the native memcache client. Returns: `memcache.Client` instance. """ if self._client is None: self._client = Client_(self.servers) return self._client
def client(self): """Get the native memcache client. Returns: `memcache.Client` instance. """ if self._client is None: #print "Connected memcached client %s" % str(self) self._client = Client_(self.servers) return self._client
class Client(object): """Wrapper for memcache.Client instance. Adds the features: - unlimited key length; - hard/soft flushing; - ability to cache None. """ class _Miss(object): def __nonzero__(self): return False miss = _Miss() logger = config.debug_printer("memcache") def __init__(self, servers, debug=False): """Create a memcached client. Args: servers (str or list of str): Server URI(s), eg '127.0.0.1:11211'. debug (bool): If True, quasi human readable keys are used. This helps debugging - run 'memcached -vv' in the foreground to see the keys being get/set/stored. """ self.servers = [servers] if isinstance(servers, basestring) else servers self.key_hasher = self._debug_key_hash if debug else self._key_hash self._client = None self.debug = debug self.current = '' def __nonzero__(self): return bool(self.servers) @property def client(self): """Get the native memcache client. Returns: `memcache.Client` instance. """ if self._client is None: self._client = Client_(self.servers) return self._client def test_servers(self): """Test that memcached servers are servicing requests. Returns: set: URIs of servers that are responding. """ responders = set() for server in self.servers: client = Client_([server]) key = uuid4().hex client.set(key, 1) if client.get(key) == 1: responders.add(server) return responders def set(self, key, val, time=0, min_compress_len=0): """See memcache.Client.""" if not self.servers: return key = self._qualified_key(key) hashed_key = self.key_hasher(key) val = (key, val) self.client.set(key=hashed_key, val=val, time=time, min_compress_len=min_compress_len) self.logger("SET: %s", key) def get(self, key): """See memcache.Client. Returns: object: A value if cached, else `self.miss`. Note that this differs from `memcache.Client`, which returns None on cache miss, and thus cannot cache the value None itself. """ if not self.servers: return self.miss key = self._qualified_key(key) hashed_key = self.key_hasher(key) entry = self.client.get(hashed_key) if isinstance(entry, tuple) and len(entry) == 2: key_, result = entry if key_ == key: self.logger("HIT: %s", key) return result self.logger("MISS: %s", key) return self.miss def delete(self, key): """See memcache.Client.""" if self.servers: key = self._qualified_key(key) hashed_key = self.key_hasher(key) self.client.delete(hashed_key) def flush(self, hard=False): """Drop existing entries from the cache. Args: hard (bool): If True, all current entries are flushed from the server(s), which affects all users. If False, only the local process is affected. """ if not self.servers: return if hard: self.client.flush_all() self.reset_stats() else: from uuid import uuid4 tag = uuid4().hex if self.debug: tag = "flushed" + tag self.current = tag def get_stats(self): """Get server statistics. Returns: A list of tuples (server_identifier, stats_dictionary). """ return self._get_stats() def reset_stats(self): """Reset the server stats.""" self._get_stats("reset") def disconnect(self): """Disconnect from server(s). Behaviour is undefined after this call.""" if self.servers and self._client: self._client.disconnect_all() #print "Disconnected memcached client %s" % str(self) def _qualified_key(self, key): return "%s:%s:%s" % (cache_interface_version, self.current, key) def _get_stats(self, stat_args=None): return self.client.get_stats(stat_args=stat_args) @classmethod def _key_hash(cls, key): return md5(key).hexdigest() @classmethod def _debug_key_hash(cls, key): import re h = cls._key_hash(key)[:16] value = "%s:%s" % (h, key) value = value[:SERVER_MAX_KEY_LENGTH] value = re.sub("[^0-9a-zA-Z]+", '_', value) return value