1
0
mirror of https://github.com/django/django.git synced 2025-10-26 15:16:09 +00:00

Fixed #4831 -- Added an "add" cache key method, for parity with memcached's

API. This works for all cache backends. Patch from Matt McClanahan.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@6572 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick
2007-10-20 15:16:34 +00:00
parent b678601df3
commit 714c09b8bd
9 changed files with 74 additions and 2 deletions

View File

@@ -14,6 +14,14 @@ class BaseCache(object):
timeout = 300
self.default_timeout = timeout
def add(self, key, value, timeout=None):
"""
Set a value in the cache if the key does not already exist. If
timeout is given, that timeout will be used for the key; otherwise
the default cache timeout will be used.
"""
raise NotImplementedError
def get(self, key, default=None):
"""
Fetch a given key from the cache. If the key does not exist, return

View File

@@ -24,6 +24,9 @@ class CacheClass(BaseCache):
except (ValueError, TypeError):
self._cull_frequency = 3
def add(self, key, value, timeout=None):
return self._base_set('add', key, value, timeout)
def get(self, key, default=None):
cursor = connection.cursor()
cursor.execute("SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s" % self._table, [key])
@@ -38,6 +41,9 @@ class CacheClass(BaseCache):
return pickle.loads(base64.decodestring(row[1]))
def set(self, key, value, timeout=None):
return self._base_set('set', key, value, timeout)
def _base_set(self, mode, key, value, timeout=None):
if timeout is None:
timeout = self.default_timeout
cursor = connection.cursor()
@@ -50,10 +56,11 @@ class CacheClass(BaseCache):
encoded = base64.encodestring(pickle.dumps(value, 2)).strip()
cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s" % self._table, [key])
try:
if cursor.fetchone():
if mode == 'set' and cursor.fetchone():
cursor.execute("UPDATE %s SET value = %%s, expires = %%s WHERE cache_key = %%s" % self._table, [encoded, str(exp), key])
else:
cursor.execute("INSERT INTO %s (cache_key, value, expires) VALUES (%%s, %%s, %%s)" % self._table, [key, encoded, str(exp)])
if mode == 'add':
cursor.execute("INSERT INTO %s (cache_key, value, expires) VALUES (%%s, %%s, %%s)" % self._table, [key, encoded, str(exp)])
except DatabaseError:
# To be threadsafe, updates/inserts are allowed to fail silently
pass

View File

@@ -6,6 +6,9 @@ class CacheClass(BaseCache):
def __init__(self, *args, **kwargs):
pass
def add(self, *args, **kwargs):
pass
def get(self, key, default=None):
return default

View File

@@ -17,6 +17,26 @@ class CacheClass(SimpleCacheClass):
del self._cache
del self._expire_info
def add(self, key, value, timeout=None):
fname = self._key_to_file(key)
if timeout is None:
timeout = self.default_timeout
try:
filelist = os.listdir(self._dir)
except (IOError, OSError):
self._createdir()
filelist = []
if len(filelist) > self._max_entries:
self._cull(filelist)
if os.path.basename(fname) not in filelist:
try:
f = open(fname, 'wb')
now = time.time()
pickle.dump(now + timeout, f, 2)
pickle.dump(value, f, 2)
except (IOError, OSError):
pass
def get(self, key, default=None):
fname = self._key_to_file(key)
try:

View File

@@ -14,6 +14,13 @@ class CacheClass(SimpleCacheClass):
SimpleCacheClass.__init__(self, host, params)
self._lock = RWLock()
def add(self, key, value, timeout=None):
self._lock.writer_enters()
try:
SimpleCacheClass.add(self, key, value, timeout)
finally:
self._lock.writer_leaves()
def get(self, key, default=None):
should_delete = False
self._lock.reader_enters()

View File

@@ -16,6 +16,9 @@ class CacheClass(BaseCache):
BaseCache.__init__(self, params)
self._cache = memcache.Client(server.split(';'))
def add(self, key, value, timeout=0):
self._cache.add(key.encode('ascii', 'ignore'), value, timeout or self.default_timeout)
def get(self, key, default=None):
val = self._cache.get(smart_str(key))
if val is None:

View File

@@ -21,6 +21,15 @@ class CacheClass(BaseCache):
except (ValueError, TypeError):
self._cull_frequency = 3
def add(self, key, value, timeout=None):
if len(self._cache) >= self._max_entries:
self._cull()
if timeout is None:
timeout = self.default_timeout
if key not in self._cache.keys():
self._cache[key] = value
self._expire_info[key] = time.time() + timeout
def get(self, key, default=None):
now = time.time()
exp = self._expire_info.get(key)