web/lib/django/core/cache/backends/locmem.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 "Thread-safe in-memory cache backend."
       
     2 
       
     3 import time
       
     4 try:
       
     5     import cPickle as pickle
       
     6 except ImportError:
       
     7     import pickle
       
     8 
       
     9 from django.core.cache.backends.base import BaseCache
       
    10 from django.utils.synch import RWLock
       
    11 
       
    12 class CacheClass(BaseCache):
       
    13     def __init__(self, _, params):
       
    14         BaseCache.__init__(self, params)
       
    15         self._cache = {}
       
    16         self._expire_info = {}
       
    17 
       
    18         max_entries = params.get('max_entries', 300)
       
    19         try:
       
    20             self._max_entries = int(max_entries)
       
    21         except (ValueError, TypeError):
       
    22             self._max_entries = 300
       
    23 
       
    24         cull_frequency = params.get('cull_frequency', 3)
       
    25         try:
       
    26             self._cull_frequency = int(cull_frequency)
       
    27         except (ValueError, TypeError):
       
    28             self._cull_frequency = 3
       
    29 
       
    30         self._lock = RWLock()
       
    31 
       
    32     def add(self, key, value, timeout=None):
       
    33         self._lock.writer_enters()
       
    34         try:
       
    35             exp = self._expire_info.get(key)
       
    36             if exp is None or exp <= time.time():
       
    37                 try:
       
    38                     self._set(key, pickle.dumps(value), timeout)
       
    39                     return True
       
    40                 except pickle.PickleError:
       
    41                     pass
       
    42             return False
       
    43         finally:
       
    44             self._lock.writer_leaves()
       
    45 
       
    46     def get(self, key, default=None):
       
    47         self._lock.reader_enters()
       
    48         try:
       
    49             exp = self._expire_info.get(key)
       
    50             if exp is None:
       
    51                 return default
       
    52             elif exp > time.time():
       
    53                 try:
       
    54                     return pickle.loads(self._cache[key])
       
    55                 except pickle.PickleError:
       
    56                     return default
       
    57         finally:
       
    58             self._lock.reader_leaves()
       
    59         self._lock.writer_enters()
       
    60         try:
       
    61             try:
       
    62                 del self._cache[key]
       
    63                 del self._expire_info[key]
       
    64             except KeyError:
       
    65                 pass
       
    66             return default
       
    67         finally:
       
    68             self._lock.writer_leaves()
       
    69 
       
    70     def _set(self, key, value, timeout=None):
       
    71         if len(self._cache) >= self._max_entries:
       
    72             self._cull()
       
    73         if timeout is None:
       
    74             timeout = self.default_timeout
       
    75         self._cache[key] = value
       
    76         self._expire_info[key] = time.time() + timeout
       
    77 
       
    78     def set(self, key, value, timeout=None):
       
    79         self._lock.writer_enters()
       
    80         # Python 2.3 and 2.4 don't allow combined try-except-finally blocks.
       
    81         try:
       
    82             try:
       
    83                 self._set(key, pickle.dumps(value), timeout)
       
    84             except pickle.PickleError:
       
    85                 pass
       
    86         finally:
       
    87             self._lock.writer_leaves()
       
    88 
       
    89     def has_key(self, key):
       
    90         self._lock.reader_enters()
       
    91         try:
       
    92             exp = self._expire_info.get(key)
       
    93             if exp is None:
       
    94                 return False
       
    95             elif exp > time.time():
       
    96                 return True
       
    97         finally:
       
    98             self._lock.reader_leaves()
       
    99 
       
   100         self._lock.writer_enters()
       
   101         try:
       
   102             try:
       
   103                 del self._cache[key]
       
   104                 del self._expire_info[key]
       
   105             except KeyError:
       
   106                 pass
       
   107             return False
       
   108         finally:
       
   109             self._lock.writer_leaves()
       
   110 
       
   111     def _cull(self):
       
   112         if self._cull_frequency == 0:
       
   113             self._cache.clear()
       
   114             self._expire_info.clear()
       
   115         else:
       
   116             doomed = [k for (i, k) in enumerate(self._cache) if i % self._cull_frequency == 0]
       
   117             for k in doomed:
       
   118                 self._delete(k)
       
   119 
       
   120     def _delete(self, key):
       
   121         try:
       
   122             del self._cache[key]
       
   123         except KeyError:
       
   124             pass
       
   125         try:
       
   126             del self._expire_info[key]
       
   127         except KeyError:
       
   128             pass
       
   129 
       
   130     def delete(self, key):
       
   131         self._lock.writer_enters()
       
   132         try:
       
   133             self._delete(key)
       
   134         finally:
       
   135             self._lock.writer_leaves()