store_interface.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /** @file store_interface.h
  2. *
  3. * @brief Common store back end interfaces.
  4. *
  5. * Code using the store interface should include NOT this header, but rahter
  6. * `store.h`.
  7. *
  8. * This header is included by all back end implementations, which are in
  9. * their turn included by `store.h`.
  10. *
  11. * The basic interfaces for store and store iterator implementations are
  12. * defined here. New store implementations should include this header and
  13. * implement three basic elements:
  14. *
  15. * - A structure representing the store back end. This structure will be
  16. * opaque to all downstream code and its layout is entirely up to the
  17. * implementer.
  18. *
  19. * - A structure representing a store iterator state, also opaque.
  20. *
  21. * - The LSUP_StoreInt interface with all the functions defined in the
  22. * interface necessary to interact with the store.
  23. *
  24. * See the `store_htable.{c,h}` and `store_mdb.{c,h}` files for examples of
  25. * fully functioning implementations.
  26. *
  27. * The #LSUP_StoreInt structure defines a store interface for raw buffer
  28. * triples. Nothing in the store functions' signatures should hint at RDF
  29. * triples—they should accept and produce exclusively raw byte buffers
  30. * (#LSUP_Buffer). A store interface may have any of the `LSUP_STORE_*` faeture
  31. * flags which should be reflected in the way its members are implemented.
  32. */
  33. #ifndef _LSUP_STORE_INTERFACE_H
  34. #define _LSUP_STORE_INTERFACE_H
  35. #include "lsup/environment.h"
  36. /** @defgroup store_interface Store interface module
  37. * @ingroup private
  38. * @{
  39. */
  40. /*
  41. * Store feature flags.
  42. *
  43. * NOTE: LSUP_STORE_PERM need only be set by an implementation based on whether
  44. * the data may be cleared before the perogram ends. It is the client's
  45. * responsibility to guarantee permanence beyond the lifespan of the program. A
  46. * store featuring LSUP_STORE_PERM MUST guarantee that the data remain
  47. * available on storage for the user to further handle them.
  48. */
  49. typedef enum {
  50. LSUP_STORE_PERM = 1<<0, ///< Store is on a permanent support.
  51. LSUP_STORE_CTX = 1<<1, ///< Store supports contexts (quads).
  52. LSUP_STORE_IDX = 1<<2, ///< Store is fully SPO(C)-indexed.
  53. LSUP_STORE_TXN = 1<<3, ///< Supports transaction handling.
  54. LSUP_STORE_COW = 1<<4, ///< Copy on write. @sa #iter_next_fn_t()
  55. LSUP_STORE_OWN_NSM = 1<<5, ///< Store has its own namespace map.
  56. } LSUP_StoreFeature;
  57. /*
  58. * Store function types.
  59. */
  60. /** @brief Prototype: create any environment necessary for the store to work.
  61. *
  62. * #LSUP_store_new() calls this function before creating the store handle.
  63. *
  64. * This function should be idempotent on separate calls to the same `id`,
  65. * unless the `clear` option is set to `true`.
  66. *
  67. * @param[in,out] id Identifier to use for the store. This should be
  68. * a URI that uniquely identifies a back end for the implementation using it,
  69. * e.g. a SQL connection string, file path for an embedded store, the URL of a
  70. * REST API endpoint, etc. It may also be NULL, in which case it will be set to
  71. * the default identifier set by the implementation. It can be retrieved from
  72. * an existing store via #store_id_fn_t() .
  73. *
  74. * @param[in] clear Whether to remove an existing environment with the same ID.
  75. */
  76. typedef LSUP_rc (*store_setup_fn_t)(const char *id, bool clear);
  77. /** @brief Prototype: create a new store.
  78. *
  79. * @param[in] id Identifier for the new store. How this is interpreted, and
  80. * whether it is even used, depends on the implementation, which should
  81. * provide documentation on how to pass and interpret this parameter.
  82. *
  83. * @param[in] size Initial size for the store. It may be 0. Only meaningful
  84. * for stores that may preallocate memory, such as #HTStore.
  85. *
  86. * @return New store handle.
  87. */
  88. typedef void * (*store_new_fn_t)(const char *id, size_t size);
  89. /** @brief Prototype: free store handle.
  90. *
  91. * @param[in] store Store handle.
  92. *
  93. */
  94. typedef void (*store_free_fn_t)(void *store);
  95. /** @brief Prototype: get the store ID.
  96. *
  97. * @param[in] store Store handle.
  98. *
  99. * @return store ID string. This is a copy and should be freed after use.
  100. */
  101. typedef char * (*store_id_fn_t)(const void *store);
  102. /** @brief Prototype: get store size.
  103. *
  104. * @param[in] store The store to calculate size of.
  105. *
  106. * @return Number of stored SPO triples (across all contexts if supported).
  107. */
  108. typedef size_t (*store_size_fn_t)(const void *store);
  109. #if 0
  110. /** @brief Print stats about a store.
  111. *
  112. * TODO
  113. *
  114. * @param[in] store The store to get stats for.
  115. */
  116. typedef LSUP_rc (*store_stat_fn_t)(void *store, void *stat);
  117. #endif
  118. /** @brief Begin a transaction.
  119. *
  120. * Only for LSUP_STORE_TXN stores.
  121. *
  122. * The transaction handle is managed by the store implementation and can be any
  123. * data type.
  124. *
  125. * @param[in] store Store handle.
  126. *
  127. * @param[in] flags Transaction flags. These vary with each implementation.
  128. *
  129. * @param[out] txn Will point to the new open transaction on success, or to
  130. * undefined content on failure.
  131. *
  132. * @return LSUP_OK if the transaction started successfully, <0 on error.
  133. */
  134. typedef LSUP_rc (*store_txn_begin_fn_t)(void *store, int flags, void **txn);
  135. /** @brief Commit a transaction.
  136. *
  137. * Only for LSUP_STORE_TXN stores.
  138. *
  139. * @param[in] txn Transaction handle initialized by #store_txn_begin_fn_t().
  140. *
  141. * @return LSUP_OK if the transaction was committed successfully, <0 on error.
  142. */
  143. typedef LSUP_rc (*store_txn_commit_fn_t)(void *txn);
  144. /** @brief Abort a transaction.
  145. *
  146. * Only for LSUP_STORE_TXN stores.
  147. *
  148. * @param[in] txn Transaction handle initialized by #store_txn_begin_fn_t().
  149. */
  150. typedef void (*store_txn_abort_fn_t)(void *txn);
  151. /** @brief Update the context of triples in a context-aware store.
  152. *
  153. * When a context URI is updated, all relationships of triples to that context
  154. * must be updated to reflect the new context.
  155. *
  156. * Only defined in stores with the LSUP_STORE_CTX feature.
  157. *
  158. * @param[in] store Store handle.
  159. *
  160. * @param[in] old_c Old context handle.
  161. *
  162. * @param[in] new_c New context handle.
  163. *
  164. * @param[in] udata Implementation-specific context data.
  165. *
  166. * @return LSUP_OK on success; LSUP_NOACTION if no triples were found under the
  167. * given context; <0 on error.
  168. */
  169. typedef LSUP_rc (*store_update_ctx_fn_t)(
  170. void *store, const LSUP_Buffer *old_c, const LSUP_Buffer *new_c,
  171. void *udata);
  172. /** @brief Initialize bulk triple load.
  173. *
  174. * This is the first step of a bulk load. It is best used when the data at hand
  175. * need to be pre-processed, which can be done in the same loop as the next
  176. * step to keep memory usage low.
  177. *
  178. * @param[in] store The store to add to.
  179. *
  180. * @param[in] sc Context as a serialized term. If this is NULL, and the
  181. * default context is not NULL, triples will be added to the default context
  182. * for the store, If the default context for the store is NULL, regardless of
  183. * the value of sc, triples will be added with no context. Only meaningful
  184. * for stores with the LSUP_STORE_CTX feature.
  185. *
  186. * @param[in] udata User data. Consult individual store implementations for
  187. * how this is interpreted.
  188. *
  189. * @return Iterator handle to be passed to the following load steps.
  190. */
  191. typedef void * (*store_add_init_fn_t)(
  192. void *store, const LSUP_Buffer *sc, void *udata);
  193. /** @brief Add one triple into the store.
  194. *
  195. * This must be called after #store_add_init_fn_t, using the iterator
  196. * yielded by that function. It may be called multiple times and must be
  197. * followed by #store_add_done_fn_t or #store_add_abort_fn_t (if supported).
  198. *
  199. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  200. * The following members are of interest:
  201. * it->i stores the total number of records inserted.
  202. *
  203. * @param[in] sspo Serialized triple to be added.
  204. *
  205. * @return LSUP_OK if the triple was inserted; LSUP_NOACTION if the triple
  206. * already existed; LSUP_DB_ERR if an MDB error occurred.
  207. */
  208. typedef LSUP_rc (*store_add_iter_fn_t)(
  209. void *it, const LSUP_BufferTriple * sspo);
  210. /** @brief Abort an add loop and free iterator.
  211. *
  212. * Usually called on an irrecoverable error from #store_add_iter_fn_t. None of
  213. * the successful inserts in the same loop is retained.
  214. *
  215. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  216. */
  217. typedef void (*store_add_abort_fn_t)(void *it);
  218. /*
  219. * Iterator function types.
  220. */
  221. /** @brief Get iterator active transaction handle.
  222. *
  223. * This function is used to get an active transaction during an iteration loop
  224. * in order to perform an action using the store state within that loop. Some
  225. * stores (e.g. MDB) only support one R/W open transaction per thread, so this
  226. * is also the only way to perform anything else than iterating or committing
  227. * while a loop is open.
  228. *
  229. * @param[in] it Iterator handle to get the transaction from.
  230. *
  231. * @return Transaction handle. DO NOT close this transaction directly.
  232. */
  233. typedef void * (*iter_txn_fn_t)(void *it);
  234. /** @brief Finalize an add loop and free iterator.
  235. *
  236. * This must be called after #store_add_iter_fn_t.
  237. *
  238. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  239. */
  240. typedef LSUP_rc (*store_add_done_fn_t)(void *it);
  241. /** @brief Add a single term to the store.
  242. *
  243. * @param[in] store Store handle.
  244. *
  245. * @param[in] sterm Serialized term to store.
  246. *
  247. * @param[in] udata Implementation-defined data. See individual
  248. * implementations' documentation.
  249. */
  250. typedef LSUP_rc (*store_add_term_fn_t)(
  251. void *store, const LSUP_Buffer *sterm, void *udata);
  252. /** @brief Prototype: look up triples by pattern matching.
  253. *
  254. * This function may return a count of matches and/or an iterator of results as
  255. * serialized triples.
  256. *
  257. * For stores with #LSUP_STORE_TXN, this opens a read-only transaction. The
  258. * transaction handle is held in the iterator structure and is closed when the
  259. * iterator is freed with #iter_free_fn_t().
  260. *
  261. * Any and all of the terms may be NULL, which indicates an unbound query
  262. * term. Stores witout context support will always ignore sc.
  263. *
  264. * @param[in] store The store to be queried.
  265. *
  266. * @param[in] ss Serialized s term.
  267. *
  268. * @param[in] sp Serialized p term.
  269. *
  270. * @param[in] so Serialized o term.
  271. *
  272. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  273. * which case search is done in all contexts. Note that triples inserted
  274. * without context are assigned the *default* context for the store.
  275. *
  276. * @param[in] udata User data. Consult individual store implementations for
  277. * how this is interpreted.
  278. *
  279. * @param[out] ct If not NULL, this will be populated with the number of
  280. * entries found. In some implementations, it is very inexpensive to set for
  281. * lookups without context, much less so for 1-bound and 2-bound context
  282. * lookups, in which cases it should be set only if needed.
  283. *
  284. * @return Iterator handle that will be populated with a result iterator. This
  285. * is always created even if no matches are found and must be freed with
  286. * #iter_free_fn_t() after use. If matches are found, the iterator points to
  287. * the first result which can be retrieved with #iter_next_fn_t.
  288. */
  289. typedef void * (*store_lookup_fn_t)(
  290. void *store,
  291. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  292. const LSUP_Buffer *sc, void *udata, size_t *ct);
  293. /** @brief Prototype: check for existence of a triple (T/F).
  294. *
  295. * @param[in] store Store to be queried.
  296. *
  297. * @param[in] sspo Triple to look up. All members must not be NULL.
  298. *
  299. * @param[in] sc Optional context to look into. It may be NULL. It is
  300. * disregarded by stores without the LSUP_STORE_CTX feature.
  301. *
  302. * @return Whether the triple exist in the store (/context).
  303. */
  304. typedef bool (*store_trp_exist_fn_t)(
  305. void *store, const LSUP_BufferTriple *sspo, const LSUP_Buffer *sc);
  306. /** @brief Prototype: delete triples by pattern matching.
  307. *
  308. * The ss, sp, so, sc terms act as a matching pattern as documented in
  309. * @sa #store_lookup_fn_t(). if not NULL, ct yields the number of triples
  310. * actually deleted.
  311. *
  312. * @param[in] udata User data. Consult individual store implementations for
  313. * how this is interpreted.
  314. */
  315. typedef LSUP_rc (*store_remove_fn_t)(
  316. void *store,
  317. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  318. const LSUP_Buffer *sc, void *udata, size_t *ct);
  319. /** @brief Update the namespace map of a store.
  320. *
  321. * This is only available in stores with the LSUP_STORE_OWN_NSM feature.
  322. *
  323. * @param[in] store Store back end to update.
  324. *
  325. * @param[in] pfx Prefix to update. If the key is already existing, it is
  326. * updated or deleted (see `ns` parameter).
  327. *
  328. * @param[in] ns Namespace to relate to the prefix. If this value is NULL, the
  329. * prefix mapping is removed, if existing, or otherwise quietly skipped.
  330. *
  331. * @param[in] udata Opaque implementation-specific data handler. Consult each
  332. * implementation for details.
  333. *
  334. * @return LSUP_OK if a mapping was added, updated, or deleted; LSUP_NOACTION
  335. * if NULL was passed for `ns` and no corresponding prefix was found to delete;
  336. * <0 if an error occurred.
  337. */
  338. typedef LSUP_rc (*store_nsm_update_fn_t)(
  339. void *store, const char *pfx, const char *ns, void *udata);
  340. /** @brief Get the store's namespace prefix map.
  341. *
  342. * @param[in] store MDB store to query.
  343. *
  344. * @return NS map or NULL on error.
  345. */
  346. typedef LSUP_NSMap * (*store_nsm_get_fn_t)(void *store);
  347. /** @brief Prototype: yield the matching triples and advance the iterator.
  348. *
  349. * @note Iterators keep transactions open. Don't hold on to them longer than
  350. * necessary.
  351. *
  352. * @note If the store interface has the LSUP_STORE_COW feature, the memory
  353. * buffer referenced by the #LSUP_Buffer handle is owned by the database. It
  354. * must not be written to or freed. To modify the data or use them beyond the
  355. * caller's scope, this memory must be copied. Note that the #LSUP_Buffer
  356. * handle must still be freed (with a plain `free()`), but not the underlying
  357. * data buffer, since only the latter is owned by the back end. Implementations
  358. * with the `LSUP_STORE_COW` feature SHOULD create buffers with the
  359. * `LSUP_BUF_BORROWED` flag, so that they can be safely freed with
  360. * #LSUP_buffer_free() and #LSUP_btriple_free().
  361. *
  362. * @param[in] it Opaque iterator handle obtained with #store_lookup_fn_t.
  363. *
  364. * @param[out] sspo #LSUP_BufferTriple to be populated with three serialized
  365. * terms if found. It may be NULL, in which case it is not populated.
  366. *
  367. * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
  368. * LSUP_Buffer structs, one for each context associated with the matching
  369. * triple. These contexts are the same regardless of the context filter used
  370. * in the lookup. The array is freed with a simple `free()`. This parameter
  371. * is ignored by implementations without the LSUP_STORE_CTX feature.
  372. *
  373. * To iterate over the context array, use this loop:
  374. *
  375. * size_t i = 0;
  376. * while (ctx[i].addr)
  377. * do_something(ctx + (i++));
  378. *
  379. * @return LSUP_OK if results were found; LSUP_END if no (more) results were
  380. * found; LSUP_DB_ERR if a backend error occurred.
  381. */
  382. typedef LSUP_rc (*iter_next_fn_t)(
  383. void *it, LSUP_BufferTriple *sspo, LSUP_Buffer **ctx);
  384. /** @brief Prototype: free an iterator allocated by a lookup.
  385. *
  386. * @param[in] it Iterator pointer. It will be set to NULL after freeing.
  387. */
  388. typedef void (*iter_free_fn_t)(void * it);
  389. /** @brief Prototype: Get index of all graph (context) URIs in a store.
  390. *
  391. * Only applicable to stores with the LSUP_STORE_CTX feature flag.
  392. *
  393. * @param[in] store Store handle.
  394. *
  395. * @return Set of all context URIs.
  396. */
  397. typedef LSUP_Buffer ** (*store_ctx_list_fn_t)(void *store, void *txn);
  398. /*
  399. * Iterface type definitions.
  400. */
  401. /** @brief Store interface.
  402. *
  403. * New store implementations should define a static structure with the relevant
  404. * members filled in. Some members are only relevant to certain types of stores
  405. * and may be set to NULL.
  406. *
  407. * #setup_fn may be optionally defined and MUST cause an idempotent action,
  408. * unless the `clear` argument is set to `true`. Callers should check if this
  409. * member is NULL and if it is not, call it at the beginning of the
  410. * interaction with the store.
  411. *
  412. * Transaction control members are only applicable to stores with the
  413. * #LSUP_STORE_TXN feature.
  414. */
  415. typedef struct store_if_t {
  416. // Basic properties.
  417. char name[16]; ///< Store type name.
  418. LSUP_StoreFeature features; ///< Feature flags.
  419. // Allocation, setup and deallocation.
  420. store_setup_fn_t setup_fn; ///< Called before #store_new_fn_t.
  421. store_new_fn_t new_fn; ///< Create a new store instance.
  422. store_free_fn_t free_fn; ///< Free the store.
  423. // Metadata.
  424. store_size_fn_t size_fn; ///< Number of triples in the store.
  425. store_id_fn_t id_fn; ///< Get store ID.
  426. // Transaction control.
  427. store_txn_begin_fn_t txn_begin_fn; ///< Begin transaction.
  428. store_txn_commit_fn_t txn_commit_fn; ///< Commit transaction.
  429. store_txn_abort_fn_t txn_abort_fn; ///< Abort transaction.
  430. iter_txn_fn_t iter_txn_fn; ///< Get iterator's transaction.
  431. //Context setting.
  432. store_update_ctx_fn_t update_ctx_fn; ///< Update context URI.
  433. ///<
  434. ///< Only available in stores with
  435. ///< #LSUP_STORE_CTX feature. Optional.
  436. // Addition.
  437. store_add_init_fn_t add_init_fn; ///< Initialize add iteration.
  438. store_add_iter_fn_t add_iter_fn; ///< Add one triple.
  439. store_add_abort_fn_t add_abort_fn; ///< Abort (roll back) the add process.
  440. ///<
  441. ///< Only available in
  442. ///< stores with #LSUP_STORE_TXN
  443. ///< feature. Optional.
  444. store_add_done_fn_t add_done_fn; ///< Complete the add process.
  445. store_add_term_fn_t add_term_fn; ///< Add (index) a term to the store.
  446. ///<
  447. ///< Only available in stores with
  448. ///< #LSUP_STORE_IDX feature. Optional.
  449. // Look up.
  450. store_lookup_fn_t lookup_fn; ///< Look up triples by pattern. 
  451. //store_trp_exist_fn_t exist_fn; ///< Check if a triple exists.
  452. iter_next_fn_t lu_next_fn; ///< Advance the lookup iterator.
  453. iter_free_fn_t lu_free_fn; ///< Free the lookup iterator.
  454. // Removal.
  455. store_remove_fn_t remove_fn; ///< Remove triples by pattern.
  456. // Namespace prefix mapping.
  457. store_nsm_update_fn_t nsm_update_fn; ///< Add a ns/pfx pair to the map.
  458. ///<
  459. ///< Only available (and mandatory)
  460. ///< in stores with the
  461. ///< #LSUP_STORE_OWN_NSM feature.
  462. store_nsm_get_fn_t nsm_get_fn; ///< Get the store's namespace map.
  463. ///<
  464. ///< Only available (and mandatory)
  465. ///< in stores with the
  466. ///< #LSUP_STORE_OWN_NSM feature.
  467. store_ctx_list_fn_t ctx_list_fn; ///< Get all context URIs in a store.
  468. ///<
  469. ///< Only applicable to stores with
  470. ///< LSUP_STORE_CTX feature.
  471. } LSUP_StoreInt;
  472. /*
  473. * Template for a new store and iterator implementation.
  474. * These should be placed in the .c file where the interface functions are
  475. * defined, and declared as `extern` in the related .h file.
  476. const LSUP_StoreInt my_store_int = {
  477. .name = "My Store", // Truncated to 15 chars.
  478. .features = LSUP_STORE_PERM | LSUP_STORE_IDX,
  479. .setup_fn = my_setup_fn,
  480. .new_fn = my_new_fn,
  481. .free_fn = my_free_fn,
  482. .size_fn = my_size_fn,
  483. .id_fn = my_id_fn,
  484. .txn_begin_fn = my_txn_begin_fn,
  485. .txn_commit_fn = my_txn_commit_fn,
  486. .txn_abort_fn = my_txn_abort_fn,
  487. .ctx_update_fn = my_ctx_update_fn,
  488. .add_init_fn = my_init_fn,
  489. .add_iter_fn = my_iter_fn,
  490. .add_abort_fn = my_add_abort_fn,
  491. .add_done_fn = my_add_done_fn,
  492. .add_term_fn = my_add_term_fn,
  493. .lookup_fn = my_lookup_fn,
  494. .lu_next_fn = my_iter_next_fn,
  495. .lu_free_fn = my_iter_free_fn,
  496. .remove_fn = my_remove_fn,
  497. .nsm_update_fn = my_nsm_update_fn,
  498. .nsm_get_fn = my_nsm_get_fn,
  499. .ctx_list_fn = my_ctx_list_fn,
  500. };
  501. */
  502. /// @} END defgroup store_interface
  503. #endif /* _LSUP_STORE_INTERFACE_H */