USER
adrian
REVISION
2287
3f0790d500a9
false
DATE
2006-02-24
LINE
1
CONTENT
"Database cache backend."
jezdez
16338
bf038debb499
false
2011-07-13
2
import base64
jezdez
16338
bf038debb499
false
2011-07-13
3
import time
jezdez
16338
bf038debb499
false
2011-07-13
4
from datetime import datetime
adrian
2287
3f0790d500a9
false
2006-02-24
2
adrian
2287
3f0790d500a9
false
2006-02-24
7
try:
adrian
2287
3f0790d500a9
false
2006-02-24
8
import cPickle as pickle
adrian
2287
3f0790d500a9
false
2006-02-24
9
except ImportError:
adrian
2287
3f0790d500a9
false
2006-02-24
10
import pickle
adrian
2287
3f0790d500a9
false
2006-02-24
11
jezdez
16338
bf038debb499
false
2011-07-13
11
from django.core.cache.backends.base import BaseCache
jezdez
16338
bf038debb499
false
2011-07-13
12
from django.db import connections, router, transaction, DatabaseError
jezdez
16338
bf038debb499
false
2011-07-13
13
jezdez
16338
bf038debb499
false
2011-07-13
14
russellm
13275
4dd52d4f3f50
false
2010-08-05
12
class Options(object):
russellm
13275
4dd52d4f3f50
false
2010-08-05
13
"""A class that will quack like a Django model _meta class.
russellm
13275
4dd52d4f3f50
false
2010-08-05
14
russellm
13275
4dd52d4f3f50
false
2010-08-05
15
This allows cache operations to be controlled by the router
russellm
13275
4dd52d4f3f50
false
2010-08-05
16
"""
russellm
13275
4dd52d4f3f50
false
2010-08-05
17
def __init__(self, table):
russellm
13275
4dd52d4f3f50
false
2010-08-05
18
self.db_table = table
russellm
13275
4dd52d4f3f50
false
2010-08-05
19
self.app_label = 'django_cache'
russellm
13275
4dd52d4f3f50
false
2010-08-05
20
self.module_name = 'cacheentry'
russellm
13275
4dd52d4f3f50
false
2010-08-05
21
self.verbose_name = 'cache entry'
russellm
13275
4dd52d4f3f50
false
2010-08-05
22
self.verbose_name_plural = 'cache entries'
russellm
13275
4dd52d4f3f50
false
2010-08-05
23
self.object_name = 'CacheEntry'
russellm
13275
4dd52d4f3f50
false
2010-08-05
24
self.abstract = False
russellm
13275
4dd52d4f3f50
false
2010-08-05
25
self.managed = True
russellm
13275
4dd52d4f3f50
false
2010-08-05
26
self.proxy = False
russellm
13275
4dd52d4f3f50
false
2010-08-05
27
russellm
14807
905c4a7e1f19
false
2010-12-21
28
class BaseDatabaseCache(BaseCache):
russellm
14807
905c4a7e1f19
false
2010-12-21
29
def __init__(self, table, params):
russellm
14807
905c4a7e1f19
false
2010-12-21
30
BaseCache.__init__(self, params)
russellm
13275
4dd52d4f3f50
false
2010-08-05
31
self._table = table
russellm
13275
4dd52d4f3f50
false
2010-08-05
32
russellm
13275
4dd52d4f3f50
false
2010-08-05
33
class CacheEntry(object):
russellm
13275
4dd52d4f3f50
false
2010-08-05
34
_meta = Options(table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
35
self.cache_model_class = CacheEntry
russellm
13275
4dd52d4f3f50
false
2010-08-05
36
russellm
14807
905c4a7e1f19
false
2010-12-21
37
class DatabaseCache(BaseDatabaseCache):
russellm
14425
793e94ba2037
false
2010-11-19
38
def get(self, key, default=None, version=None):
russellm
14425
793e94ba2037
false
2010-11-19
39
key = self.make_key(key, version=version)
mtredinnick
13568
7e0b7bf098d2
false
2010-09-12
49
self.validate_key(key)
russellm
13275
4dd52d4f3f50
false
2010-08-05
49
db = router.db_for_read(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
50
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
51
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
52
russellm
13275
4dd52d4f3f50
false
2010-08-05
53
cursor.execute("SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s" % table, [key])
adrian
2287
3f0790d500a9
false
2006-02-24
30
row = cursor.fetchone()
adrian
2287
3f0790d500a9
false
2006-02-24
31
if row is None:
adrian
2287
3f0790d500a9
false
2006-02-24
32
return default
adrian
2287
3f0790d500a9
false
2006-02-24
33
now = datetime.now()
adrian
2287
3f0790d500a9
false
2006-02-24
34
if row[2] < now:
russellm
13275
4dd52d4f3f50
false
2010-08-05
59
db = router.db_for_write(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
60
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
61
cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % table, [key])
russellm
13275
4dd52d4f3f50
false
2010-08-05
62
transaction.commit_unless_managed(using=db)
adrian
2287
3f0790d500a9
false
2006-02-24
37
return default
russellm
13275
4dd52d4f3f50
false
2010-08-05
64
value = connections[db].ops.process_clob(row[1])
ikelly
9862
8739c35149dd
false
2009-03-13
39
return pickle.loads(base64.decodestring(value))
adrian
2287
3f0790d500a9
false
2006-02-24
39
russellm
14425
793e94ba2037
false
2010-11-19
59
def set(self, key, value, timeout=None, version=None):
russellm
14425
793e94ba2037
false
2010-11-19
60
key = self.make_key(key, version=version)
mtredinnick
13568
7e0b7bf098d2
false
2010-09-12
69
self.validate_key(key)
mtredinnick
8110
c787c7f62142
false
2008-08-10
41
self._base_set('set', key, value, timeout)
mtredinnick
6421
b4175804cc7b
false
2007-10-20
45
russellm
14425
793e94ba2037
false
2010-11-19
64
def add(self, key, value, timeout=None, version=None):
russellm
14425
793e94ba2037
false
2010-11-19
65
key = self.make_key(key, version=version)
mtredinnick
13568
7e0b7bf098d2
false
2010-09-12
73
self.validate_key(key)
mtredinnick
6438
5096a56a9ac6
false
2007-10-21
44
return self._base_set('add', key, value, timeout)
mtredinnick
6438
5096a56a9ac6
false
2007-10-21
45
mtredinnick
6421
b4175804cc7b
false
2007-10-20
46
def _base_set(self, mode, key, value, timeout=None):
adrian
2287
3f0790d500a9
false
2006-02-24
41
if timeout is None:
adrian
2287
3f0790d500a9
false
2006-02-24
42
timeout = self.default_timeout
russellm
13275
4dd52d4f3f50
false
2010-08-05
76
db = router.db_for_write(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
77
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
78
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
79
russellm
13275
4dd52d4f3f50
false
2010-08-05
80
cursor.execute("SELECT COUNT(*) FROM %s" % table)
adrian
2287
3f0790d500a9
false
2006-02-24
45
num = cursor.fetchone()[0]
adrian
2287
3f0790d500a9
false
2006-02-24
46
now = datetime.now().replace(microsecond=0)
adrian
2287
3f0790d500a9
false
2006-02-24
47
exp = datetime.fromtimestamp(time.time() + timeout).replace(microsecond=0)
adrian
2287
3f0790d500a9
false
2006-02-24
48
if num > self._max_entries:
russellm
13275
4dd52d4f3f50
false
2010-08-05
85
self._cull(db, cursor, now)
adrian
2287
3f0790d500a9
false
2006-02-24
50
encoded = base64.encodestring(pickle.dumps(value, 2)).strip()
russellm
13275
4dd52d4f3f50
false
2010-08-05
87
cursor.execute("SELECT cache_key, expires FROM %s WHERE cache_key = %%s" % table, [key])
adrian
2287
3f0790d500a9
false
2006-02-24
52
try:
mtredinnick
9753
0ab5ef23e1bc
false
2009-03-02
59
result = cursor.fetchone()
mtredinnick
9753
0ab5ef23e1bc
false
2009-03-02
60
if result and (mode == 'set' or
mtredinnick
9753
0ab5ef23e1bc
false
2009-03-02
61
(mode == 'add' and result[1] < now)):
russellm
13275
4dd52d4f3f50
false
2010-08-05
92
cursor.execute("UPDATE %s SET value = %%s, expires = %%s WHERE cache_key = %%s" % table,
russellm
13275
4dd52d4f3f50
false
2010-08-05
93
[encoded, connections[db].ops.value_to_db_datetime(exp), key])
adrian
2287
3f0790d500a9
false
2006-02-24
55
else:
russellm
13275
4dd52d4f3f50
false
2010-08-05
95
cursor.execute("INSERT INTO %s (cache_key, value, expires) VALUES (%%s, %%s, %%s)" % table,
russellm
13275
4dd52d4f3f50
false
2010-08-05
96
[key, encoded, connections[db].ops.value_to_db_datetime(exp)])
adrian
2287
3f0790d500a9
false
2006-02-24
57
except DatabaseError:
adrian
2287
3f0790d500a9
false
2006-02-24
58
# To be threadsafe, updates/inserts are allowed to fail silently
russellm
13275
4dd52d4f3f50
false
2010-08-05
99
transaction.rollback_unless_managed(using=db)
mtredinnick
8110
c787c7f62142
false
2008-08-10
65
return False
adrian
2287
3f0790d500a9
false
2006-02-24
60
else:
russellm
13275
4dd52d4f3f50
false
2010-08-05
102
transaction.commit_unless_managed(using=db)
mtredinnick
8110
c787c7f62142
false
2008-08-10
68
return True
adrian
2287
3f0790d500a9
false
2006-02-24
62
russellm
14425
793e94ba2037
false
2010-11-19
101
def delete(self, key, version=None):
russellm
14425
793e94ba2037
false
2010-11-19
102
key = self.make_key(key, version=version)
mtredinnick
13568
7e0b7bf098d2
false
2010-09-12
109
self.validate_key(key)
russellm
14425
793e94ba2037
false
2010-11-19
104
russellm
13275
4dd52d4f3f50
false
2010-08-05
106
db = router.db_for_write(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
107
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
108
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
109
russellm
13275
4dd52d4f3f50
false
2010-08-05
110
cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % table, [key])
russellm
13275
4dd52d4f3f50
false
2010-08-05
111
transaction.commit_unless_managed(using=db)
adrian
2287
3f0790d500a9
false
2006-02-24
67
russellm
14425
793e94ba2037
false
2010-11-19
112
def has_key(self, key, version=None):
russellm
14425
793e94ba2037
false
2010-11-19
113
key = self.make_key(key, version=version)
mtredinnick
13568
7e0b7bf098d2
false
2010-09-12
118
self.validate_key(key)
russellm
14425
793e94ba2037
false
2010-11-19
115
russellm
13275
4dd52d4f3f50
false
2010-08-05
114
db = router.db_for_read(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
115
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
116
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
117
mtredinnick
9753
0ab5ef23e1bc
false
2009-03-02
78
now = datetime.now().replace(microsecond=0)
russellm
13275
4dd52d4f3f50
false
2010-08-05
119
cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s and expires > %%s" % table,
russellm
13275
4dd52d4f3f50
false
2010-08-05
120
[key, connections[db].ops.value_to_db_datetime(now)])
adrian
2287
3f0790d500a9
false
2006-02-24
71
return cursor.fetchone() is not None
adrian
2287
3f0790d500a9
false
2006-02-24
72
russellm
13275
4dd52d4f3f50
false
2010-08-05
123
def _cull(self, db, cursor, now):
adrian
2287
3f0790d500a9
false
2006-02-24
74
if self._cull_frequency == 0:
russellm
12116
c1ad14c551a9
false
2010-01-27
87
self.clear()
adrian
2287
3f0790d500a9
false
2006-02-24
76
else:
russellm
13480
7351411944a9
false
2010-08-31
127
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
127
cursor.execute("DELETE FROM %s WHERE expires < %%s" % table,
russellm
13275
4dd52d4f3f50
false
2010-08-05
128
[connections[db].ops.value_to_db_datetime(now)])
russellm
13275
4dd52d4f3f50
false
2010-08-05
129
cursor.execute("SELECT COUNT(*) FROM %s" % table)
adrian
2287
3f0790d500a9
false
2006-02-24
79
num = cursor.fetchone()[0]
adrian
2287
3f0790d500a9
false
2006-02-24
80
if num > self._max_entries:
russellm
13275
4dd52d4f3f50
false
2010-08-05
132
cursor.execute("SELECT cache_key FROM %s ORDER BY cache_key LIMIT 1 OFFSET %%s" % table, [num / self._cull_frequency])
russellm
13275
4dd52d4f3f50
false
2010-08-05
133
cursor.execute("DELETE FROM %s WHERE cache_key < %%s" % table, [cursor.fetchone()[0]])
russellm
12116
c1ad14c551a9
false
2010-01-27
95
russellm
12116
c1ad14c551a9
false
2010-01-27
96
def clear(self):
russellm
13275
4dd52d4f3f50
false
2010-08-05
136
db = router.db_for_write(self.cache_model_class)
russellm
13275
4dd52d4f3f50
false
2010-08-05
137
table = connections[db].ops.quote_name(self._table)
russellm
13275
4dd52d4f3f50
false
2010-08-05
138
cursor = connections[db].cursor()
russellm
13275
4dd52d4f3f50
false
2010-08-05
139
cursor.execute('DELETE FROM %s' % table)
russellm
14807
905c4a7e1f19
false
2010-12-21
143
russellm
14807
905c4a7e1f19
false
2010-12-21
144
# For backwards compatibility
russellm
14807
905c4a7e1f19
false
2010-12-21
145
class CacheClass(DatabaseCache):
russellm
14807
905c4a7e1f19
false
2010-12-21
146
pass