store.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /** @file store.h
  2. *
  3. * @brief Generic store dependency.
  4. *
  5. * This code allows to use the store interface with any supported back end
  6. * without any knowledge of the back end implementations. Code using the store
  7. * interface need only include this file.
  8. *
  9. * New store implementations should be added to this file as `#include`s as
  10. * well as entries in the `BACKEND_TBL` macro.
  11. */
  12. #ifndef _LSUP_STORE_H
  13. #define _LSUP_STORE_H
  14. /*
  15. * Add new back end headers here.
  16. */
  17. #include "lsup/store_htable.h"
  18. #include "lsup/store_mdb.h"
  19. /** @defgroup store Backend store module
  20. * @ingroup public
  21. * @{
  22. */
  23. /*
  24. * Define backend types.
  25. *
  26. * Add new store implementations to this table.
  27. */
  28. #define BACKEND_TBL \
  29. /* #enum suffix#store if */\
  30. ENTRY( HTABLE, htstore_int ) \
  31. ENTRY( MDB, mdbstore_int ) \
  32. /// Store types. All prefixed with `LSUP_STORE_`.
  33. typedef enum {
  34. #define ENTRY(a, b) \
  35. LSUP_STORE_##a,
  36. BACKEND_TBL
  37. #undef ENTRY
  38. } LSUP_StoreType;
  39. /** @brief Store structure.
  40. *
  41. * Code using the store interface should create an instance of this structure
  42. * with pointers to the store interface of their choice, and to an opaque
  43. * structure to hold the store state.
  44. *
  45. * Iterator state handles generated by lookup and add functions are kept
  46. * outside of this structure, but manipulated by the interface specified in
  47. * here.
  48. *
  49. * @sa #LSUP_graph_new()
  50. */
  51. typedef struct store_t {
  52. LSUP_StoreType type; ///< Store type.
  53. char * id; /**< Store ID.
  54. *
  55. * NOTE: This is
  56. * NULL for volatile stores.
  57. */
  58. const LSUP_StoreInt * sif; ///< Store interface.
  59. void * data; ///< Store back end data.
  60. } LSUP_Store;
  61. /** @brief Return store interface for a specific type.
  62. */
  63. const LSUP_StoreInt *
  64. LSUP_store_int (LSUP_StoreType type);
  65. /** @brief Return the store type label.
  66. *
  67. * @param type Store type enum.
  68. *
  69. * @return Store type label as `STORE_<type>`.
  70. */
  71. const char *
  72. LSUP_store_type_label (LSUP_StoreType type);
  73. /** @brief Create a new store.
  74. *
  75. * The life cycle of a store normally outspans the one of one or multiple
  76. * graphs with the same back end, hence it is managed independently.
  77. *
  78. * @param[in] store_type Type of store backing the graph. One of the values of
  79. * #LSUP_StoreType.
  80. *
  81. * @param[in] store_id Identifier for the store. This may be
  82. * interpreted differently by each store implementation. For the MDB store,
  83. * this is the file path where the store is located. It is ignored by volatile
  84. * stores (with LSUP_STORE_PERM feature flag set to false). If a store
  85. * does not exist for the given identifier, a new one is initialized. If this
  86. * parameter is NULL, the default store for the selected type is used.
  87. *
  88. * @param[in] size Initial size of the store. Only used for optimization
  89. * purposes. It may be ignored by some implementations and it is always safe
  90. * to set to 0.
  91. *
  92. * @param clear Flag that is passed to the `init_fn` function of the store
  93. * interface, if present, to clear an existing store with the same ID.
  94. *
  95. * @return Store handle. It must be freed with #LSUP_store_free().
  96. */
  97. LSUP_Store *
  98. LSUP_store_new (
  99. const LSUP_StoreType store_type, const char *store_id, size_t size,
  100. bool clear);
  101. /** @brief Free a store created with #LSUP_store_new().
  102. *
  103. * @param[in] store Store handle.
  104. */
  105. void
  106. LSUP_store_free (LSUP_Store *store);
  107. size_t
  108. LSUP_store_size (const LSUP_Store *store);
  109. /// Feature flags belonging to the store interface.
  110. const LSUP_StoreFeature
  111. LSUP_store_features (const LSUP_Store *store);
  112. /// Store identifier.
  113. char *
  114. LSUP_store_id (const LSUP_Store *store);
  115. /** @brief Begin a transaction.
  116. *
  117. * If the store supports it, begin a transaction. Only one transaction may be
  118. * opened at a time.
  119. *
  120. * The transaction must be either committed with #LSUP_store_commit() or
  121. * rolled back with #LSUP_store_abort().
  122. *
  123. * @param[in] store Store handle.
  124. *
  125. * @param[in] flags Unused for now, use 0. TODO
  126. *
  127. * @param[out] txn Address to be populated with the new transaction handle.
  128. *
  129. * @return LSUP_OK on success; LSUP_VALUE_ERR if the store does not
  130. * support transactions; LSUP_TXN_ERR if the store has already an uncommitted
  131. * transaction; <0 on other errors.
  132. */
  133. LSUP_rc
  134. LSUP_store_begin (LSUP_Store *store, int flags, void **txn);
  135. /** @brief Commit a transaction.
  136. *
  137. * If the store supports it, commit an open transaction. In case of
  138. * error, the transaction is left open and it is advisable to roll it back with
  139. * #LSUP_store_abort().
  140. *
  141. * @param[in] store Store handle.
  142. *
  143. * @param[in] txn transaction handle to commit.
  144. *
  145. * @return LSUP_OK if the transaction was committed successfully; LSUP_NOACTION
  146. * if NULL was passed; LSUP_TXN_ERR on error.
  147. */
  148. LSUP_rc
  149. LSUP_store_commit (LSUP_Store *store, void *txn);
  150. /** @brief Abort (roll back) a transaction.
  151. *
  152. * If the store supports it, abort an open transaction and abandon all changes.
  153. *
  154. * @param[in] store Store handle.
  155. *
  156. * @param[in] txn transaction handle to abort.
  157. */
  158. void
  159. LSUP_store_abort (LSUP_Store *store, void *txn);
  160. /** @brief Update the context of triples in a context-aware store.
  161. *
  162. * When a context URI is updated, all relationships of triples to that context
  163. * must be updated to reflect the new context.
  164. *
  165. * @param[in] store Store handle.
  166. *
  167. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  168. * This is ignored by non-transactional back ends.
  169. *
  170. * @param[in] old_c Old context handle.
  171. *
  172. * @param[in] new_c New context handle.
  173. *
  174. * @return LSUP_OK on success; LSUP_NOACTION if no triples were found under the
  175. * given context; <0 on error.
  176. */
  177. LSUP_rc
  178. LSUP_store_update_ctx_txn (
  179. LSUP_Store *store, void *txn, const LSUP_Buffer *old_c,
  180. const LSUP_Buffer *new_c);
  181. #define LSUP_store_update_ctx(store, ...) \
  182. LSUP_store_update_txn (store, NULL, __VA_ARGS__)
  183. /** @brief Initialize bulk triple load.
  184. *
  185. * This is the first step of a bulk load. It is best used when the data at hand
  186. * need to be pre-processed, which can be done in the same loop as the next
  187. * step to keep memory usage low.
  188. *
  189. * @param[in] store The store to add to.
  190. *
  191. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  192. * This is ignored by non-transactional back ends.
  193. *
  194. * @param[in] sc Context as a serialized term. If this is NULL, and the
  195. * default context is not NULL, triples will be added to the default context
  196. * for the store, If the default context for the store is NULL, regardless of
  197. * the value of sc, triples will be added with no context. Only meaningful
  198. * for stores with the LSUP_STORE_CTX feature.
  199. *
  200. * @return Iterator handle to be passed to the following load steps.
  201. */
  202. void *
  203. LSUP_store_add_init_txn (
  204. LSUP_Store *store, void *txn, const LSUP_Buffer *sc);
  205. /// Non-transactional version of #LSUP_store_add_init_txn().
  206. #define LSUP_store_add_init(store, ...) \
  207. LSUP_store_add_init_txn (store, NULL, __VA_ARGS__)
  208. /** @brief Add one triple into the store.
  209. *
  210. * This must be called after #store_add_init_fn_t, using the iterator
  211. * yielded by that function. It may be called multiple times and must be
  212. * followed by #store_add_done_fn_t or #store_add_abort_fn_t (if supported).
  213. *
  214. * @param[in] store Store handle.
  215. *
  216. * @param[in] it Iterator obtained by #LSUP_store_add_init().
  217. *
  218. * @param[in] sspo Serialized triple to be added.
  219. *
  220. * @return LSUP_OK if the triple was inserted; LSUP_NOACTION if the triple
  221. * already existed; LSUP_DB_ERR if an MDB error occurred.
  222. */
  223. LSUP_rc
  224. LSUP_store_add_iter (
  225. LSUP_Store *store, void *it, const LSUP_BufferTriple *sspo);
  226. /** @brief Abort an add loop and free iterator.
  227. *
  228. * Usually called on an irrecoverable error from #store_add_iter_fn_t. None of
  229. * the successful inserts in the same loop is retained.
  230. *
  231. * @param[in] store Store handle.
  232. *
  233. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  234. */
  235. void
  236. LSUP_store_add_abort (LSUP_Store *store, void *it);
  237. /** @brief Finalize an add loop and free iterator.
  238. *
  239. * This must be called after #store_add_iter_fn_t.
  240. *
  241. * @param[in] store Store handle.
  242. *
  243. * @param[in] it Iterator obtained by #LSUP_store_add_init().
  244. *
  245. * @return LSUP_OK on success, <0 on failure. In the latter case, a transaction
  246. * may be aborted in a transactional back end.
  247. */
  248. LSUP_rc
  249. LSUP_store_add_done (LSUP_Store *store, void *it);
  250. /** @brief Add a single term to the store.
  251. *
  252. * @param[in] store Store handle.
  253. *
  254. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  255. * This is ignored by non-transactional back ends.
  256. *
  257. * @param[in] sterm Serialized term to store.
  258. */
  259. LSUP_rc
  260. LSUP_store_add_term_txn (LSUP_Store *store, void *txn, LSUP_Buffer *sterm);
  261. /// Non-transactional version of #LSUP_store_add_term_txn().
  262. #define LSUP_store_add_term(store, ...) \
  263. LSUP_store_add_term_txn (store, NULL, __VA_ARGS__)
  264. /** @brief Look up triples by pattern matching.
  265. *
  266. * This function may return a count of matches and/or an iterator of results as
  267. * serialized triples.
  268. *
  269. * For stores with #LSUP_STORE_TXN, this opens a read-only transaction. The
  270. * transaction handle is held in the iterator structure and is closed when the
  271. * iterator is freed with #iter_free_fn_t().
  272. *
  273. * Any and all of the terms may be NULL, which indicates an unbound query
  274. * term. Stores witout context support will always ignore sc.
  275. *
  276. * @param[in] store The store to be queried.
  277. *
  278. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  279. * This is ignored by non-transactional back ends.
  280. *
  281. * @param[in] ss Serialized s term.
  282. *
  283. * @param[in] sp Serialized p term.
  284. *
  285. * @param[in] so Serialized o term.
  286. *
  287. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  288. * which case search is done in all contexts. Note that triples inserted
  289. * without context are assigned the *default* context for the store.
  290. *
  291. * @param[out] ct If not NULL, this will be populated with the number of
  292. * entries found. In some implementations, it is very inexpensive to set for
  293. * lookups without context, much less so for 1-bound and 2-bound context
  294. * lookups, in which cases it should be set only if needed.
  295. *
  296. * @return Iterator handle that will be populated with a result iterator. This
  297. * is always created even if no matches are found and must be freed with
  298. * #iter_free_fn_t() after use. If matches are found, the iterator points to
  299. * the first result which can be retrieved with #iter_next_fn_t.
  300. */
  301. void *
  302. LSUP_store_lookup_txn (
  303. const LSUP_Store *store, void *txn,
  304. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  305. const LSUP_Buffer *sc, size_t *ct);
  306. /// Non-transactional version of #LSUP_store_lookup_txn().
  307. #define LSUP_store_lookup(store, ...) \
  308. LSUP_store_lookup_txn (store, NULL, __VA_ARGS__)
  309. /** @brief Yield the matching triples and advance the iterator.
  310. *
  311. * @note Iterators keep transactions open. Don't hold on to them longer than
  312. * necessary.
  313. *
  314. * @note If the store interface has the LSUP_STORE_COW feature, the memory
  315. * buffer referenced by the #LSUP_Buffer handle is owned by the database. It
  316. * must not be written to or freed. To modify the data or use them beyond the
  317. * caller's scope, this memory must be copied. Note that the #LSUP_Buffer
  318. * handle must still be freed (with a plain `free()`), but not the underlying
  319. * data buffer, since only the latter is owned by the back end. Implementations
  320. * with the `LSUP_STORE_COW` feature SHOULD create buffers with the
  321. * `LSUP_BUF_BORROWED` flag, so that they can be safely freed with
  322. * #LSUP_buffer_free() and #LSUP_btriple_free().
  323. *
  324. * @param[in] store Store handle.
  325. *
  326. * @param[in] it Opaque iterator handle obtained with #store_lookup_fn_t.
  327. *
  328. * @param[out] sspo #LSUP_BufferTriple to be populated with three serialized
  329. * terms if found. It may be NULL, in which case it is not populated.
  330. *
  331. * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
  332. * LSUP_Buffer structs, one for each context associated with the matching
  333. * triple. These contexts are the same regardless of the context filter used
  334. * in the lookup. The array is freed with a simple `free()`. This parameter
  335. * is ignored by implementations without the LSUP_STORE_CTX feature.
  336. *
  337. * To iterate over the context array, use this loop:
  338. *
  339. * size_t i = 0;
  340. * while (ctx[i].addr)
  341. * do_something(ctx + (i++));
  342. *
  343. * @return LSUP_OK if results were found; LSUP_END if no (more) results were
  344. * found; LSUP_DB_ERR if a backend error occurred.
  345. */
  346. LSUP_rc
  347. LSUP_store_iter_next (
  348. LSUP_Store *store, void *it, LSUP_BufferTriple *sspo,
  349. LSUP_Buffer **ctx);
  350. /** @brief Free an iterator allocated by a lookup.
  351. *
  352. * @param[in] store Store handle.
  353. *
  354. * @param[in] it Iterator pointer. It will be set to NULL after freeing.
  355. */
  356. void
  357. LSUP_store_iter_free (LSUP_Store *store, void *it);
  358. /** @brief Get iterator active transaction handle.
  359. *
  360. * This function is used to get an active transaction during an iteration loop
  361. * in order to perform an action using the store state within that loop. Some
  362. * stores (e.g. MDB) only support one R/W open transaction per thread, so this
  363. * is also the only way to perform anything else than iterating or committing
  364. * while a loop is open.
  365. *
  366. * @param[in] store Store handle.
  367. *
  368. * @param[in] it Iterator handle to get the transaction from.
  369. *
  370. * @return Transaction handle. DO NOT close this transaction directly.
  371. */
  372. void *
  373. LSUP_store_iter_txn (const LSUP_Store *store, void *it);
  374. /** @brief Delete triples by pattern matching.
  375. *
  376. * @param[in] store The store to be queried.
  377. *
  378. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  379. * This is ignored by non-transactional back ends.
  380. *
  381. * @param[in] ss Serialized s term.
  382. *
  383. * @param[in] sp Serialized p term.
  384. *
  385. * @param[in] so Serialized o term.
  386. *
  387. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  388. * which case search is done in all contexts. Note that triples inserted
  389. * without context are assigned the *default* context for the store.
  390. *
  391. * @param[out] ct If not NULL, this will be populated with the number of
  392. * triples actually deleted.
  393. *
  394. * @return LSUP_OK on success; LSUP_NOACTION if no triples were deleted;
  395. * <0 on error.
  396. *
  397. */
  398. LSUP_rc
  399. LSUP_store_remove_txn (
  400. LSUP_Store *store, void *txn,
  401. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  402. const LSUP_Buffer *sc, size_t *ct);
  403. /// Non-transactional version of #LSUP_store_remove_txn().
  404. #define LSUP_store_remove(store, ...) \
  405. LSUP_store_remove_txn (store, NULL, __VA_ARGS__)
  406. /** @brief get index of all graph (context) URIs in a store.
  407. *
  408. * Only applicable to stores with the LSUP_STORE_CTX feature flag.
  409. *
  410. * @param[in] store Store handle.
  411. *
  412. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  413. * This is ignored by non-transactional back ends.
  414. *
  415. * @return Set of all context URIs.
  416. */
  417. LSUP_Buffer **
  418. LSUP_store_ctx_list_txn (LSUP_Store *store, void *txn);
  419. /// Non-transactional version of #LSUP_store_ctx_list_txn().
  420. #define LSUP_store_ctx_list(store) \
  421. LSUP_store_ctx_list_txn (store, NULL)
  422. /// @} END store
  423. #endif /* LSUP_STORE_H */