A small persistent key-value store backed by SQLite. Keys and values
may be arbitrary Racket values and are stored using transparent
serialization.
The keystore provides persistent storage with automatic
serialization and deserialization. Keys are additionally stored in a
stringified lowercase form, which allows glob-style queries.
(struct keystore (file path dbh lock-sem in-lock entered))
|
| file : any/c |
| path : path? |
| dbh : any/c |
| lock-sem : semaphore? |
| in-lock : (or/c thread? #f) |
| entered : exact-nonnegative-integer? |
Represents an open keystore. The file field contains the
original argument, path is the resolved database path, and
dbh is the SQLite connection. The remaining fields implement
the reentrant lock used by ks-with-lock: lock-sem
serializes access, in-lock records the thread that holds the
lock, and entered records that thread’s nesting depth. The
in-lock and entered fields are mutable internal state.
The keystore? predicate is altered to also check if the
database connection is (still) valid.
(keystore? ks) → boolean?
|
| ks : any/c |
Returns #t, if ks is a valid keystore.
Returns #f, otherwise.
Note. When a previously opened keystore (which is valid), is closed with ks-close,
keystore? will return #f, because the keystore is not valid anymore.
3 Opening & Closing🔗ℹ
(ks-open file) → keystore?
|
| file : (or/c path? string? symbol?) |
Opens or creates a keystore. When file is a symbol, a cache
location is used; otherwise it is interpreted as a filesystem path.
The database schema is created automatically if it does not yet exist.
(ks-close ks) → boolean?
|
| ks : keystore? |
Closes the keystore. The keystore handle is invalidated after closing
the underlying storage (database).
4 Basic Operations🔗ℹ
(ks-set! ks key value) → boolean?
|
| ks : keystore? |
| key : any/c |
| value : any/c |
Stores value under key, replacing any existing value.
The function always returns #t.
(ks-get ks key default ...) → any/c
|
| ks : keystore? |
| key : any/c |
| default : any/c |
Retrieves the value associated with key. If the key is not
present, the provided default value is returned when given; otherwise
the symbol 'ks-nil is returned.
(ks-exists? ks key) → boolean?
|
| ks : keystore? |
| key : any/c |
Returns #t if the key exists, and #f otherwise.
(ks-key-count ks) → number?
|
| ks : keystore? |
Returns the number of keys in the keystore.
(ks-drop! ks key) → boolean?
|
| ks : keystore? |
| key : any/c |
Removes the key from the store. The function always returns #t.
(ks-keys ks) → (listof any/c)
|
| ks : keystore? |
Returns all keys in the store.
(ks-key-values ks) → (listof (cons/c any/c any/c))
|
| ks : keystore? |
Returns all key-value pairs as cons cells.
Glob queries operate on a lowercase string representation of keys.
(ks-keys-glob ks pattern) → (listof any/c)
|
| ks : keystore? |
| pattern : string? |
Returns all keys whose string form matches pattern.
(ks-key-values-glob ks pattern) → (listof (cons/c any/c any/c))
|
| ks : keystore? |
| pattern : string? |
Returns key-value pairs whose keys match pattern.
(ks-keys-raw ks) → list?
|
| ks : keystore? |
Returns raw key rows in the form:
(list key-string str-key)
(ks-key-values-raw ks) → list?
|
| ks : keystore? |
Returns raw key-value rows in the form:
(list key-string str-key value-string)
(ks-transaction [ks keystore?] b1 ...)
|
Puts b1 ... in a "BEGIN/COMMIT" transaction.
It uses with-handlers exn?, so if you raise an exception,
it will do a "BEGIN/ROLLBACK" abd re-raise the exception.
(ks-commit ks) → boolean?
|
| ks : keystore? |
Commits (part of a transaction) using COMMIT/BEGIN.
Fits in a ks-transaction form.
(ks-begin-transaction ks) → boolean?
|
| ks : keystore? |
Begins a transaction with "BEGIN".
(ks-end-transaction ks) → boolean?
|
| ks : keystore? |
Commits a transaction with "COMMIT".
(ks-abort-transaction ks) → boolean?
|
| ks : keystore? |
Aborts a transaction with "ROLLBACK".
(ks-with-lock ks proc) → any/c
|
| ks : keystore? |
| proc : (-> any/c) |
Calls proc while holding the lock belonging to ks and
returns the value produced by proc. Other threads using
ks-with-lock with the same keystore handle wait until the lock
is released.
The lock is reentrant: proc may call ks-with-lock
again on the same handle and thread. The lock is released when control
leaves proc, including when an exception is raised.
The lock coordinates only code that uses the same keystore handle and
explicitly calls ks-with-lock. Individual keystore operations
do not acquire it automatically.
10.1 Basic Usage🔗ℹ
| (define ks (ks-open 'demo)) |
| |
| (ks-set! ks 'a 42) |
| (ks-set! ks "b" '(1 2 3)) |
| |
| (ks-get ks 'a) |
| (ks-get ks 'missing) |
| (ks-get ks 'missing 0) |
10.2 Enumeration Example🔗ℹ
| (ks-keys ks) |
| |
| |
| (ks-key-values ks) |
10.3 Glob Query Example🔗ℹ
(ks-keys-glob ks "*b*")
10.4 Locking Example🔗ℹ
| (ks-with-lock |
| ks |
| (λ () |
| (ks-set! ks 'counter |
| (add1 (ks-get ks 'counter 0))))) |