/** @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 "lsup/environment.h" /** @defgroup store_interface Store interface module * @ingroup private * @{ */ /* * Store feature flags. * * NOTE: LSUP_STORE_PERM need only be set by an implementation based on whether * the data may be cleared before the perogram ends. It is the client's * responsibility to guarantee permanence beyond the lifespan of the program. A * store featuring LSUP_STORE_PERM MUST guarantee that the data remain * available on storage for the user to further handle them. */ 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. * * #LSUP_store_new() calls this function before creating the store handle. * * 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 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); /** @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); #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] txn Transaction handle initialized 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 *txn); /** @brief Abort a transaction. * * Only for LSUP_STORE_TXN stores. * * @param[in] txn Transaction handle initialized by #store_txn_begin_fn_t(). */ typedef void (*store_txn_abort_fn_t)(void *txn); /** @brief Update the context of triples in a context-aware store. * * Only defined in stores with the LSUP_STORE_CTX feature. * * @sa #LSUP_store_update_ctx_txn() */ typedef LSUP_rc (*store_update_ctx_fn_t)( void *store, const LSUP_Buffer *old_c, const LSUP_Buffer *new_c, void *udata); /** @brief Initialize bulk triple load. * * @sa #LSUP_store_add_init_txn() */ typedef void * (*store_add_init_fn_t)( void *store, const LSUP_Buffer *sc, void *udata); /** @brief Add one triple into the store. * * @sa LSUP_store_add_iter(). */ typedef LSUP_rc (*store_add_iter_fn_t)( void *it, const LSUP_BufferTriple * sspo); /** @brief Abort an add loop and free iterator. * * Only available for stores with the LSUP_STORE_CTX feature. * * @sa LSUP_store_add_abort(). */ typedef void (*store_add_abort_fn_t)(void *it); /** @brief Finalize an add loop and free iterator. * * @sa #LSUP_store_add_done(). */ typedef LSUP_rc (*store_add_done_fn_t)(void *it); /** @brief Add a single term to the store. * * @sa #LSUP_store_add_term_txn(). */ typedef LSUP_rc (*store_add_term_fn_t)( void *store, const LSUP_Buffer *sterm, void *udata); /* * Iterator function types. */ /** @brief Prototype: look up triples by pattern matching. * * @sa #LSUP_store_lookup_txn(). */ 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). * * @note Unused interface function. * * @param[in] store Store to be queried. * * @param[in] sspo Triple to look up. All members must not be NULL. * * @param[in] sc 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: yield the matching triples and advance the iterator. * * @sa LSUP_store_iter_next(). */ typedef LSUP_rc (*iter_next_fn_t)( void *it, LSUP_BufferTriple *sspo, LSUP_Buffer **ctx); /** @brief Prototype: free an iterator allocated by a lookup. * * @sa #LSUP_store_iter_free(). */ typedef void (*iter_free_fn_t)(void * it); /** @brief Prototype: get iterator active transaction handle. * * @sa #LSUP_store_iter_txn(). */ typedef void * (*iter_txn_fn_t)(void *it); /** @brief Prototype: delete triples by pattern matching. * * @sa #LSUP_store_remove_txn(). */ 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 Prototype: Get index of all graph (context) URIs in a store. * * @sa #LSUP_store_ctx_list_txn() */ typedef LSUP_Buffer ** (*store_ctx_list_fn_t)(void *store, void *txn); /* * 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. //Context setting. store_update_ctx_fn_t update_ctx_fn; ///< Update context URI. ///< ///< Only available in stores with ///< #LSUP_STORE_CTX feature. Optional. // 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. iter_txn_fn_t iter_txn_fn; ///< Get iterator's transaction. // Removal. store_remove_fn_t remove_fn; ///< Remove triples by pattern. // Context. store_ctx_list_fn_t ctx_list_fn; ///< Get all context URIs in a store. ///< ///< Only applicable to stores with ///< LSUP_STORE_CTX 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, .ctx_update_fn = my_ctx_update_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, .iter_txn_fn = my_iter_txn_fn, .remove_fn = my_remove_fn, .ctx_list_fn = my_ctx_list_fn, }; */ /// @} END defgroup store_interface #endif /* _LSUP_STORE_INTERFACE_H */