123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- /** @file store_interface.h
- *
- * @brief Common store back end interfaces.
- *
- * Code using the store interface should include NOT this header, but rahter
- * `store.h`.
- *
- * This header is included by all back end implementations, which are in
- * their turn included by `store.h`.
- *
- * The basic interfaces for store and store iterator implementations are
- * defined here. New store implementations should include this header and
- * implement three basic elements:
- *
- * - A structure representing the store back end. This structure will be
- * opaque to all downstream code and its layout is entirely up to the
- * implementer.
- *
- * - A structure representing a store iterator state, also opaque.
- *
- * - The LSUP_StoreInt interface with all the functions defined in the
- * interface necessary to interact with the store.
- *
- * See the `store_htable.{c,h}` and `store_mdb.{c,h}` files for examples of
- * fully functioning implementations.
- *
- * The #LSUP_StoreInt structure defines a store interface for raw buffer
- * triples. Nothing in the store functions' signatures should hint at RDF
- * triples—they should accept and produce exclusively raw byte buffers
- * (#LSUP_Buffer). A store interface may have any of the `LSUP_STORE_*` faeture
- * flags which should be reflected in the way its members are implemented.
- */
- #ifndef _LSUP_STORE_INTERFACE_H
- #define _LSUP_STORE_INTERFACE_H
- #include "environment.h"
- /*
- * Store feature flags.
- *
- * NOTE: LSUP_STORE_PERM need only be set by an implementation based on whether
- * its path is on a default temporary dir (e.g. LSUP_MDB_RAMDISK_PATH). If this
- * flag is not set, it means the data will be cleared before the next execution
- * of the program. However, its being set does not guarantee the persistence of
- * the medium (i.e. a "permanent" store may have been created ad hoc on a
- * tempfs).
- */
- typedef enum {
- LSUP_STORE_PERM = 1<<0, ///< Store is on a permanent support.
- LSUP_STORE_CTX = 1<<1, ///< Store supports contexts (quads).
- LSUP_STORE_IDX = 1<<2, ///< Store is fully SPO(C)-indexed.
- LSUP_STORE_TXN = 1<<3, ///< Supports transaction handling.
- LSUP_STORE_COW = 1<<4, ///< Copy on write. @sa #iter_next_fn_t()
- } LSUP_StoreFeature;
- /*
- * Store function types.
- */
- /** @brief Prototype: create any environment necessary for the store to work.
- *
- * This function should be idempotent on separate calls to the same `id`,
- * unless the `clear` option is set to `true`.
- *
- * @param[in,out] id Identifier to use for the store. This should be
- * a URI that uniquely identifies a back end for the implementation using it,
- * e.g. a SQL connection string, file path for an embedded store, the URL of a
- * REST API endpoint, etc. It may also be NULL, in which case it will be set to
- * the default identifier set by the implementation. It can be retrieved from
- * an existing store via #store_id_fn_t .
- *
- * @param[in] clear Whether to remove an existing environment with the same ID.
- */
- typedef LSUP_rc (*store_setup_fn_t)(const char *id, bool clear);
- /** @brief Prototype: create a new store.
- *
- * @param[in] id Identifier for the new store. How this is interpreted, and
- * whether it is even used, depends on the implementation, which should
- * provide documentation on how to pass and interpret this parameter.
- *
- * @param[in] size Initial size for the store. It may be 0. Only meaningful
- * for stores that may preallocate memory, such as #HTStore.
- *
- * @return New store handle.
- */
- typedef void * (*store_new_fn_t)(const char *id, size_t size);
- /** @brief Prototype: free store handle.
- *
- * @param[in] store Store handle.
- *
- */
- typedef void (*store_free_fn_t)(void *store);
- /** @brief Prototype: get the store ID.
- *
- * @param[in] store Store handle.
- *
- * @return store ID string. This is a copy and should be freed after use.
- */
- typedef char * (*store_id_fn_t)(const void *store);
- /** @brief Prototype: get store size.
- *
- * @param[in] store The store to calculate size of.
- *
- * @return Number of stored SPO triples (across all contexts if supported).
- */
- typedef size_t (*store_size_fn_t)(const void *store);
- #if 0
- /** @brief Print stats about a store.
- *
- * TODO
- *
- * @param[in] store The store to get stats for.
- */
- typedef LSUP_rc (*store_stat_fn_t)(void *store, void *stat);
- #endif
- /** @brief Begin a transaction.
- *
- * Only for LSUP_STORE_TXN stores.
- *
- * The transaction handle is managed by the store implementation and can be any
- * data type.
- *
- * @param[in] store Store handle.
- *
- * @param[in] flags Transaction flags. These vary with each implementation.
- *
- * @param[out] txn Will point to the new open transaction on success, or to
- * undefined content on failure.
- *
- * @return LSUP_OK if the transaction started successfully, <0 on error.
- */
- typedef LSUP_rc (*store_txn_begin_fn_t)(void *store, int flags, void **txn);
- /** @brief Commit a transaction.
- *
- * Only for LSUP_STORE_TXN stores.
- *
- * @param[in] store Store handle.
- *
- * @param[in] txn Transaction handle generated by #store_txn_begin_fn_t.
- *
- * @return LSUP_OK if the transaction was committed successfully, <0 on error.
- */
- typedef LSUP_rc (*store_txn_commit_fn_t)(void *store);
- /** @brief Abort a transaction.
- *
- * Only for LSUP_STORE_TXN stores.
- *
- * @param[in] store Store handle.
- *
- * @param[in] txn Transaction handle generated by #store_txn_begin_fn_t.
- */
- typedef void (*store_txn_abort_fn_t)(void *store);
- /** @brief Initialize bulk triple load.
- *
- * This is the first step of a bulk load. It is best used when the data at hand
- * need to be pre-processed, which can be done in the same loop as the next
- * step to keep memory usage low.
- *
- * @param store[in] The store to add to.
- *
- * @param sc[in] Context as a serialized term. If this is NULL, and the
- * default context is not NULL, triples will be added to the default context
- * for the store, If the default context for the store is NULL, regardless of
- * the value of sc, triples will be added with no context. Only meaningful
- * for stores with the LSUP_STORE_CTX feature.
- *
- * @param[in] udata User data. Consult individual store implementations for
- * how this is interpreted.
- *
- * @return Iterator handle to be passed to the following load steps.
- */
- typedef void * (*store_add_init_fn_t)(
- void *store, const LSUP_Buffer *sc, void *udata);
- /** @brief Add one triple into the store.
- *
- * This must be called after #add_init_fn, using the iterator
- * yielded by that function. It may be called multiple times and must be
- * followed by #add_done_fn or #add_abort_fn (if supported).
- *
- * @param it[in] Iterator obtained by #store_add_init_fn_t.
- * The following members are of interest:
- * it->i stores the total number of records inserted.
- *
- * @param sspo[in] Serialized triple to be added.
- *
- * @return LSUP_OK if the triple was inserted; LSUP_NOACTION if the triple
- * already existed; LSUP_DB_ERR if an MDB error occurred.
- */
- typedef LSUP_rc (*store_add_iter_fn_t)(
- void *it, const LSUP_BufferTriple * sspo);
- /** @brief Abort an add loop and free iterator.
- *
- * Usually called on an irrecoverable error from #add_iter_fn. None of the
- * successful inserts in the same loop is retained.
- *
- * @param it[in] Iterator obtained by #store_add_init_fn_t.
- */
- typedef void (*store_add_abort_fn_t)(void *it);
- /*
- * Iterator function types.
- */
- /** @brief Get iterator active transaction handle.
- *
- * This function is used to get an active transaction during an iteration loop
- * in order to perform an action using the store state within that loop. Some
- * stores (e.g. MDB) only support one R/W open transaction per thread, so this
- * is also the only way to perform anything else than iterating or committing
- * while a loop is open.
- *
- * @param[in] it Iterator handle to get the transaction from.
- *
- * @return Transaction handle. DO NOT close this transaction directly.
- */
- typedef void * (*iter_txn_fn_t)(void *it);
- /** @brief Finalize an add loop and free iterator.
- *
- * This must be called after #add_iter_fn.
- *
- * @param it[in] Iterator obtained by #LSUP_mdbstore_add_init.
- */
- typedef LSUP_rc (*store_add_done_fn_t)(void *it);
- /** @brief Add a single term to the store.
- *
- * @param[in] store Store handle.
- *
- * @param[in] sterm Serialized term to store.
- */
- typedef LSUP_rc (*store_add_term_fn_t)(
- void *store, const LSUP_Buffer *sterm, void *udata);
- /** @brief Prototype: look up triples by pattern matching.
- *
- * This function may return a count of matches and/or an iterator of results as
- * serialized triples.
- *
- * For stores with #LSUP_STORE_TXN, this opens a read-only transaction. The
- * transaction handle is held in the iterator structure and is closed when the
- * iterator is freed with #iter_free_fn_t().
- *
- * Any and all of the terms may be NULL, which indicates an unbound query
- * term. Stores witout context support will always ignore sc.
- *
- * @param[in] store The store to be queried.
- *
- * @param[in] ss Serialized s term.
- *
- * @param[in] sp Serialized p term.
- *
- * @param[in] so Serialized o term.
- *
- * @param[in] sc Serialized context to limit search to. It may be NULL, in
- * which case search is done in all contexts. Note that triples inserted
- * without context are assigned the *default* context for the store.
- *
- * @param[out] ct If not NULL, this will be populated with the number of
- * entries found. It is very inexpensive to set for lookups without context,
- * much less so for 1-bound and 2-bound context lookups, in which cases it
- * should be set only if needed.
- *
- * @param[in] udata User data. Consult individual store implementations for
- * how this is interpreted.
- *
- * @return Iterator handle that will be populated with a result iterator. This
- * is always created even if no matches are found and must be freed with
- * #LSUP_mdbiter_free() after use. If matches are found, the iterator points to
- * the first result which can be retrieved with #iter_next_fn().
- */
- typedef void * (*store_lookup_fn_t)(
- void *store,
- const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
- const LSUP_Buffer *sc, void *udata, size_t *ct);
- /** @brief Prototype: check for existence of a triple (T/F).
- *
- * @param[in] Store to be queried.
- *
- * @param[in] spo Triple to look up. All members must not be NULL.
- *
- * @param[in] c Optional context to look into. It may be NULL. It is
- * disregarded by stores without the LSUP_STORE_CTX feature.
- *
- * @return Whether the triple exist in the store (/context).
- */
- typedef bool (*store_trp_exist_fn_t)(
- void *store, const LSUP_BufferTriple *sspo, const LSUP_Buffer *sc);
- /** @brief Prototype: delete triples by pattern matching.
- *
- * The ss, sp, so, sc terms act as a matching pattern as documented in
- * @sa #store_lookup_fn. if not NULL, ct yields the number of triples actually
- * deleted.
- *
- * @param[in] udata User data. Consult individual store implementations for
- * how this is interpreted.
- */
- typedef LSUP_rc (*store_remove_fn_t)(
- void *store,
- const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
- const LSUP_Buffer *sc, void *udata, size_t *ct);
- /** @brief Put an in-memory namespace map into a permanent back end.
- *
- * This is only available in stores with the LSUP_STORE_PERM feature.
- *
- * Existing prefixes and namespaces are not updated. Thus, if the following are
- * already stored:
- *
- * ns1: <urn:ns:a#>
- * ns2: <urn:ns:b#>
- *
- * Neither of the following will be inserted:
- *
- * ns3: <urn:ns:a#>
- * ns2: <urn:ns:c#>
- *
- * @param[in] store MDB store to update.
- *
- * @param[out] nsm Namespace map handle to store.
- *
- * @param[in] udata User-defined data. Consult individual implementations for
- * details.
- *
- * @return LSUP_OK if all terms were updated; LSUP_CONFLICT if one or more
- * namespaces or terms were not updated because they already existed; <0 if
- * an error occurred.
- */
- typedef LSUP_rc (*store_nsm_put_fn_t)(
- void *store, const LSUP_NSMap * nsm, void *udata);
- /** @brief Get the store's namespace prefix map.
- *
- * @param[in] store MDB store to query.
- *
- * @return NS map or NULL on error.
- */
- typedef LSUP_NSMap * (*store_nsm_get_fn_t)(void *store);
- /** @brief Prototype: yield the matching triples and advance the iterator.
- *
- * NOTE: Iterators keep transactions open. Don't hold on to them longer than
- * necessary.
- *
- * NOTE: If the store interface has the LSUP_STORE_COW feature, the memory
- * buffer referenced by the #LSUP_Buffer handle is owned by the database. It
- * must not be written to or freed. To modify the data or use them beyond the
- * caller's scope, this memory must be copied. Note that the #LSUP_Buffer
- * handle must still be freed (with a plain `free()`), but not the underlying
- * data buffer, since only the latter is owned by the back end. For stores
- * without the LSUP_STORE_COW, data are copied on retrieval and the resulting
- * buffers can be freed with #LSUP_buffer_free() or analogous methods.
- *
- * @param[in] it Opaque iterator handle obtained with the store's #lookup_fn.
- *
- * @param[out] sspo #LSUP_BufferTriple to be populated with three serialized
- * terms if found. It may be NULL, in which case it is not populated.
- *
- * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
- * LSUP_Buffer structs, one for each context associated with the matching
- * triple. These contexts are the same regardless of the context filter used
- * in the lookup. The array is freed with a simple #free(). This parameter
- * is ignored by implementations without the LSUP_STORE_CTX feature.
- *
- * To iterate over the context array, use this loop:
- *
- * size_t i = 0;
- * while (ctx[i].addr)
- * do_something(ctx + (i++));
- *
- * @return LSUP_OK if results were found; LSUP_END if no (more) results were
- * found; LSUP_DB_ERR if a backend error occurred.
- */
- typedef LSUP_rc (*iter_next_fn_t)(
- void *it, LSUP_BufferTriple *sspo, LSUP_Buffer **ctx);
- /** @brief Prototype: free an iterator allocated by a lookup.
- *
- * @param it[in] Iterator pointer. It will be set to NULL after freeing.
- */
- typedef void (*iter_free_fn_t)(void * it);
- /*
- * Iterface type definitions.
- */
- /** @brief Store interface.
- *
- * New store implementations should define a static structure with the relevant
- * members filled in. Some members are only relevant to certain types of stores
- * and may be set to NULL.
- *
- * #setup_fn may be optionally defined and MUST cause an idempotent action,
- * unless the `clear` argument is set to `true`. Callers should check if this
- * member is NULL and if it is not, call it at the beginning of the
- * interaction with the store.
- *
- * Transaction control members are only applicable to stores with the
- * #LSUP_STORE_TXN feature.
- */
- typedef struct store_if_t {
- // Basic properties.
- char name[16]; ///< Store type name.
- LSUP_StoreFeature features; ///< Feature flags.
- // Allocation, setup and deallocation.
- store_setup_fn_t setup_fn; ///< Called before #store_new_fn_t.
- store_new_fn_t new_fn; ///< Create a new store instance.
- store_free_fn_t free_fn; ///< Free the store.
- // Metadata.
- store_size_fn_t size_fn; ///< Number of triples in the store.
- store_id_fn_t id_fn; ///< Get store ID.
- // Transaction control.
- store_txn_begin_fn_t txn_begin_fn; ///< Begin transaction.
- store_txn_commit_fn_t txn_commit_fn; ///< Commit transaction.
- store_txn_abort_fn_t txn_abort_fn; ///< Abort transaction.
- iter_txn_fn_t iter_txn_fn; ///< Get iterator's transaction.
- // Addition.
- store_add_init_fn_t add_init_fn; ///< Initialize add iteration.
- store_add_iter_fn_t add_iter_fn; ///< Add one triple.
- store_add_abort_fn_t add_abort_fn; /**< Abort (roll back) the add process.
- *
- * Only available in
- * stores with #LSUP_STORE_TXN
- * feature. Optional.
- */
- store_add_done_fn_t add_done_fn; ///< Complete the add process.
- store_add_term_fn_t add_term_fn; /**< Add (index) a term to the store.
- *
- * Only available in stores with
- * #LSUP_STORE_IDX feature. Optional.
- */
- // Look up.
- store_lookup_fn_t lookup_fn; ///< Look up triples by pattern.
- //store_trp_exist_fn_t exist_fn; ///< Check if a triple exists.
- iter_next_fn_t lu_next_fn; ///< Advance the lookup iterator.
- iter_free_fn_t lu_free_fn; ///< Free the lookup iterator.
- // Removal.
- store_remove_fn_t remove_fn; ///< Remove triples by pattern.
- // Namespace prefix mapping.
- store_nsm_put_fn_t nsm_put_fn; /**< Add a ns/pfx pair to the map.
- *
- * Only available (and mandatory)
- * in stores with the
- * #LSUP_STORE_IDX feature.
- */
- store_nsm_get_fn_t nsm_get_fn; /**< Get a namespace from the map.
- *
- * Only available (and mandatory)
- * in stores with the
- * #LSUP_STORE_IDX feature.
- */
- } LSUP_StoreInt;
- /*
- * Template for a new store and iterator implementation.
- * These should be placed in the .c file where the interface functions are
- * defined, and declared as `extern` in the related .h file.
- const LSUP_StoreInt my_store_int = {
- .name = "My Store", // Truncated to 15 chars.
- .features = LSUP_STORE_PERM | LSUP_STORE_IDX,
- .setup_fn = my_setup_fn,
- .new_fn = my_new_fn,
- .free_fn = my_free_fn,
- .size_fn = my_size_fn,
- .id_fn = my_id_fn,
- .txn_begin_fn = my_txn_begin_fn,
- .txn_commit_fn = my_txn_commit_fn,
- .txn_abort_fn = my_txn_abort_fn,
- .add_init_fn = my_init_fn,
- .add_iter_fn = my_iter_fn,
- .add_abort_fn = my_add_abort_fn,
- .add_done_fn = my_add_done_fn,
- .add_term_fn = my_add_term_fn,
- .lookup_fn = my_lookup_fn,
- .lu_next_fn = my_iter_next_fn,
- .lu_free_fn = my_iter_free_fn,
- .remove_fn = my_remove_fn,
- .nsm_put_fn = my_nsm_put_fn,
- .nsm_get_fn = my_nsm_get_fn,
- };
- */
- #endif /* _LSUP_STORE_INTERFACE_H */
|