store.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 _VOLK_STORE_H
  13. #define _VOLK_STORE_H
  14. /*
  15. * Add new back end headers here.
  16. */
  17. #include "volksdata/store_htable.h"
  18. #include "volksdata/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 `VOLK_STORE_`.
  33. typedef enum {
  34. #define ENTRY(a, b) \
  35. VOLK_STORE_##a,
  36. BACKEND_TBL
  37. #undef ENTRY
  38. } VOLK_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 #VOLK_graph_new()
  50. */
  51. typedef struct store_t {
  52. VOLK_StoreType type; ///< Store type.
  53. char * id; /**< Store ID.
  54. *
  55. * NOTE: This is
  56. * NULL for volatile stores.
  57. */
  58. const VOLK_StoreInt * sif; ///< Store interface.
  59. void * data; ///< Store back end data.
  60. } VOLK_Store;
  61. /** @brief Return store interface for a specific type.
  62. */
  63. const VOLK_StoreInt *
  64. VOLK_store_int (VOLK_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. VOLK_store_type_label (VOLK_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. * #VOLK_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 VOLK_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 #VOLK_store_free().
  96. */
  97. VOLK_Store *
  98. VOLK_store_new (
  99. const VOLK_StoreType store_type, const char *store_id, size_t size,
  100. bool clear);
  101. /** @brief Free a store created with #VOLK_store_new().
  102. *
  103. * @param[in] store Store handle.
  104. */
  105. void
  106. VOLK_store_free (VOLK_Store *store);
  107. /** @brief Store size in triples.
  108. *
  109. * @param[in] store Store handle.
  110. *
  111. * @return Number of triples in the store, across all contexts.
  112. */
  113. size_t
  114. VOLK_store_size (const VOLK_Store *store);
  115. /// Feature flags belonging to the store interface.
  116. const VOLK_StoreFeature
  117. VOLK_store_features (const VOLK_Store *store);
  118. /// Store identifier.
  119. char *
  120. VOLK_store_id (const VOLK_Store *store);
  121. /** @brief Begin a transaction.
  122. *
  123. * If the store supports it, begin a transaction. Only one transaction may be
  124. * opened at a time.
  125. *
  126. * The transaction must be either committed with #VOLK_store_commit() or
  127. * rolled back with #VOLK_store_abort().
  128. *
  129. * @param[in] store Store handle.
  130. *
  131. * @param[in] flags Unused for now, use 0. TODO
  132. *
  133. * @param[out] txn Address to be populated with the new transaction handle.
  134. *
  135. * @return VOLK_OK on success; VOLK_VALUE_ERR if the store does not
  136. * support transactions; VOLK_TXN_ERR if the store has already an uncommitted
  137. * transaction; <0 on other errors.
  138. */
  139. VOLK_rc
  140. VOLK_store_begin (VOLK_Store *store, int flags, void **txn);
  141. /** @brief Commit a transaction.
  142. *
  143. * If the store supports it, commit an open transaction. In case of
  144. * error, the transaction is left open and it is advisable to roll it back with
  145. * #VOLK_store_abort().
  146. *
  147. * @param[in] store Store handle.
  148. *
  149. * @param[in] txn transaction handle to commit.
  150. *
  151. * @return VOLK_OK if the transaction was committed successfully; VOLK_NOACTION
  152. * if NULL was passed; VOLK_TXN_ERR on error.
  153. */
  154. VOLK_rc
  155. VOLK_store_commit (VOLK_Store *store, void *txn);
  156. /** @brief Abort (roll back) a transaction.
  157. *
  158. * If the store supports it, abort an open transaction and abandon all changes.
  159. *
  160. * @param[in] store Store handle.
  161. *
  162. * @param[in] txn transaction handle to abort.
  163. */
  164. void
  165. VOLK_store_abort (VOLK_Store *store, void *txn);
  166. /** @brief Update the context of triples in a context-aware store.
  167. *
  168. * When a context URI is updated, all relationships of triples to that context
  169. * must be updated to reflect the new context.
  170. *
  171. * @param[in] store Store handle.
  172. *
  173. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  174. * This is ignored by non-transactional back ends.
  175. *
  176. * @param[in] old_c Old context handle.
  177. *
  178. * @param[in] new_c New context handle.
  179. *
  180. * @return VOLK_OK on success; VOLK_NOACTION if no triples were found under the
  181. * given context; <0 on error.
  182. */
  183. VOLK_rc
  184. VOLK_store_update_ctx_txn (
  185. VOLK_Store *store, void *txn, const VOLK_Buffer *old_c,
  186. const VOLK_Buffer *new_c);
  187. #define VOLK_store_update_ctx(store, ...) \
  188. VOLK_store_update_txn (store, NULL, __VA_ARGS__)
  189. /** @brief Initialize bulk triple load.
  190. *
  191. * This is the first step of a bulk load. It is best used when the data at hand
  192. * need to be pre-processed, which can be done in the same loop as the next
  193. * step to keep memory usage low.
  194. *
  195. * @param[in] store The store to add to.
  196. *
  197. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  198. * This is ignored by non-transactional back ends.
  199. *
  200. * @param[in] sc Context as a serialized term. If this is NULL, and the
  201. * default context is not NULL, triples will be added to the default context
  202. * for the store, If the default context for the store is NULL, regardless of
  203. * the value of sc, triples will be added with no context. Only meaningful
  204. * for stores with the VOLK_STORE_CTX feature.
  205. *
  206. * @return Iterator handle to be passed to the following load steps.
  207. */
  208. void *
  209. VOLK_store_add_init_txn (
  210. VOLK_Store *store, void *txn, const VOLK_Buffer *sc);
  211. /// Non-transactional version of #VOLK_store_add_init_txn().
  212. #define VOLK_store_add_init(store, ...) \
  213. VOLK_store_add_init_txn (store, NULL, __VA_ARGS__)
  214. /** @brief Add one triple into the store.
  215. *
  216. * This must be called after #store_add_init_fn_t, using the iterator
  217. * yielded by that function. It may be called multiple times and must be
  218. * followed by #store_add_done_fn_t or #store_add_abort_fn_t (if supported).
  219. *
  220. * @param[in] store Store handle.
  221. *
  222. * @param[in] it Iterator obtained by #VOLK_store_add_init().
  223. *
  224. * @param[in] sspo Serialized triple to be added.
  225. *
  226. * @return VOLK_OK if the triple was inserted; VOLK_NOACTION if the triple
  227. * already existed; VOLK_DB_ERR if an MDB error occurred.
  228. */
  229. VOLK_rc
  230. VOLK_store_add_iter (
  231. VOLK_Store *store, void *it, const VOLK_BufferTriple *sspo);
  232. /** @brief Abort an add loop and free iterator.
  233. *
  234. * Usually called on an irrecoverable error from #store_add_iter_fn_t. None of
  235. * the successful inserts in the same loop is retained.
  236. *
  237. * @param[in] store Store handle.
  238. *
  239. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  240. */
  241. void
  242. VOLK_store_add_abort (VOLK_Store *store, void *it);
  243. /** @brief Finalize an add loop and free iterator.
  244. *
  245. * This must be called after #store_add_iter_fn_t.
  246. *
  247. * @param[in] store Store handle.
  248. *
  249. * @param[in] it Iterator obtained by #VOLK_store_add_init().
  250. *
  251. * @return VOLK_OK on success, <0 on failure. In the latter case, a transaction
  252. * may be aborted in a transactional back end.
  253. */
  254. VOLK_rc
  255. VOLK_store_add_done (VOLK_Store *store, void *it);
  256. /** @brief Add a single term to the store.
  257. *
  258. * @param[in] store Store handle.
  259. *
  260. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  261. * This is ignored by non-transactional back ends.
  262. *
  263. * @param[in] sterm Serialized term to store.
  264. */
  265. VOLK_rc
  266. VOLK_store_add_term_txn (VOLK_Store *store, void *txn, VOLK_Buffer *sterm);
  267. /// Non-transactional version of #VOLK_store_add_term_txn().
  268. #define VOLK_store_add_term(store, ...) \
  269. VOLK_store_add_term_txn (store, NULL, __VA_ARGS__)
  270. /** @brief Look up triples by pattern matching.
  271. *
  272. * This function may return a count of matches and/or an iterator of results as
  273. * serialized triples.
  274. *
  275. * For stores with #VOLK_STORE_TXN, this opens a read-only transaction. The
  276. * transaction handle is held in the iterator structure and is closed when the
  277. * iterator is freed with #iter_free_fn_t().
  278. *
  279. * Any and all of the terms may be NULL, which indicates an unbound query
  280. * term. Stores witout context support will always ignore sc.
  281. *
  282. * @param[in] store The store to be queried.
  283. *
  284. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  285. * This is ignored by non-transactional back ends.
  286. *
  287. * @param[in] ss Serialized s term.
  288. *
  289. * @param[in] sp Serialized p term.
  290. *
  291. * @param[in] so Serialized o term.
  292. *
  293. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  294. * which case search is done in all contexts. Note that triples inserted
  295. * without context are assigned the *default* context for the store.
  296. *
  297. * @param[out] ct If not NULL, this will be populated with the number of
  298. * entries found. In some implementations, it is very inexpensive to set for
  299. * lookups without context, much less so for 1-bound and 2-bound context
  300. * lookups, in which cases it should be set only if needed.
  301. *
  302. * @return Iterator handle that will be populated with a result iterator. This
  303. * is always created even if no matches are found and must be freed with
  304. * #iter_free_fn_t() after use. If matches are found, the iterator points to
  305. * the first result which can be retrieved with #iter_next_fn_t.
  306. */
  307. void *
  308. VOLK_store_lookup_txn (
  309. const VOLK_Store *store, void *txn,
  310. const VOLK_Buffer *ss, const VOLK_Buffer *sp, const VOLK_Buffer *so,
  311. const VOLK_Buffer *sc, size_t *ct);
  312. /// Non-transactional version of #VOLK_store_lookup_txn().
  313. #define VOLK_store_lookup(store, ...) \
  314. VOLK_store_lookup_txn (store, NULL, __VA_ARGS__)
  315. /** @brief Yield the matching triples and advance the iterator.
  316. *
  317. * @note Iterators keep transactions open. Don't hold on to them longer than
  318. * necessary.
  319. *
  320. * @note If the store interface has the VOLK_STORE_COW feature, the memory
  321. * buffer referenced by the #VOLK_Buffer handle is owned by the database. It
  322. * must not be written to or freed. To modify the data or use them beyond the
  323. * caller's scope, this memory must be copied. Note that the #VOLK_Buffer
  324. * handle must still be freed (with a plain `free()`), but not the underlying
  325. * data buffer, since only the latter is owned by the back end. Implementations
  326. * with the `VOLK_STORE_COW` feature SHOULD create buffers with the
  327. * `VOLK_BUF_BORROWED` flag, so that they can be safely freed with
  328. * #VOLK_buffer_free() and #VOLK_btriple_free().
  329. *
  330. * @param[in] store Store handle.
  331. *
  332. * @param[in] it Opaque iterator handle obtained with #store_lookup_fn_t.
  333. *
  334. * @param[out] sspo #VOLK_BufferTriple to be populated with three serialized
  335. * terms if found. It may be NULL, in which case it is not populated.
  336. *
  337. * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
  338. * VOLK_Buffer structs, one for each context associated with the matching
  339. * triple. These contexts are the same regardless of the context filter used
  340. * in the lookup. The array is freed with a simple `free()`. This parameter
  341. * is ignored by implementations without the VOLK_STORE_CTX feature.
  342. *
  343. * To iterate over the context array, use this loop:
  344. *
  345. * size_t i = 0;
  346. * while (ctx[i].addr)
  347. * do_something(ctx + (i++));
  348. *
  349. * @return VOLK_OK if results were found; VOLK_END if no (more) results were
  350. * found; VOLK_DB_ERR if a backend error occurred.
  351. */
  352. VOLK_rc
  353. VOLK_store_iter_next (
  354. VOLK_Store *store, void *it, VOLK_BufferTriple *sspo,
  355. VOLK_Buffer **ctx);
  356. /** @brief Free an iterator allocated by a lookup.
  357. *
  358. * @param[in] store Store handle.
  359. *
  360. * @param[in] it Iterator pointer. It will be set to NULL after freeing.
  361. */
  362. void
  363. VOLK_store_iter_free (VOLK_Store *store, void *it);
  364. /** @brief Get iterator active transaction handle.
  365. *
  366. * This function is used to get an active transaction during an iteration loop
  367. * in order to perform an action using the store state within that loop. Some
  368. * stores (e.g. MDB) only support one R/W open transaction per thread, so this
  369. * is also the only way to perform anything else than iterating or committing
  370. * while a loop is open.
  371. *
  372. * @param[in] store Store handle.
  373. *
  374. * @param[in] it Iterator handle to get the transaction from.
  375. *
  376. * @return Transaction handle. DO NOT close this transaction directly.
  377. */
  378. void *
  379. VOLK_store_iter_txn (const VOLK_Store *store, void *it);
  380. /** @brief Delete triples by pattern matching.
  381. *
  382. * @param[in] store The store to be queried.
  383. *
  384. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  385. * This is ignored by non-transactional back ends.
  386. *
  387. * @param[in] ss Serialized s term.
  388. *
  389. * @param[in] sp Serialized p term.
  390. *
  391. * @param[in] so Serialized o term.
  392. *
  393. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  394. * which case search is done in all contexts. Note that triples inserted
  395. * without context are assigned the *default* context for the store.
  396. *
  397. * @param[out] ct If not NULL, this will be populated with the number of
  398. * triples actually deleted.
  399. *
  400. * @return VOLK_OK on success; VOLK_NOACTION if no triples were deleted;
  401. * <0 on error.
  402. *
  403. */
  404. VOLK_rc
  405. VOLK_store_remove_txn (
  406. VOLK_Store *store, void *txn,
  407. const VOLK_Buffer *ss, const VOLK_Buffer *sp, const VOLK_Buffer *so,
  408. const VOLK_Buffer *sc, size_t *ct);
  409. /// Non-transactional version of #VOLK_store_remove_txn().
  410. #define VOLK_store_remove(store, ...) \
  411. VOLK_store_remove_txn (store, NULL, __VA_ARGS__)
  412. /** @brief get index of all graph (context) URIs in a store.
  413. *
  414. * Only applicable to stores with the VOLK_STORE_CTX feature flag.
  415. *
  416. * @param[in] store Store handle.
  417. *
  418. * @param[in] txn Transaction handle. If NULL, a new transaction is opened.
  419. * This is ignored by non-transactional back ends.
  420. *
  421. * @return Set of all context URIs.
  422. */
  423. VOLK_Buffer **
  424. VOLK_store_ctx_list_txn (VOLK_Store *store, void *txn);
  425. /// Non-transactional version of #VOLK_store_ctx_list_txn().
  426. #define VOLK_store_ctx_list(store) \
  427. VOLK_store_ctx_list_txn (store, NULL)
  428. /// @} END store
  429. #endif /* VOLK_STORE_H */