115 lines
3.7 KiB
Python
115 lines
3.7 KiB
Python
|
from gluon.contrib.memcache.memcache import Client
|
||
|
from gluon.cache import CacheAbstract
|
||
|
import time
|
||
|
|
||
|
"""
|
||
|
examle of usage:
|
||
|
|
||
|
cache.memcache = MemcacheClient(request,[127.0.0.1:11211],debug=true)
|
||
|
"""
|
||
|
|
||
|
import cPickle as pickle
|
||
|
import thread
|
||
|
from gluon import current
|
||
|
|
||
|
DEFAULT_TIME_EXPIRE = 300 # seconds (must be the same as cache.ram)
|
||
|
|
||
|
def MemcacheClient(*a, **b):
|
||
|
if not hasattr(current,'__memcache_client'):
|
||
|
current.__memcache_client = MemcacheClientObj(*a, **b)
|
||
|
return current.__memcache_client
|
||
|
|
||
|
class MemcacheClientObj(Client):
|
||
|
|
||
|
def initialize(self):
|
||
|
pass
|
||
|
|
||
|
meta_storage = {}
|
||
|
max_time_expire = 24*3600
|
||
|
|
||
|
def __init__(self, request, servers, debug=0, pickleProtocol=0,
|
||
|
pickler=pickle.Pickler, unpickler=pickle.Unpickler,
|
||
|
pload=None, pid=None,
|
||
|
default_time_expire = DEFAULT_TIME_EXPIRE):
|
||
|
self.request=request
|
||
|
self.default_time_expire = default_time_expire
|
||
|
if request:
|
||
|
app = request.application
|
||
|
else:
|
||
|
app = ''
|
||
|
Client.__init__(self, servers, debug, pickleProtocol,
|
||
|
pickler, unpickler, pload, pid)
|
||
|
if not app in self.meta_storage:
|
||
|
self.storage = self.meta_storage[app] = {
|
||
|
CacheAbstract.cache_stats_name: {
|
||
|
'hit_total': 0,
|
||
|
'misses': 0,
|
||
|
}}
|
||
|
else:
|
||
|
self.storage = self.meta_storage[app]
|
||
|
|
||
|
def __call__(self, key, f, time_expire = 'default'):
|
||
|
if time_expire == 'default':
|
||
|
time_expire = self.default_time_expire
|
||
|
if time_expire == None:
|
||
|
time_expire = self.max_time_expire
|
||
|
# this must be commented because get and set are redefined
|
||
|
# key = self.__keyFormat__(key)
|
||
|
now = time.time()
|
||
|
value = None
|
||
|
if f is None: # force deletion of value
|
||
|
self.delete(key)
|
||
|
return None
|
||
|
elif time_expire==0: # value forced expired
|
||
|
item = None # value to be computed
|
||
|
else:
|
||
|
item = self.get(key)
|
||
|
if item:
|
||
|
if not isinstance(item,(list,tuple)):
|
||
|
value = item
|
||
|
elif (item[0] < now - time_expire): # value expired
|
||
|
item = None # value to be computed
|
||
|
else:
|
||
|
value = item[1]
|
||
|
if not item:
|
||
|
value = f()
|
||
|
self.set(key, (now,value), self.max_time_expire)
|
||
|
return value
|
||
|
|
||
|
def increment(self, key, value=1, time_expire='default'):
|
||
|
""" time_expire is ignored """
|
||
|
if time_expire == 'default':
|
||
|
time_expire = self.default_time_expire
|
||
|
newKey = self.__keyFormat__(key)
|
||
|
obj = Client.get(self, newKey)
|
||
|
if obj:
|
||
|
if isinstance(obj,(int,float,long)):
|
||
|
return Client.incr(self, newKey, value)
|
||
|
else:
|
||
|
value += obj[1]
|
||
|
Client.set(self,newKey,(time.time(),value),
|
||
|
self.max_time_expire)
|
||
|
return value
|
||
|
else:
|
||
|
Client.set(self, newKey, value, self.max_time_expire)
|
||
|
return value
|
||
|
|
||
|
def set(self, key, value, time_expire='default'):
|
||
|
if time_expire == 'default':
|
||
|
time_expire = self.default_time_expire
|
||
|
newKey = self.__keyFormat__(key)
|
||
|
return Client.set(self, newKey, value, time_expire)
|
||
|
|
||
|
def get(self, key):
|
||
|
newKey = self.__keyFormat__(key)
|
||
|
return Client.get(self, newKey)
|
||
|
|
||
|
def delete(self, key):
|
||
|
newKey = self.__keyFormat__(key)
|
||
|
return Client.delete(self, newKey)
|
||
|
|
||
|
def __keyFormat__(self, key):
|
||
|
return '%s/%s' % (self.request.application, key.replace(' ', '_'))
|
||
|
|
||
|
|