1 | # coding=utf-8
|
---|
2 | import os
|
---|
3 | import tempfile
|
---|
4 | import time
|
---|
5 | from multiprocessing import Pool
|
---|
6 | from django.conf import settings
|
---|
7 | try:
|
---|
8 | from django.utils.six.moves import cPickle as pickle
|
---|
9 | except ImportError:
|
---|
10 | import pickle
|
---|
11 |
|
---|
12 | settings.configure()
|
---|
13 |
|
---|
14 | from django.core.cache.backends.filebased import FileBasedCache
|
---|
15 |
|
---|
16 |
|
---|
17 | class SafeFileBasedCache(FileBasedCache):
|
---|
18 | """
|
---|
19 | FileBasedCache backend that uses temp file write-troughs to prevent
|
---|
20 | concurrency issues.
|
---|
21 | """
|
---|
22 | _tmp_suffix = '.__django_cache'
|
---|
23 |
|
---|
24 | def set(self, key, value, timeout=None, version=None):
|
---|
25 | key = self.make_key(key, version=version)
|
---|
26 | self.validate_key(key)
|
---|
27 |
|
---|
28 | fname = self._key_to_file(key)
|
---|
29 | dirname = os.path.dirname(fname)
|
---|
30 |
|
---|
31 | if timeout is None:
|
---|
32 | timeout = self.default_timeout
|
---|
33 |
|
---|
34 | self._cull()
|
---|
35 |
|
---|
36 | try:
|
---|
37 | if not os.path.exists(dirname):
|
---|
38 | os.makedirs(dirname)
|
---|
39 |
|
---|
40 | fd, tmp = tempfile.mkstemp(suffix=self._tmp_suffix, dir=dirname)
|
---|
41 | with os.fdopen(fd, 'wb') as f:
|
---|
42 | now = time.time()
|
---|
43 | pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL)
|
---|
44 | pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
|
---|
45 | os.rename(tmp, fname)
|
---|
46 | except (IOError, OSError):
|
---|
47 | pass
|
---|
48 |
|
---|
49 |
|
---|
50 | cache = FileBasedCache('./tmp', {})
|
---|
51 | safecache = SafeFileBasedCache('./tmp', {})
|
---|
52 | text = u'Iñtërnâtiônàlizætiøn' * 1024
|
---|
53 |
|
---|
54 |
|
---|
55 | def test(cache):
|
---|
56 | value = {'list1': range(1024), 'text': text, 'list': range(1024)}
|
---|
57 | try:
|
---|
58 | cache.set('test', value)
|
---|
59 | cached = cache.get('test')
|
---|
60 | if cached is None:
|
---|
61 | return 'miss'
|
---|
62 | elif cached != value:
|
---|
63 | return 'fail'
|
---|
64 | except Exception, e:
|
---|
65 | return str(e)
|
---|
66 |
|
---|
67 |
|
---|
68 | def test_cache(i):
|
---|
69 | return test(cache)
|
---|
70 |
|
---|
71 |
|
---|
72 | def test_safe_cache(i):
|
---|
73 | return test(safecache)
|
---|
74 |
|
---|
75 |
|
---|
76 | def test_multiprocess(func):
|
---|
77 | pool = Pool(processes=6)
|
---|
78 | result = pool.map_async(func, xrange(512))
|
---|
79 | pool.close()
|
---|
80 | pool.join()
|
---|
81 | results = result.get()
|
---|
82 | misses = [fail for fail in results if fail == 'miss']
|
---|
83 | fails = [fail for fail in results if fail is not None and fail != 'miss']
|
---|
84 | print '%s miss(es), %s fail(s)' % (len(misses), len(fails))
|
---|
85 |
|
---|
86 |
|
---|
87 | if __name__ == '__main__':
|
---|
88 | test_multiprocess(test_cache)
|
---|
89 | test_multiprocess(test_safe_cache)
|
---|