dirq - C implementation of the simple directory queue algorithm
/*
* constants
*/
#define DIRQ_VERSION_MAJOR 0
#define DIRQ_VERSION_MINOR 5
#define DIRQ_VERSION_HEX ((DIRQ_VERSION_MAJOR << 8) | DIRQ_VERSION_MINOR)
/*
* types
*/
typedef struct dirq_s *dirq_t;
typedef int (*dirq_iow)(dirq_t, char *, size_t);
typedef int (*dirq_ior)(dirq_t, const char *, size_t);
/*
* constructors & destructor
*/
dirq_t dirq_new (const char *path);
dirq_t dirq_copy (dirq_t dirq);
void dirq_free (dirq_t dirq);
/*
* accessors
*/
void dirq_set_granularity (dirq_t dirq, int value);
int dirq_get_granularity (dirq_t dirq);
void dirq_set_rndhex (dirq_t dirq, int value);
int dirq_get_rndhex (dirq_t dirq);
void dirq_set_umask (dirq_t dirq, mode_t value);
mode_t dirq_get_umask (dirq_t dirq);
void dirq_set_maxlock (dirq_t dirq, int value);
int dirq_get_maxlock (dirq_t dirq);
void dirq_set_maxtemp (dirq_t dirq, int value);
int dirq_get_maxtemp (dirq_t dirq);
/*
* iterators
*/
const char *dirq_first (dirq_t dirq);
const char *dirq_next (dirq_t dirq);
/*
* main methods
*/
const char *dirq_add (dirq_t dirq, dirq_iow cb);
const char *dirq_add_path (dirq_t dirq, const char *path);
int dirq_get (dirq_t dirq, const char *name, dirq_ior cb);
const char *dirq_get_path (dirq_t dirq, const char *name);
int dirq_lock (dirq_t dirq, const char *name, int permissive);
int dirq_unlock (dirq_t dirq, const char *name, int permissive);
int dirq_remove (dirq_t dirq, const char *name);
int dirq_touch (dirq_t dirq, const char *name);
int dirq_get_size (dirq_t dirq, const char *name);
int dirq_count (dirq_t dirq);
int dirq_purge (dirq_t dirq);
/*
* other methods
*/
void dirq_now (dirq_t dirq, struct timespec *ts);
int dirq_get_errcode (dirq_t dirq);
const char *dirq_get_errstr (dirq_t dirq);
void dirq_clear_error (dirq_t dirq);
The goal of this library is to offer a "simple" queue system using the underlying filesystem for storage, security and to prevent race conditions via atomic operations. It focuses on simplicity, robustness and scalability.
Multiple concurrent readers and writers can interact with the same queue.
Other implementations of the same algorithm exist so readers and writers can be written in different programming languages:
The Perl implementation is the reference one and contains extensive documentation.
The object oriented API to access the directory queue is implemented with an opaque data type (dirq_t
), a constructor (dirq_new
) and methods which are C functions requiring the "object" as their first argument. The destructor (dirq_free
) must be called when the object is not needed anymore.
The directory queue object is not considered to be thread safe: different threads must use different objects.
All the functions that return a string (i.e. const char *
) in fact return a pointer to statically allocated data inside the directory queue object. The caller must use or copy the string before calling other functions since they may override this statically allocated data.
Adding and getting elements (i.e. sequences of bytes) is achieved via callback functions working on chunks of bytes so it is never needed to allocate memory holding complete elements.
In case of error, the dirq_get_errcode
and dirq_get_errstr
functions can be used to get more information. The safest approach is then to stop using the object and free it. However, if needed, the error information can be cleared with dirq_clear_error
.
creates a new directory queue object using the given path, setting the internal error information (see dirq_get_errcode
or dirq_get_errstr
) in case of error
creates a new directory queue object which is a copy of the given one
frees the memory associated with the directory queue object
sets the time granularity for intermediate directories (default: 60)
gets the time granularity for intermediate directories
sets the random hexadecimal digit to use in element names (default: randomly generated)
gets the random hexadecimal digit to use in element names
sets the umask to use when creating files and directories (default: use the running process' umask)
gets the umask to use when creating files and directories
sets the maximum time for a locked element in seconds (default 600)
gets the maximum time for a locked element in seconds
sets the maximum time for a temporary element in seconds (default 300)
gets the maximum time for a temporary element in seconds
returns the first element in the queue, resetting the iterator; returns NULL if the queue is empty or an error occurred
returns the next element in the queue, incrementing the iterator; returns NULL if there is no next element or an error occurred
adds the given data (via callback) to the queue and returns the corresponding element name or NULL on error
adds the given file (identified by its path) to the queue and returns the corresponding element name or NULL on error, the file must be on the same filesystem and will be moved to the queue
gets the data from the given element (which must be locked) via callback; returns 0 on success, -1 on error
gets the file path of the given element (which must be locked), this file can be read but not removed, you must use the remove() method for this; if the given name is NULL, returns the directory queue path itself
attempts to lock the given element and returns 0 on success; in case of error, returns 1 (permissive) or -1 (non permissive)
attempts to unlock the given element and returns 0 on success; in case of error, returns 1 (permissive) or -1 (non permissive)
removes the given element (which must be locked) from the queue; returns 0 on success, -1 on error
"touches" the given element (i.e. updates the access and modification times to the current time); returns 0 on success, -1 on error
returns the size (in bytes) of the given element or -1 on error
returns the number of elements in the queue or -1 on error; this also resets the iterator
purges the queue by removing unused intermediate directories, removing too old temporary elements and unlocking too old locked elements (aka staled locks); this is using the maxlock
and maxtemp
attributes of the directory queue object; returns the number of elements purged or -1 on error; this also resets the iterator
returns the current time in the given timespec
structure
returns the current error code (usually errno
) or 0 if there is no error
returns the current error string or NULL if there is no error
clears the current error
Lionel Cons http://cern.ch/lionel.cons
Copyright (C) CERN 2012-2017