store.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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] old_c Old context handle.
  168. *
  169. * @param[in] new_c New context handle.
  170. *
  171. * @param[in] udata Implementation-specific context data.
  172. *
  173. * @return LSUP_OK on success; LSUP_NOACTION if no triples were found under the
  174. * given context; <0 on error.
  175. */
  176. LSUP_rc
  177. LSUP_store_update_ctx_txn (
  178. LSUP_Store *store, void *txn, const LSUP_Buffer *old_c,
  179. const LSUP_Buffer *new_c);
  180. #define LSUP_store_update_ctx(store, ...) \
  181. LSUP_store_update_txn (store, NULL, __VA_ARGS__)
  182. /** @brief Initialize bulk triple load.
  183. *
  184. * This is the first step of a bulk load. It is best used when the data at hand
  185. * need to be pre-processed, which can be done in the same loop as the next
  186. * step to keep memory usage low.
  187. *
  188. * @param[in] store The store to add to.
  189. *
  190. * @param[in] sc Context as a serialized term. If this is NULL, and the
  191. * default context is not NULL, triples will be added to the default context
  192. * for the store, If the default context for the store is NULL, regardless of
  193. * the value of sc, triples will be added with no context. Only meaningful
  194. * for stores with the LSUP_STORE_CTX feature.
  195. *
  196. * @param[in] udata User data. Consult individual store implementations for
  197. * how this is interpreted.
  198. *
  199. * @return Iterator handle to be passed to the following load steps.
  200. */
  201. void *
  202. LSUP_store_add_init_txn (
  203. LSUP_Store *store, void *txn, const LSUP_Buffer *sc);
  204. /// Non-transactional version of #LSUP_store_add_init_txn().
  205. #define LSUP_store_add_init(store, ...) \
  206. LSUP_store_add_init_txn (store, NULL, __VA_ARGS__)
  207. /** @brief Add one triple into the store.
  208. *
  209. * This must be called after #store_add_init_fn_t, using the iterator
  210. * yielded by that function. It may be called multiple times and must be
  211. * followed by #store_add_done_fn_t or #store_add_abort_fn_t (if supported).
  212. *
  213. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  214. * The following members are of interest:
  215. * it->i stores the total number of records inserted.
  216. *
  217. * @param[in] sspo Serialized triple to be added.
  218. *
  219. * @return LSUP_OK if the triple was inserted; LSUP_NOACTION if the triple
  220. * already existed; LSUP_DB_ERR if an MDB error occurred.
  221. */
  222. LSUP_rc
  223. LSUP_store_add_iter (
  224. LSUP_Store *store, void *it, const LSUP_BufferTriple *sspo);
  225. /** @brief Abort an add loop and free iterator.
  226. *
  227. * Usually called on an irrecoverable error from #store_add_iter_fn_t. None of
  228. * the successful inserts in the same loop is retained.
  229. *
  230. * @param[in] store Store handle.
  231. *
  232. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  233. */
  234. void
  235. LSUP_store_add_abort (LSUP_Store *store, void *it);
  236. /** @brief Finalize an add loop and free iterator.
  237. *
  238. * This must be called after #store_add_iter_fn_t.
  239. *
  240. * @param[in] store Store handle.
  241. *
  242. * @param[in] it Iterator obtained by #store_add_init_fn_t.
  243. */
  244. LSUP_rc
  245. LSUP_store_add_done (LSUP_Store *store, void *it);
  246. /** @brief Add a single term to the store.
  247. *
  248. * @param[in] store Store handle.
  249. *
  250. * @param[in] sterm Serialized term to store.
  251. *
  252. * @param[in] udata Implementation-defined data. See individual
  253. * implementations' documentation.
  254. */
  255. LSUP_rc
  256. LSUP_store_add_term_txn (LSUP_Store *store, void *txn, LSUP_Buffer *sterm);
  257. /// Non-transactional version of #LSUP_store_add_term_txn().
  258. #define LSUP_store_add_term(store, ...) \
  259. LSUP_store_add_term_txn (store, NULL, __VA_ARGS__)
  260. /** @brief Look up triples by pattern matching.
  261. *
  262. * This function may return a count of matches and/or an iterator of results as
  263. * serialized triples.
  264. *
  265. * For stores with #LSUP_STORE_TXN, this opens a read-only transaction. The
  266. * transaction handle is held in the iterator structure and is closed when the
  267. * iterator is freed with #iter_free_fn_t().
  268. *
  269. * Any and all of the terms may be NULL, which indicates an unbound query
  270. * term. Stores witout context support will always ignore sc.
  271. *
  272. * @param[in] store The store to be queried.
  273. *
  274. * @param[in] ss Serialized s term.
  275. *
  276. * @param[in] sp Serialized p term.
  277. *
  278. * @param[in] so Serialized o term.
  279. *
  280. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  281. * which case search is done in all contexts. Note that triples inserted
  282. * without context are assigned the *default* context for the store.
  283. *
  284. * @param[in] udata User data. Consult individual store implementations for
  285. * how this is interpreted.
  286. *
  287. * @param[out] ct If not NULL, this will be populated with the number of
  288. * entries found. In some implementations, it is very inexpensive to set for
  289. * lookups without context, much less so for 1-bound and 2-bound context
  290. * lookups, in which cases it should be set only if needed.
  291. *
  292. * @return Iterator handle that will be populated with a result iterator. This
  293. * is always created even if no matches are found and must be freed with
  294. * #iter_free_fn_t() after use. If matches are found, the iterator points to
  295. * the first result which can be retrieved with #iter_next_fn_t.
  296. */
  297. void *
  298. LSUP_store_lookup_txn (
  299. const LSUP_Store *store, void *txn,
  300. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  301. const LSUP_Buffer *sc, size_t *ct);
  302. /// Non-transactional version of #LSUP_store_lookup_txn().
  303. #define LSUP_store_lookup(store, ...) \
  304. LSUP_store_lookup_txn (store, NULL, __VA_ARGS__)
  305. /** @brief Yield the matching triples and advance the iterator.
  306. *
  307. * @note Iterators keep transactions open. Don't hold on to them longer than
  308. * necessary.
  309. *
  310. * @note If the store interface has the LSUP_STORE_COW feature, the memory
  311. * buffer referenced by the #LSUP_Buffer handle is owned by the database. It
  312. * must not be written to or freed. To modify the data or use them beyond the
  313. * caller's scope, this memory must be copied. Note that the #LSUP_Buffer
  314. * handle must still be freed (with a plain `free()`), but not the underlying
  315. * data buffer, since only the latter is owned by the back end. Implementations
  316. * with the `LSUP_STORE_COW` feature SHOULD create buffers with the
  317. * `LSUP_BUF_BORROWED` flag, so that they can be safely freed with
  318. * #LSUP_buffer_free() and #LSUP_btriple_free().
  319. *
  320. * @param[in] it Opaque iterator handle obtained with #store_lookup_fn_t.
  321. *
  322. * @param[out] sspo #LSUP_BufferTriple to be populated with three serialized
  323. * terms if found. It may be NULL, in which case it is not populated.
  324. *
  325. * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
  326. * LSUP_Buffer structs, one for each context associated with the matching
  327. * triple. These contexts are the same regardless of the context filter used
  328. * in the lookup. The array is freed with a simple `free()`. This parameter
  329. * is ignored by implementations without the LSUP_STORE_CTX feature.
  330. *
  331. * To iterate over the context array, use this loop:
  332. *
  333. * size_t i = 0;
  334. * while (ctx[i].addr)
  335. * do_something(ctx + (i++));
  336. *
  337. * @return LSUP_OK if results were found; LSUP_END if no (more) results were
  338. * found; LSUP_DB_ERR if a backend error occurred.
  339. */
  340. LSUP_rc
  341. LSUP_store_iter_next (
  342. LSUP_Store *store, void *it, LSUP_BufferTriple *sspo,
  343. LSUP_Buffer **ctx);
  344. /** @brief Free an iterator allocated by a lookup.
  345. *
  346. * @param[in] it Iterator pointer. It will be set to NULL after freeing.
  347. */
  348. void
  349. LSUP_store_iter_free (LSUP_Store *store, void *it);
  350. /** @brief Get iterator active transaction handle.
  351. *
  352. * This function is used to get an active transaction during an iteration loop
  353. * in order to perform an action using the store state within that loop. Some
  354. * stores (e.g. MDB) only support one R/W open transaction per thread, so this
  355. * is also the only way to perform anything else than iterating or committing
  356. * while a loop is open.
  357. *
  358. * @param[in] it Iterator handle to get the transaction from.
  359. *
  360. * @return Transaction handle. DO NOT close this transaction directly.
  361. */
  362. void *
  363. LSUP_store_iter_txn (const LSUP_Store *store, void *it);
  364. /** @brief Delete triples by pattern matching.
  365. *
  366. * The ss, sp, so, sc terms act as a matching pattern as documented in
  367. * @sa #store_lookup_fn_t(). if not NULL, ct yields the number of triples
  368. * actually deleted.
  369. *
  370. * @param[in] udata User data. Consult individual store implementations for
  371. * how this is interpreted.
  372. */
  373. LSUP_rc
  374. LSUP_store_remove_txn (
  375. LSUP_Store *store, void *txn,
  376. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  377. const LSUP_Buffer *sc, size_t *ct);
  378. /// Non-transactional version of #LSUP_store_remove_txn().
  379. #define LSUP_store_remove(store, ...) \
  380. LSUP_store_remove_txn (store, NULL, __VA_ARGS__)
  381. /** @brief get index of all graph (context) URIs in a store.
  382. *
  383. * Only applicable to stores with the LSUP_STORE_CTX feature flag.
  384. *
  385. * @param[in] store Store handle.
  386. *
  387. * @return Set of all context URIs.
  388. */
  389. LSUP_Buffer **
  390. LSUP_store_ctx_list_txn (LSUP_Store *store, void *txn);
  391. /// Non-transactional version of #LSUP_store_ctx_list_txn().
  392. #define LSUP_store_ctx_list(store) \
  393. LSUP_store_ctx_list_txn (store, NULL)
  394. /// @} END store
  395. #endif /* LSUP_STORE_H */