Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

locmem.py 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. "Thread-safe in-memory cache backend."
  2. import pickle
  3. import time
  4. from collections import OrderedDict
  5. from threading import Lock
  6. from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
  7. # Global in-memory store of cache data. Keyed by name, to provide
  8. # multiple named local memory caches.
  9. _caches = {}
  10. _expire_info = {}
  11. _locks = {}
  12. class LocMemCache(BaseCache):
  13. def __init__(self, name, params):
  14. super().__init__(params)
  15. self._cache = _caches.setdefault(name, OrderedDict())
  16. self._expire_info = _expire_info.setdefault(name, {})
  17. self._lock = _locks.setdefault(name, Lock())
  18. def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  19. key = self.make_key(key, version=version)
  20. self.validate_key(key)
  21. pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
  22. with self._lock:
  23. if self._has_expired(key):
  24. self._set(key, pickled, timeout)
  25. return True
  26. return False
  27. def get(self, key, default=None, version=None):
  28. key = self.make_key(key, version=version)
  29. self.validate_key(key)
  30. with self._lock:
  31. if self._has_expired(key):
  32. self._delete(key)
  33. return default
  34. pickled = self._cache[key]
  35. self._cache.move_to_end(key, last=False)
  36. return pickle.loads(pickled)
  37. def _set(self, key, value, timeout=DEFAULT_TIMEOUT):
  38. if len(self._cache) >= self._max_entries:
  39. self._cull()
  40. self._cache[key] = value
  41. self._cache.move_to_end(key, last=False)
  42. self._expire_info[key] = self.get_backend_timeout(timeout)
  43. def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  44. key = self.make_key(key, version=version)
  45. self.validate_key(key)
  46. pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
  47. with self._lock:
  48. self._set(key, pickled, timeout)
  49. def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None):
  50. key = self.make_key(key, version=version)
  51. with self._lock:
  52. if self._has_expired(key):
  53. return False
  54. self._expire_info[key] = self.get_backend_timeout(timeout)
  55. return True
  56. def incr(self, key, delta=1, version=None):
  57. key = self.make_key(key, version=version)
  58. self.validate_key(key)
  59. with self._lock:
  60. if self._has_expired(key):
  61. self._delete(key)
  62. raise ValueError("Key '%s' not found" % key)
  63. pickled = self._cache[key]
  64. value = pickle.loads(pickled)
  65. new_value = value + delta
  66. pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL)
  67. self._cache[key] = pickled
  68. self._cache.move_to_end(key, last=False)
  69. return new_value
  70. def has_key(self, key, version=None):
  71. key = self.make_key(key, version=version)
  72. self.validate_key(key)
  73. with self._lock:
  74. if self._has_expired(key):
  75. self._delete(key)
  76. return False
  77. return True
  78. def _has_expired(self, key):
  79. exp = self._expire_info.get(key, -1)
  80. return exp is not None and exp <= time.time()
  81. def _cull(self):
  82. if self._cull_frequency == 0:
  83. self._cache.clear()
  84. self._expire_info.clear()
  85. else:
  86. count = len(self._cache) // self._cull_frequency
  87. for i in range(count):
  88. key, _ = self._cache.popitem()
  89. del self._expire_info[key]
  90. def _delete(self, key):
  91. try:
  92. del self._cache[key]
  93. del self._expire_info[key]
  94. except KeyError:
  95. pass
  96. def delete(self, key, version=None):
  97. key = self.make_key(key, version=version)
  98. self.validate_key(key)
  99. with self._lock:
  100. self._delete(key)
  101. def clear(self):
  102. with self._lock:
  103. self._cache.clear()
  104. self._expire_info.clear()