store_base.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /** @file store.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_BASE_H
  34. #define _LSUP_STORE_BASE_H
  35. #include "environment.h"
  36. /*
  37. * Store feature flags.
  38. *
  39. * NOTE: LSUP_STORE_PERM need only be set by an implementation based on whether
  40. * its path is on a default temporary dir (e.g. LSUP_MDB_RAMDISK_PATH). If this
  41. * flag is not set, it means the data will be cleared before the next execution
  42. * of the program. However, its being set does not guarantee the persistence of
  43. * the medium (i.e. a "permanent" store may have been created ad hoc on a
  44. * tempfs).
  45. */
  46. typedef enum {
  47. LSUP_STORE_PERM = 1<<0, ///< Store is on a permanent support.
  48. LSUP_STORE_CTX = 1<<1, ///< Store supports contexts (quads).
  49. LSUP_STORE_IDX = 1<<2, ///< Store is fully SPO(C)-indexed.
  50. LSUP_STORE_TXN = 1<<3, ///< Supports transaction handling.
  51. LSUP_STORE_COW = 1<<4, ///< Copy on write. @sa #iter_next_fn_t()
  52. //LSUP_STORE_NET = 1<<5, ///< Store is over a network protocol.
  53. } LSUP_StoreFeature;
  54. /*
  55. * Store function types.
  56. */
  57. /** @brief Prototype: create any environment necessary for the store to work.
  58. *
  59. * This function should be idempotent on separate calls to the same `id`,
  60. * unless the `clear` option is set to `true`.
  61. *
  62. * @param[in,out] id Identifier to use for the store. This should be
  63. * a URI that uniquely identifies a back end for the implementation using it,
  64. * e.g. a SQL connection string, file path for an embedded store, the URL of a
  65. * REST API endpoint, etc. It may also be NULL, in which case it will be set to
  66. * the default identifier set by the implementation. It can be retrieved from
  67. * an existing store via #store_id_fn_t .
  68. *
  69. * @param[in] clear Whether to remove an existing environment with the same ID.
  70. */
  71. typedef LSUP_rc (*store_setup_fn_t)(const char *id, bool clear);
  72. /** @brief Prototype: create a new store.
  73. *
  74. * @param[in] id Identifier for the new store. How this is interpreted, and
  75. * whether it is even used, depends on the implementation, which should
  76. * provide documentation on how to pass and interpret this parameter.
  77. *
  78. * @param[in] size Initial size for the store. It may be 0. Only meaningful
  79. * for stores that may preallocate memory, such as #HTStore.
  80. *
  81. * @return New store handle.
  82. */
  83. typedef void * (*store_new_fn_t)(const char *id, size_t size);
  84. /** @brief Prototype: free store handle.
  85. *
  86. * @param[in] store Store handle.
  87. *
  88. */
  89. typedef void (*store_free_fn_t)(void *store);
  90. /** @brief Prototype: get the store ID.
  91. *
  92. * @param store[in] Store handle.
  93. *
  94. * @return store ID string. This is a copy and should be freed after use.
  95. */
  96. typedef char * (*store_id_fn_t)(const void *store);
  97. /** @brief Prototype: get store size.
  98. *
  99. * @param store[in] The store to calculate size of.
  100. *
  101. * @return Number of stored SPO triples (across all contexts if supported).
  102. */
  103. typedef size_t (*store_size_fn_t)(const void *store);
  104. /** @brief Print stats about a store.
  105. *
  106. * TODO
  107. *
  108. * @param store[in] The store to get stats for.
  109. */
  110. /* TODO
  111. typedef LSUP_rc (*store_stat_fn_t)(void *store, void *stat);
  112. */
  113. /** @brief Initialize bulk triple load.
  114. *
  115. * This is the first step of a bulk load. It is best used when the data at hand
  116. * need to be pre-processed, which can be done in the same loop as the next
  117. * step to keep memory usage low.
  118. *
  119. * @param store[in] The store to add to.
  120. *
  121. * @param sc[in] Context as a serialized term. If this is NULL, and the
  122. * default context is not NULL, triples will be added to the default context
  123. * for the store, If the default context for the store is NULL, regardless of
  124. * the value of sc, triples will be added with no context. Only meaningful
  125. * for stores with the LSUP_STORE_CTX feature.
  126. *
  127. * @return Iterator handle to be passed to the following load steps.
  128. */
  129. typedef void * (*store_add_init_fn_t)(void *store, const LSUP_Buffer * sc);
  130. /** @brief Add one triple into the store.
  131. *
  132. * This must be called after #add_init_fn, using the iterator
  133. * yielded by that function. It may be called multiple times and must be
  134. * followed by #add_done_fn or #add_abort_fn (if supported).
  135. *
  136. * @param it[in] Iterator obtained by #LSUP_mdbstore_add_init.
  137. * The following members are of interest:
  138. * it->i stores the total number of records inserted.
  139. *
  140. * @param sspo[in] Serialized triple to be added.
  141. *
  142. * @return LSUP_OK if the triple was inserted; LSUP_NOACTION if the triple
  143. * already existed; LSUP_DB_ERR if an MDB error occurred.
  144. */
  145. typedef LSUP_rc (*store_add_iter_fn_t)(
  146. void *it, const LSUP_BufferTriple * sspo);
  147. /** @brief Abort an add loop and free iterator.
  148. *
  149. * Usually called on an irrecoverable error from #add_iter_fn. None of the
  150. * successful inserts in the same loop is retained.
  151. *
  152. * @param it[in] Iterator obtained by #LSUP_mdbstore_add_init.
  153. */
  154. typedef void (*store_add_abort_fn_t)(void *it);
  155. /** @brief Finalize an add loop and free iterator.
  156. *
  157. * This must be called after #add_iter_fn.
  158. *
  159. * @param it[in] Iterator obtained by #LSUP_mdbstore_add_init.
  160. */
  161. typedef LSUP_rc (*store_add_done_fn_t)(void *it);
  162. /** @brief Add a single term to the store.
  163. *
  164. * @param[in] store Store handle.
  165. *
  166. * @param[in] sterm Serialized term to store.
  167. */
  168. typedef LSUP_rc (*store_add_term_fn_t)(void *store, const LSUP_Buffer *sterm);
  169. /** @brief Prototype: look up triples by pattern matching.
  170. *
  171. * This function may return a count of matches and/or an iterator of results as
  172. * serialized triples.
  173. *
  174. * Any and all of the terms may be NULL, which indicates an unbound query
  175. * term. Stores with context not set or witout context support will always
  176. * ignore the fourth term.
  177. *
  178. * @param[in] store The store to be queried.
  179. *
  180. * @param[in] ss Buffer representing the serialized s term.
  181. *
  182. * @param[in] sp Buffer representing the serialized p term.
  183. *
  184. * @param[in] so Buffer representing the serialized o term.
  185. *
  186. * @param[in] sc Serialized context to limit search to. It may be NULL, in
  187. * which case search is done in all contexts. Note that triples inserted
  188. * without context are assigned the *default* context for the store.
  189. *
  190. * @param[out] ct If not NULL, this will be populated with the number of
  191. * entries found. It is very inexpensive to set for lookups without context,
  192. * much less so for 1-bound and 2-bound context lookups, in which cases it
  193. * should be set only if needed.
  194. *
  195. * @return Iterator handle that will be populated with a result iterator. This
  196. * is always created even if no matches are found and must be freed with
  197. * #LSUP_mdbiter_free() after use. If matches are found, the iterator points to
  198. * the first result which can be retrieved with #iter_next_fn().
  199. */
  200. typedef void * (*store_lookup_fn_t)(
  201. void *store,
  202. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  203. const LSUP_Buffer *sc, size_t *ct);
  204. /** @brief Prototype: check for existence of a triple (T/F).
  205. *
  206. * @param[in] Store to be queried.
  207. *
  208. * @param[in] spo Triple to look up. All members must not be NULL.
  209. *
  210. * @param[in] c Optional context to look into. It may be NULL. It is
  211. * disregarded by stores without the LSUP_STORE_CTX feature.
  212. *
  213. * @return Whether the triple exist in the store (/context).
  214. */
  215. typedef bool (*store_trp_exist_fn_t)(
  216. void *store, const LSUP_BufferTriple *sspo, const LSUP_Buffer *sc);
  217. /** @brief Prototype: delete triples by pattern matching.
  218. *
  219. * The ss, sp, so, sc terms act as a matching pattern as documented in
  220. * #store_lookup_fn. if not NULL, ct yields the number of triples actually
  221. * deleted.
  222. */
  223. typedef LSUP_rc (*store_remove_fn_t)(
  224. void *store,
  225. const LSUP_Buffer *ss, const LSUP_Buffer *sp, const LSUP_Buffer *so,
  226. const LSUP_Buffer *sc, size_t *ct);
  227. /** @brief Put an in-memory namespace map into a permanent back end.
  228. *
  229. * This is only available in stores with the LSUP_STORE_PERM feature.
  230. *
  231. * Existing prefixes and namespaces are not updated. Thus, if the following are
  232. * already stored:
  233. *
  234. * ns1: <urn:ns:a#>
  235. * ns2: <urn:ns:b#>
  236. *
  237. * Neither of the following will be inserted:
  238. *
  239. * ns3: <urn:ns:a#>
  240. * ns2: <urn:ns:c#>
  241. *
  242. * @param[in] store MDB store to update.
  243. *
  244. * @param[out] nsm Namespace map handle to store.
  245. *
  246. * @return LSUP_OK if all terms were updated; LSUP_CONFLICT if one or more
  247. * namespaces or terms were not updated because they already existed; <0 if
  248. * an error occurred.
  249. */
  250. typedef LSUP_rc (*store_nsm_put_fn_t)(void *store, const LSUP_NSMap * nsm);
  251. /** @brief Get the store's namespace prefix map.
  252. *
  253. * @param[in] store MDB store to query.
  254. *
  255. * @return NS map or NULL on error.
  256. */
  257. typedef LSUP_NSMap * (*store_nsm_get_fn_t)(void *store);
  258. /*
  259. * Iterator function types.
  260. */
  261. /** @brief Prototype: yield the matching triples and advance the iterator.
  262. *
  263. * NOTE: Iterators keep transactions open. Don't hold on to them longer than
  264. * necessary.
  265. *
  266. * NOTE: If the store interface has the LSUP_STORE_COW feature, the memory
  267. * buffer referenced by the #LSUP_Buffer handle is owned by the database. It
  268. * must not be written to or freed. To modify the data or use them beyond the
  269. * caller's scope, this memory must be copied. Note that the #LSUP_Buffer
  270. * handle must still be freed (with a plain `free()`), but not the underlying
  271. * data buffer, since only the latter is owned by the back end. For stores
  272. * without the LSUP_STORE_COW, data are copied on retrieval and the resulting
  273. * buffers can be freed with #LSUP_buffer_free() or analogous methods.
  274. *
  275. * @param[in] it Opaque iterator handle obtained with the store's #lookup_fn.
  276. *
  277. * @param[out] sspo #LSUP_BufferTriple to be populated with three serialized
  278. * terms if found. It may be NULL. NOTE: the content of this variable is
  279. * undefined on rc != LSUP_OK.
  280. *
  281. * @param[out] ctx If not NULL, it is populated with a NULL-terminated array of
  282. * LSUP_Buffer structs, one for each context associated with the matching
  283. * triple. These contexts are the same regardless of the context filter used
  284. * in the lookup. The array is freed with a simple #free(). This parameter
  285. * is ignored by implementations without the LSUP_STORE_CTX feature.
  286. *
  287. * To iterate over the context array, use this loop:
  288. *
  289. * size_t i = 0;
  290. * while (ctx[i].addr)
  291. * do_something(ctx + (i++));
  292. *
  293. * @return LSUP_OK if results were found; LSUP_END if no (more) results were
  294. * found; LSUP_DB_ERR if a backend error occurred.
  295. */
  296. typedef LSUP_rc (*iter_next_fn_t)(
  297. void *it, LSUP_BufferTriple *sspo, LSUP_Buffer **ctx);
  298. /** @brief Prototype: free an iterator allocated by a lookup.
  299. *
  300. * @param it[in] Iterator pointer. It will be set to NULL after freeing.
  301. */
  302. typedef void (*iter_free_fn_t)(void * it);
  303. /*
  304. * Iterface type definitions.
  305. */
  306. /** @brief Store interface.
  307. */
  308. typedef struct store_if_t {
  309. // Basic properties.
  310. char name[16]; ///< Store type name.
  311. LSUP_StoreFeature features; ///< Feature flags.
  312. // Allocation, setup and deallocation.
  313. store_setup_fn_t setup_fn; ///< Called before #store_new_fn_t.
  314. store_new_fn_t new_fn; ///< Create a new store instance.
  315. store_free_fn_t free_fn; ///< Free the store.
  316. // Metadata.
  317. store_size_fn_t size_fn; ///< Number of triples in the store.
  318. store_id_fn_t id_fn; ///< Get store ID.
  319. // Addition.
  320. store_add_init_fn_t add_init_fn; ///< Initialize add iteration.
  321. store_add_iter_fn_t add_iter_fn; ///< Add one triple.
  322. store_add_abort_fn_t add_abort_fn; /**< Abort (roll back) the add
  323. * process. Only available in
  324. * stores with #LSUP_STORE_TXN
  325. * feature. Optional.
  326. */
  327. store_add_done_fn_t add_done_fn; ///< Complete the add process.
  328. store_add_term_fn_t add_term_fn; /**< Add (index) a term to the store.
  329. * Only available in stores with
  330. * #LSUP_STORE_IDX feature. Optional.
  331. */
  332. // Look up.
  333. store_lookup_fn_t lookup_fn; ///< Look up triples by pattern. 
  334. //store_trp_exist_fn_t exist_fn; ///< Check if a triple exists.
  335. iter_next_fn_t lu_next_fn; ///< Advance the lookup iterator.
  336. iter_free_fn_t lu_free_fn; ///< Free the lookup iterator.
  337. // Removal.
  338. store_remove_fn_t remove_fn; ///< Remove triples by pattern.
  339. // Namespace prefix mapping.
  340. store_nsm_put_fn_t nsm_put_fn; /**< Add a namespace/prefix pair to
  341. * the prefix map.
  342. * Only available (and mandatory)
  343. * in stores with the
  344. * #LSUP_STORE_IDX feature.
  345. */
  346. store_nsm_get_fn_t nsm_get_fn; /**< Get a namespace/prefix from
  347. * the prefix map.
  348. * Only available (and mandatory)
  349. * in stores with the
  350. * #LSUP_STORE_IDX feature.
  351. */
  352. } LSUP_StoreInt;
  353. /*
  354. * Template for a new store and iterator implementation.
  355. * These should be placed in the .c file where the interface functions are
  356. * defined, and declared as `extern` in the related .h file.
  357. const LSUP_StoreInt my_store_int = {
  358. .name = "My Store", // Truncated to 15 chars.
  359. .features = LSUP_STORE_PERM | LSUP_STORE_IDX,
  360. .setup_fn = my_setup_fn,
  361. .new_fn = my_new_fn,
  362. .free_fn = my_free_fn,
  363. .size_fn = my_size_fn,
  364. .add_init_fn = my_init_fn,
  365. .add_iter_fn = my_iter_fn,
  366. .add_abort_fn = my_add_abort_fn,
  367. .add_done_fn = my_add_done_fn,
  368. .add_term_fn = my_add_term_fn,
  369. .lookup_fn = my_lookup_fn,
  370. .lu_next_fn = my_iter_next_fn,
  371. .lu_free_fn = my_iter_free_fn,
  372. .remove_fn = my_remove_fn,
  373. .nsm_put_fn = my_nsm_put_fn,
  374. .nsm_get_fn = my_nsm_get_fn,
  375. };
  376. */
  377. #endif /* _LSUP_STORE_BASE_H */