Ticket #6099: md5_no_refcount.patch

File md5_no_refcount.patch, 6.3 KB (added by sherbang, 7 years ago)

New patch - removes refcounting stubs

  • django/core/cache/backends/filebased.py

    diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py
    index 72cb877..5299ab4 100644
    a b  
    11"File-based cache backend"
    22
     3import md5
    34import os, time
    45try:
    56    import cPickle as pickle
    67except ImportError:
    78    import pickle
    89from django.core.cache.backends.base import BaseCache
    9 from django.utils.http import urlquote_plus
    1010
    1111class CacheClass(BaseCache):
    1212    def __init__(self, dir, params):
    class CacheClass(BaseCache): 
    2929            self._createdir()
    3030
    3131    def add(self, key, value, timeout=None):
    32         fname = self._key_to_file(key)
    33         if timeout is None:
    34             timeout = self.default_timeout
    35         try:
    36             filelist = os.listdir(self._dir)
    37         except (IOError, OSError):
    38             self._createdir()
    39             filelist = []
    40         if len(filelist) > self._max_entries:
    41             self._cull(filelist)
    42         if os.path.basename(fname) not in filelist:
    43             try:
    44                 f = open(fname, 'wb')
    45                 now = time.time()
    46                 pickle.dump(now + timeout, f, 2)
    47                 pickle.dump(value, f, 2)
    48             except (IOError, OSError):
    49                 pass
     32        if self.has_key(key):
     33            return None
     34       
     35        self.set(key, value, timeout)
    5036
    5137    def get(self, key, default=None):
    5238        fname = self._key_to_file(key)
    class CacheClass(BaseCache): 
    5642            now = time.time()
    5743            if exp < now:
    5844                f.close()
    59                 os.remove(fname)
     45                self._delete(fname)
    6046            else:
    6147                return pickle.load(f)
    6248        except (IOError, OSError, EOFError, pickle.PickleError):
    class CacheClass(BaseCache): 
    6551
    6652    def set(self, key, value, timeout=None):
    6753        fname = self._key_to_file(key)
     54        dir = os.path.dirname(fname)
     55       
    6856        if timeout is None:
    6957            timeout = self.default_timeout
     58           
     59        self._cull()
     60       
    7061        try:
    71             filelist = os.listdir(self._dir)
    72         except (IOError, OSError):
    73             self._createdir()
    74             filelist = []
    75         if len(filelist) > self._max_entries:
    76             self._cull(filelist)
    77         try:
     62            if not os.path.exists(dir):
     63                os.makedirs(dir)
     64
    7865            f = open(fname, 'wb')
    7966            now = time.time()
    8067            pickle.dump(now + timeout, f, 2)
    class CacheClass(BaseCache): 
    8471
    8572    def delete(self, key):
    8673        try:
    87             os.remove(self._key_to_file(key))
     74            self._delete(self._key_to_file(key))
    8875        except (IOError, OSError):
    8976            pass
    9077
     78    def _delete(self, file):
     79        os.remove(file)
     80        try:
     81            #remove the 2 subdirs if they're empty
     82            dir = os.path.dirname(file)
     83            os.rmdir(dir)
     84            os.rmdir(os.path.dirname(dir))
     85        except:
     86            pass
     87
    9188    def has_key(self, key):
    92         return os.path.exists(self._key_to_file(key))
     89        fname = self._key_to_file(key)
     90        try:
     91            f = open(fname, 'rb')
     92            exp = pickle.load(f)
     93            now = time.time()
     94            if exp < now:
     95                f.close()
     96                self._delete(fname)
     97                return False
     98            else:
     99                return True
     100        except (IOError, OSError, EOFError, pickle.PickleError):
     101            return False
    93102
    94     def _cull(self, filelist):
     103    def _cull(self):
     104        if int(self._num_entries) < self._max_entries:
     105            return
     106       
     107        try:
     108            filelist = os.listdir(self._dir)
     109        except (IOError, OSError):
     110            return
     111       
    95112        if self._cull_frequency == 0:
    96113            doomed = filelist
    97114        else:
    98             doomed = [k for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
    99         for fname in doomed:
     115            doomed = [os.path.join(self._dir, k) for (i, k) in enumerate(filelist) if i % self._cull_frequency == 0]
     116
     117        for topdir in doomed:
    100118            try:
    101                 os.remove(os.path.join(self._dir, fname))
     119                for root, _, files in os.walk(topdir):
     120                    for file in files:
     121                        self._delete(os.path.join(root,file))
    102122            except (IOError, OSError):
    103123                pass
    104124
    class CacheClass(BaseCache): 
    109129            raise EnvironmentError, "Cache directory '%s' does not exist and could not be created'" % self._dir
    110130
    111131    def _key_to_file(self, key):
    112         return os.path.join(self._dir, urlquote_plus(key))
     132        path = md5.new(key.encode('utf-8')).hexdigest()
     133        path = os.path.join(path[:2], path[2:4], path[4:])
     134        return os.path.join(self._dir, path)
     135
     136    def _get_num_entries(self):
     137        count = 0
     138        for _,_,files in os.walk(self._dir):
     139            count += len(files)
     140        return count
     141    _num_entries = property(_get_num_entries)
     142
  • tests/regressiontests/cache/tests.py

    diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
    index 9ac2722..c6b8742 100644
    a b class Cache(unittest.TestCase): 
    2424
    2525    def test_add(self):
    2626        # test add (only add if key isn't already in cache)
    27         cache.add("addkey1", "value")
     27        cache.set("addkey1", "value")
    2828        cache.add("addkey1", "newvalue")
    2929        self.assertEqual(cache.get("addkey1"), "value")
    30 
     30       
    3131    def test_non_existent(self):
    3232        # get with non-existent keys
    3333        self.assertEqual(cache.get("does_not_exist"), None)
    class Cache(unittest.TestCase): 
    7777
    7878    def test_expiration(self):
    7979        # expiration
    80         cache.set('expire', 'very quickly', 1)
     80        cache.set('expire1', 'very quickly', 1)
     81        cache.set('expire2', 'very quickly', 1)
     82        cache.set('expire3', 'very quickly', 1)
    8183        time.sleep(2)
    82         self.assertEqual(cache.get("expire"), None)
     84       
     85        self.assertEqual(cache.get("expire1"), None)
     86       
     87        cache.add("expire2", "newvalue")
     88        self.assertEqual(cache.get("expire2"), "newvalue")
     89   
     90        self.assertEqual(cache.has_key("expire3"), False)
    8391
    8492    def test_unicode(self):
    8593        stuff = {
Back to Top