def getLockList(self, path, include_root, include_children, token_only): """Return a list of direct locks for <path>. See wsgidav.lock_storage.LockStorageDict.getLockList() """ path = normalize_lock_root(path) lockRoots = cached_lock.get("*") if not lockRoots: return [] def __appendLocks(toklist): if token_only: lockList.extend(toklist) else: for token in toklist: lock = self.get(token) if lock: lockList.append(lock) lockList = [] if include_root and path in lockRoots: __appendLocks(lockRoots[path]) if include_children: for root, toks in list(lockRoots.items()): if util.is_child_uri(path, root): __appendLocks(toks) return lockList
def create(self, path, lock): """Create a direct lock for a resource path. path: Normalized path (utf8 encoded string, no trailing '/') lock: lock dictionary, without a token entry Returns: New unique lock token.: <lock **Note:** the lock dictionary may be modified on return: - lock['root'] is ignored and set to the normalized <path> - lock['timeout'] may be normalized and shorter than requested - lock['token'] is added """ # We expect only a lock definition, not an existing lock assert lock.get("token") is None assert lock.get("expire") is None, "Use timeout instead of expire" assert path and "/" in path # Normalize root: /foo/bar org_path = path path = normalize_lock_root(path) lock["root"] = path # Normalize timeout from ttl to expire-date timeout = float(lock.get("timeout")) if timeout is None: timeout = LockStorageRedis.LOCK_TIME_OUT_DEFAULT elif timeout < 0 or timeout > LockStorageRedis.LOCK_TIME_OUT_MAX: timeout = LockStorageRedis.LOCK_TIME_OUT_MAX lock["timeout"] = timeout lock["expire"] = time.time() + timeout validate_lock(lock) token = generate_lock_token() lock["token"] = token # Store lock self._redis.set( self._redis_lock_prefix.format(token), pickle.dumps(lock), ex=int(timeout) ) # Store locked path reference key = self._redis_url2token_prefix.format(path) if not self._redis.exists(key): self._redis.lpush(key, token) else: self._redis.lpush(key, token) self._flush() _logger.debug( "LockStorageRedis.set({!r}): {}".format(org_path, lock_string(lock)) ) return lock
def get_lock_list(self, path, include_root, include_children, token_only): """Return a list of direct locks for <path>. Expired locks are *not* returned (but may be purged). path: Normalized path (utf8 encoded string, no trailing '/') include_root: False: don't add <path> lock (only makes sense, when include_children is True). include_children: True: Also check all sub-paths for existing locks. token_only: True: only a list of token is returned. This may be implemented more efficiently by some providers. Returns: List of valid lock dictionaries (may be empty). """ assert compat.is_native(path) assert path and path.startswith("/") assert include_root or include_children def __appendLocks(toklist): # Since we can do this quickly, we use self.get() even if # token_only is set, so expired locks are purged. for token in toklist: lock = self.get(token) if lock: if token_only: lockList.append(lock["token"]) else: lockList.append(lock) path = normalize_lock_root(path) self._lock.acquire_read() try: key = "URL2TOKEN:{}".format(path) tokList = self._dict.get(key, []) lockList = [] if include_root: __appendLocks(tokList) if include_children: for u, ltoks in self._dict.items(): if util.is_child_uri(key, u): __appendLocks(ltoks) return lockList finally: self._lock.release()
def get_lock_list(self, path, include_root, include_children, token_only): """Return a list of direct locks for <path>. Expired locks are *not* returned (but may be purged). path: Normalized path (utf8 encoded string, no trailing '/') include_root: False: don't add <path> lock (only makes sense, when include_children is True). include_children: True: Also check all sub-paths for existing locks. token_only: True: only a list of token is returned. This may be implemented more efficiently by some providers. Returns: List of valid lock dictionaries (may be empty). """ assert compat.is_native(path) assert path and path.startswith("/") assert include_root or include_children def __appendLocks(toklist): # Since we can do this quickly, we use self.get() even if # token_only is set, so expired locks are purged. for token in map(lambda x: x.decode("utf-8"), toklist): lock = self._redis.get(self._redis_lock_prefix.format(token)) if lock: lock = pickle.loads(lock) if token_only: lockList.append(lock["token"]) else: lockList.append(lock) path = normalize_lock_root(path) key = self._redis_url2token_prefix.format(path) tokList = self._redis.lrange(key, 0, -1) lockList = [] if include_root: __appendLocks(tokList) if include_children: for u in map(lambda x: x.decode("utf-8"), self._redis.keys(key + "/*")): if util.is_child_uri(key, u): __appendLocks(self._redis.lrange(u, 0, -1)) return lockList
def create(self, path, lock): """Create a direct lock for a resource path. See wsgidav.lock_storage.LockStorageDict.create() """ # We expect only a lock definition, not an existing lock assert lock.get("token") is None assert lock.get("expire") is None, "Use timeout instead of expire" assert path and "/" in path # Normalize root: /foo/bar org_path = path path = normalize_lock_root(path) lock["root"] = path # Normalize timeout from ttl to expire-date timeout = float(lock.get("timeout")) if timeout is None: timeout = LockStorageMemcache.LOCK_TIME_OUT_DEFAULT elif timeout < 0 or timeout > LockStorageMemcache.LOCK_TIME_OUT_MAX: timeout = LockStorageMemcache.LOCK_TIME_OUT_MAX lock["timeout"] = timeout lock["expire"] = time.time() + timeout validate_lock(lock) token = generate_lock_token() lock["token"] = token # Append this lock root to current path list lockRoots = cached_lock.get("*") if lockRoots is None: lockRoots = {} lockRoots.setdefault(path, []).append(token) # Store lock and path lock list mapping = {token: lock, "*": lockRoots} res = cached_lock.set_multi(mapping) if len(res) > 0: raise RuntimeError("Could not store lock") logging.info("lock.create(%r): %s\n\t%s" % (org_path, lock, lockRoots)) return lock
def create(self, path, lock): """Create a direct lock for a resource path. path: Normalized path (utf8 encoded string, no trailing '/') lock: lock dictionary, without a token entry Returns: New unique lock token.: <lock **Note:** the lock dictionary may be modified on return: - lock['root'] is ignored and set to the normalized <path> - lock['timeout'] may be normalized and shorter than requested - lock['token'] is added """ self._lock.acquire_write() try: # We expect only a lock definition, not an existing lock assert lock.get("token") is None assert lock.get("expire") is None, "Use timeout instead of expire" assert path and "/" in path # Normalize root: /foo/bar org_path = path path = normalize_lock_root(path) lock["root"] = path # Normalize timeout from ttl to expire-date timeout = float(lock.get("timeout")) if timeout is None: timeout = LockStorageDict.LOCK_TIME_OUT_DEFAULT elif timeout < 0 or timeout > LockStorageDict.LOCK_TIME_OUT_MAX: timeout = LockStorageDict.LOCK_TIME_OUT_MAX lock["timeout"] = timeout lock["expire"] = time.time() + timeout validate_lock(lock) token = generate_lock_token() lock["token"] = token # Store lock self._dict[token] = lock # Store locked path reference key = "URL2TOKEN:{}".format(path) if key not in self._dict: self._dict[key] = [token] else: # Note: Shelve dictionary returns copies, so we must reassign # values: tokList = self._dict[key] tokList.append(token) self._dict[key] = tokList self._flush() _logger.debug( "LockStorageDict.set({!r}): {}".format(org_path, lock_string(lock)) ) return lock finally: self._lock.release()