Volksdata 1.0b7
RDF library
Loading...
Searching...
No Matches
store_htable.c
Go to the documentation of this file.
2
3
7typedef bool (*VOLK_key_eq_fn_t)(
8 const VOLK_Key spok[], const VOLK_Key luk[]);
9
10
11typedef struct idx_entry_t {
13 void * data;
14 size_t size;
16
17typedef struct ht_store_t {
18 struct hashmap * keys;
19 struct hashmap * idx;
20} HTStore;
21
22typedef struct ht_iterator_t {
24 size_t cur;
27 int rc;
32
33
37static bool lookup_none_eq_fn (
38 const VOLK_Key spok[], const VOLK_Key luk[])
39{
40 (void) spok;
41 (void) luk;
42 return true;
43}
44
48static bool lookup_sk_eq_fn (
49 const VOLK_Key spok[], const VOLK_Key luk[])
50{ return spok[0] == luk[0]; }
51
55static bool lookup_pk_eq_fn (
56 const VOLK_Key spok[], const VOLK_Key luk[])
57{ return spok[1] == luk[1]; }
58
62static bool lookup_ok_eq_fn (
63 const VOLK_Key spok[], const VOLK_Key luk[])
64{ return spok[2] == luk[2]; }
65
69static bool lookup_spk_eq_fn (
70 const VOLK_Key spok[], const VOLK_Key luk[])
71{ return spok[0] == luk[0] && spok[1] == luk[1]; }
72
76static bool lookup_sok_eq_fn (
77 const VOLK_Key spok[], const VOLK_Key luk[])
78{ return spok[0] == luk[0] && spok[2] == luk[2]; }
79
83static bool lookup_pok_eq_fn (
84 const VOLK_Key spok[], const VOLK_Key luk[])
85{ return spok[1] == luk[1] && spok[2] == luk[2]; }
86
90static bool lookup_spok_eq_fn (
91 const VOLK_Key spok[], const VOLK_Key luk[])
92{ return spok[0] == luk[0] && spok[1] == luk[1] && spok[2] == luk[2]; }
93
94
95/* * * CALLBACKS * * */
96
98 const void *item, uint64_t seed0, uint64_t seed1)
99{
100 (void) seed1;
101
102 return (uint64_t) (VOLK_HASH (item, TRP_KLEN, seed0));
103}
104
105
106int trp_key_cmp_fn (const void *a, const void *b, void *udata)
107{
108 (void) udata;
109
110 return memcmp (a, b, TRP_KLEN);
111}
112
113
117static uint64_t htstore_idx_hash_fn (
118 const void *item, uint64_t seed0, uint64_t seed1)
119{
120 (void) seed0;
121 (void) seed1;
122
123 return ((IndexEntry *) item)->key;
124}
125
126
130static int htstore_idx_cmp_fn (const void *a, const void *b, void *udata)
131{
132 (void) udata;
133
134 return ((const IndexEntry *) a)->key - ((const IndexEntry *) b)->key;
135}
136
137
141static void htstore_idx_free_fn (void *item)
142{ free (((IndexEntry *) item)->data); }
143
144
145/* * * Other prototypes. * * */
146
147inline static VOLK_rc
148tkey_to_strp (
149 const HTStore *store, const VOLK_Key *spok, VOLK_BufferTriple *sspo);
150
151
152static VOLK_rc
153add_key_iter (HTIterator *it, const VOLK_Key *spok);
154
155
160static VOLK_rc
161htiter_next_key (HTIterator *it);
162
163
164/*
165 * Interface members.
166 */
167
178static void *
179htstore_new (const char *id, size_t size)
180{
181 (void) id;
182
183 HTStore *ht;
184 CALLOC_GUARD (ht, NULL);
185
186 ht->idx = hashmap_new (
187 sizeof (IndexEntry), 0, VOLK_HASH_SEED, 0,
188 htstore_idx_hash_fn, htstore_idx_cmp_fn, htstore_idx_free_fn,
189 NULL);
190
191 ht->keys = hashmap_new (
192 sizeof (VOLK_TripleKey), size, VOLK_HASH_SEED, 0,
194 NULL);
195
196 return ht;
197}
198
199
200#if 0
201static VOLK_rc
202htstore_copy_contents (HTStore *dest, const HTStore *src)
203{
204 size_t i = 0;
205 VOLK_TripleKey *spok;
206 IndexEntry *entry;
207 while (hashmap_iter (src->keys, &i, (void **) &spok)) {
208 hashmap_set (dest->keys, spok);
209 if (UNLIKELY (hashmap_oom (dest->keys))) return VOLK_MEM_ERR;
210 }
211 i = 0;
212 while (hashmap_iter (src->idx, &i, (void **) &entry)) {
213 hashmap_set (dest->idx, entry);
214 if (UNLIKELY (hashmap_oom (dest->idx))) return VOLK_MEM_ERR;
215 }
216
217 return VOLK_OK;
218}
219#endif
220
221
222static void
223htstore_free (void *h)
224{
225 HTStore *store = h;
226 hashmap_free (store->idx);
227 hashmap_free (store->keys);
228 free (store);
229}
230
231
232static size_t
233htstore_size (const void *h)
234{
235 const HTStore *store = h;
236 return hashmap_count (store->keys);
237}
238
239
240static VOLK_rc
241htstore_add_term (void *h, const VOLK_Buffer *sterm, void *_unused)
242{
243 (void) _unused;
244 HTStore *store = h;
245 IndexEntry entry_s = {
246 .key = VOLK_buffer_hash (sterm),
247 };
248 if (hashmap_get (store->idx, &entry_s)) return VOLK_NOACTION;
249
250 entry_s.data = malloc (sterm->size);
251 memcpy (entry_s.data, sterm->addr, sterm->size);
252 entry_s.size = sterm->size;
253
254 LOG_TRACE("Adding term key: %lx", entry_s.key);
255 hashmap_set (store->idx, &entry_s);
256 //LOG_TRACE("Term index size: %lu", hashmap_count (store->idx));
257
258 return VOLK_OK;
259}
260
261
262static void *
263htstore_add_init (void *h, const VOLK_Buffer *_unused, void *_unused2)
264{
265 (void) _unused;
266 (void) _unused2;
267 HTIterator *it;
268 MALLOC_GUARD (it, NULL);
269
270 it->store = h;
271
272 return it;
273}
274
275
276static VOLK_rc
277htstore_add_iter (void *h, const VOLK_BufferTriple *sspo)
278{
279 HTIterator *it = h;
280 VOLK_TripleKey spok = {
281 VOLK_buffer_hash (sspo->s),
282 VOLK_buffer_hash (sspo->p),
283 VOLK_buffer_hash (sspo->o),
284 };
285
286 VOLK_rc rc = add_key_iter (it, spok);
287
288 if (rc != VOLK_OK) return rc;
289
290 for (int i = 0; i < 3; i++)
291 htstore_add_term (it->store, VOLK_btriple_pos (sspo, i), NULL);
292
293 return rc;
294}
295
296
297static VOLK_rc
298htstore_add_done (void *h)
299{
300 free (h);
301 return VOLK_OK;
302}
303
304
305static void *
306htstore_lookup (
307 void *h,
308 const VOLK_Buffer *ss, const VOLK_Buffer *sp, const VOLK_Buffer *so,
309 const VOLK_Buffer *_unused, void *_unused2, size_t *ct)
310{
311 (void) _unused;
312 (void) _unused2;
313
314 HTStore *store = h;
315 HTIterator *it;
316 CALLOC_GUARD (it, NULL);
317
318 it->store = store;
319 it->rc = VOLK_END;
320
321 if (ct) *ct = 0;
322 if (hashmap_count (store->keys) == 0) return it;
323
324 it->luk[0] = VOLK_buffer_hash (ss);
325 it->luk[1] = VOLK_buffer_hash (sp);
326 it->luk[2] = VOLK_buffer_hash (so);
327
328 // s p o
329 if (ss && sp && so) {
330 it->eq_fn = lookup_spok_eq_fn;
331
332 } else if (ss) {
333 // s p ?
334 if (sp) {
335 it->eq_fn = lookup_spk_eq_fn;
336
337 // s ? o
338 } else if (so) {
339 it->eq_fn = lookup_sok_eq_fn;
340
341 // s ? ?
342 } else {
343 it->eq_fn = lookup_sk_eq_fn;
344 }
345
346 } else if (sp) {
347 // ? p o
348 if (so) {
349 it->eq_fn = lookup_pok_eq_fn;
350
351 // ? p ?
352 } else it->eq_fn = lookup_pk_eq_fn;
353
354 // ? ? o
355 } else if (so) {
356 it->eq_fn = lookup_ok_eq_fn;
357
358 // ? ? ?
359 } else it->eq_fn = lookup_none_eq_fn;
360
361 LOG_TRACE("LUK: {%lx, %lx, %lx}", it->luk[0], it->luk[1], it->luk[2]);
362
363 if (ct) {
364 // Loop over results to determine count.
365 while (htiter_next_key (it) == VOLK_OK) (*ct)++;
366
367 // Reposition cursor to the hashtable beginning.
368 it->cur = 0;
369 it->rc = VOLK_OK;
370 }
371
372 return it;
373}
374
375
376static VOLK_rc
377htstore_remove(
378 void *h, const VOLK_Buffer *ss, const VOLK_Buffer *sp,
379 const VOLK_Buffer *so, const VOLK_Buffer *_unused,
380 void *_unused2, size_t *ct_p)
381{
382 (void) _unused;
383 (void) _unused2;
384 HTStore *store = h;
385 size_t ct;
386
387 HTIterator *it = htstore_lookup (store, ss, sp, so, NULL, NULL, &ct);
388 if (UNLIKELY (!it)) return VOLK_DB_ERR;
389
390 VOLK_rc rc;
391 if (ct == 0) {
392 rc = VOLK_NOACTION;
393 goto finally;
394 }
395
396 while (htiter_next_key (it) == VOLK_OK) {
397 LOG_TRACE(
398 "Deleting {%lx, %lx, %lx}.",
399 it->entry[0][0], it->entry[0][1], it->entry[0][2]);
400 hashmap_delete (store->keys, it->entry);
401 rc = VOLK_OK;
402 it->cur = 0; // Reset cursor, buckets are rearranged after deletion.
403 }
404
405finally:
406 free (it);
407 if (ct_p) *ct_p = ct;
408
409 return rc;
410}
411
412
413static VOLK_rc
414htiter_next_key (HTIterator *it)
415{
416 if (UNLIKELY (!it)) return VOLK_VALUE_ERR;
417
418 // This value is for internal looping only. It shall never be returned.
419 it->rc = VOLK_NORESULT;
420
421 do {
422 // Loop through all triples until a match is found, or end is reached.
423 if (hashmap_iter (it->store->keys, &it->cur, (void **) &it->entry)) {
424 //LOG_TRACE("it->cur: %lu", it->cur);
425 if (it->eq_fn (*it->entry, it->luk)) {
426 LOG_TRACE(
427 "Found spok: {%lx, %lx, %lx}",
428 it->entry[0][0], it->entry[0][1], it->entry[0][2]
429 );
430
431 it->rc = VOLK_OK;
432 }
433 }
434 else it->rc = VOLK_END;
435
436 } while (it->rc == VOLK_NORESULT);
437
438 return it->rc;
439}
440
441
442static VOLK_rc
443htiter_next (void *h, VOLK_BufferTriple *sspo, VOLK_Buffer **_unused)
444{
445 (void) _unused;
446 HTIterator *it = h;
447 VOLK_rc rc = htiter_next_key (it);
448 if (rc != VOLK_OK) return rc;
449
450 return tkey_to_strp (it->store, *it->entry, sspo);
451}
452
453
455 .name = "Hashtable Store",
456 .features = VOLK_STORE_COW | VOLK_STORE_EMBED,
457
458 .setup_fn = NULL,
459 .new_fn = htstore_new,
460 .free_fn = htstore_free,
461
462 .size_fn = htstore_size,
463
464 .add_init_fn = htstore_add_init,
465 .add_iter_fn = htstore_add_iter,
466 .add_done_fn = htstore_add_done,
467 .add_term_fn = htstore_add_term,
468
469 .lookup_fn = htstore_lookup,
470 .lu_next_fn = htiter_next,
471 .lu_free_fn = free,
472
473 .remove_fn = htstore_remove,
474};
475
476
477/*
478 * Other statics.
479 */
480
481inline static VOLK_rc
482tkey_to_strp (
483 const HTStore *store, const VOLK_Key *spok, VOLK_BufferTriple *sspo)
484{
485 // Data owned by the store.
486 const IndexEntry *tmp;
487
488 for (int i = 0; i < 3; i++) {
489 tmp = hashmap_get (store->idx, spok + i);
490 if (UNLIKELY (!tmp)) return VOLK_DB_ERR;
491 VOLK_btriple_pos(sspo, i)->addr = tmp->data;
492 VOLK_btriple_pos(sspo, i)->size = tmp->size;
494 }
495
496 return VOLK_OK;
497}
498
499
500static VOLK_rc
501add_key_iter (HTIterator *it, const VOLK_Key *spok)
502{
503 // Add triple.
504 LOG_TRACE("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
505
506 if (hashmap_get (it->store->keys, spok)) {
507 LOG_TRACE("Triple found. Not adding.");
508 return VOLK_NOACTION;
509 }
510
511 LOG_TRACE("Triple not found, inserting.");
512
513 hashmap_set (it->store->keys, (void *)spok);
514 if (hashmap_oom(it->store->keys)) return VOLK_MEM_ERR;
515
516 return VOLK_OK;
517}
#define UNLIKELY(x)
Definition core.h:39
VOLK_Key VOLK_buffer_hash(const VOLK_Buffer *buf)
Hash a buffer.
Definition buffer.h:175
VOLK_Buffer * VOLK_btriple_pos(const VOLK_BufferTriple *trp, VOLK_TriplePos n)
Get serialized triple by term position.
Definition buffer.h:297
@ VOLK_BUF_BORROWED
Definition buffer.h:28
#define TRP_KLEN
Definition core.h:59
#define VOLK_HASH_SEED
Seed used for all hashing. Compile-time configurable.
Definition core.h:175
#define VOLK_HASH(...)
Default hashing function. Depends on architecture.
Definition core.h:186
#define MALLOC_GUARD(var, rc)
Allocate one pointer with malloc and return rc if it fails.
Definition core.h:375
#define LOG_TRACE(...)
Definition core.h:276
#define CALLOC_GUARD(var, rc)
Allocate one pointer with calloc and return rc if it fails.
Definition core.h:381
size_t VOLK_Key
Term key, i.e., hash of a serialized term.
Definition core.h:230
VOLK_Key VOLK_TripleKey[3]
Array of three VOLK_Key values, representing a triple.
Definition core.h:234
#define VOLK_VALUE_ERR
An invalid input value was provided.
Definition core.h:129
#define VOLK_MEM_ERR
Memory allocation error.
Definition core.h:144
#define VOLK_NORESULT
No result yielded.
Definition core.h:100
#define VOLK_DB_ERR
Low-level database error.
Definition core.h:135
#define VOLK_END
Loop end.
Definition core.h:107
#define VOLK_OK
Generic success return code.
Definition core.h:83
#define VOLK_NOACTION
No action taken.
Definition core.h:93
int VOLK_rc
Definition core.h:79
@ VOLK_STORE_EMBED
@ VOLK_STORE_COW
Copy on write.
bool(* VOLK_key_eq_fn_t)(const VOLK_Key spok[], const VOLK_Key luk[])
Definition store_htable.c:7
const VOLK_StoreInt htstore_int
int trp_key_cmp_fn(const void *a, const void *b, void *udata)
uint64_t trp_key_hash_fn(const void *item, uint64_t seed0, uint64_t seed1)
Simple in-memory triple store back end based on hash tables.
VOLK_TripleKey * entry
Retrieved SPO key.
VOLK_key_eq_fn_t eq_fn
Equality function to test triples.
size_t cur
Internal hash table cursor.
VOLK_Key luk[3]
0รท3 lookup keys.
HTStore * store
Store being iterated.
struct hashmap * keys
Triple keys (set).
struct hashmap * idx
Map of keys to serialized terms.
VOLK_Key key
Serialized term key.
size_t size
Serialized term size.
void * data
Serialized term data.
Triple of byte buffers.
Definition buffer.h:60
VOLK_Buffer * o
Definition buffer.h:63
VOLK_Buffer * s
Definition buffer.h:61
VOLK_Buffer * p
Definition buffer.h:62
General-purpose data buffer.
Definition buffer.h:47
VOLK_BufferFlag flags
Definition buffer.h:50
unsigned char * addr
Definition buffer.h:48
size_t size
Definition buffer.h:49
Store interface.