##// END OF EJS Templates
caches: improved locking problems with distributed lock new cache backend
super-admin -
r946:aa8791b1 stable
parent child Browse files
Show More
@@ -10,7 +10,7 b' from redis import StrictRedis'
10 10 __version__ = '3.7.0'
11 11
12 12 loggers = {
13 k: getLogger("vcsserver" + ".".join((__name__, k)))
13 k: getLogger("vcsserver." + ".".join((__name__, k)))
14 14 for k in [
15 15 "acquire",
16 16 "refresh.thread.start",
@@ -221,10 +221,11 b' class Lock(object):'
221 221 """
222 222 logger = loggers["acquire"]
223 223
224 logger.debug("Getting %r ...", self._name)
224 logger.debug("Getting acquire on %r ...", self._name)
225 225
226 226 if self._held:
227 raise AlreadyAcquired("Already acquired from this Lock instance.")
227 owner_id = self.get_owner_id()
228 raise AlreadyAcquired("Already acquired from this Lock instance. Lock id: {}".format(owner_id))
228 229
229 230 if not blocking and timeout is not None:
230 231 raise TimeoutNotUsable("Timeout cannot be used if blocking=False")
@@ -124,7 +124,14 b' class FileNamespaceBackend(PickleSeriali'
124 124
125 125 def __init__(self, arguments):
126 126 arguments['lock_factory'] = CustomLockFactory
127 db_file = arguments.get('filename')
128
129 log.debug('initialing %s DB in %s', self.__class__.__name__, db_file)
130 try:
127 131 super(FileNamespaceBackend, self).__init__(arguments)
132 except Exception:
133 log.error('Failed to initialize db at: %s', db_file)
134 raise
128 135
129 136 def __repr__(self):
130 137 return '{} `{}`'.format(self.__class__, self.filename)
@@ -141,13 +148,16 b' class FileNamespaceBackend(PickleSeriali'
141 148 return False
142 149
143 150 with self._dbm_file(True) as dbm:
144
151 try:
145 152 return filter(cond, dbm.keys())
153 except Exception:
154 log.error('Failed to fetch DBM keys from DB: %s', self.get_store())
155 raise
146 156
147 157 def get_store(self):
148 158 return self.filename
149 159
150 def get(self, key):
160 def _dbm_get(self, key):
151 161 with self._dbm_file(False) as dbm:
152 162 if hasattr(dbm, 'get'):
153 163 value = dbm.get(key, NO_VALUE)
@@ -161,6 +171,13 b' class FileNamespaceBackend(PickleSeriali'
161 171 value = self._loads(value)
162 172 return value
163 173
174 def get(self, key):
175 try:
176 return self._dbm_get(key)
177 except Exception:
178 log.error('Failed to fetch DBM key %s from DB: %s', key, self.get_store())
179 raise
180
164 181 def set(self, key, value):
165 182 with self._dbm_file(True) as dbm:
166 183 dbm[key] = self._dumps(value)
@@ -235,17 +252,16 b' class BaseRedisBackend(redis_backend.Red'
235 252
236 253 def get_mutex(self, key):
237 254 if self.distributed_lock:
238 import redis_lock
239 255 lock_key = redis_backend.u('_lock_{0}').format(key)
240 256 log.debug('Trying to acquire Redis lock for key %s', lock_key)
241 lock = redis_lock.Lock(
242 redis_client=self.client,
243 name=lock_key,
244 expire=self.lock_timeout,
245 auto_renewal=False,
246 strict=True,
247 )
248 return lock
257
258 auto_renewal = True
259 lock_timeout = self.lock_timeout
260 if auto_renewal and not self.lock_timeout:
261 # set default timeout for auto_renewal
262 lock_timeout = 10
263 return get_mutex_lock(self.client, lock_key, lock_timeout,
264 auto_renewal=auto_renewal)
249 265 else:
250 266 return None
251 267
@@ -258,3 +274,34 b' class RedisPickleBackend(PickleSerialize'
258 274 class RedisMsgPackBackend(MsgPackSerializer, BaseRedisBackend):
259 275 key_prefix = 'redis_msgpack_backend'
260 276 pass
277
278
279 def get_mutex_lock(client, lock_key, lock_timeout, auto_renewal=False):
280 import redis_lock
281
282 class _RedisLockWrapper(object):
283 """LockWrapper for redis_lock"""
284
285 def __init__(self):
286 pass
287
288 @property
289 def lock(self):
290 return redis_lock.Lock(
291 redis_client=client,
292 name=lock_key,
293 expire=lock_timeout,
294 auto_renewal=auto_renewal,
295 strict=True,
296 )
297
298 def acquire(self, wait=True):
299 return self.lock.acquire(wait)
300
301 def release(self):
302 try:
303 self.lock.release()
304 except redis_lock.NotAcquired:
305 pass
306
307 return _RedisLockWrapper()
General Comments 0
You need to be logged in to leave comments. Login now