]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/hashmap.c
shared: add random-util.[ch]
[thirdparty/systemd.git] / src / shared / hashmap.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2014 Michal Schmidt
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <stdlib.h>
24 #include <errno.h>
25
26 #include "util.h"
27 #include "hashmap.h"
28 #include "set.h"
29 #include "macro.h"
30 #include "siphash24.h"
31 #include "strv.h"
32 #include "mempool.h"
33 #include "random-util.h"
34
35 #ifdef ENABLE_DEBUG_HASHMAP
36 #include "list.h"
37 #endif
38
39 /*
40 * Implementation of hashmaps.
41 * Addressing: open
42 * - uses less RAM compared to closed addressing (chaining), because
43 * our entries are small (especially in Sets, which tend to contain
44 * the majority of entries in systemd).
45 * Collision resolution: Robin Hood
46 * - tends to equalize displacement of entries from their optimal buckets.
47 * Probe sequence: linear
48 * - though theoretically worse than random probing/uniform hashing/double
49 * hashing, it is good for cache locality.
50 *
51 * References:
52 * Celis, P. 1986. Robin Hood Hashing.
53 * Ph.D. Dissertation. University of Waterloo, Waterloo, Ont., Canada, Canada.
54 * https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf
55 * - The results are derived for random probing. Suggests deletion with
56 * tombstones and two mean-centered search methods. None of that works
57 * well for linear probing.
58 *
59 * Janson, S. 2005. Individual displacements for linear probing hashing with different insertion policies.
60 * ACM Trans. Algorithms 1, 2 (October 2005), 177-213.
61 * DOI=10.1145/1103963.1103964 http://doi.acm.org/10.1145/1103963.1103964
62 * http://www.math.uu.se/~svante/papers/sj157.pdf
63 * - Applies to Robin Hood with linear probing. Contains remarks on
64 * the unsuitability of mean-centered search with linear probing.
65 *
66 * Viola, A. 2005. Exact distribution of individual displacements in linear probing hashing.
67 * ACM Trans. Algorithms 1, 2 (October 2005), 214-242.
68 * DOI=10.1145/1103963.1103965 http://doi.acm.org/10.1145/1103963.1103965
69 * - Similar to Janson. Note that Viola writes about C_{m,n} (number of probes
70 * in a successful search), and Janson writes about displacement. C = d + 1.
71 *
72 * Goossaert, E. 2013. Robin Hood hashing: backward shift deletion.
73 * http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/
74 * - Explanation of backward shift deletion with pictures.
75 *
76 * Khuong, P. 2013. The Other Robin Hood Hashing.
77 * http://www.pvk.ca/Blog/2013/11/26/the-other-robin-hood-hashing/
78 * - Short summary of random vs. linear probing, and tombstones vs. backward shift.
79 */
80
81 /*
82 * XXX Ideas for improvement:
83 * For unordered hashmaps, randomize iteration order, similarly to Perl:
84 * http://blog.booking.com/hardening-perls-hash-function.html
85 */
86
87 /* INV_KEEP_FREE = 1 / (1 - max_load_factor)
88 * e.g. 1 / (1 - 0.8) = 5 ... keep one fifth of the buckets free. */
89 #define INV_KEEP_FREE 5U
90
91 /* Fields common to entries of all hashmap/set types */
92 struct hashmap_base_entry {
93 const void *key;
94 };
95
96 /* Entry types for specific hashmap/set types
97 * hashmap_base_entry must be at the beginning of each entry struct. */
98
99 struct plain_hashmap_entry {
100 struct hashmap_base_entry b;
101 void *value;
102 };
103
104 struct ordered_hashmap_entry {
105 struct plain_hashmap_entry p;
106 unsigned iterate_next, iterate_previous;
107 };
108
109 struct set_entry {
110 struct hashmap_base_entry b;
111 };
112
113 /* In several functions it is advantageous to have the hash table extended
114 * virtually by a couple of additional buckets. We reserve special index values
115 * for these "swap" buckets. */
116 #define _IDX_SWAP_BEGIN (UINT_MAX - 3)
117 #define IDX_PUT (_IDX_SWAP_BEGIN + 0)
118 #define IDX_TMP (_IDX_SWAP_BEGIN + 1)
119 #define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2)
120
121 #define IDX_FIRST (UINT_MAX - 1) /* special index for freshly initialized iterators */
122 #define IDX_NIL UINT_MAX /* special index value meaning "none" or "end" */
123
124 assert_cc(IDX_FIRST == _IDX_SWAP_END);
125 assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST);
126
127 /* Storage space for the "swap" buckets.
128 * All entry types can fit into a ordered_hashmap_entry. */
129 struct swap_entries {
130 struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN];
131 };
132
133 /* Distance from Initial Bucket */
134 typedef uint8_t dib_raw_t;
135 #define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
136 #define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
137 #define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */
138 #define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */
139
140 #define DIB_FREE UINT_MAX
141
142 #ifdef ENABLE_DEBUG_HASHMAP
143 struct hashmap_debug_info {
144 LIST_FIELDS(struct hashmap_debug_info, debug_list);
145 unsigned max_entries; /* high watermark of n_entries */
146
147 /* who allocated this hashmap */
148 int line;
149 const char *file;
150 const char *func;
151
152 /* fields to detect modification while iterating */
153 unsigned put_count; /* counts puts into the hashmap */
154 unsigned rem_count; /* counts removals from hashmap */
155 unsigned last_rem_idx; /* remembers last removal index */
156 };
157
158 /* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */
159 static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
160
161 #define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug;
162
163 #else /* !ENABLE_DEBUG_HASHMAP */
164 #define HASHMAP_DEBUG_FIELDS
165 #endif /* ENABLE_DEBUG_HASHMAP */
166
167 enum HashmapType {
168 HASHMAP_TYPE_PLAIN,
169 HASHMAP_TYPE_ORDERED,
170 HASHMAP_TYPE_SET,
171 _HASHMAP_TYPE_MAX
172 };
173
174 struct _packed_ indirect_storage {
175 char *storage; /* where buckets and DIBs are stored */
176 uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
177
178 unsigned n_entries; /* number of stored entries */
179 unsigned n_buckets; /* number of buckets */
180
181 unsigned idx_lowest_entry; /* Index below which all buckets are free.
182 Makes "while(hashmap_steal_first())" loops
183 O(n) instead of O(n^2) for unordered hashmaps. */
184 uint8_t _pad[3]; /* padding for the whole HashmapBase */
185 /* The bitfields in HashmapBase complete the alignment of the whole thing. */
186 };
187
188 struct direct_storage {
189 /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
190 * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
191 * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
192 char storage[sizeof(struct indirect_storage)];
193 };
194
195 #define DIRECT_BUCKETS(entry_t) \
196 (sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t)))
197
198 /* We should be able to store at least one entry directly. */
199 assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1);
200
201 /* We have 3 bits for n_direct_entries. */
202 assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
203
204 /* Hashmaps with directly stored entries all use this shared hash key.
205 * It's no big deal if the key is guessed, because there can be only
206 * a handful of directly stored entries in a hashmap. When a hashmap
207 * outgrows direct storage, it gets its own key for indirect storage. */
208 static uint8_t shared_hash_key[HASH_KEY_SIZE];
209 static bool shared_hash_key_initialized;
210
211 /* Fields that all hashmap/set types must have */
212 struct HashmapBase {
213 const struct hash_ops *hash_ops; /* hash and compare ops to use */
214
215 union _packed_ {
216 struct indirect_storage indirect; /* if has_indirect */
217 struct direct_storage direct; /* if !has_indirect */
218 };
219
220 enum HashmapType type:2; /* HASHMAP_TYPE_* */
221 bool has_indirect:1; /* whether indirect storage is used */
222 unsigned n_direct_entries:3; /* Number of entries in direct storage.
223 * Only valid if !has_indirect. */
224 bool from_pool:1; /* whether was allocated from mempool */
225 HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
226 };
227
228 /* Specific hash types
229 * HashmapBase must be at the beginning of each hashmap struct. */
230
231 struct Hashmap {
232 struct HashmapBase b;
233 };
234
235 struct OrderedHashmap {
236 struct HashmapBase b;
237 unsigned iterate_list_head, iterate_list_tail;
238 };
239
240 struct Set {
241 struct HashmapBase b;
242 };
243
244 DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8);
245 DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8);
246 /* No need for a separate Set pool */
247 assert_cc(sizeof(Hashmap) == sizeof(Set));
248
249 struct hashmap_type_info {
250 size_t head_size;
251 size_t entry_size;
252 struct mempool *mempool;
253 unsigned n_direct_buckets;
254 };
255
256 static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
257 [HASHMAP_TYPE_PLAIN] = {
258 .head_size = sizeof(Hashmap),
259 .entry_size = sizeof(struct plain_hashmap_entry),
260 .mempool = &hashmap_pool,
261 .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry),
262 },
263 [HASHMAP_TYPE_ORDERED] = {
264 .head_size = sizeof(OrderedHashmap),
265 .entry_size = sizeof(struct ordered_hashmap_entry),
266 .mempool = &ordered_hashmap_pool,
267 .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry),
268 },
269 [HASHMAP_TYPE_SET] = {
270 .head_size = sizeof(Set),
271 .entry_size = sizeof(struct set_entry),
272 .mempool = &hashmap_pool,
273 .n_direct_buckets = DIRECT_BUCKETS(struct set_entry),
274 },
275 };
276
277 unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
278 uint64_t u;
279 siphash24((uint8_t*) &u, p, strlen(p), hash_key);
280 return (unsigned long) u;
281 }
282
283 int string_compare_func(const void *a, const void *b) {
284 return strcmp(a, b);
285 }
286
287 const struct hash_ops string_hash_ops = {
288 .hash = string_hash_func,
289 .compare = string_compare_func
290 };
291
292 unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
293 uint64_t u;
294 siphash24((uint8_t*) &u, &p, sizeof(p), hash_key);
295 return (unsigned long) u;
296 }
297
298 int trivial_compare_func(const void *a, const void *b) {
299 return a < b ? -1 : (a > b ? 1 : 0);
300 }
301
302 const struct hash_ops trivial_hash_ops = {
303 .hash = trivial_hash_func,
304 .compare = trivial_compare_func
305 };
306
307 unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
308 uint64_t u;
309 siphash24((uint8_t*) &u, p, sizeof(uint64_t), hash_key);
310 return (unsigned long) u;
311 }
312
313 int uint64_compare_func(const void *_a, const void *_b) {
314 uint64_t a, b;
315 a = *(const uint64_t*) _a;
316 b = *(const uint64_t*) _b;
317 return a < b ? -1 : (a > b ? 1 : 0);
318 }
319
320 const struct hash_ops uint64_hash_ops = {
321 .hash = uint64_hash_func,
322 .compare = uint64_compare_func
323 };
324
325 #if SIZEOF_DEV_T != 8
326 unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
327 uint64_t u;
328 siphash24((uint8_t*) &u, p, sizeof(dev_t), hash_key);
329 return (unsigned long) u;
330 }
331
332 int devt_compare_func(const void *_a, const void *_b) {
333 dev_t a, b;
334 a = *(const dev_t*) _a;
335 b = *(const dev_t*) _b;
336 return a < b ? -1 : (a > b ? 1 : 0);
337 }
338
339 const struct hash_ops devt_hash_ops = {
340 .hash = devt_hash_func,
341 .compare = devt_compare_func
342 };
343 #endif
344
345 static unsigned n_buckets(HashmapBase *h) {
346 return h->has_indirect ? h->indirect.n_buckets
347 : hashmap_type_info[h->type].n_direct_buckets;
348 }
349
350 static unsigned n_entries(HashmapBase *h) {
351 return h->has_indirect ? h->indirect.n_entries
352 : h->n_direct_entries;
353 }
354
355 static void n_entries_inc(HashmapBase *h) {
356 if (h->has_indirect)
357 h->indirect.n_entries++;
358 else
359 h->n_direct_entries++;
360 }
361
362 static void n_entries_dec(HashmapBase *h) {
363 if (h->has_indirect)
364 h->indirect.n_entries--;
365 else
366 h->n_direct_entries--;
367 }
368
369 static char *storage_ptr(HashmapBase *h) {
370 return h->has_indirect ? h->indirect.storage
371 : h->direct.storage;
372 }
373
374 static uint8_t *hash_key(HashmapBase *h) {
375 return h->has_indirect ? h->indirect.hash_key
376 : shared_hash_key;
377 }
378
379 static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
380 return (unsigned) (h->hash_ops->hash(p, hash_key(h)) % n_buckets(h));
381 }
382 #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
383
384 static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
385 static uint8_t current[HASH_KEY_SIZE];
386 static bool current_initialized = false;
387
388 /* Returns a hash function key to use. In order to keep things
389 * fast we will not generate a new key each time we allocate a
390 * new hash table. Instead, we'll just reuse the most recently
391 * generated one, except if we never generated one or when we
392 * are rehashing an entire hash table because we reached a
393 * fill level */
394
395 if (!current_initialized || !reuse_is_ok) {
396 random_bytes(current, sizeof(current));
397 current_initialized = true;
398 }
399
400 memcpy(hash_key, current, sizeof(current));
401 }
402
403 static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
404 return (struct hashmap_base_entry*)
405 (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
406 }
407
408 static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
409 return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
410 }
411
412 static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) {
413 return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
414 }
415
416 static struct set_entry *set_bucket_at(Set *h, unsigned idx) {
417 return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx);
418 }
419
420 static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) {
421 return &swap->e[idx - _IDX_SWAP_BEGIN];
422 }
423
424 /* Returns a pointer to the bucket at index idx.
425 * Understands real indexes and swap indexes, hence "_virtual". */
426 static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap,
427 unsigned idx) {
428 if (idx < _IDX_SWAP_BEGIN)
429 return bucket_at(h, idx);
430
431 if (idx < _IDX_SWAP_END)
432 return &bucket_at_swap(swap, idx)->p.b;
433
434 assert_not_reached("Invalid index");
435 }
436
437 static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
438 return (dib_raw_t*)
439 (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
440 }
441
442 static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
443 return idx >= from ? idx - from
444 : n_buckets(h) + idx - from;
445 }
446
447 static unsigned bucket_calculate_dib(HashmapBase *h, unsigned idx, dib_raw_t raw_dib) {
448 unsigned initial_bucket;
449
450 if (raw_dib == DIB_RAW_FREE)
451 return DIB_FREE;
452
453 if (_likely_(raw_dib < DIB_RAW_OVERFLOW))
454 return raw_dib;
455
456 /*
457 * Having an overflow DIB value is very unlikely. The hash function
458 * would have to be bad. For example, in a table of size 2^24 filled
459 * to load factor 0.9 the maximum observed DIB is only about 60.
460 * In theory (assuming I used Maxima correctly), for an infinite size
461 * hash table with load factor 0.8 the probability of a given entry
462 * having DIB > 40 is 1.9e-8.
463 * This returns the correct DIB value by recomputing the hash value in
464 * the unlikely case. XXX Hitting this case could be a hint to rehash.
465 */
466 initial_bucket = bucket_hash(h, bucket_at(h, idx)->key);
467 return bucket_distance(h, idx, initial_bucket);
468 }
469
470 static void bucket_set_dib(HashmapBase *h, unsigned idx, unsigned dib) {
471 dib_raw_ptr(h)[idx] = dib != DIB_FREE ? MIN(dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE;
472 }
473
474 static unsigned skip_free_buckets(HashmapBase *h, unsigned idx) {
475 dib_raw_t *dibs;
476
477 dibs = dib_raw_ptr(h);
478
479 for ( ; idx < n_buckets(h); idx++)
480 if (dibs[idx] != DIB_RAW_FREE)
481 return idx;
482
483 return IDX_NIL;
484 }
485
486 static void bucket_mark_free(HashmapBase *h, unsigned idx) {
487 memzero(bucket_at(h, idx), hashmap_type_info[h->type].entry_size);
488 bucket_set_dib(h, idx, DIB_FREE);
489 }
490
491 static void bucket_move_entry(HashmapBase *h, struct swap_entries *swap,
492 unsigned from, unsigned to) {
493 struct hashmap_base_entry *e_from, *e_to;
494
495 assert(from != to);
496
497 e_from = bucket_at_virtual(h, swap, from);
498 e_to = bucket_at_virtual(h, swap, to);
499
500 memcpy(e_to, e_from, hashmap_type_info[h->type].entry_size);
501
502 if (h->type == HASHMAP_TYPE_ORDERED) {
503 OrderedHashmap *lh = (OrderedHashmap*) h;
504 struct ordered_hashmap_entry *le, *le_to;
505
506 le_to = (struct ordered_hashmap_entry*) e_to;
507
508 if (le_to->iterate_next != IDX_NIL) {
509 le = (struct ordered_hashmap_entry*)
510 bucket_at_virtual(h, swap, le_to->iterate_next);
511 le->iterate_previous = to;
512 }
513
514 if (le_to->iterate_previous != IDX_NIL) {
515 le = (struct ordered_hashmap_entry*)
516 bucket_at_virtual(h, swap, le_to->iterate_previous);
517 le->iterate_next = to;
518 }
519
520 if (lh->iterate_list_head == from)
521 lh->iterate_list_head = to;
522 if (lh->iterate_list_tail == from)
523 lh->iterate_list_tail = to;
524 }
525 }
526
527 static unsigned next_idx(HashmapBase *h, unsigned idx) {
528 return (idx + 1U) % n_buckets(h);
529 }
530
531 static unsigned prev_idx(HashmapBase *h, unsigned idx) {
532 return (n_buckets(h) + idx - 1U) % n_buckets(h);
533 }
534
535 static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) {
536 switch (h->type) {
537
538 case HASHMAP_TYPE_PLAIN:
539 case HASHMAP_TYPE_ORDERED:
540 return ((struct plain_hashmap_entry*)e)->value;
541
542 case HASHMAP_TYPE_SET:
543 return (void*) e->key;
544
545 default:
546 assert_not_reached("Unknown hashmap type");
547 }
548 }
549
550 static void base_remove_entry(HashmapBase *h, unsigned idx) {
551 unsigned left, right, prev, dib;
552 dib_raw_t raw_dib, *dibs;
553
554 dibs = dib_raw_ptr(h);
555 assert(dibs[idx] != DIB_RAW_FREE);
556
557 #ifdef ENABLE_DEBUG_HASHMAP
558 h->debug.rem_count++;
559 h->debug.last_rem_idx = idx;
560 #endif
561
562 left = idx;
563 /* Find the stop bucket ("right"). It is either free or has DIB == 0. */
564 for (right = next_idx(h, left); ; right = next_idx(h, right)) {
565 raw_dib = dibs[right];
566 if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
567 break;
568
569 /* The buckets are not supposed to be all occupied and with DIB > 0.
570 * That would mean we could make everyone better off by shifting them
571 * backward. This scenario is impossible. */
572 assert(left != right);
573 }
574
575 if (h->type == HASHMAP_TYPE_ORDERED) {
576 OrderedHashmap *lh = (OrderedHashmap*) h;
577 struct ordered_hashmap_entry *le = ordered_bucket_at(lh, idx);
578
579 if (le->iterate_next != IDX_NIL)
580 ordered_bucket_at(lh, le->iterate_next)->iterate_previous = le->iterate_previous;
581 else
582 lh->iterate_list_tail = le->iterate_previous;
583
584 if (le->iterate_previous != IDX_NIL)
585 ordered_bucket_at(lh, le->iterate_previous)->iterate_next = le->iterate_next;
586 else
587 lh->iterate_list_head = le->iterate_next;
588 }
589
590 /* Now shift all buckets in the interval (left, right) one step backwards */
591 for (prev = left, left = next_idx(h, left); left != right;
592 prev = left, left = next_idx(h, left)) {
593 dib = bucket_calculate_dib(h, left, dibs[left]);
594 assert(dib != 0);
595 bucket_move_entry(h, NULL, left, prev);
596 bucket_set_dib(h, prev, dib - 1);
597 }
598
599 bucket_mark_free(h, prev);
600 n_entries_dec(h);
601 }
602 #define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx)
603
604 static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *i) {
605 struct ordered_hashmap_entry *e;
606 unsigned idx;
607
608 assert(h);
609 assert(i);
610
611 if (i->idx == IDX_NIL)
612 goto at_end;
613
614 if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL)
615 goto at_end;
616
617 if (i->idx == IDX_FIRST) {
618 idx = h->iterate_list_head;
619 e = ordered_bucket_at(h, idx);
620 } else {
621 idx = i->idx;
622 e = ordered_bucket_at(h, idx);
623 /*
624 * We allow removing the current entry while iterating, but removal may cause
625 * a backward shift. The next entry may thus move one bucket to the left.
626 * To detect when it happens, we remember the key pointer of the entry we were
627 * going to iterate next. If it does not match, there was a backward shift.
628 */
629 if (e->p.b.key != i->next_key) {
630 idx = prev_idx(HASHMAP_BASE(h), idx);
631 e = ordered_bucket_at(h, idx);
632 }
633 assert(e->p.b.key == i->next_key);
634 }
635
636 #ifdef ENABLE_DEBUG_HASHMAP
637 i->prev_idx = idx;
638 #endif
639
640 if (e->iterate_next != IDX_NIL) {
641 struct ordered_hashmap_entry *n;
642 i->idx = e->iterate_next;
643 n = ordered_bucket_at(h, i->idx);
644 i->next_key = n->p.b.key;
645 } else
646 i->idx = IDX_NIL;
647
648 return idx;
649
650 at_end:
651 i->idx = IDX_NIL;
652 return IDX_NIL;
653 }
654
655 static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) {
656 unsigned idx;
657
658 assert(h);
659 assert(i);
660
661 if (i->idx == IDX_NIL)
662 goto at_end;
663
664 if (i->idx == IDX_FIRST) {
665 /* fast forward to the first occupied bucket */
666 if (h->has_indirect) {
667 i->idx = skip_free_buckets(h, h->indirect.idx_lowest_entry);
668 h->indirect.idx_lowest_entry = i->idx;
669 } else
670 i->idx = skip_free_buckets(h, 0);
671
672 if (i->idx == IDX_NIL)
673 goto at_end;
674 } else {
675 struct hashmap_base_entry *e;
676
677 assert(i->idx > 0);
678
679 e = bucket_at(h, i->idx);
680 /*
681 * We allow removing the current entry while iterating, but removal may cause
682 * a backward shift. The next entry may thus move one bucket to the left.
683 * To detect when it happens, we remember the key pointer of the entry we were
684 * going to iterate next. If it does not match, there was a backward shift.
685 */
686 if (e->key != i->next_key)
687 e = bucket_at(h, --i->idx);
688
689 assert(e->key == i->next_key);
690 }
691
692 idx = i->idx;
693 #ifdef ENABLE_DEBUG_HASHMAP
694 i->prev_idx = idx;
695 #endif
696
697 i->idx = skip_free_buckets(h, i->idx + 1);
698 if (i->idx != IDX_NIL)
699 i->next_key = bucket_at(h, i->idx)->key;
700 else
701 i->idx = IDX_NIL;
702
703 return idx;
704
705 at_end:
706 i->idx = IDX_NIL;
707 return IDX_NIL;
708 }
709
710 static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
711 if (!h) {
712 i->idx = IDX_NIL;
713 return IDX_NIL;
714 }
715
716 #ifdef ENABLE_DEBUG_HASHMAP
717 if (i->idx == IDX_FIRST) {
718 i->put_count = h->debug.put_count;
719 i->rem_count = h->debug.rem_count;
720 } else {
721 /* While iterating, must not add any new entries */
722 assert(i->put_count == h->debug.put_count);
723 /* ... or remove entries other than the current one */
724 assert(i->rem_count == h->debug.rem_count ||
725 (i->rem_count == h->debug.rem_count - 1 &&
726 i->prev_idx == h->debug.last_rem_idx));
727 /* Reset our removals counter */
728 i->rem_count = h->debug.rem_count;
729 }
730 #endif
731
732 return h->type == HASHMAP_TYPE_ORDERED ? hashmap_iterate_in_insertion_order((OrderedHashmap*) h, i)
733 : hashmap_iterate_in_internal_order(h, i);
734 }
735
736 void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key) {
737 struct hashmap_base_entry *e;
738 void *data;
739 unsigned idx;
740
741 idx = hashmap_iterate_entry(h, i);
742 if (idx == IDX_NIL) {
743 if (key)
744 *key = NULL;
745
746 return NULL;
747 }
748
749 e = bucket_at(h, idx);
750 data = entry_value(h, e);
751 if (key)
752 *key = e->key;
753
754 return data;
755 }
756
757 void *set_iterate(Set *s, Iterator *i) {
758 return internal_hashmap_iterate(HASHMAP_BASE(s), i, NULL);
759 }
760
761 #define HASHMAP_FOREACH_IDX(idx, h, i) \
762 for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \
763 (idx != IDX_NIL); \
764 (idx) = hashmap_iterate_entry((h), &(i)))
765
766 static void reset_direct_storage(HashmapBase *h) {
767 const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
768 void *p;
769
770 assert(!h->has_indirect);
771
772 p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets);
773 memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
774 }
775
776 static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
777 HashmapBase *h;
778 const struct hashmap_type_info *hi = &hashmap_type_info[type];
779 bool use_pool;
780
781 use_pool = is_main_thread();
782
783 h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
784
785 if (!h)
786 return NULL;
787
788 h->type = type;
789 h->from_pool = use_pool;
790 h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
791
792 if (type == HASHMAP_TYPE_ORDERED) {
793 OrderedHashmap *lh = (OrderedHashmap*)h;
794 lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
795 }
796
797 reset_direct_storage(h);
798
799 if (!shared_hash_key_initialized) {
800 random_bytes(shared_hash_key, sizeof(shared_hash_key));
801 shared_hash_key_initialized= true;
802 }
803
804 #ifdef ENABLE_DEBUG_HASHMAP
805 LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug);
806 h->debug.func = func;
807 h->debug.file = file;
808 h->debug.line = line;
809 #endif
810
811 return h;
812 }
813
814 Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
815 return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
816 }
817
818 OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
819 return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
820 }
821
822 Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
823 return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
824 }
825
826 static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
827 enum HashmapType type HASHMAP_DEBUG_PARAMS) {
828 HashmapBase *q;
829
830 assert(h);
831
832 if (*h)
833 return 0;
834
835 q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
836 if (!q)
837 return -ENOMEM;
838
839 *h = q;
840 return 0;
841 }
842
843 int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
844 return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
845 }
846
847 int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
848 return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
849 }
850
851 int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
852 return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
853 }
854
855 static void hashmap_free_no_clear(HashmapBase *h) {
856 assert(!h->has_indirect);
857 assert(!h->n_direct_entries);
858
859 #ifdef ENABLE_DEBUG_HASHMAP
860 LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
861 #endif
862
863 if (h->from_pool)
864 mempool_free_tile(hashmap_type_info[h->type].mempool, h);
865 else
866 free(h);
867 }
868
869 void internal_hashmap_free(HashmapBase *h) {
870
871 /* Free the hashmap, but nothing in it */
872
873 if (!h)
874 return;
875
876 internal_hashmap_clear(h);
877 hashmap_free_no_clear(h);
878 }
879
880 void internal_hashmap_free_free(HashmapBase *h) {
881
882 /* Free the hashmap and all data objects in it, but not the
883 * keys */
884
885 if (!h)
886 return;
887
888 internal_hashmap_clear_free(h);
889 hashmap_free_no_clear(h);
890 }
891
892 void hashmap_free_free_free(Hashmap *h) {
893
894 /* Free the hashmap and all data and key objects in it */
895
896 if (!h)
897 return;
898
899 hashmap_clear_free_free(h);
900 hashmap_free_no_clear(HASHMAP_BASE(h));
901 }
902
903 void internal_hashmap_clear(HashmapBase *h) {
904 if (!h)
905 return;
906
907 if (h->has_indirect) {
908 free(h->indirect.storage);
909 h->has_indirect = false;
910 }
911
912 h->n_direct_entries = 0;
913 reset_direct_storage(h);
914
915 if (h->type == HASHMAP_TYPE_ORDERED) {
916 OrderedHashmap *lh = (OrderedHashmap*) h;
917 lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
918 }
919 }
920
921 void internal_hashmap_clear_free(HashmapBase *h) {
922 unsigned idx;
923
924 if (!h)
925 return;
926
927 for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
928 idx = skip_free_buckets(h, idx + 1))
929 free(entry_value(h, bucket_at(h, idx)));
930
931 internal_hashmap_clear(h);
932 }
933
934 void hashmap_clear_free_free(Hashmap *h) {
935 unsigned idx;
936
937 if (!h)
938 return;
939
940 for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL;
941 idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) {
942 struct plain_hashmap_entry *e = plain_bucket_at(h, idx);
943 free((void*)e->b.key);
944 free(e->value);
945 }
946
947 internal_hashmap_clear(HASHMAP_BASE(h));
948 }
949
950 static int resize_buckets(HashmapBase *h, unsigned entries_add);
951
952 /*
953 * Finds an empty bucket to put an entry into, starting the scan at 'idx'.
954 * Performs Robin Hood swaps as it goes. The entry to put must be placed
955 * by the caller into swap slot IDX_PUT.
956 * If used for in-place resizing, may leave a displaced entry in swap slot
957 * IDX_PUT. Caller must rehash it next.
958 * Returns: true if it left a displaced entry to rehash next in IDX_PUT,
959 * false otherwise.
960 */
961 static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
962 struct swap_entries *swap) {
963 dib_raw_t raw_dib, *dibs;
964 unsigned dib, distance;
965
966 #ifdef ENABLE_DEBUG_HASHMAP
967 h->debug.put_count++;
968 #endif
969
970 dibs = dib_raw_ptr(h);
971
972 for (distance = 0; ; distance++) {
973 raw_dib = dibs[idx];
974 if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
975 if (raw_dib == DIB_RAW_REHASH)
976 bucket_move_entry(h, swap, idx, IDX_TMP);
977
978 if (h->has_indirect && h->indirect.idx_lowest_entry > idx)
979 h->indirect.idx_lowest_entry = idx;
980
981 bucket_set_dib(h, idx, distance);
982 bucket_move_entry(h, swap, IDX_PUT, idx);
983 if (raw_dib == DIB_RAW_REHASH) {
984 bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
985 return true;
986 }
987
988 return false;
989 }
990
991 dib = bucket_calculate_dib(h, idx, raw_dib);
992
993 if (dib < distance) {
994 /* Found a wealthier entry. Go Robin Hood! */
995
996 bucket_set_dib(h, idx, distance);
997
998 /* swap the entries */
999 bucket_move_entry(h, swap, idx, IDX_TMP);
1000 bucket_move_entry(h, swap, IDX_PUT, idx);
1001 bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
1002
1003 distance = dib;
1004 }
1005
1006 idx = next_idx(h, idx);
1007 }
1008 }
1009
1010 /*
1011 * Puts an entry into a hashmap, boldly - no check whether key already exists.
1012 * The caller must place the entry (only its key and value, not link indexes)
1013 * in swap slot IDX_PUT.
1014 * Caller must ensure: the key does not exist yet in the hashmap.
1015 * that resize is not needed if !may_resize.
1016 * Returns: 1 if entry was put successfully.
1017 * -ENOMEM if may_resize==true and resize failed with -ENOMEM.
1018 * Cannot return -ENOMEM if !may_resize.
1019 */
1020 static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
1021 struct swap_entries *swap, bool may_resize) {
1022 struct ordered_hashmap_entry *new_entry;
1023 int r;
1024
1025 assert(idx < n_buckets(h));
1026
1027 new_entry = bucket_at_swap(swap, IDX_PUT);
1028
1029 if (may_resize) {
1030 r = resize_buckets(h, 1);
1031 if (r < 0)
1032 return r;
1033 if (r > 0)
1034 idx = bucket_hash(h, new_entry->p.b.key);
1035 }
1036 assert(n_entries(h) < n_buckets(h));
1037
1038 if (h->type == HASHMAP_TYPE_ORDERED) {
1039 OrderedHashmap *lh = (OrderedHashmap*) h;
1040
1041 new_entry->iterate_next = IDX_NIL;
1042 new_entry->iterate_previous = lh->iterate_list_tail;
1043
1044 if (lh->iterate_list_tail != IDX_NIL) {
1045 struct ordered_hashmap_entry *old_tail;
1046
1047 old_tail = ordered_bucket_at(lh, lh->iterate_list_tail);
1048 assert(old_tail->iterate_next == IDX_NIL);
1049 old_tail->iterate_next = IDX_PUT;
1050 }
1051
1052 lh->iterate_list_tail = IDX_PUT;
1053 if (lh->iterate_list_head == IDX_NIL)
1054 lh->iterate_list_head = IDX_PUT;
1055 }
1056
1057 assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
1058
1059 n_entries_inc(h);
1060 #ifdef ENABLE_DEBUG_HASHMAP
1061 h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
1062 #endif
1063
1064 return 1;
1065 }
1066 #define hashmap_put_boldly(h, idx, swap, may_resize) \
1067 hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize)
1068
1069 /*
1070 * Returns 0 if resize is not needed.
1071 * 1 if successfully resized.
1072 * -ENOMEM on allocation failure.
1073 */
1074 static int resize_buckets(HashmapBase *h, unsigned entries_add) {
1075 struct swap_entries swap;
1076 char *new_storage;
1077 dib_raw_t *old_dibs, *new_dibs;
1078 const struct hashmap_type_info *hi;
1079 unsigned idx, optimal_idx;
1080 unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries;
1081 uint8_t new_shift;
1082 bool rehash_next;
1083
1084 assert(h);
1085
1086 hi = &hashmap_type_info[h->type];
1087 new_n_entries = n_entries(h) + entries_add;
1088
1089 /* overflow? */
1090 if (_unlikely_(new_n_entries < entries_add))
1091 return -ENOMEM;
1092
1093 /* For direct storage we allow 100% load, because it's tiny. */
1094 if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets)
1095 return 0;
1096
1097 /*
1098 * Load factor = n/m = 1 - (1/INV_KEEP_FREE).
1099 * From it follows: m = n + n/(INV_KEEP_FREE - 1)
1100 */
1101 new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1);
1102 /* overflow? */
1103 if (_unlikely_(new_n_buckets < new_n_entries))
1104 return -ENOMEM;
1105
1106 if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t))))
1107 return -ENOMEM;
1108
1109 old_n_buckets = n_buckets(h);
1110
1111 if (_likely_(new_n_buckets <= old_n_buckets))
1112 return 0;
1113
1114 new_shift = log2u_round_up(MAX(
1115 new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)),
1116 2 * sizeof(struct direct_storage)));
1117
1118 /* Realloc storage (buckets and DIB array). */
1119 new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL,
1120 1U << new_shift);
1121 if (!new_storage)
1122 return -ENOMEM;
1123
1124 /* Must upgrade direct to indirect storage. */
1125 if (!h->has_indirect) {
1126 memcpy(new_storage, h->direct.storage,
1127 old_n_buckets * (hi->entry_size + sizeof(dib_raw_t)));
1128 h->indirect.n_entries = h->n_direct_entries;
1129 h->indirect.idx_lowest_entry = 0;
1130 h->n_direct_entries = 0;
1131 }
1132
1133 /* Get a new hash key. If we've just upgraded to indirect storage,
1134 * allow reusing a previously generated key. It's still a different key
1135 * from the shared one that we used for direct storage. */
1136 get_hash_key(h->indirect.hash_key, !h->has_indirect);
1137
1138 h->has_indirect = true;
1139 h->indirect.storage = new_storage;
1140 h->indirect.n_buckets = (1U << new_shift) /
1141 (hi->entry_size + sizeof(dib_raw_t));
1142
1143 old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
1144 new_dibs = dib_raw_ptr(h);
1145
1146 /*
1147 * Move the DIB array to the new place, replacing valid DIB values with
1148 * DIB_RAW_REHASH to indicate all of the used buckets need rehashing.
1149 * Note: Overlap is not possible, because we have at least doubled the
1150 * number of buckets and dib_raw_t is smaller than any entry type.
1151 */
1152 for (idx = 0; idx < old_n_buckets; idx++) {
1153 assert(old_dibs[idx] != DIB_RAW_REHASH);
1154 new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE
1155 : DIB_RAW_REHASH;
1156 }
1157
1158 /* Zero the area of newly added entries (including the old DIB area) */
1159 memzero(bucket_at(h, old_n_buckets),
1160 (n_buckets(h) - old_n_buckets) * hi->entry_size);
1161
1162 /* The upper half of the new DIB array needs initialization */
1163 memset(&new_dibs[old_n_buckets], DIB_RAW_INIT,
1164 (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t));
1165
1166 /* Rehash entries that need it */
1167 n_rehashed = 0;
1168 for (idx = 0; idx < old_n_buckets; idx++) {
1169 if (new_dibs[idx] != DIB_RAW_REHASH)
1170 continue;
1171
1172 optimal_idx = bucket_hash(h, bucket_at(h, idx)->key);
1173
1174 /*
1175 * Not much to do if by luck the entry hashes to its current
1176 * location. Just set its DIB.
1177 */
1178 if (optimal_idx == idx) {
1179 new_dibs[idx] = 0;
1180 n_rehashed++;
1181 continue;
1182 }
1183
1184 new_dibs[idx] = DIB_RAW_FREE;
1185 bucket_move_entry(h, &swap, idx, IDX_PUT);
1186 /* bucket_move_entry does not clear the source */
1187 memzero(bucket_at(h, idx), hi->entry_size);
1188
1189 do {
1190 /*
1191 * Find the new bucket for the current entry. This may make
1192 * another entry homeless and load it into IDX_PUT.
1193 */
1194 rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap);
1195 n_rehashed++;
1196
1197 /* Did the current entry displace another one? */
1198 if (rehash_next)
1199 optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key);
1200 } while (rehash_next);
1201 }
1202
1203 assert(n_rehashed == n_entries(h));
1204
1205 return 1;
1206 }
1207
1208 /*
1209 * Finds an entry with a matching key
1210 * Returns: index of the found entry, or IDX_NIL if not found.
1211 */
1212 static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) {
1213 struct hashmap_base_entry *e;
1214 unsigned dib, distance;
1215 dib_raw_t *dibs = dib_raw_ptr(h);
1216
1217 assert(idx < n_buckets(h));
1218
1219 for (distance = 0; ; distance++) {
1220 if (dibs[idx] == DIB_RAW_FREE)
1221 return IDX_NIL;
1222
1223 dib = bucket_calculate_dib(h, idx, dibs[idx]);
1224
1225 if (dib < distance)
1226 return IDX_NIL;
1227 if (dib == distance) {
1228 e = bucket_at(h, idx);
1229 if (h->hash_ops->compare(e->key, key) == 0)
1230 return idx;
1231 }
1232
1233 idx = next_idx(h, idx);
1234 }
1235 }
1236 #define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key)
1237
1238 int hashmap_put(Hashmap *h, const void *key, void *value) {
1239 struct swap_entries swap;
1240 struct plain_hashmap_entry *e;
1241 unsigned hash, idx;
1242
1243 assert(h);
1244
1245 hash = bucket_hash(h, key);
1246 idx = bucket_scan(h, hash, key);
1247 if (idx != IDX_NIL) {
1248 e = plain_bucket_at(h, idx);
1249 if (e->value == value)
1250 return 0;
1251 return -EEXIST;
1252 }
1253
1254 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1255 e->b.key = key;
1256 e->value = value;
1257 return hashmap_put_boldly(h, hash, &swap, true);
1258 }
1259
1260 int set_put(Set *s, const void *key) {
1261 struct swap_entries swap;
1262 struct hashmap_base_entry *e;
1263 unsigned hash, idx;
1264
1265 assert(s);
1266
1267 hash = bucket_hash(s, key);
1268 idx = bucket_scan(s, hash, key);
1269 if (idx != IDX_NIL)
1270 return 0;
1271
1272 e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1273 e->key = key;
1274 return hashmap_put_boldly(s, hash, &swap, true);
1275 }
1276
1277 int hashmap_replace(Hashmap *h, const void *key, void *value) {
1278 struct swap_entries swap;
1279 struct plain_hashmap_entry *e;
1280 unsigned hash, idx;
1281
1282 assert(h);
1283
1284 hash = bucket_hash(h, key);
1285 idx = bucket_scan(h, hash, key);
1286 if (idx != IDX_NIL) {
1287 e = plain_bucket_at(h, idx);
1288 #ifdef ENABLE_DEBUG_HASHMAP
1289 /* Although the key is equal, the key pointer may have changed,
1290 * and this would break our assumption for iterating. So count
1291 * this operation as incompatible with iteration. */
1292 if (e->b.key != key) {
1293 h->b.debug.put_count++;
1294 h->b.debug.rem_count++;
1295 h->b.debug.last_rem_idx = idx;
1296 }
1297 #endif
1298 e->b.key = key;
1299 e->value = value;
1300 return 0;
1301 }
1302
1303 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1304 e->b.key = key;
1305 e->value = value;
1306 return hashmap_put_boldly(h, hash, &swap, true);
1307 }
1308
1309 int hashmap_update(Hashmap *h, const void *key, void *value) {
1310 struct plain_hashmap_entry *e;
1311 unsigned hash, idx;
1312
1313 assert(h);
1314
1315 hash = bucket_hash(h, key);
1316 idx = bucket_scan(h, hash, key);
1317 if (idx == IDX_NIL)
1318 return -ENOENT;
1319
1320 e = plain_bucket_at(h, idx);
1321 e->value = value;
1322 return 0;
1323 }
1324
1325 void *internal_hashmap_get(HashmapBase *h, const void *key) {
1326 struct hashmap_base_entry *e;
1327 unsigned hash, idx;
1328
1329 if (!h)
1330 return NULL;
1331
1332 hash = bucket_hash(h, key);
1333 idx = bucket_scan(h, hash, key);
1334 if (idx == IDX_NIL)
1335 return NULL;
1336
1337 e = bucket_at(h, idx);
1338 return entry_value(h, e);
1339 }
1340
1341 void *hashmap_get2(Hashmap *h, const void *key, void **key2) {
1342 struct plain_hashmap_entry *e;
1343 unsigned hash, idx;
1344
1345 if (!h)
1346 return NULL;
1347
1348 hash = bucket_hash(h, key);
1349 idx = bucket_scan(h, hash, key);
1350 if (idx == IDX_NIL)
1351 return NULL;
1352
1353 e = plain_bucket_at(h, idx);
1354 if (key2)
1355 *key2 = (void*) e->b.key;
1356
1357 return e->value;
1358 }
1359
1360 bool internal_hashmap_contains(HashmapBase *h, const void *key) {
1361 unsigned hash;
1362
1363 if (!h)
1364 return false;
1365
1366 hash = bucket_hash(h, key);
1367 return bucket_scan(h, hash, key) != IDX_NIL;
1368 }
1369
1370 void *internal_hashmap_remove(HashmapBase *h, const void *key) {
1371 struct hashmap_base_entry *e;
1372 unsigned hash, idx;
1373 void *data;
1374
1375 if (!h)
1376 return NULL;
1377
1378 hash = bucket_hash(h, key);
1379 idx = bucket_scan(h, hash, key);
1380 if (idx == IDX_NIL)
1381 return NULL;
1382
1383 e = bucket_at(h, idx);
1384 data = entry_value(h, e);
1385 remove_entry(h, idx);
1386
1387 return data;
1388 }
1389
1390 void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) {
1391 struct plain_hashmap_entry *e;
1392 unsigned hash, idx;
1393 void *data;
1394
1395 if (!h) {
1396 if (rkey)
1397 *rkey = NULL;
1398 return NULL;
1399 }
1400
1401 hash = bucket_hash(h, key);
1402 idx = bucket_scan(h, hash, key);
1403 if (idx == IDX_NIL) {
1404 if (rkey)
1405 *rkey = NULL;
1406 return NULL;
1407 }
1408
1409 e = plain_bucket_at(h, idx);
1410 data = e->value;
1411 if (rkey)
1412 *rkey = (void*) e->b.key;
1413
1414 remove_entry(h, idx);
1415
1416 return data;
1417 }
1418
1419 int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
1420 struct swap_entries swap;
1421 struct plain_hashmap_entry *e;
1422 unsigned old_hash, new_hash, idx;
1423
1424 if (!h)
1425 return -ENOENT;
1426
1427 old_hash = bucket_hash(h, old_key);
1428 idx = bucket_scan(h, old_hash, old_key);
1429 if (idx == IDX_NIL)
1430 return -ENOENT;
1431
1432 new_hash = bucket_hash(h, new_key);
1433 if (bucket_scan(h, new_hash, new_key) != IDX_NIL)
1434 return -EEXIST;
1435
1436 remove_entry(h, idx);
1437
1438 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1439 e->b.key = new_key;
1440 e->value = value;
1441 assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
1442
1443 return 0;
1444 }
1445
1446 int set_remove_and_put(Set *s, const void *old_key, const void *new_key) {
1447 struct swap_entries swap;
1448 struct hashmap_base_entry *e;
1449 unsigned old_hash, new_hash, idx;
1450
1451 if (!s)
1452 return -ENOENT;
1453
1454 old_hash = bucket_hash(s, old_key);
1455 idx = bucket_scan(s, old_hash, old_key);
1456 if (idx == IDX_NIL)
1457 return -ENOENT;
1458
1459 new_hash = bucket_hash(s, new_key);
1460 if (bucket_scan(s, new_hash, new_key) != IDX_NIL)
1461 return -EEXIST;
1462
1463 remove_entry(s, idx);
1464
1465 e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1466 e->key = new_key;
1467 assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1);
1468
1469 return 0;
1470 }
1471
1472 int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
1473 struct swap_entries swap;
1474 struct plain_hashmap_entry *e;
1475 unsigned old_hash, new_hash, idx_old, idx_new;
1476
1477 if (!h)
1478 return -ENOENT;
1479
1480 old_hash = bucket_hash(h, old_key);
1481 idx_old = bucket_scan(h, old_hash, old_key);
1482 if (idx_old == IDX_NIL)
1483 return -ENOENT;
1484
1485 old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key;
1486
1487 new_hash = bucket_hash(h, new_key);
1488 idx_new = bucket_scan(h, new_hash, new_key);
1489 if (idx_new != IDX_NIL)
1490 if (idx_old != idx_new) {
1491 remove_entry(h, idx_new);
1492 /* Compensate for a possible backward shift. */
1493 if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key)
1494 idx_old = prev_idx(HASHMAP_BASE(h), idx_old);
1495 assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key);
1496 }
1497
1498 remove_entry(h, idx_old);
1499
1500 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1501 e->b.key = new_key;
1502 e->value = value;
1503 assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
1504
1505 return 0;
1506 }
1507
1508 void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
1509 struct plain_hashmap_entry *e;
1510 unsigned hash, idx;
1511
1512 if (!h)
1513 return NULL;
1514
1515 hash = bucket_hash(h, key);
1516 idx = bucket_scan(h, hash, key);
1517 if (idx == IDX_NIL)
1518 return NULL;
1519
1520 e = plain_bucket_at(h, idx);
1521 if (e->value != value)
1522 return NULL;
1523
1524 remove_entry(h, idx);
1525
1526 return value;
1527 }
1528
1529 static unsigned find_first_entry(HashmapBase *h) {
1530 Iterator i = ITERATOR_FIRST;
1531
1532 if (!h || !n_entries(h))
1533 return IDX_NIL;
1534
1535 return hashmap_iterate_entry(h, &i);
1536 }
1537
1538 void *internal_hashmap_first(HashmapBase *h) {
1539 unsigned idx;
1540
1541 idx = find_first_entry(h);
1542 if (idx == IDX_NIL)
1543 return NULL;
1544
1545 return entry_value(h, bucket_at(h, idx));
1546 }
1547
1548 void *internal_hashmap_first_key(HashmapBase *h) {
1549 struct hashmap_base_entry *e;
1550 unsigned idx;
1551
1552 idx = find_first_entry(h);
1553 if (idx == IDX_NIL)
1554 return NULL;
1555
1556 e = bucket_at(h, idx);
1557 return (void*) e->key;
1558 }
1559
1560 void *internal_hashmap_steal_first(HashmapBase *h) {
1561 struct hashmap_base_entry *e;
1562 void *data;
1563 unsigned idx;
1564
1565 idx = find_first_entry(h);
1566 if (idx == IDX_NIL)
1567 return NULL;
1568
1569 e = bucket_at(h, idx);
1570 data = entry_value(h, e);
1571 remove_entry(h, idx);
1572
1573 return data;
1574 }
1575
1576 void *internal_hashmap_steal_first_key(HashmapBase *h) {
1577 struct hashmap_base_entry *e;
1578 void *key;
1579 unsigned idx;
1580
1581 idx = find_first_entry(h);
1582 if (idx == IDX_NIL)
1583 return NULL;
1584
1585 e = bucket_at(h, idx);
1586 key = (void*) e->key;
1587 remove_entry(h, idx);
1588
1589 return key;
1590 }
1591
1592 unsigned internal_hashmap_size(HashmapBase *h) {
1593
1594 if (!h)
1595 return 0;
1596
1597 return n_entries(h);
1598 }
1599
1600 unsigned internal_hashmap_buckets(HashmapBase *h) {
1601
1602 if (!h)
1603 return 0;
1604
1605 return n_buckets(h);
1606 }
1607
1608 int internal_hashmap_merge(Hashmap *h, Hashmap *other) {
1609 Iterator i;
1610 unsigned idx;
1611
1612 assert(h);
1613
1614 HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
1615 struct plain_hashmap_entry *pe = plain_bucket_at(other, idx);
1616 int r;
1617
1618 r = hashmap_put(h, pe->b.key, pe->value);
1619 if (r < 0 && r != -EEXIST)
1620 return r;
1621 }
1622
1623 return 0;
1624 }
1625
1626 int set_merge(Set *s, Set *other) {
1627 Iterator i;
1628 unsigned idx;
1629
1630 assert(s);
1631
1632 HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
1633 struct set_entry *se = set_bucket_at(other, idx);
1634 int r;
1635
1636 r = set_put(s, se->b.key);
1637 if (r < 0)
1638 return r;
1639 }
1640
1641 return 0;
1642 }
1643
1644 int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
1645 int r;
1646
1647 assert(h);
1648
1649 r = resize_buckets(h, entries_add);
1650 if (r < 0)
1651 return r;
1652
1653 return 0;
1654 }
1655
1656 /*
1657 * The same as hashmap_merge(), but every new item from other is moved to h.
1658 * Keys already in h are skipped and stay in other.
1659 * Returns: 0 on success.
1660 * -ENOMEM on alloc failure, in which case no move has been done.
1661 */
1662 int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
1663 struct swap_entries swap;
1664 struct hashmap_base_entry *e, *n;
1665 Iterator i;
1666 unsigned idx;
1667 int r;
1668
1669 assert(h);
1670
1671 if (!other)
1672 return 0;
1673
1674 assert(other->type == h->type);
1675
1676 /*
1677 * This reserves buckets for the worst case, where none of other's
1678 * entries are yet present in h. This is preferable to risking
1679 * an allocation failure in the middle of the moving and having to
1680 * rollback or return a partial result.
1681 */
1682 r = resize_buckets(h, n_entries(other));
1683 if (r < 0)
1684 return r;
1685
1686 HASHMAP_FOREACH_IDX(idx, other, i) {
1687 unsigned h_hash;
1688
1689 e = bucket_at(other, idx);
1690 h_hash = bucket_hash(h, e->key);
1691 if (bucket_scan(h, h_hash, e->key) != IDX_NIL)
1692 continue;
1693
1694 n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1695 n->key = e->key;
1696 if (h->type != HASHMAP_TYPE_SET)
1697 ((struct plain_hashmap_entry*) n)->value =
1698 ((struct plain_hashmap_entry*) e)->value;
1699 assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1);
1700
1701 remove_entry(other, idx);
1702 }
1703
1704 return 0;
1705 }
1706
1707 int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
1708 struct swap_entries swap;
1709 unsigned h_hash, other_hash, idx;
1710 struct hashmap_base_entry *e, *n;
1711 int r;
1712
1713 assert(h);
1714
1715 h_hash = bucket_hash(h, key);
1716 if (bucket_scan(h, h_hash, key) != IDX_NIL)
1717 return -EEXIST;
1718
1719 if (!other)
1720 return -ENOENT;
1721
1722 assert(other->type == h->type);
1723
1724 other_hash = bucket_hash(other, key);
1725 idx = bucket_scan(other, other_hash, key);
1726 if (idx == IDX_NIL)
1727 return -ENOENT;
1728
1729 e = bucket_at(other, idx);
1730
1731 n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1732 n->key = e->key;
1733 if (h->type != HASHMAP_TYPE_SET)
1734 ((struct plain_hashmap_entry*) n)->value =
1735 ((struct plain_hashmap_entry*) e)->value;
1736 r = hashmap_put_boldly(h, h_hash, &swap, true);
1737 if (r < 0)
1738 return r;
1739
1740 remove_entry(other, idx);
1741 return 0;
1742 }
1743
1744 HashmapBase *internal_hashmap_copy(HashmapBase *h) {
1745 HashmapBase *copy;
1746 int r;
1747
1748 assert(h);
1749
1750 copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
1751 if (!copy)
1752 return NULL;
1753
1754 switch (h->type) {
1755 case HASHMAP_TYPE_PLAIN:
1756 case HASHMAP_TYPE_ORDERED:
1757 r = hashmap_merge((Hashmap*)copy, (Hashmap*)h);
1758 break;
1759 case HASHMAP_TYPE_SET:
1760 r = set_merge((Set*)copy, (Set*)h);
1761 break;
1762 default:
1763 assert_not_reached("Unknown hashmap type");
1764 }
1765
1766 if (r < 0) {
1767 internal_hashmap_free(copy);
1768 return NULL;
1769 }
1770
1771 return copy;
1772 }
1773
1774 char **internal_hashmap_get_strv(HashmapBase *h) {
1775 char **sv;
1776 Iterator i;
1777 unsigned idx, n;
1778
1779 sv = new(char*, n_entries(h)+1);
1780 if (!sv)
1781 return NULL;
1782
1783 n = 0;
1784 HASHMAP_FOREACH_IDX(idx, h, i)
1785 sv[n++] = entry_value(h, bucket_at(h, idx));
1786 sv[n] = NULL;
1787
1788 return sv;
1789 }
1790
1791 void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
1792 struct ordered_hashmap_entry *e;
1793 unsigned hash, idx;
1794
1795 assert(key);
1796
1797 if (!h)
1798 return NULL;
1799
1800 hash = bucket_hash(h, key);
1801 idx = bucket_scan(h, hash, key);
1802 if (idx == IDX_NIL)
1803 return NULL;
1804
1805 e = ordered_bucket_at(h, idx);
1806 if (e->iterate_next == IDX_NIL)
1807 return NULL;
1808 return ordered_bucket_at(h, e->iterate_next)->p.value;
1809 }
1810
1811 int set_consume(Set *s, void *value) {
1812 int r;
1813
1814 r = set_put(s, value);
1815 if (r <= 0)
1816 free(value);
1817
1818 return r;
1819 }
1820
1821 int set_put_strdup(Set *s, const char *p) {
1822 char *c;
1823 int r;
1824
1825 assert(s);
1826 assert(p);
1827
1828 c = strdup(p);
1829 if (!c)
1830 return -ENOMEM;
1831
1832 r = set_consume(s, c);
1833 if (r == -EEXIST)
1834 return 0;
1835
1836 return r;
1837 }
1838
1839 int set_put_strdupv(Set *s, char **l) {
1840 int n = 0, r;
1841 char **i;
1842
1843 STRV_FOREACH(i, l) {
1844 r = set_put_strdup(s, *i);
1845 if (r < 0)
1846 return r;
1847
1848 n += r;
1849 }
1850
1851 return n;
1852 }