app/django/core/cache/backends/filebased.py
changeset 323 ff1a9aa48cfd
parent 54 03e267d67478
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
     1 "File-based cache backend"
     1 "File-based cache backend"
     2 
     2 
     3 import md5
     3 import os
     4 import os, time
     4 import time
     5 try:
     5 try:
     6     import cPickle as pickle
     6     import cPickle as pickle
     7 except ImportError:
     7 except ImportError:
     8     import pickle
     8     import pickle
       
     9 
     9 from django.core.cache.backends.base import BaseCache
    10 from django.core.cache.backends.base import BaseCache
       
    11 from django.utils.hashcompat import md5_constructor
    10 
    12 
    11 class CacheClass(BaseCache):
    13 class CacheClass(BaseCache):
    12     def __init__(self, dir, params):
    14     def __init__(self, dir, params):
    13         BaseCache.__init__(self, params)
    15         BaseCache.__init__(self, params)
    14         
    16 
    15         max_entries = params.get('max_entries', 300)
    17         max_entries = params.get('max_entries', 300)
    16         try:
    18         try:
    17             self._max_entries = int(max_entries)
    19             self._max_entries = int(max_entries)
    18         except (ValueError, TypeError):
    20         except (ValueError, TypeError):
    19             self._max_entries = 300
    21             self._max_entries = 300
    20             
    22 
    21         cull_frequency = params.get('cull_frequency', 3)
    23         cull_frequency = params.get('cull_frequency', 3)
    22         try:
    24         try:
    23             self._cull_frequency = int(cull_frequency)
    25             self._cull_frequency = int(cull_frequency)
    24         except (ValueError, TypeError):
    26         except (ValueError, TypeError):
    25             self._cull_frequency = 3
    27             self._cull_frequency = 3
    26             
    28 
    27         self._dir = dir
    29         self._dir = dir
    28         if not os.path.exists(self._dir):
    30         if not os.path.exists(self._dir):
    29             self._createdir()
    31             self._createdir()
    30 
    32 
    31     def add(self, key, value, timeout=None):
    33     def add(self, key, value, timeout=None):
    32         if self.has_key(key):
    34         if self.has_key(key):
    33             return None
    35             return False
    34         
    36 
    35         self.set(key, value, timeout)
    37         self.set(key, value, timeout)
       
    38         return True
    36 
    39 
    37     def get(self, key, default=None):
    40     def get(self, key, default=None):
    38         fname = self._key_to_file(key)
    41         fname = self._key_to_file(key)
    39         try:
    42         try:
    40             f = open(fname, 'rb')
    43             f = open(fname, 'rb')
    50         return default
    53         return default
    51 
    54 
    52     def set(self, key, value, timeout=None):
    55     def set(self, key, value, timeout=None):
    53         fname = self._key_to_file(key)
    56         fname = self._key_to_file(key)
    54         dirname = os.path.dirname(fname)
    57         dirname = os.path.dirname(fname)
    55         
    58 
    56         if timeout is None:
    59         if timeout is None:
    57             timeout = self.default_timeout
    60             timeout = self.default_timeout
    58             
    61 
    59         self._cull()
    62         self._cull()
    60         
    63 
    61         try:
    64         try:
    62             if not os.path.exists(dirname):
    65             if not os.path.exists(dirname):
    63                 os.makedirs(dirname)
    66                 os.makedirs(dirname)
    64 
    67 
    65             f = open(fname, 'wb')
    68             f = open(fname, 'wb')
   101             return False
   104             return False
   102 
   105 
   103     def _cull(self):
   106     def _cull(self):
   104         if int(self._num_entries) < self._max_entries:
   107         if int(self._num_entries) < self._max_entries:
   105             return
   108             return
   106         
   109 
   107         try:
   110         try:
   108             filelist = os.listdir(self._dir)
   111             filelist = os.listdir(self._dir)
   109         except (IOError, OSError):
   112         except (IOError, OSError):
   110             return
   113             return
   111         
   114 
   112         if self._cull_frequency == 0:
   115         if self._cull_frequency == 0:
   113             doomed = filelist
   116             doomed = filelist
   114         else:
   117         else:
   115             doomed = [os.path.join(self._dir, k) for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
   118             doomed = [os.path.join(self._dir, k) for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
   116 
   119 
   131     def _key_to_file(self, key):
   134     def _key_to_file(self, key):
   132         """
   135         """
   133         Convert the filename into an md5 string. We'll turn the first couple
   136         Convert the filename into an md5 string. We'll turn the first couple
   134         bits of the path into directory prefixes to be nice to filesystems
   137         bits of the path into directory prefixes to be nice to filesystems
   135         that have problems with large numbers of files in a directory.
   138         that have problems with large numbers of files in a directory.
   136         
   139 
   137         Thus, a cache key of "foo" gets turnned into a file named
   140         Thus, a cache key of "foo" gets turnned into a file named
   138         ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
   141         ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
   139         """
   142         """
   140         path = md5.new(key.encode('utf-8')).hexdigest()
   143         path = md5_constructor(key.encode('utf-8')).hexdigest()
   141         path = os.path.join(path[:2], path[2:4], path[4:])
   144         path = os.path.join(path[:2], path[2:4], path[4:])
   142         return os.path.join(self._dir, path)
   145         return os.path.join(self._dir, path)
   143 
   146 
   144     def _get_num_entries(self):
   147     def _get_num_entries(self):
   145         count = 0
   148         count = 0
   146         for _,_,files in os.walk(self._dir):
   149         for _,_,files in os.walk(self._dir):
   147             count += len(files)
   150             count += len(files)
   148         return count
   151         return count
   149     _num_entries = property(_get_num_entries)
   152     _num_entries = property(_get_num_entries)
   150