# 🗃 Store::Directories 🗃

Manage a key/value store of directories with controls for
concurrent access and locking.

**Version:** 0.4.1

# SYNOPSIS

```perl
use Store::Directories;

# Create a new store at given directory
# (or adopt one that is already there)
my $store = Store::Directories->init("path/to/store/")

# (In this example, we create a new directory containing a text file
# and then atomically increment the value written in the file)

my $value = 1;

# Get a directory with the key 'foo' in the store,
# creating it if it doesn't exist yet
my $lock;
my $dir = $store->get_or_add('foo' {

    # as an option, we can provide a subroutine to use to
    # initialize the directory contents if we create it
    # (but if the directory already exists, this won't be called)
    init => sub {
        my $dir = shift;
        open(my $fh, '>', "$dir/hello.txt") or die "could not open file: $!";
        print $fh $value;
        close $fh;
    }
});

{
    # Get an exclusive lock on the directory before reading/writing to it.
    # This ensure no other process is reading or modifying the directory
    # contents while we're working.
    my $lock = $store->lock_ex('foo');

    open(my $fh, '<', "$dir/hello.txt") or die "could not open file: $!";
    $value = <$fh>;
    open($fh, '>', "$dir/hello.txt")    or die "could not re-open file: $!";
    print $fh $value + 1;
    close $fh;

    # The lock is released once $lock is out-of-scope
}
```

# DESCRIPTION

[Store::Directories](https://metacpan.org/pod/Store%3A%3ADirectories) manages a key/value store of directories and allows
processes to assert shared (read-only) or exclusive (writable) locks on
those directories.

Directories in a [Store::Directories](https://metacpan.org/pod/Store%3A%3ADirectories) Store are referenced by unique
string "keys". Internally, the directories are named with hexadecimal UUIDS,
so the keys you use to identify them can contain illegal or unusual characters
for filenames. (web URLs are a common example).

Processes can perform operations on these directories in parallel by requesting
"locks" on particualr directories. These locks can be either _shared_ or
_exclusive_ (to borrow [flock(2)](http://man.he.net/man2/flock) terminology). Lock objects are obtained
with the `lock_sh` or `lock_ex` methods of a [Store::Directories](https://metacpan.org/pod/Store%3A%3ADirectories) instance
and are automatically released once they go out of scope.

**Shared** locks are used when a process wants to read, but not modify the
contents of a directory while being sure that no other process can modify the
contents while its reading. There can be multiple shared locks from different
processes on a directory at once, but never at the same time as an _exclusive_
lock.

**Exclusive** locks are used when a process wants to read _and_ modify the
contents of a directory while being sure that no other process can modify
or read the contents while its working. There can only be one exclusive lock
on a directory at once and there can't be any _shared_ locks with it.

If a process requests a lock that is unavailable at the moment (due to another
process already having an incompatible lock), then the process will block until
the lock can be obtained (either by the other process dying or releasing its
locks). Be aware that the order in which locks are granted is _not_ necessarily
the same order that that they were requested in.

**WARNING:** The guarantees around locking make the assumption that every
process is using this package and playing by its rules.
Unrelated processes are free to ignore the rules and mess things up as
much as they like.

# Documentation

For full documentation, please see the man pages installed with the module
or the page on MetaCPAN [HERE](https://metacpan.org/pod/Store%3A%3ADirectories).

# AUTHOR

Cameron Tauxe `camerontauxe@gmail.com`

# LICENSE AND COPYRIGHT

This software is copyright (c) 2020 by Cameron Tauxe.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
