]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hashmap.c
Merge pull request #1465 from teg/siphash24
[thirdparty/systemd.git] / src / basic / 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 #include <pthread.h>
26
27 #include "util.h"
28 #include "hashmap.h"
29 #include "set.h"
30 #include "macro.h"
31 #include "siphash24.h"
32 #include "strv.h"
33 #include "mempool.h"
34 #include "random-util.h"
35
36 #ifdef ENABLE_DEBUG_HASHMAP
37 #include "list.h"
38 #endif
39
40 /*
41 * Implementation of hashmaps.
42 * Addressing: open
43 * - uses less RAM compared to closed addressing (chaining), because
44 * our entries are small (especially in Sets, which tend to contain
45 * the majority of entries in systemd).
46 * Collision resolution: Robin Hood
47 * - tends to equalize displacement of entries from their optimal buckets.
48 * Probe sequence: linear
49 * - though theoretically worse than random probing/uniform hashing/double
50 * hashing, it is good for cache locality.
51 *
52 * References:
53 * Celis, P. 1986. Robin Hood Hashing.
54 * Ph.D. Dissertation. University of Waterloo, Waterloo, Ont., Canada, Canada.
55 * https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf
56 * - The results are derived for random probing. Suggests deletion with
57 * tombstones and two mean-centered search methods. None of that works
58 * well for linear probing.
59 *
60 * Janson, S. 2005. Individual displacements for linear probing hashing with different insertion policies.
61 * ACM Trans. Algorithms 1, 2 (October 2005), 177-213.
62 * DOI=10.1145/1103963.1103964 http://doi.acm.org/10.1145/1103963.1103964
63 * http://www.math.uu.se/~svante/papers/sj157.pdf
64 * - Applies to Robin Hood with linear probing. Contains remarks on
65 * the unsuitability of mean-centered search with linear probing.
66 *
67 * Viola, A. 2005. Exact distribution of individual displacements in linear probing hashing.
68 * ACM Trans. Algorithms 1, 2 (October 2005), 214-242.
69 * DOI=10.1145/1103963.1103965 http://doi.acm.org/10.1145/1103963.1103965
70 * - Similar to Janson. Note that Viola writes about C_{m,n} (number of probes
71 * in a successful search), and Janson writes about displacement. C = d + 1.
72 *
73 * Goossaert, E. 2013. Robin Hood hashing: backward shift deletion.
74 * http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/
75 * - Explanation of backward shift deletion with pictures.
76 *
77 * Khuong, P. 2013. The Other Robin Hood Hashing.
78 * http://www.pvk.ca/Blog/2013/11/26/the-other-robin-hood-hashing/
79 * - Short summary of random vs. linear probing, and tombstones vs. backward shift.
80 */
81
82 /*
83 * XXX Ideas for improvement:
84 * For unordered hashmaps, randomize iteration order, similarly to Perl:
85 * http://blog.booking.com/hardening-perls-hash-function.html
86 */
87
88 /* INV_KEEP_FREE = 1 / (1 - max_load_factor)
89 * e.g. 1 / (1 - 0.8) = 5 ... keep one fifth of the buckets free. */
90 #define INV_KEEP_FREE 5U
91
92 /* Fields common to entries of all hashmap/set types */
93 struct hashmap_base_entry {
94 const void *key;
95 };
96
97 /* Entry types for specific hashmap/set types
98 * hashmap_base_entry must be at the beginning of each entry struct. */
99
100 struct plain_hashmap_entry {
101 struct hashmap_base_entry b;
102 void *value;
103 };
104
105 struct ordered_hashmap_entry {
106 struct plain_hashmap_entry p;
107 unsigned iterate_next, iterate_previous;
108 };
109
110 struct set_entry {
111 struct hashmap_base_entry b;
112 };
113
114 /* In several functions it is advantageous to have the hash table extended
115 * virtually by a couple of additional buckets. We reserve special index values
116 * for these "swap" buckets. */
117 #define _IDX_SWAP_BEGIN (UINT_MAX - 3)
118 #define IDX_PUT (_IDX_SWAP_BEGIN + 0)
119 #define IDX_TMP (_IDX_SWAP_BEGIN + 1)
120 #define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2)
121
122 #define IDX_FIRST (UINT_MAX - 1) /* special index for freshly initialized iterators */
123 #define IDX_NIL UINT_MAX /* special index value meaning "none" or "end" */
124
125 assert_cc(IDX_FIRST == _IDX_SWAP_END);
126 assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST);
127
128 /* Storage space for the "swap" buckets.
129 * All entry types can fit into a ordered_hashmap_entry. */
130 struct swap_entries {
131 struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN];
132 };
133
134 /* Distance from Initial Bucket */
135 typedef uint8_t dib_raw_t;
136 #define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
137 #define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
138 #define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */
139 #define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */
140
141 #define DIB_FREE UINT_MAX
142
143 #ifdef ENABLE_DEBUG_HASHMAP
144 struct hashmap_debug_info {
145 LIST_FIELDS(struct hashmap_debug_info, debug_list);
146 unsigned max_entries; /* high watermark of n_entries */
147
148 /* who allocated this hashmap */
149 int line;
150 const char *file;
151 const char *func;
152
153 /* fields to detect modification while iterating */
154 unsigned put_count; /* counts puts into the hashmap */
155 unsigned rem_count; /* counts removals from hashmap */
156 unsigned last_rem_idx; /* remembers last removal index */
157 };
158
159 /* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */
160 static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
161 static pthread_mutex_t hashmap_debug_list_mutex = PTHREAD_MUTEX_INITIALIZER;
162
163 #define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug;
164
165 #else /* !ENABLE_DEBUG_HASHMAP */
166 #define HASHMAP_DEBUG_FIELDS
167 #endif /* ENABLE_DEBUG_HASHMAP */
168
169 enum HashmapType {
170 HASHMAP_TYPE_PLAIN,
171 HASHMAP_TYPE_ORDERED,
172 HASHMAP_TYPE_SET,
173 _HASHMAP_TYPE_MAX
174 };
175
176 struct _packed_ indirect_storage {
177 char *storage; /* where buckets and DIBs are stored */
178 uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
179
180 unsigned n_entries; /* number of stored entries */
181 unsigned n_buckets; /* number of buckets */
182
183 unsigned idx_lowest_entry; /* Index below which all buckets are free.
184 Makes "while(hashmap_steal_first())" loops
185 O(n) instead of O(n^2) for unordered hashmaps. */
186 uint8_t _pad[3]; /* padding for the whole HashmapBase */
187 /* The bitfields in HashmapBase complete the alignment of the whole thing. */
188 };
189
190 struct direct_storage {
191 /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
192 * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
193 * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
194 char storage[sizeof(struct indirect_storage)];
195 };
196
197 #define DIRECT_BUCKETS(entry_t) \
198 (sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t)))
199
200 /* We should be able to store at least one entry directly. */
201 assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1);
202
203 /* We have 3 bits for n_direct_entries. */
204 assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
205
206 /* Hashmaps with directly stored entries all use this shared hash key.
207 * It's no big deal if the key is guessed, because there can be only
208 * a handful of directly stored entries in a hashmap. When a hashmap
209 * outgrows direct storage, it gets its own key for indirect storage. */
210 static uint8_t shared_hash_key[HASH_KEY_SIZE];
211 static bool shared_hash_key_initialized;
212
213 /* Fields that all hashmap/set types must have */
214 struct HashmapBase {
215 const struct hash_ops *hash_ops; /* hash and compare ops to use */
216
217 union _packed_ {
218 struct indirect_storage indirect; /* if has_indirect */
219 struct direct_storage direct; /* if !has_indirect */
220 };
221
222 enum HashmapType type:2; /* HASHMAP_TYPE_* */
223 bool has_indirect:1; /* whether indirect storage is used */
224 unsigned n_direct_entries:3; /* Number of entries in direct storage.
225 * Only valid if !has_indirect. */
226 bool from_pool:1; /* whether was allocated from mempool */
227 HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
228 };
229
230 /* Specific hash types
231 * HashmapBase must be at the beginning of each hashmap struct. */
232
233 struct Hashmap {
234 struct HashmapBase b;
235 };
236
237 struct OrderedHashmap {
238 struct HashmapBase b;
239 unsigned iterate_list_head, iterate_list_tail;
240 };
241
242 struct Set {
243 struct HashmapBase b;
244 };
245
246 DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8);
247 DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8);
248 /* No need for a separate Set pool */
249 assert_cc(sizeof(Hashmap) == sizeof(Set));
250
251 struct hashmap_type_info {
252 size_t head_size;
253 size_t entry_size;
254 struct mempool *mempool;
255 unsigned n_direct_buckets;
256 };
257
258 static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
259 [HASHMAP_TYPE_PLAIN] = {
260 .head_size = sizeof(Hashmap),
261 .entry_size = sizeof(struct plain_hashmap_entry),
262 .mempool = &hashmap_pool,
263 .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry),
264 },
265 [HASHMAP_TYPE_ORDERED] = {
266 .head_size = sizeof(OrderedHashmap),
267 .entry_size = sizeof(struct ordered_hashmap_entry),
268 .mempool = &ordered_hashmap_pool,
269 .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry),
270 },
271 [HASHMAP_TYPE_SET] = {
272 .head_size = sizeof(Set),
273 .entry_size = sizeof(struct set_entry),
274 .mempool = &hashmap_pool,
275 .n_direct_buckets = DIRECT_BUCKETS(struct set_entry),
276 },
277 };
278
279 void string_hash_func(const void *p, struct siphash *state) {
280 siphash24_compress(p, strlen(p) + 1, state);
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 void trivial_hash_func(const void *p, struct siphash *state) {
293 siphash24_compress(&p, sizeof(p), state);
294 }
295
296 int trivial_compare_func(const void *a, const void *b) {
297 return a < b ? -1 : (a > b ? 1 : 0);
298 }
299
300 const struct hash_ops trivial_hash_ops = {
301 .hash = trivial_hash_func,
302 .compare = trivial_compare_func
303 };
304
305 void uint64_hash_func(const void *p, struct siphash *state) {
306 siphash24_compress(p, sizeof(uint64_t), state);
307 }
308
309 int uint64_compare_func(const void *_a, const void *_b) {
310 uint64_t a, b;
311 a = *(const uint64_t*) _a;
312 b = *(const uint64_t*) _b;
313 return a < b ? -1 : (a > b ? 1 : 0);
314 }
315
316 const struct hash_ops uint64_hash_ops = {
317 .hash = uint64_hash_func,
318 .compare = uint64_compare_func
319 };
320
321 #if SIZEOF_DEV_T != 8
322 void devt_hash_func(const void *p, struct siphash *state) {
323 siphash24_compress(p, sizeof(dev_t), state);
324 }
325
326 int devt_compare_func(const void *_a, const void *_b) {
327 dev_t a, b;
328 a = *(const dev_t*) _a;
329 b = *(const dev_t*) _b;
330 return a < b ? -1 : (a > b ? 1 : 0);
331 }
332
333 const struct hash_ops devt_hash_ops = {
334 .hash = devt_hash_func,
335 .compare = devt_compare_func
336 };
337 #endif
338
339 static unsigned n_buckets(HashmapBase *h) {
340 return h->has_indirect ? h->indirect.n_buckets
341 : hashmap_type_info[h->type].n_direct_buckets;
342 }
343
344 static unsigned n_entries(HashmapBase *h) {
345 return h->has_indirect ? h->indirect.n_entries
346 : h->n_direct_entries;
347 }
348
349 static void n_entries_inc(HashmapBase *h) {
350 if (h->has_indirect)
351 h->indirect.n_entries++;
352 else
353 h->n_direct_entries++;
354 }
355
356 static void n_entries_dec(HashmapBase *h) {
357 if (h->has_indirect)
358 h->indirect.n_entries--;
359 else
360 h->n_direct_entries--;
361 }
362
363 static char *storage_ptr(HashmapBase *h) {
364 return h->has_indirect ? h->indirect.storage
365 : h->direct.storage;
366 }
367
368 static uint8_t *hash_key(HashmapBase *h) {
369 return h->has_indirect ? h->indirect.hash_key
370 : shared_hash_key;
371 }
372
373 static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
374 struct siphash state;
375
376 siphash_init(&state, hash_key(h));
377
378 h->hash_ops->hash(p, &state);
379
380 return (unsigned) (siphash24_finalize(&state) % 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 bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, 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 (value)
744 *value = NULL;
745 if (key)
746 *key = NULL;
747
748 return false;
749 }
750
751 e = bucket_at(h, idx);
752 data = entry_value(h, e);
753 if (value)
754 *value = data;
755 if (key)
756 *key = e->key;
757
758 return true;
759 }
760
761 bool set_iterate(Set *s, Iterator *i, void **value) {
762 return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL);
763 }
764
765 #define HASHMAP_FOREACH_IDX(idx, h, i) \
766 for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \
767 (idx != IDX_NIL); \
768 (idx) = hashmap_iterate_entry((h), &(i)))
769
770 static void reset_direct_storage(HashmapBase *h) {
771 const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
772 void *p;
773
774 assert(!h->has_indirect);
775
776 p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets);
777 memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
778 }
779
780 static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
781 HashmapBase *h;
782 const struct hashmap_type_info *hi = &hashmap_type_info[type];
783 bool use_pool;
784
785 use_pool = is_main_thread();
786
787 h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
788
789 if (!h)
790 return NULL;
791
792 h->type = type;
793 h->from_pool = use_pool;
794 h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
795
796 if (type == HASHMAP_TYPE_ORDERED) {
797 OrderedHashmap *lh = (OrderedHashmap*)h;
798 lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
799 }
800
801 reset_direct_storage(h);
802
803 if (!shared_hash_key_initialized) {
804 random_bytes(shared_hash_key, sizeof(shared_hash_key));
805 shared_hash_key_initialized= true;
806 }
807
808 #ifdef ENABLE_DEBUG_HASHMAP
809 h->debug.func = func;
810 h->debug.file = file;
811 h->debug.line = line;
812 assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
813 LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug);
814 assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
815 #endif
816
817 return h;
818 }
819
820 Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
821 return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
822 }
823
824 OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
825 return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
826 }
827
828 Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
829 return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
830 }
831
832 static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
833 enum HashmapType type HASHMAP_DEBUG_PARAMS) {
834 HashmapBase *q;
835
836 assert(h);
837
838 if (*h)
839 return 0;
840
841 q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
842 if (!q)
843 return -ENOMEM;
844
845 *h = q;
846 return 0;
847 }
848
849 int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
850 return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
851 }
852
853 int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
854 return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
855 }
856
857 int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
858 return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
859 }
860
861 static void hashmap_free_no_clear(HashmapBase *h) {
862 assert(!h->has_indirect);
863 assert(!h->n_direct_entries);
864
865 #ifdef ENABLE_DEBUG_HASHMAP
866 assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
867 LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
868 assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
869 #endif
870
871 if (h->from_pool)
872 mempool_free_tile(hashmap_type_info[h->type].mempool, h);
873 else
874 free(h);
875 }
876
877 HashmapBase *internal_hashmap_free(HashmapBase *h) {
878
879 /* Free the hashmap, but nothing in it */
880
881 if (h) {
882 internal_hashmap_clear(h);
883 hashmap_free_no_clear(h);
884 }
885
886 return NULL;
887 }
888
889 HashmapBase *internal_hashmap_free_free(HashmapBase *h) {
890
891 /* Free the hashmap and all data objects in it, but not the
892 * keys */
893
894 if (h) {
895 internal_hashmap_clear_free(h);
896 hashmap_free_no_clear(h);
897 }
898
899 return NULL;
900 }
901
902 Hashmap *hashmap_free_free_free(Hashmap *h) {
903
904 /* Free the hashmap and all data and key objects in it */
905
906 if (h) {
907 hashmap_clear_free_free(h);
908 hashmap_free_no_clear(HASHMAP_BASE(h));
909 }
910
911 return NULL;
912 }
913
914 void internal_hashmap_clear(HashmapBase *h) {
915 if (!h)
916 return;
917
918 if (h->has_indirect) {
919 free(h->indirect.storage);
920 h->has_indirect = false;
921 }
922
923 h->n_direct_entries = 0;
924 reset_direct_storage(h);
925
926 if (h->type == HASHMAP_TYPE_ORDERED) {
927 OrderedHashmap *lh = (OrderedHashmap*) h;
928 lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
929 }
930 }
931
932 void internal_hashmap_clear_free(HashmapBase *h) {
933 unsigned idx;
934
935 if (!h)
936 return;
937
938 for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
939 idx = skip_free_buckets(h, idx + 1))
940 free(entry_value(h, bucket_at(h, idx)));
941
942 internal_hashmap_clear(h);
943 }
944
945 void hashmap_clear_free_free(Hashmap *h) {
946 unsigned idx;
947
948 if (!h)
949 return;
950
951 for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL;
952 idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) {
953 struct plain_hashmap_entry *e = plain_bucket_at(h, idx);
954 free((void*)e->b.key);
955 free(e->value);
956 }
957
958 internal_hashmap_clear(HASHMAP_BASE(h));
959 }
960
961 static int resize_buckets(HashmapBase *h, unsigned entries_add);
962
963 /*
964 * Finds an empty bucket to put an entry into, starting the scan at 'idx'.
965 * Performs Robin Hood swaps as it goes. The entry to put must be placed
966 * by the caller into swap slot IDX_PUT.
967 * If used for in-place resizing, may leave a displaced entry in swap slot
968 * IDX_PUT. Caller must rehash it next.
969 * Returns: true if it left a displaced entry to rehash next in IDX_PUT,
970 * false otherwise.
971 */
972 static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
973 struct swap_entries *swap) {
974 dib_raw_t raw_dib, *dibs;
975 unsigned dib, distance;
976
977 #ifdef ENABLE_DEBUG_HASHMAP
978 h->debug.put_count++;
979 #endif
980
981 dibs = dib_raw_ptr(h);
982
983 for (distance = 0; ; distance++) {
984 raw_dib = dibs[idx];
985 if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
986 if (raw_dib == DIB_RAW_REHASH)
987 bucket_move_entry(h, swap, idx, IDX_TMP);
988
989 if (h->has_indirect && h->indirect.idx_lowest_entry > idx)
990 h->indirect.idx_lowest_entry = idx;
991
992 bucket_set_dib(h, idx, distance);
993 bucket_move_entry(h, swap, IDX_PUT, idx);
994 if (raw_dib == DIB_RAW_REHASH) {
995 bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
996 return true;
997 }
998
999 return false;
1000 }
1001
1002 dib = bucket_calculate_dib(h, idx, raw_dib);
1003
1004 if (dib < distance) {
1005 /* Found a wealthier entry. Go Robin Hood! */
1006 bucket_set_dib(h, idx, distance);
1007
1008 /* swap the entries */
1009 bucket_move_entry(h, swap, idx, IDX_TMP);
1010 bucket_move_entry(h, swap, IDX_PUT, idx);
1011 bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
1012
1013 distance = dib;
1014 }
1015
1016 idx = next_idx(h, idx);
1017 }
1018 }
1019
1020 /*
1021 * Puts an entry into a hashmap, boldly - no check whether key already exists.
1022 * The caller must place the entry (only its key and value, not link indexes)
1023 * in swap slot IDX_PUT.
1024 * Caller must ensure: the key does not exist yet in the hashmap.
1025 * that resize is not needed if !may_resize.
1026 * Returns: 1 if entry was put successfully.
1027 * -ENOMEM if may_resize==true and resize failed with -ENOMEM.
1028 * Cannot return -ENOMEM if !may_resize.
1029 */
1030 static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
1031 struct swap_entries *swap, bool may_resize) {
1032 struct ordered_hashmap_entry *new_entry;
1033 int r;
1034
1035 assert(idx < n_buckets(h));
1036
1037 new_entry = bucket_at_swap(swap, IDX_PUT);
1038
1039 if (may_resize) {
1040 r = resize_buckets(h, 1);
1041 if (r < 0)
1042 return r;
1043 if (r > 0)
1044 idx = bucket_hash(h, new_entry->p.b.key);
1045 }
1046 assert(n_entries(h) < n_buckets(h));
1047
1048 if (h->type == HASHMAP_TYPE_ORDERED) {
1049 OrderedHashmap *lh = (OrderedHashmap*) h;
1050
1051 new_entry->iterate_next = IDX_NIL;
1052 new_entry->iterate_previous = lh->iterate_list_tail;
1053
1054 if (lh->iterate_list_tail != IDX_NIL) {
1055 struct ordered_hashmap_entry *old_tail;
1056
1057 old_tail = ordered_bucket_at(lh, lh->iterate_list_tail);
1058 assert(old_tail->iterate_next == IDX_NIL);
1059 old_tail->iterate_next = IDX_PUT;
1060 }
1061
1062 lh->iterate_list_tail = IDX_PUT;
1063 if (lh->iterate_list_head == IDX_NIL)
1064 lh->iterate_list_head = IDX_PUT;
1065 }
1066
1067 assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
1068
1069 n_entries_inc(h);
1070 #ifdef ENABLE_DEBUG_HASHMAP
1071 h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
1072 #endif
1073
1074 return 1;
1075 }
1076 #define hashmap_put_boldly(h, idx, swap, may_resize) \
1077 hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize)
1078
1079 /*
1080 * Returns 0 if resize is not needed.
1081 * 1 if successfully resized.
1082 * -ENOMEM on allocation failure.
1083 */
1084 static int resize_buckets(HashmapBase *h, unsigned entries_add) {
1085 struct swap_entries swap;
1086 char *new_storage;
1087 dib_raw_t *old_dibs, *new_dibs;
1088 const struct hashmap_type_info *hi;
1089 unsigned idx, optimal_idx;
1090 unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries;
1091 uint8_t new_shift;
1092 bool rehash_next;
1093
1094 assert(h);
1095
1096 hi = &hashmap_type_info[h->type];
1097 new_n_entries = n_entries(h) + entries_add;
1098
1099 /* overflow? */
1100 if (_unlikely_(new_n_entries < entries_add))
1101 return -ENOMEM;
1102
1103 /* For direct storage we allow 100% load, because it's tiny. */
1104 if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets)
1105 return 0;
1106
1107 /*
1108 * Load factor = n/m = 1 - (1/INV_KEEP_FREE).
1109 * From it follows: m = n + n/(INV_KEEP_FREE - 1)
1110 */
1111 new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1);
1112 /* overflow? */
1113 if (_unlikely_(new_n_buckets < new_n_entries))
1114 return -ENOMEM;
1115
1116 if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t))))
1117 return -ENOMEM;
1118
1119 old_n_buckets = n_buckets(h);
1120
1121 if (_likely_(new_n_buckets <= old_n_buckets))
1122 return 0;
1123
1124 new_shift = log2u_round_up(MAX(
1125 new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)),
1126 2 * sizeof(struct direct_storage)));
1127
1128 /* Realloc storage (buckets and DIB array). */
1129 new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL,
1130 1U << new_shift);
1131 if (!new_storage)
1132 return -ENOMEM;
1133
1134 /* Must upgrade direct to indirect storage. */
1135 if (!h->has_indirect) {
1136 memcpy(new_storage, h->direct.storage,
1137 old_n_buckets * (hi->entry_size + sizeof(dib_raw_t)));
1138 h->indirect.n_entries = h->n_direct_entries;
1139 h->indirect.idx_lowest_entry = 0;
1140 h->n_direct_entries = 0;
1141 }
1142
1143 /* Get a new hash key. If we've just upgraded to indirect storage,
1144 * allow reusing a previously generated key. It's still a different key
1145 * from the shared one that we used for direct storage. */
1146 get_hash_key(h->indirect.hash_key, !h->has_indirect);
1147
1148 h->has_indirect = true;
1149 h->indirect.storage = new_storage;
1150 h->indirect.n_buckets = (1U << new_shift) /
1151 (hi->entry_size + sizeof(dib_raw_t));
1152
1153 old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
1154 new_dibs = dib_raw_ptr(h);
1155
1156 /*
1157 * Move the DIB array to the new place, replacing valid DIB values with
1158 * DIB_RAW_REHASH to indicate all of the used buckets need rehashing.
1159 * Note: Overlap is not possible, because we have at least doubled the
1160 * number of buckets and dib_raw_t is smaller than any entry type.
1161 */
1162 for (idx = 0; idx < old_n_buckets; idx++) {
1163 assert(old_dibs[idx] != DIB_RAW_REHASH);
1164 new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE
1165 : DIB_RAW_REHASH;
1166 }
1167
1168 /* Zero the area of newly added entries (including the old DIB area) */
1169 memzero(bucket_at(h, old_n_buckets),
1170 (n_buckets(h) - old_n_buckets) * hi->entry_size);
1171
1172 /* The upper half of the new DIB array needs initialization */
1173 memset(&new_dibs[old_n_buckets], DIB_RAW_INIT,
1174 (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t));
1175
1176 /* Rehash entries that need it */
1177 n_rehashed = 0;
1178 for (idx = 0; idx < old_n_buckets; idx++) {
1179 if (new_dibs[idx] != DIB_RAW_REHASH)
1180 continue;
1181
1182 optimal_idx = bucket_hash(h, bucket_at(h, idx)->key);
1183
1184 /*
1185 * Not much to do if by luck the entry hashes to its current
1186 * location. Just set its DIB.
1187 */
1188 if (optimal_idx == idx) {
1189 new_dibs[idx] = 0;
1190 n_rehashed++;
1191 continue;
1192 }
1193
1194 new_dibs[idx] = DIB_RAW_FREE;
1195 bucket_move_entry(h, &swap, idx, IDX_PUT);
1196 /* bucket_move_entry does not clear the source */
1197 memzero(bucket_at(h, idx), hi->entry_size);
1198
1199 do {
1200 /*
1201 * Find the new bucket for the current entry. This may make
1202 * another entry homeless and load it into IDX_PUT.
1203 */
1204 rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap);
1205 n_rehashed++;
1206
1207 /* Did the current entry displace another one? */
1208 if (rehash_next)
1209 optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key);
1210 } while (rehash_next);
1211 }
1212
1213 assert(n_rehashed == n_entries(h));
1214
1215 return 1;
1216 }
1217
1218 /*
1219 * Finds an entry with a matching key
1220 * Returns: index of the found entry, or IDX_NIL if not found.
1221 */
1222 static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) {
1223 struct hashmap_base_entry *e;
1224 unsigned dib, distance;
1225 dib_raw_t *dibs = dib_raw_ptr(h);
1226
1227 assert(idx < n_buckets(h));
1228
1229 for (distance = 0; ; distance++) {
1230 if (dibs[idx] == DIB_RAW_FREE)
1231 return IDX_NIL;
1232
1233 dib = bucket_calculate_dib(h, idx, dibs[idx]);
1234
1235 if (dib < distance)
1236 return IDX_NIL;
1237 if (dib == distance) {
1238 e = bucket_at(h, idx);
1239 if (h->hash_ops->compare(e->key, key) == 0)
1240 return idx;
1241 }
1242
1243 idx = next_idx(h, idx);
1244 }
1245 }
1246 #define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key)
1247
1248 int hashmap_put(Hashmap *h, const void *key, void *value) {
1249 struct swap_entries swap;
1250 struct plain_hashmap_entry *e;
1251 unsigned hash, idx;
1252
1253 assert(h);
1254
1255 hash = bucket_hash(h, key);
1256 idx = bucket_scan(h, hash, key);
1257 if (idx != IDX_NIL) {
1258 e = plain_bucket_at(h, idx);
1259 if (e->value == value)
1260 return 0;
1261 return -EEXIST;
1262 }
1263
1264 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1265 e->b.key = key;
1266 e->value = value;
1267 return hashmap_put_boldly(h, hash, &swap, true);
1268 }
1269
1270 int set_put(Set *s, const void *key) {
1271 struct swap_entries swap;
1272 struct hashmap_base_entry *e;
1273 unsigned hash, idx;
1274
1275 assert(s);
1276
1277 hash = bucket_hash(s, key);
1278 idx = bucket_scan(s, hash, key);
1279 if (idx != IDX_NIL)
1280 return 0;
1281
1282 e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1283 e->key = key;
1284 return hashmap_put_boldly(s, hash, &swap, true);
1285 }
1286
1287 int hashmap_replace(Hashmap *h, const void *key, void *value) {
1288 struct swap_entries swap;
1289 struct plain_hashmap_entry *e;
1290 unsigned hash, idx;
1291
1292 assert(h);
1293
1294 hash = bucket_hash(h, key);
1295 idx = bucket_scan(h, hash, key);
1296 if (idx != IDX_NIL) {
1297 e = plain_bucket_at(h, idx);
1298 #ifdef ENABLE_DEBUG_HASHMAP
1299 /* Although the key is equal, the key pointer may have changed,
1300 * and this would break our assumption for iterating. So count
1301 * this operation as incompatible with iteration. */
1302 if (e->b.key != key) {
1303 h->b.debug.put_count++;
1304 h->b.debug.rem_count++;
1305 h->b.debug.last_rem_idx = idx;
1306 }
1307 #endif
1308 e->b.key = key;
1309 e->value = value;
1310 return 0;
1311 }
1312
1313 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1314 e->b.key = key;
1315 e->value = value;
1316 return hashmap_put_boldly(h, hash, &swap, true);
1317 }
1318
1319 int hashmap_update(Hashmap *h, const void *key, void *value) {
1320 struct plain_hashmap_entry *e;
1321 unsigned hash, idx;
1322
1323 assert(h);
1324
1325 hash = bucket_hash(h, key);
1326 idx = bucket_scan(h, hash, key);
1327 if (idx == IDX_NIL)
1328 return -ENOENT;
1329
1330 e = plain_bucket_at(h, idx);
1331 e->value = value;
1332 return 0;
1333 }
1334
1335 void *internal_hashmap_get(HashmapBase *h, const void *key) {
1336 struct hashmap_base_entry *e;
1337 unsigned hash, idx;
1338
1339 if (!h)
1340 return NULL;
1341
1342 hash = bucket_hash(h, key);
1343 idx = bucket_scan(h, hash, key);
1344 if (idx == IDX_NIL)
1345 return NULL;
1346
1347 e = bucket_at(h, idx);
1348 return entry_value(h, e);
1349 }
1350
1351 void *hashmap_get2(Hashmap *h, const void *key, void **key2) {
1352 struct plain_hashmap_entry *e;
1353 unsigned hash, idx;
1354
1355 if (!h)
1356 return NULL;
1357
1358 hash = bucket_hash(h, key);
1359 idx = bucket_scan(h, hash, key);
1360 if (idx == IDX_NIL)
1361 return NULL;
1362
1363 e = plain_bucket_at(h, idx);
1364 if (key2)
1365 *key2 = (void*) e->b.key;
1366
1367 return e->value;
1368 }
1369
1370 bool internal_hashmap_contains(HashmapBase *h, const void *key) {
1371 unsigned hash;
1372
1373 if (!h)
1374 return false;
1375
1376 hash = bucket_hash(h, key);
1377 return bucket_scan(h, hash, key) != IDX_NIL;
1378 }
1379
1380 void *internal_hashmap_remove(HashmapBase *h, const void *key) {
1381 struct hashmap_base_entry *e;
1382 unsigned hash, idx;
1383 void *data;
1384
1385 if (!h)
1386 return NULL;
1387
1388 hash = bucket_hash(h, key);
1389 idx = bucket_scan(h, hash, key);
1390 if (idx == IDX_NIL)
1391 return NULL;
1392
1393 e = bucket_at(h, idx);
1394 data = entry_value(h, e);
1395 remove_entry(h, idx);
1396
1397 return data;
1398 }
1399
1400 void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) {
1401 struct plain_hashmap_entry *e;
1402 unsigned hash, idx;
1403 void *data;
1404
1405 if (!h) {
1406 if (rkey)
1407 *rkey = NULL;
1408 return NULL;
1409 }
1410
1411 hash = bucket_hash(h, key);
1412 idx = bucket_scan(h, hash, key);
1413 if (idx == IDX_NIL) {
1414 if (rkey)
1415 *rkey = NULL;
1416 return NULL;
1417 }
1418
1419 e = plain_bucket_at(h, idx);
1420 data = e->value;
1421 if (rkey)
1422 *rkey = (void*) e->b.key;
1423
1424 remove_entry(h, idx);
1425
1426 return data;
1427 }
1428
1429 int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
1430 struct swap_entries swap;
1431 struct plain_hashmap_entry *e;
1432 unsigned old_hash, new_hash, idx;
1433
1434 if (!h)
1435 return -ENOENT;
1436
1437 old_hash = bucket_hash(h, old_key);
1438 idx = bucket_scan(h, old_hash, old_key);
1439 if (idx == IDX_NIL)
1440 return -ENOENT;
1441
1442 new_hash = bucket_hash(h, new_key);
1443 if (bucket_scan(h, new_hash, new_key) != IDX_NIL)
1444 return -EEXIST;
1445
1446 remove_entry(h, idx);
1447
1448 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1449 e->b.key = new_key;
1450 e->value = value;
1451 assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
1452
1453 return 0;
1454 }
1455
1456 int set_remove_and_put(Set *s, const void *old_key, const void *new_key) {
1457 struct swap_entries swap;
1458 struct hashmap_base_entry *e;
1459 unsigned old_hash, new_hash, idx;
1460
1461 if (!s)
1462 return -ENOENT;
1463
1464 old_hash = bucket_hash(s, old_key);
1465 idx = bucket_scan(s, old_hash, old_key);
1466 if (idx == IDX_NIL)
1467 return -ENOENT;
1468
1469 new_hash = bucket_hash(s, new_key);
1470 if (bucket_scan(s, new_hash, new_key) != IDX_NIL)
1471 return -EEXIST;
1472
1473 remove_entry(s, idx);
1474
1475 e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1476 e->key = new_key;
1477 assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1);
1478
1479 return 0;
1480 }
1481
1482 int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
1483 struct swap_entries swap;
1484 struct plain_hashmap_entry *e;
1485 unsigned old_hash, new_hash, idx_old, idx_new;
1486
1487 if (!h)
1488 return -ENOENT;
1489
1490 old_hash = bucket_hash(h, old_key);
1491 idx_old = bucket_scan(h, old_hash, old_key);
1492 if (idx_old == IDX_NIL)
1493 return -ENOENT;
1494
1495 old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key;
1496
1497 new_hash = bucket_hash(h, new_key);
1498 idx_new = bucket_scan(h, new_hash, new_key);
1499 if (idx_new != IDX_NIL)
1500 if (idx_old != idx_new) {
1501 remove_entry(h, idx_new);
1502 /* Compensate for a possible backward shift. */
1503 if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key)
1504 idx_old = prev_idx(HASHMAP_BASE(h), idx_old);
1505 assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key);
1506 }
1507
1508 remove_entry(h, idx_old);
1509
1510 e = &bucket_at_swap(&swap, IDX_PUT)->p;
1511 e->b.key = new_key;
1512 e->value = value;
1513 assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
1514
1515 return 0;
1516 }
1517
1518 void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
1519 struct plain_hashmap_entry *e;
1520 unsigned hash, idx;
1521
1522 if (!h)
1523 return NULL;
1524
1525 hash = bucket_hash(h, key);
1526 idx = bucket_scan(h, hash, key);
1527 if (idx == IDX_NIL)
1528 return NULL;
1529
1530 e = plain_bucket_at(h, idx);
1531 if (e->value != value)
1532 return NULL;
1533
1534 remove_entry(h, idx);
1535
1536 return value;
1537 }
1538
1539 static unsigned find_first_entry(HashmapBase *h) {
1540 Iterator i = ITERATOR_FIRST;
1541
1542 if (!h || !n_entries(h))
1543 return IDX_NIL;
1544
1545 return hashmap_iterate_entry(h, &i);
1546 }
1547
1548 void *internal_hashmap_first(HashmapBase *h) {
1549 unsigned idx;
1550
1551 idx = find_first_entry(h);
1552 if (idx == IDX_NIL)
1553 return NULL;
1554
1555 return entry_value(h, bucket_at(h, idx));
1556 }
1557
1558 void *internal_hashmap_first_key(HashmapBase *h) {
1559 struct hashmap_base_entry *e;
1560 unsigned idx;
1561
1562 idx = find_first_entry(h);
1563 if (idx == IDX_NIL)
1564 return NULL;
1565
1566 e = bucket_at(h, idx);
1567 return (void*) e->key;
1568 }
1569
1570 void *internal_hashmap_steal_first(HashmapBase *h) {
1571 struct hashmap_base_entry *e;
1572 void *data;
1573 unsigned idx;
1574
1575 idx = find_first_entry(h);
1576 if (idx == IDX_NIL)
1577 return NULL;
1578
1579 e = bucket_at(h, idx);
1580 data = entry_value(h, e);
1581 remove_entry(h, idx);
1582
1583 return data;
1584 }
1585
1586 void *internal_hashmap_steal_first_key(HashmapBase *h) {
1587 struct hashmap_base_entry *e;
1588 void *key;
1589 unsigned idx;
1590
1591 idx = find_first_entry(h);
1592 if (idx == IDX_NIL)
1593 return NULL;
1594
1595 e = bucket_at(h, idx);
1596 key = (void*) e->key;
1597 remove_entry(h, idx);
1598
1599 return key;
1600 }
1601
1602 unsigned internal_hashmap_size(HashmapBase *h) {
1603
1604 if (!h)
1605 return 0;
1606
1607 return n_entries(h);
1608 }
1609
1610 unsigned internal_hashmap_buckets(HashmapBase *h) {
1611
1612 if (!h)
1613 return 0;
1614
1615 return n_buckets(h);
1616 }
1617
1618 int internal_hashmap_merge(Hashmap *h, Hashmap *other) {
1619 Iterator i;
1620 unsigned idx;
1621
1622 assert(h);
1623
1624 HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
1625 struct plain_hashmap_entry *pe = plain_bucket_at(other, idx);
1626 int r;
1627
1628 r = hashmap_put(h, pe->b.key, pe->value);
1629 if (r < 0 && r != -EEXIST)
1630 return r;
1631 }
1632
1633 return 0;
1634 }
1635
1636 int set_merge(Set *s, Set *other) {
1637 Iterator i;
1638 unsigned idx;
1639
1640 assert(s);
1641
1642 HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
1643 struct set_entry *se = set_bucket_at(other, idx);
1644 int r;
1645
1646 r = set_put(s, se->b.key);
1647 if (r < 0)
1648 return r;
1649 }
1650
1651 return 0;
1652 }
1653
1654 int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
1655 int r;
1656
1657 assert(h);
1658
1659 r = resize_buckets(h, entries_add);
1660 if (r < 0)
1661 return r;
1662
1663 return 0;
1664 }
1665
1666 /*
1667 * The same as hashmap_merge(), but every new item from other is moved to h.
1668 * Keys already in h are skipped and stay in other.
1669 * Returns: 0 on success.
1670 * -ENOMEM on alloc failure, in which case no move has been done.
1671 */
1672 int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
1673 struct swap_entries swap;
1674 struct hashmap_base_entry *e, *n;
1675 Iterator i;
1676 unsigned idx;
1677 int r;
1678
1679 assert(h);
1680
1681 if (!other)
1682 return 0;
1683
1684 assert(other->type == h->type);
1685
1686 /*
1687 * This reserves buckets for the worst case, where none of other's
1688 * entries are yet present in h. This is preferable to risking
1689 * an allocation failure in the middle of the moving and having to
1690 * rollback or return a partial result.
1691 */
1692 r = resize_buckets(h, n_entries(other));
1693 if (r < 0)
1694 return r;
1695
1696 HASHMAP_FOREACH_IDX(idx, other, i) {
1697 unsigned h_hash;
1698
1699 e = bucket_at(other, idx);
1700 h_hash = bucket_hash(h, e->key);
1701 if (bucket_scan(h, h_hash, e->key) != IDX_NIL)
1702 continue;
1703
1704 n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1705 n->key = e->key;
1706 if (h->type != HASHMAP_TYPE_SET)
1707 ((struct plain_hashmap_entry*) n)->value =
1708 ((struct plain_hashmap_entry*) e)->value;
1709 assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1);
1710
1711 remove_entry(other, idx);
1712 }
1713
1714 return 0;
1715 }
1716
1717 int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
1718 struct swap_entries swap;
1719 unsigned h_hash, other_hash, idx;
1720 struct hashmap_base_entry *e, *n;
1721 int r;
1722
1723 assert(h);
1724
1725 h_hash = bucket_hash(h, key);
1726 if (bucket_scan(h, h_hash, key) != IDX_NIL)
1727 return -EEXIST;
1728
1729 if (!other)
1730 return -ENOENT;
1731
1732 assert(other->type == h->type);
1733
1734 other_hash = bucket_hash(other, key);
1735 idx = bucket_scan(other, other_hash, key);
1736 if (idx == IDX_NIL)
1737 return -ENOENT;
1738
1739 e = bucket_at(other, idx);
1740
1741 n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
1742 n->key = e->key;
1743 if (h->type != HASHMAP_TYPE_SET)
1744 ((struct plain_hashmap_entry*) n)->value =
1745 ((struct plain_hashmap_entry*) e)->value;
1746 r = hashmap_put_boldly(h, h_hash, &swap, true);
1747 if (r < 0)
1748 return r;
1749
1750 remove_entry(other, idx);
1751 return 0;
1752 }
1753
1754 HashmapBase *internal_hashmap_copy(HashmapBase *h) {
1755 HashmapBase *copy;
1756 int r;
1757
1758 assert(h);
1759
1760 copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
1761 if (!copy)
1762 return NULL;
1763
1764 switch (h->type) {
1765 case HASHMAP_TYPE_PLAIN:
1766 case HASHMAP_TYPE_ORDERED:
1767 r = hashmap_merge((Hashmap*)copy, (Hashmap*)h);
1768 break;
1769 case HASHMAP_TYPE_SET:
1770 r = set_merge((Set*)copy, (Set*)h);
1771 break;
1772 default:
1773 assert_not_reached("Unknown hashmap type");
1774 }
1775
1776 if (r < 0) {
1777 internal_hashmap_free(copy);
1778 return NULL;
1779 }
1780
1781 return copy;
1782 }
1783
1784 char **internal_hashmap_get_strv(HashmapBase *h) {
1785 char **sv;
1786 Iterator i;
1787 unsigned idx, n;
1788
1789 sv = new(char*, n_entries(h)+1);
1790 if (!sv)
1791 return NULL;
1792
1793 n = 0;
1794 HASHMAP_FOREACH_IDX(idx, h, i)
1795 sv[n++] = entry_value(h, bucket_at(h, idx));
1796 sv[n] = NULL;
1797
1798 return sv;
1799 }
1800
1801 void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
1802 struct ordered_hashmap_entry *e;
1803 unsigned hash, idx;
1804
1805 if (!h)
1806 return NULL;
1807
1808 hash = bucket_hash(h, key);
1809 idx = bucket_scan(h, hash, key);
1810 if (idx == IDX_NIL)
1811 return NULL;
1812
1813 e = ordered_bucket_at(h, idx);
1814 if (e->iterate_next == IDX_NIL)
1815 return NULL;
1816 return ordered_bucket_at(h, e->iterate_next)->p.value;
1817 }
1818
1819 int set_consume(Set *s, void *value) {
1820 int r;
1821
1822 r = set_put(s, value);
1823 if (r <= 0)
1824 free(value);
1825
1826 return r;
1827 }
1828
1829 int set_put_strdup(Set *s, const char *p) {
1830 char *c;
1831 int r;
1832
1833 assert(s);
1834 assert(p);
1835
1836 c = strdup(p);
1837 if (!c)
1838 return -ENOMEM;
1839
1840 r = set_consume(s, c);
1841 if (r == -EEXIST)
1842 return 0;
1843
1844 return r;
1845 }
1846
1847 int set_put_strdupv(Set *s, char **l) {
1848 int n = 0, r;
1849 char **i;
1850
1851 STRV_FOREACH(i, l) {
1852 r = set_put_strdup(s, *i);
1853 if (r < 0)
1854 return r;
1855
1856 n += r;
1857 }
1858
1859 return n;
1860 }