Skip to main content

treelock CircleCI Maintainability Test Coverage

Constant-time read/write sub-tree locking for asyncio Python. Suitable for large trees, when it's not feasible or desired to have the entire tree in memory at once.

Inspired by the work of Ritik Malhotra.

Usage

Each instance of TreeLock is callable, and returns an asynchronous context manager. In order to acquire a read (shared) lock on the sub-trees with root nodes in the iterable read_roots; and to acquire a write (exclusive) lock of the sub-trees with root nodes in the iterable write_roots, you must pass them to the instance of TreeLock:

from treelock import TreeLock

lock = TreeLock()

def access(read_roots, write_roots):
  async with lock(read=read_roots, write=write_roots):
    # access the sub-trees

The lock is not re-entrant: the same task attempting to enter multiple context managers with incompatible sub-trees will deadlock. Hence the locks for all the required sub-trees must be requested up-front.

A typical use-case will be for read/write (shared/exclusive) locking of a path in a filesystem hierarchy. For example, if treating S3 as a filesystem, but allowing what-whould-be non-atomic operations on folders.

For example, you could define delete, write, rename, copy and read operations on folders at certain paths, e.g. instances of PurePosixPath. A read lock of such a path should allow reads of the corresponding folder, but block all operations that would change it. A write lock should prevent all other access to that folder. You can do this using TreeLock, noting that each path is in fact a node in the tree of all possible paths.

from treelock import TreeLock

lock = TreeLock()

async def delete(path):
  async with lock(read=[], write=[path]):
    ...

async def write(path, ...):
  async with lock(read=[], write=[path]):
    ...

async def rename(path_from, path_to):
  async with lock(read=[], write=[path_from, path_to]):
    ...

async def copy(path_from, path_to):
  async with lock(read=[path_from], write=[path_to]):
    ...

async def read(path):
  async with lock(read=[path], write=[]):
    ...

There is more information on this usage, as well as details of the underlying algorithm, at https://charemza.name/blog/posts/python/asyncio/s3-path-locking/.

Required properties of the nodes

These are a subset of the properties of PurePosixPath.

  • Each defines the __cmp__ and __hash__ methods. These are used for dictionary and sets internally, so __hash__ must be reasonable enough to to acheive constant-time behaviour.

  • Each must define the __lt__ method. This must be well-behaved, i.e. defines a total order between all possible nodes, otherwise deadlock can occur.

  • Each has a property parents that is an iterator to the ancestors of the node, in any order. This is a slightly mis-named property, but this is consistent with PurePosixPath.

Note that a node does not need to be aware of its child nodes. This makes TreeLock suitable for locking sub-trees below a node without knowledge of the descendants of that node.

Constant-time locking and unlocking

The number of operations to lock or unlock a node only depends on the ancestors of a node. Specifically, it does not increase as the number of descendants increase, nor does it increase with the number of locks currently being held.

Running tests

python setup.py test

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

treelock-0.0.9.tar.gz (3.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

treelock-0.0.9-py3-none-any.whl (4.4 kB view details)

Uploaded Python 3

File details

Details for the file treelock-0.0.9.tar.gz.

File metadata

  • Download URL: treelock-0.0.9.tar.gz
  • Upload date:
  • Size: 3.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.20.0 setuptools/40.4.3 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.6.6

File hashes

Hashes for treelock-0.0.9.tar.gz
Algorithm Hash digest
SHA256 d8a2e2ba94c7d8fdae16edeb1454b6e003194ca5827e249e30635ddfaa0e0e64
MD5 b91557cdf791694c5ab2c94030d646c6
BLAKE2b-256 728162063bde60c6e9584a55b33700d36c7c347f530ce2b3924b4f8b22e575e0

See more details on using hashes here.

File details

Details for the file treelock-0.0.9-py3-none-any.whl.

File metadata

  • Download URL: treelock-0.0.9-py3-none-any.whl
  • Upload date:
  • Size: 4.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.20.0 setuptools/40.4.3 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.6.6

File hashes

Hashes for treelock-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 2b4ca47e3169745edb18fbd618c587e58bea50baaeef8fc8c88407032efab683
MD5 c2cd2c6ce6cf5d1819ec6f99fb3cec23
BLAKE2b-256 1f491ece27291ae771e96c0c78b966d4f05dc09f06809ddedfcd6d17c67e0739

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page