PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/benji-bou/urotechchallenge-Serenity
Python | 153 lines | 127 code | 14 blank | 12 comment | 26 complexity | 182e9986766c00fca8e90375755d5cbf MD5 | raw file
  1. "File-based cache backend"
  2. import errno
  3. import glob
  4. import hashlib
  5. import io
  6. import os
  7. import random
  8. import tempfile
  9. import time
  10. import zlib
  11. from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
  12. from django.core.files.move import file_move_safe
  13. from django.utils.encoding import force_bytes
  14. try:
  15. from django.utils.six.moves import cPickle as pickle
  16. except ImportError:
  17. import pickle
  18. class FileBasedCache(BaseCache):
  19. cache_suffix = '.djcache'
  20. def __init__(self, dir, params):
  21. super(FileBasedCache, self).__init__(params)
  22. self._dir = os.path.abspath(dir)
  23. self._createdir()
  24. def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  25. if self.has_key(key, version):
  26. return False
  27. self.set(key, value, timeout, version)
  28. return True
  29. def get(self, key, default=None, version=None):
  30. fname = self._key_to_file(key, version)
  31. try:
  32. with io.open(fname, 'rb') as f:
  33. if not self._is_expired(f):
  34. return pickle.loads(zlib.decompress(f.read()))
  35. except IOError as e:
  36. if e.errno != errno.ENOENT:
  37. raise
  38. return default
  39. def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  40. self._createdir() # Cache dir can be deleted at any time.
  41. fname = self._key_to_file(key, version)
  42. self._cull() # make some room if necessary
  43. fd, tmp_path = tempfile.mkstemp(dir=self._dir)
  44. renamed = False
  45. try:
  46. with io.open(fd, 'wb') as f:
  47. expiry = self.get_backend_timeout(timeout)
  48. f.write(pickle.dumps(expiry, pickle.HIGHEST_PROTOCOL))
  49. f.write(zlib.compress(pickle.dumps(value, pickle.HIGHEST_PROTOCOL)))
  50. file_move_safe(tmp_path, fname, allow_overwrite=True)
  51. renamed = True
  52. finally:
  53. if not renamed:
  54. os.remove(tmp_path)
  55. def delete(self, key, version=None):
  56. self._delete(self._key_to_file(key, version))
  57. def _delete(self, fname):
  58. if not fname.startswith(self._dir) or not os.path.exists(fname):
  59. return
  60. try:
  61. os.remove(fname)
  62. except OSError as e:
  63. # ENOENT can happen if the cache file is removed (by another
  64. # process) after the os.path.exists check.
  65. if e.errno != errno.ENOENT:
  66. raise
  67. def has_key(self, key, version=None):
  68. fname = self._key_to_file(key, version)
  69. if os.path.exists(fname):
  70. with io.open(fname, 'rb') as f:
  71. return not self._is_expired(f)
  72. return False
  73. def _cull(self):
  74. """
  75. Removes random cache entries if max_entries is reached at a ratio
  76. of num_entries / cull_frequency. A value of 0 for CULL_FREQUENCY means
  77. that the entire cache will be purged.
  78. """
  79. filelist = self._list_cache_files()
  80. num_entries = len(filelist)
  81. if num_entries < self._max_entries:
  82. return # return early if no culling is required
  83. if self._cull_frequency == 0:
  84. return self.clear() # Clear the cache when CULL_FREQUENCY = 0
  85. # Delete a random selection of entries
  86. filelist = random.sample(filelist,
  87. int(num_entries / self._cull_frequency))
  88. for fname in filelist:
  89. self._delete(fname)
  90. def _createdir(self):
  91. if not os.path.exists(self._dir):
  92. try:
  93. os.makedirs(self._dir, 0o700)
  94. except OSError as e:
  95. if e.errno != errno.EEXIST:
  96. raise EnvironmentError(
  97. "Cache directory '%s' does not exist "
  98. "and could not be created'" % self._dir)
  99. def _key_to_file(self, key, version=None):
  100. """
  101. Convert a key into a cache file path. Basically this is the
  102. root cache path joined with the md5sum of the key and a suffix.
  103. """
  104. key = self.make_key(key, version=version)
  105. self.validate_key(key)
  106. return os.path.join(self._dir, ''.join(
  107. [hashlib.md5(force_bytes(key)).hexdigest(), self.cache_suffix]))
  108. def clear(self):
  109. """
  110. Remove all the cache files.
  111. """
  112. if not os.path.exists(self._dir):
  113. return
  114. for fname in self._list_cache_files():
  115. self._delete(fname)
  116. def _is_expired(self, f):
  117. """
  118. Takes an open cache file and determines if it has expired,
  119. deletes the file if it is has passed its expiry time.
  120. """
  121. exp = pickle.load(f)
  122. if exp is not None and exp < time.time():
  123. f.close() # On Windows a file has to be closed before deleting
  124. self._delete(f.name)
  125. return True
  126. return False
  127. def _list_cache_files(self):
  128. """
  129. Get a list of paths to all the cache files. These are all the files
  130. in the root cache dir that end on the cache_suffix.
  131. """
  132. if not os.path.exists(self._dir):
  133. return []
  134. filelist = [os.path.join(self._dir, fname) for fname
  135. in glob.glob1(self._dir, '*%s' % self.cache_suffix)]
  136. return filelist