Example #1
0
    def delete(self, token):
        """Delete lock.

        Returns True on success. False, if token does not exist, or is expired.
        """
        self._lock.acquire_write()
        try:
            lock = self._dict.get(token)
            _logger.debug("delete {}".format(lock_string(lock)))
            if lock is None:
                return False
            # Remove url to lock mapping
            key = "URL2TOKEN:{}".format(lock.get("root"))
            if key in self._dict:
                # _logger.debug("    delete token {} from url {}".format(token, lock.get("root")))
                tokList = self._dict[key]
                if len(tokList) > 1:
                    # Note: shelve dictionary returns copies, so we must
                    # reassign values:
                    tokList.remove(token)
                    self._dict[key] = tokList
                else:
                    del self._dict[key]
            # Remove the lock
            del self._dict[token]

            self._flush()
        finally:
            self._lock.release()
        return True
Example #2
0
    def get(self, token):
        """Return a lock dictionary for a token.

        If the lock does not exist or is expired, None is returned.

        token:
            lock token
        Returns:
            Lock dictionary or <None>

        Side effect: if lock is expired, it will be purged and None is returned.
        """
        self._lock.acquire_read()
        try:
            lock = self._dict.get(token)
            if lock is None:
                # Lock not found: purge dangling URL2TOKEN entries
                _logger.debug("Lock purged dangling: {}".format(token))
                self.delete(token)
                return None
            expire = float(lock["expire"])
            if expire >= 0 and expire < time.time():
                _logger.debug(
                    "Lock timed-out({}): {}".format(expire, lock_string(lock))
                )
                self.delete(token)
                return None
            return lock
        finally:
            self._lock.release()
Example #3
0
    def delete(self, token):
        """Delete lock.

        See wsgidav.lock_storage.LockStorageDict.delete()
        """
        lock = self.get(token)
        logging.debug("delete %s" % lock_string(lock))
        return self._deleteLock(lock)
Example #4
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
        """
        # 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
Example #5
0
 def delete(self, token):
     """Delete lock.
     Returns True on success. False, if token does not exist, or is expired.
     """
     lock = self._redis.get(self._redis_lock_prefix.format(token))
     if lock is None:
         return False
     lock = pickle.loads(lock)
     _logger.debug("delete {}".format(lock_string(lock)))
     # Remove url to lock mapping
     key = self._redis_url2token_prefix.format(lock.get("root"))
     self._redis.lrem(key, 1, token)
     self._redis.delete(self._redis_lock_prefix.format(token))
     self._flush()
     return True
Example #6
0
    def get(self, token):
        """Return a lock dictionary for a token.

        See wsgidav.lock_storage.LockStorageDict.get()
        """
        lock = cached_lock.get(token)
        if lock is None:
            # Lock not found: purge dangling root-path entries
            _logger.debug("Lock purged dangling: %s" % token)
            self._deleteLock(lock)
            return None
        expire = float(lock["expire"])
        if expire >= 0 and expire < time.time():
            _logger.debug("Lock timed-out(%s): %s" %
                          (expire, lock_string(lock)))
            self._deleteLock(lock)
            return None
        return lock
Example #7
0
 def get(self, token):
     """Return a lock dictionary for a token.
     If the lock does not exist or is expired, None is returned.
     token:
         lock token
     Returns:
         Lock dictionary or <None>
     Side effect: if lock is expired, it will be purged and None is returned.
     """
     lock = self._redis.get(self._redis_lock_prefix.format(token))
     if lock is None:
         # Lock not found: purge dangling URL2TOKEN entries
         _logger.debug("Lock purged dangling: {}".format(token))
         self.delete(token)
         return None
     lock = pickle.loads(lock)
     expire = float(lock["expire"])
     if 0 <= expire < time.time():
         _logger.debug("Lock timed-out({}): {}".format(expire, lock_string(lock)))
         self.delete(token)
         return None
     return lock
Example #8
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()
Example #9
0
def test():
    logging.info("test.test()")

    logging.getLogger().setLevel(logging.DEBUG)

    # Test data_fs.py
    data_fs.initfs()
    assert data_fs.isdir("/")

    rootpath = "/run_test"
    if data_fs.exists(rootpath):
        logging.info("removing " + rootpath)
        data_fs.rmtree(rootpath)
    assert not data_fs.exists(rootpath)

    data_fs.mkdir(rootpath)
    assert data_fs.isdir(rootpath)

    data = b"file content"
    data_fs.mkdir(rootpath + "/dir1")
    assert data_fs.isdir(rootpath + "/dir1")
    f1 = data_fs.btopen(rootpath + "/dir1/file1.txt", "w")
    f1.write(data)
    f1.close()
    assert data_fs.isfile(rootpath + "/dir1/file1.txt")

    # data_fs.unlink(rootpath+"/dir1/file1.txt")
    # assert not data_fs.isfile(rootpath+"/dir1/file1.txt")

    print("*** data_fs tests passed ***")

    # Test providers
    provider = BTFSResourceProvider()
    lockman = LockManager(LockStorageMemcache())
    provider.set_lock_manager(lockman)
    environ = {"wsgidav.provider": provider}
    environ["wsgidav.auth.user_name"] = "test"
    environ["wsgidav.auth.roles"] = ["editor"]

    resRoot = provider.get_resource_inst(rootpath + "/", environ)
    resRoot.create_collection("folder1")
    assert data_fs.isdir(rootpath + "/folder1")
    assert not data_fs.isfile(rootpath + "/folder1")
    resChild = provider.get_resource_inst(rootpath + "/folder1", environ)
    assert resChild
    resFile = resChild.create_empty_resource("file_empty.txt")
    assert resFile
    assert not data_fs.isdir(rootpath + "/folder1/file_empty.txt")
    assert data_fs.isfile(rootpath + "/folder1/file_empty.txt")
    # write
    data = b"x" * 1024
    res = resChild.create_empty_resource("file2.txt")
    f = res.begin_write()
    f.write(data)
    f.close()
    # copy
    res = provider.get_resource_inst(rootpath + "/folder1/file2.txt", environ)
    res.copy_move_single(rootpath + "/folder1/file2_copy.txt", False)

    res = provider.get_resource_inst(rootpath + "/folder1/file2_copy.txt",
                                     environ)
    f = res.get_content()
    assert data == f.read()
    f.close()

    print("*** provider tests passed ***")

    lock = provider.lock_manager.acquire(
        rootpath + "/folder1",
        "write",
        "exclusive",
        "infinity",
        b"test_owner",
        timeout=100,
        principal="martin",
        token_list=[],
    )
    assert lock["root"] == rootpath + "/folder1"
    lock = provider.lock_manager.get_lock(lock["token"])
    print(lock_string(lock))
    assert lock["root"] == rootpath + "/folder1"

    locklist = provider.lock_manager.get_indirect_url_lock_list(
        rootpath + "/folder1/file2.txt")
    print(locklist)
    assert len(locklist) == 1

    print("*** lock tests passed ***")