github.com/moontrade/nogc@v0.1.7/collections/wormhole/kv.h (about) 1 /* 2 * Copyright (c) 2016--2021 Wu, Xingbo <wuxb45@gmail.com> 3 * 4 * All rights reserved. No warranty, explicit or implicit, provided. 5 */ 6 #pragma once 7 8 #ifdef __cplusplus 9 extern "C" { 10 #endif 11 12 // crc32c {{{ 13 #define KV_CRC32C_SEED ((0xDEADBEEFu)) 14 15 extern u32 16 kv_crc32c(const void * const ptr, u32 len); 17 18 extern u64 19 kv_crc32c_extend(const u32 crc32c); 20 // }}} crc32c 21 22 // kv {{{ 23 24 // struct {{{ 25 /* 26 * Some internal union names can be ignored: 27 * struct kv { 28 * u32 klen; 29 * u32 vlen; 30 * u64 hash; 31 * u8 kv[]; 32 * }; 33 */ 34 struct kv { 35 union { // the first u64 36 u64 kvlen; 37 struct { 38 u32 klen; 39 union { u32 vlen; u32 refcnt; }; 40 }; 41 }; 42 union { 43 u64 hash; // hashvalue of the key 44 u64 priv; // can hide a value here if hash is not used 45 void * privptr; 46 struct { u32 hashlo; u32 hashhi; }; // little endian 47 struct { u32 privlo; u32 privhi; }; 48 }; 49 u8 kv[0]; // len(kv) == klen + vlen 50 } __attribute__((packed)); 51 52 struct kref { 53 u32 len; 54 union { u32 hash32; u32 priv; }; 55 const u8 * ptr; 56 } __attribute__((packed)); 57 58 struct kvref { 59 const u8 * kptr; // read-only 60 const u8 * vptr; // read-only 61 struct kv hdr; // hdr.kv[] is invalid 62 }; 63 // }}} struct 64 65 // kv {{{ 66 typedef int (*kv_kv_cmp_func)(const struct kv *, const struct kv *); 67 68 extern size_t 69 kv_size(const struct kv * const kv); 70 71 extern size_t 72 kv_size_align(const struct kv * const kv, const u64 align); 73 74 extern size_t 75 key_size(const struct kv * const key); 76 77 extern size_t 78 key_size_align(const struct kv * const key, const u64 align); 79 80 extern void 81 kv_update_hash(struct kv * const kv); 82 83 extern void 84 kv_refill_value(struct kv * const kv, const void * const value, const u32 vlen); 85 86 extern void 87 kv_refill(struct kv * const kv, const void * const key, const u32 klen, 88 const void * const value, const u32 vlen); 89 90 extern void 91 kv_refill_str(struct kv * const kv, const char * const key, 92 const void * const value, const u32 vlen); 93 94 extern void 95 kv_refill_str_str(struct kv * const kv, const char * const key, 96 const char * const value); 97 98 // the u64 key is filled in big-endian byte order 99 extern void 100 kv_refill_u64(struct kv * const kv, const u64 key, const void * const value, const u32 vlen); 101 102 extern void 103 kv_refill_hex32(struct kv * const kv, const u32 hex, const void * const value, const u32 vlen); 104 105 extern void 106 kv_refill_hex64(struct kv * const kv, const u64 hex, const void * const value, const u32 vlen); 107 108 extern void 109 kv_refill_hex64_klen(struct kv * const kv, const u64 hex, const u32 klen, 110 const void * const value, const u32 vlen); 111 112 extern void 113 kv_refill_kref(struct kv * const kv, const struct kref * const kref); 114 115 extern void 116 kv_refill_kref_v(struct kv * const kv, const struct kref * const kref, 117 const void * const value, const u32 vlen); 118 119 extern struct kref 120 kv_kref(const struct kv * const key); 121 122 extern struct kv * 123 kv_create(const void * const key, const u32 klen, const void * const value, const u32 vlen); 124 125 extern struct kv * 126 kv_create_str(const char * const key, const void * const value, const u32 vlen); 127 128 extern struct kv * 129 kv_create_str_str(const char * const key, const char * const value); 130 131 extern struct kv * 132 kv_create_kref(const struct kref * const kref, const void * const value, const u32 vlen); 133 134 // a static kv with klen == 0 135 extern const struct kv * 136 kv_null(void); 137 138 extern struct kv * 139 kv_dup(const struct kv * const kv); 140 141 extern struct kv * 142 kv_dup_key(const struct kv * const kv); 143 144 extern struct kv * 145 kv_dup2(const struct kv * const from, struct kv * const to); 146 147 extern struct kv * 148 kv_dup2_key(const struct kv * const from, struct kv * const to); 149 150 extern struct kv * 151 kv_dup2_key_prefix(const struct kv * const from, struct kv * const to, const u32 plen); 152 153 extern bool 154 kv_match(const struct kv * const key1, const struct kv * const key2); 155 156 extern bool 157 kv_match_hash(const struct kv * const key1, const struct kv * const key2); 158 159 extern bool 160 kv_match_full(const struct kv * const kv1, const struct kv * const kv2); 161 162 extern bool 163 kv_match_kv128(const struct kv * const sk, const u8 * const kv128); 164 165 extern int 166 kv_compare(const struct kv * const kv1, const struct kv * const kv2); 167 168 extern int 169 kv_k128_compare(const struct kv * const sk, const u8 * const k128); 170 171 extern int 172 kv_kv128_compare(const struct kv * const sk, const u8 * const kv128); 173 174 extern void 175 kv_qsort(struct kv ** const kvs, const size_t nr); 176 177 extern u32 178 kv_key_lcp(const struct kv * const key1, const struct kv * const key2); 179 180 extern u32 181 kv_key_lcp_skip(const struct kv * const key1, const struct kv * const key2, const u32 lcp0); 182 183 extern void 184 kv_psort(struct kv ** const kvs, const u64 nr, const u64 tlo, const u64 thi); 185 186 extern void * 187 kv_vptr(struct kv * const kv); 188 189 extern void * 190 kv_kptr(struct kv * const kv); 191 192 extern const void * 193 kv_vptr_c(const struct kv * const kv); 194 195 extern const void * 196 kv_kptr_c(const struct kv * const kv); 197 198 extern void 199 kv_print(const struct kv * const kv, const char * const cmd, FILE * const out); 200 // }}} kv 201 202 // mm {{{ 203 typedef struct kv * (* kvmap_mm_in_func)(struct kv * kv, void * priv); 204 typedef struct kv * (* kvmap_mm_out_func)(struct kv * kv, struct kv * out); 205 typedef void (* kvmap_mm_free_func)(struct kv * kv, void * priv); 206 207 // manage internal kv data of kvmap 208 struct kvmap_mm { 209 // to create a private copy of "kv" 210 // see put() functions 211 kvmap_mm_in_func in; 212 // to duplicate a private copy of "kv" to "out" 213 // see get() and iter_peek() functions 214 kvmap_mm_out_func out; 215 // to free a kv 216 // see del() and put() functions 217 kvmap_mm_free_func free; 218 void * priv; 219 }; 220 221 extern struct kv * 222 kvmap_mm_in_noop(struct kv * const kv, void * const priv); 223 224 extern struct kv * 225 kvmap_mm_out_noop(struct kv * const kv, struct kv * const out); 226 227 extern void 228 kvmap_mm_free_noop(struct kv * const kv, void * const priv); 229 230 extern struct kv * 231 kvmap_mm_in_dup(struct kv * const kv, void * const priv); 232 233 extern struct kv * 234 kvmap_mm_out_dup(struct kv * const kv, struct kv * const out); 235 236 extern void 237 kvmap_mm_free_free(struct kv * const kv, void * const priv); 238 239 // the default mm 240 extern const struct kvmap_mm kvmap_mm_dup; // in:Dup, out:Dup, free:Free 241 extern const struct kvmap_mm kvmap_mm_ndf; // in:Noop, out:Dup, free:Free 242 // }}} mm 243 244 // ref {{{ 245 typedef int (*kref_kv_cmp_func)(const struct kref *, const struct kv *); 246 247 // ptr and len only 248 extern void 249 kref_ref_raw(struct kref * const kref, const u8 * const ptr, const u32 len); 250 251 // this calculates hash32 252 extern void 253 kref_ref_hash32(struct kref * const kref, const u8 * const ptr, const u32 len); 254 255 extern void 256 kref_update_hash32(struct kref * const kref); 257 258 extern void 259 kref_ref_kv(struct kref * const kref, const struct kv * const kv); 260 261 extern void 262 kref_ref_kv_hash32(struct kref * const kref, const struct kv * const kv); 263 264 extern bool 265 kref_match(const struct kref * const k1, const struct kref * const k2); 266 267 extern bool 268 kref_kv_match(const struct kref * const kref, const struct kv * const k); 269 270 extern int 271 kref_compare(const struct kref * const kref1, const struct kref * const kref2); 272 273 extern int 274 kref_kv_compare(const struct kref * const kref, const struct kv * const k); 275 276 extern u32 277 kref_lcp(const struct kref * const k1, const struct kref * const k2); 278 279 extern u32 280 kref_kv_lcp(const struct kref * const kref, const struct kv * const kv); 281 282 extern int 283 kref_k128_compare(const struct kref * const sk, const u8 * const k128); 284 285 extern int 286 kref_kv128_compare(const struct kref * const sk, const u8 * const kv128); 287 288 extern const struct kref * 289 kref_null(void); 290 291 extern void 292 kvref_ref_kv(struct kvref * const ref, struct kv * const kv); 293 294 extern struct kv * 295 kvref_dup2_kv(struct kvref * const ref, struct kv * const to); 296 297 extern struct kv * 298 kvref_dup2_key(struct kvref * const ref, struct kv * const to); 299 300 extern int 301 kvref_kv_compare(const struct kvref * const ref, const struct kv * const kv); 302 // }}} ref 303 304 // kv128 {{{ 305 extern size_t 306 kv128_estimate_kv(const struct kv * const kv); 307 308 extern u8 * 309 kv128_encode_kv(const struct kv * const kv, u8 * const out, size_t * const pesize); 310 311 extern struct kv * 312 kv128_decode_kv(const u8 * const ptr, struct kv * const out, size_t * const pesize); 313 314 extern size_t 315 kv128_size(const u8 * const ptr); 316 // }}} kv128 317 318 // }}} kv 319 320 // kvmap {{{ 321 322 // kvmap_api {{{ 323 typedef void (* kv_inp_func)(struct kv * const curr, void * const priv); 324 325 // the merge function should: 326 // 1: return NULL if the origin kv is not changed at all 327 // 2: return kv0 if updates has been applied in-place 328 // 3: return a different kv if the original kv must be replaced 329 // In an in-memory kvmap, 2==1 and no further action is needed 330 // In a persistent kv store with a memtable, 2 will need an insertion if kv0 is not from the memtable 331 typedef struct kv * (* kv_merge_func)(struct kv * const kv0, void * const priv); 332 333 struct kvmap_api { 334 // feature bits 335 bool hashkey; // true: caller needs to provide correct hash in kv/kref 336 bool ordered; // true: has iter_seek 337 bool threadsafe; // true: support thread_safe access 338 bool readonly; // true: no put() and del() 339 bool irefsafe; // true: iter's kref/kvref can be safely accessed after iter_seek/iter_skip/iter_park 340 bool unique; // provide unique keys, especially for iterators 341 bool refpark; // ref has park() and resume() 342 bool async; // XXX for testing KVell 343 344 // put (aka put/upsert): return true on success; false on error 345 // mm.in() controls how things move into the kvmap; the default mm make a copy with malloc() 346 // mm.free() controls how old kv get disposed when replaced 347 bool (* put) (void * const ref, struct kv * const kv); 348 // get: search and return a kv if found, or NULL if not 349 // with the default mm: malloc() if out == NULL; otherwise, use out as buffer 350 // with custom kvmap_mm: mm.out() controls buffer; use with caution 351 // caller should use the returned ptr even if out is provided 352 struct kv * (* get) (void * const ref, const struct kref * const key, struct kv * const out); 353 // probe: return true on found, false on not found 354 bool (* probe) (void * const ref, const struct kref * const key); 355 // del: return true on something deleted, false on not found 356 // mm.free() controls how old kv get disposed when replaced 357 bool (* del) (void * const ref, const struct kref * const key); 358 // inp: inplace operation if key exists; otherwise return false; uf() is always executed even with NULL key 359 // inpr/inpw acquires r/w locks respectively. 360 // Note that in inpw() you can only change the value. 361 bool (* inpr) (void * const ref, const struct kref * const key, kv_inp_func uf, void * const priv); 362 bool (* inpw) (void * const ref, const struct kref * const key, kv_inp_func uf, void * const priv); 363 // merge: put+callback on old/new keys; another name: read-modify-write 364 // return true if successfull; return false on error 365 bool (* merge) (void * const ref, const struct kref * const key, kv_merge_func uf, void * const priv); 366 // delete-range: delete all keys from start (inclusive) to end (exclusive) 367 u64 (* delr) (void * const ref, const struct kref * const start, const struct kref * const end); 368 // make everything persist; for persistent maps only 369 void (* sync) (void * const ref); 370 371 // general guidelines for thread-safe iters: 372 // - it is assumed that the key under the cursor is locked/freezed/immutable 373 // - once created one must call iter_seek to make it valid 374 // - the ownership of ref is given to the iter so ref should not be used until iter_destroy 375 // - creating and use more than one iter based on a ref can cause deadlocks 376 void * (* iter_create) (void * const ref); 377 // move the cursor to the first key >= search-key; 378 void (* iter_seek) (void * const iter, const struct kref * const key); 379 // check if the cursor points to a valid key 380 bool (* iter_valid) (void * const iter); 381 // return the current key; copy to out if (out != NULL) 382 // mm.out() controls copy-out 383 struct kv * (* iter_peek) (void * const iter, struct kv * const out); 384 // similar to peek but does not copy; return false if iter is invalid 385 bool (* iter_kref) (void * const iter, struct kref * const kref); 386 // similar to iter_kref but also provide the value 387 bool (* iter_kvref) (void * const iter, struct kvref * const kvref); 388 // iter_retain makes kref or kvref of the current iter remain valid until released 389 // the returned opaque pointer should be provided when releasing the hold 390 u64 (* iter_retain) (void * const iter); 391 void (* iter_release) (void * const iter, const u64 opaque); 392 // skip one element 393 void (* iter_skip1) (void * const iter); 394 // skip nr elements 395 void (* iter_skip) (void * const iter, const u32 nr); 396 // iter_next == iter_peek + iter_skip1 397 struct kv * (* iter_next) (void * const iter, struct kv * const out); 398 // perform inplace opeation if the current key is valid; return false if no current key 399 // the uf() is always executed even with NULL key 400 bool (* iter_inp) (void * const iter, kv_inp_func uf, void * const priv); 401 // invalidate the iter to release any resources or locks 402 // afterward, must call seek() again before accessing data 403 void (* iter_park) (void * const iter); 404 // destroy iter 405 void (* iter_destroy) (void * const iter); 406 407 // misc: 408 // create refs for maps if required; always use use kvmap_ref() and kvmap_unref() 409 // if there are ref/unref functions, ref-ptr should be used as map for all kv operations 410 void * (* ref) (void * map); 411 // return the original map 412 void * (* unref) (void * ref); 413 // pause access without unref; must call resume later before access index again 414 void (* park) (void * ref); 415 // resume access of ref; must be paired with a park() 416 void (* resume) (void * ref); 417 418 // UNSAFE functions: 419 // empty the map 420 void (* clean) (void * map); 421 // erase everything 422 void (* destroy) (void * map); 423 // for debugging 424 void (* fprint) (void * map, FILE * const out); 425 }; 426 427 // registry 428 struct kvmap_api_reg { 429 int nargs; // number of arguments after name 430 const char * name; 431 const char * args_msg; // see ...helper_message 432 // multiple apis may share one create function 433 // arguments: name (e.g., "rdb"), mm (usually NULL), the remaining args 434 void * (*create)(const char *, const struct kvmap_mm *, char **); 435 const struct kvmap_api * api; 436 }; 437 438 // call this function to register a kvmap_api 439 extern void 440 kvmap_api_register(const int nargs, const char * const name, const char * const args_msg, 441 void * (*create)(const char *, const struct kvmap_mm *, char **), const struct kvmap_api * const api); 442 443 extern void 444 kvmap_api_helper_message(void); 445 446 extern int 447 kvmap_api_helper(int argc, char ** const argv, const struct kvmap_mm * const mm, 448 const struct kvmap_api ** const api_out, void ** const map_out); 449 // }}} kvmap_api 450 451 // helpers {{{ 452 extern void 453 kvmap_inp_steal_kv(struct kv * const kv, void * const priv); 454 455 extern void * 456 kvmap_ref(const struct kvmap_api * const api, void * const map); 457 458 extern void * 459 kvmap_unref(const struct kvmap_api * const api, void * const ref); 460 461 extern struct kv * 462 kvmap_kv_get(const struct kvmap_api * const api, void * const ref, 463 const struct kv * const key, struct kv * const out); 464 465 extern bool 466 kvmap_kv_probe(const struct kvmap_api * const api, void * const ref, 467 const struct kv * const key); 468 469 extern bool 470 kvmap_kv_put(const struct kvmap_api * const api, void * const ref, 471 struct kv * const kv); 472 473 extern bool 474 kvmap_kv_del(const struct kvmap_api * const api, void * const ref, 475 const struct kv * const key); 476 477 extern bool 478 kvmap_kv_inpr(const struct kvmap_api * const api, void * const ref, 479 const struct kv * const key, kv_inp_func uf, void * const priv); 480 481 extern bool 482 kvmap_kv_inpw(const struct kvmap_api * const api, void * const ref, 483 const struct kv * const key, kv_inp_func uf, void * const priv); 484 485 extern bool 486 kvmap_kv_merge(const struct kvmap_api * const api, void * const ref, 487 const struct kv * const key, kv_merge_func uf, void * const priv); 488 489 extern u64 490 kvmap_kv_delr(const struct kvmap_api * const api, void * const ref, 491 const struct kv * const start, const struct kv * const end); 492 493 extern void 494 kvmap_kv_iter_seek(const struct kvmap_api * const api, void * const iter, 495 const struct kv * const key); 496 497 extern struct kv * 498 kvmap_raw_get(const struct kvmap_api * const api, void * const ref, 499 const u32 len, const u8 * const ptr, struct kv * const out); 500 501 extern bool 502 kvmap_raw_probe(const struct kvmap_api * const api, void * const ref, 503 const u32 len, const u8 * const ptr); 504 505 extern bool 506 kvmap_raw_del(const struct kvmap_api * const api, void * const ref, 507 const u32 len, const u8 * const ptr); 508 509 extern bool 510 kvmap_raw_inpr(const struct kvmap_api * const api, void * const ref, 511 const u32 len, const u8 * const ptr, kv_inp_func uf, void * const priv); 512 513 extern bool 514 kvmap_raw_inpw(const struct kvmap_api * const api, void * const ref, 515 const u32 len, const u8 * const ptr, kv_inp_func uf, void * const priv); 516 517 extern void 518 kvmap_raw_iter_seek(const struct kvmap_api * const api, void * const iter, 519 const u32 len, const u8 * const ptr); 520 521 extern u64 522 kvmap_dump_keys(const struct kvmap_api * const api, void * const map, const int fd); 523 // }}} helpers 524 525 // }}} kvmap 526 527 #ifdef __cplusplus 528 } 529 #endif 530 // vim:fdm=marker