Exemple #1
0
    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
Exemple #3
0
    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
Exemple #5
0
    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
Exemple #6
0
    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()