This module provides simple persistent storage for one or more dynamic predicates. A database is always associated with a module. A module that wishes to maintain a database must declare the terms that can be placed in the database using the directive persistent/1.
The persistent/1 expands each declaration into four predicates:
As mentioned, a database can only be accessed from within a single module. This limitation is on purpose, forcing the user to provide a proper API for accessing the shared persistent data.
Below is a simple example:
:- module(user_db, [ attach_user_db/1, % +File current_user_role/2, % ?User, ?Role add_user/2, % +User, +Role set_user_role/2 % +User, +Role ]). :- use_module(library(persistency)). :- persistent user_role(name:atom, role:oneof([user,administrator])). attach_user_db(File) :- db_attach(File, ). %% current_user_role(+Name, -Role) is semidet. current_user_role(Name, Role) :- with_mutex(user_db, user_role(Name, Role)). add_user(Name, Role) :- assert_user_role(Name, Role). set_user_role(Name, Role) :- user_role(Name, Role), !. set_user_role(Name, Role) :- with_mutex(user_db, ( retractall_user_role(Name, _), assert_user_role(Name, Role))).
- Declare dynamic database terms. Declarations appear in a
directive and have the following format:
:- persistent <callable>, <callable>, ...
Each specification is a callable term, following the conventions of library(record), where each argument is of the form
Types are defined by library(error).
- current_persistent_predicate(:PI) is nondet
- True if PI is a predicate that provides access to the persistent database DB.
- db_attach(:File, +Options)
- Use File as persistent database for the calling module. The calling
module must defined persistent/1 to declare the database terms.
- One of
close(close journal after write),
flush(default, flush journal after write) or
none(handle as fully buffered stream).
If File is already attached this operation may change the
- db_size(+Module, -Terms) is det[private]
- Terms is the total number of terms in the DB for Module.
- db_attached(:File) is semidet
- True if the context module attached to the persistent database File.
- db_assert(:Term) is det[private]
- Assert Term into the database and record it for persistency. Note that if the on-disk file has been modified it is first reloaded.
- db_detach is det
- Detach persistency from the calling module and delete all persistent clauses from the Prolog database. Note that the file is not affected. After this operation another file may be attached, providing it satisfies the same persistency declaration.
- sync(+Module, +Stream) is det[private]
- Synchronise journal after a write. Using
close, the journal file is closed, making it easier to edit the file externally. Using
flushflushes the stream but does not close it. This provides better performance. Using
none, the stream is not even flushed. This makes the journal sensitive to crashes, but much faster.
- db_retractall(:Term) is det[private]
- Retract all matching facts and do the same in the database. If Term is unbound, persistent/1 from the calling module is used as generator.
- db_retract(:Term) is nondet[private]
- Retract terms from the database one-by-one.
- Synchronise database with the associated file. What is one of:
- Database is reloaded from file if the file was modified since loaded.
reload, but use incremental loading if possible. This allows for two processes to examine the same database file, where one writes the database and the other periodycally calls
db_sync(update)to follow the modified data.
- Database was re-written, deleting all retractall
statements. This is the same as
- GC DB if the number of deleted terms is the given percentage of the total number of terms.
- Database stream was closed
- Remove all registered persistency for the calling module
- No-operation performed
With unbound What, db_sync/1 reloads the database if it was modified on disk, gc it if it is dirty and close it if it is opened.
- Sync all registered databases.