mirror of
https://git.sr.ht/~cismonx/bookmarkfs
synced 2025-06-07 19:58:50 +00:00
hashmap: refactor interface
- `hashmap_insert()` no longer takes key as argument, and takes the pointer to be associated with the entry as argument. - Rename `hashmap_entry_delete` -> `hashmap_delete`. - Make `user_data` the first argument for `hashmap_walk_func`. - Other misc renames.
This commit is contained in:
parent
b585a05c91
commit
c2a91d6420
5 changed files with 84 additions and 110 deletions
|
@ -527,7 +527,7 @@ fsck_apply (
|
|||
|
||||
entry->name = json_string_value(name_node);
|
||||
entry->name_len = name_len;
|
||||
*hashmap_insert(assoc_map, key_assoc, hashcode_assoc) = entry;
|
||||
hashmap_insert(assoc_map, hashcode_assoc, entry);
|
||||
return 0;
|
||||
|
||||
callback:
|
||||
|
@ -670,10 +670,8 @@ update_guid (
|
|||
uint8_t *guid,
|
||||
unsigned long hashcode
|
||||
) {
|
||||
hashmap_entry_delete(guid_map, entry, old_entry_id);
|
||||
|
||||
union hashmap_key key = { .ptr = guid };
|
||||
*hashmap_insert(guid_map, key, hashcode) = entry;
|
||||
hashmap_delete(guid_map, entry, old_entry_id);
|
||||
hashmap_insert(guid_map, hashcode, entry);
|
||||
|
||||
memcpy(entry->guid, guid, UUID_LEN);
|
||||
}
|
||||
|
@ -768,13 +766,11 @@ build_maps (
|
|||
.node = root,
|
||||
.children = children,
|
||||
};
|
||||
union hashmap_key key_id = { .u64 = root_id };
|
||||
unsigned long hashcode_id = hash_digest(&root_id, sizeof(root_id));
|
||||
*hashmap_insert(id_map, key_id, hashcode_id) = root_entry;
|
||||
unsigned long hashcode_id = hash_digest(&root_id, sizeof(root_id));
|
||||
hashmap_insert(id_map, hashcode_id, root_entry);
|
||||
|
||||
union hashmap_key key_guid = { .ptr = root_entry->guid };
|
||||
unsigned long hashcode_guid = hash_digest(root_entry->guid, UUID_LEN);
|
||||
*hashmap_insert(guid_map, key_guid, hashcode_guid) = root_entry;
|
||||
unsigned long hashcode_guid = hash_digest(root_entry->guid, UUID_LEN);
|
||||
hashmap_insert(guid_map, hashcode_guid, root_entry);
|
||||
|
||||
struct idmap_iter_ctx iter_ctx = {
|
||||
.id_map = id_map,
|
||||
|
@ -879,8 +875,8 @@ free_blcookie (
|
|||
|
||||
static void
|
||||
free_entry_cb (
|
||||
void *entry,
|
||||
void *UNUSED_VAR(user_data)
|
||||
void *UNUSED_VAR(user_data),
|
||||
void *entry
|
||||
) {
|
||||
free(entry);
|
||||
}
|
||||
|
@ -1321,8 +1317,8 @@ maps_iter_cb (
|
|||
entry->node = node;
|
||||
entry->children = children;
|
||||
memcpy(entry->guid, guid, UUID_LEN);
|
||||
*hashmap_insert(ctx->id_map, key, hashcode) = entry;
|
||||
*hashmap_insert(ctx->guid_map, key_guid, hashcode_guid) = entry;
|
||||
hashmap_insert(ctx->id_map, hashcode, entry);
|
||||
hashmap_insert(ctx->guid_map, hashcode_guid, entry);
|
||||
|
||||
// bookmark bar, mobile bookmarks, other bookmarks, ...
|
||||
if (parent->id == BOOKMARKS_ROOT_ID) {
|
||||
|
@ -1359,7 +1355,7 @@ maps_iter_cb (
|
|||
|
||||
entry->name = name;
|
||||
entry->name_len = name_len;
|
||||
*hashmap_insert(assoc_map, key_assoc, hashcode_assoc) = entry;
|
||||
hashmap_insert(assoc_map, hashcode_assoc, entry);
|
||||
|
||||
end:
|
||||
#ifdef BOOKMARKFS_BACKEND_CHROMIUM_WRITE
|
||||
|
@ -2265,9 +2261,7 @@ bookmark_create (
|
|||
.node = node,
|
||||
.children = is_dir ? json_object_sget(node, "children") : NULL,
|
||||
};
|
||||
|
||||
union hashmap_key key = { .u64 = id };
|
||||
*hashmap_insert(ctx->id_map, key, hash_digest(&id, sizeof(id))) = entry;
|
||||
hashmap_insert(ctx->id_map, hash_digest(&id, sizeof(id)), entry);
|
||||
|
||||
void *guid = lctx.guid;
|
||||
unsigned long hashcode_guid = lctx.hashcode;
|
||||
|
@ -2275,16 +2269,9 @@ bookmark_create (
|
|||
guid = bctx.guid;
|
||||
hashcode_guid = bctx.hashcode;
|
||||
|
||||
key.ptr = &(struct assocmap_key) {
|
||||
.parent_id = parent_id,
|
||||
.name = name,
|
||||
.name_len = name_len,
|
||||
};
|
||||
*hashmap_insert(ctx->assoc_map, key, lctx.hashcode) = entry;
|
||||
hashmap_insert(ctx->assoc_map, lctx.hashcode, entry);
|
||||
}
|
||||
|
||||
key.ptr = guid;
|
||||
*hashmap_insert(ctx->guid_map, key, hashcode_guid) = entry;
|
||||
hashmap_insert(ctx->guid_map, hashcode_guid, entry);
|
||||
|
||||
memcpy(entry->guid, guid, UUID_LEN);
|
||||
ctx->dirty = DIRTY_LEVEL_DATA;
|
||||
|
@ -2344,10 +2331,10 @@ bookmark_delete (
|
|||
long guidmap_entry_id = lctx.entry_id;
|
||||
if (!(ctx->flags & BACKEND_FILENAME_GUID)) {
|
||||
guidmap_entry_id = -1;
|
||||
hashmap_entry_delete(ctx->assoc_map, entry, lctx.entry_id);
|
||||
hashmap_delete(ctx->assoc_map, entry, lctx.entry_id);
|
||||
}
|
||||
hashmap_entry_delete(ctx->guid_map, entry, guidmap_entry_id);
|
||||
hashmap_entry_delete(ctx->id_map, entry, -1);
|
||||
hashmap_delete(ctx->guid_map, entry, guidmap_entry_id);
|
||||
hashmap_delete(ctx->id_map, entry, -1);
|
||||
free(entry);
|
||||
|
||||
// Remove from store
|
||||
|
@ -2566,10 +2553,10 @@ bookmark_rename (
|
|||
long new_guidmap_entry_id = new_lctx.entry_id;
|
||||
if (!filename_is_guid) {
|
||||
new_guidmap_entry_id = -1;
|
||||
hashmap_entry_delete(ctx->assoc_map, new_entry, new_lctx.entry_id);
|
||||
hashmap_delete(ctx->assoc_map, new_entry, new_lctx.entry_id);
|
||||
}
|
||||
hashmap_entry_delete(ctx->guid_map, new_entry, new_guidmap_entry_id);
|
||||
hashmap_entry_delete(ctx->id_map, new_entry, -1);
|
||||
hashmap_delete(ctx->guid_map, new_entry, new_guidmap_entry_id);
|
||||
hashmap_delete(ctx->id_map, new_entry, -1);
|
||||
free(new_entry);
|
||||
}
|
||||
|
||||
|
@ -2577,16 +2564,8 @@ bookmark_rename (
|
|||
update_guid(old_entry, ctx->guid_map, old_lctx.entry_id, new_lctx.guid,
|
||||
new_lctx.hashcode);
|
||||
} else {
|
||||
hashmap_entry_delete(ctx->assoc_map, old_entry, old_lctx.entry_id);
|
||||
|
||||
union hashmap_key key = {
|
||||
.ptr = &(struct assocmap_key) {
|
||||
.parent_id = new_parent_id,
|
||||
.name = old_entry->name,
|
||||
.name_len = new_name_len,
|
||||
},
|
||||
};
|
||||
*hashmap_insert(ctx->assoc_map, key, new_lctx.hashcode) = old_entry;
|
||||
hashmap_delete(ctx->assoc_map, old_entry, old_lctx.entry_id);
|
||||
hashmap_insert(ctx->assoc_map, new_lctx.hashcode, old_entry);
|
||||
}
|
||||
ctx->dirty = DIRTY_LEVEL_DATA;
|
||||
|
||||
|
|
|
@ -533,7 +533,7 @@ fsck_apply (
|
|||
dentry->name_len = name_len;
|
||||
memcpy(dentry->name, name, name_len);
|
||||
|
||||
*hashmap_insert(map, key, hashcode) = dentry;
|
||||
hashmap_insert(map, hashcode, dentry);
|
||||
goto end;
|
||||
|
||||
callback:
|
||||
|
@ -2347,7 +2347,7 @@ bookmark_check_cb (
|
|||
map = hashmap_create(dentmap_comp, dentmap_hash);
|
||||
ctx->dentry_map = map;
|
||||
}
|
||||
*hashmap_insert(map, key, hashcode) = dentry;
|
||||
hashmap_insert(map, hashcode, dentry);
|
||||
return 0;
|
||||
}
|
||||
if (dentry->id == (uint64_t)id) {
|
||||
|
@ -2457,7 +2457,7 @@ bookmark_list_cb (
|
|||
dentry->name_len = name_len;
|
||||
memcpy(dentry->name, name, name_len);
|
||||
|
||||
*hashmap_insert(map, key, hashcode) = dentry;
|
||||
hashmap_insert(map, hashcode, dentry);
|
||||
}
|
||||
return ctx->status;
|
||||
|
||||
|
@ -2547,8 +2547,8 @@ free_dentmap (
|
|||
|
||||
static void
|
||||
free_dentmap_entry (
|
||||
void *entry,
|
||||
void *UNUSED_VAR(user_data)
|
||||
void *UNUSED_VAR(user_data),
|
||||
void *entry
|
||||
) {
|
||||
struct bookmark_dentry *dentry = entry;
|
||||
|
||||
|
|
|
@ -458,7 +458,7 @@ bm_fh_free (
|
|||
struct fs_file_handle *fh,
|
||||
long entry_id
|
||||
) {
|
||||
hashmap_entry_delete(ctx.fh_map, fh, entry_id);
|
||||
hashmap_delete(ctx.fh_map, fh, entry_id);
|
||||
free(fh);
|
||||
}
|
||||
|
||||
|
@ -493,8 +493,7 @@ bm_fh_new (
|
|||
.id = id,
|
||||
.refcount = 1,
|
||||
};
|
||||
union hashmap_key key = { .u64 = id };
|
||||
*hashmap_insert(ctx.fh_map, key, hashcode) = fh;
|
||||
hashmap_insert(ctx.fh_map, hashcode, fh);
|
||||
return fh;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,14 +155,14 @@ count_tz (
|
|||
*/
|
||||
static int
|
||||
find_entry (
|
||||
struct hashmap const *h,
|
||||
struct hashmap const *map,
|
||||
void const *entry,
|
||||
struct bucket **home_ptr
|
||||
) {
|
||||
unsigned exp = h->exp;
|
||||
unsigned long hashcode = h->entry_hash(entry);
|
||||
unsigned exp = map->exp;
|
||||
unsigned long hashcode = map->entry_hash(entry);
|
||||
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
|
||||
struct bucket *home = h->buckets + hash_idx;
|
||||
struct bucket *home = map->buckets + hash_idx;
|
||||
unsigned long hop = home->bits;
|
||||
unsigned long hash_mask = BUCKET_HASH_MASK(exp);
|
||||
|
||||
|
@ -172,10 +172,10 @@ find_entry (
|
|||
debug_assert(hop_idx < exp);
|
||||
|
||||
struct bucket *b = home + hop_idx;
|
||||
if ((b->bits & hash_mask) != (hashcode << h->exp)) {
|
||||
if ((b->bits & hash_mask) != (hashcode << map->exp)) {
|
||||
continue;
|
||||
}
|
||||
if (entry != h->buckets[b - h->buckets].entry) {
|
||||
if (entry != map->buckets[b - map->buckets].entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -241,10 +241,10 @@ make_room (
|
|||
|
||||
static int
|
||||
rehash (
|
||||
struct hashmap *h,
|
||||
struct hashmap *map,
|
||||
bool grow
|
||||
) {
|
||||
unsigned new_exp = h->exp;
|
||||
unsigned new_exp = map->exp;
|
||||
if (grow) {
|
||||
if (unlikely(++new_exp > EXP_MAX)) {
|
||||
log_puts("rehash(): hashmap size exceeds max limit");
|
||||
|
@ -257,9 +257,9 @@ rehash (
|
|||
size_t new_nbuckets = BUCKET_CNT(new_exp);
|
||||
struct bucket *new_buckets = xcalloc(new_nbuckets, sizeof(struct bucket));
|
||||
|
||||
struct bucket *old_buckets_end = h->buckets + h->num_buckets;
|
||||
unsigned long new_hop_mask = BUCKET_HOP_MASK(new_exp);
|
||||
for (struct bucket *old_b = h->buckets; old_b < old_buckets_end; ++old_b) {
|
||||
struct bucket *old_b_end = map->buckets + map->num_buckets;
|
||||
unsigned long new_hop_mask = BUCKET_HOP_MASK(new_exp);
|
||||
for (struct bucket *old_b = map->buckets; old_b < old_b_end; ++old_b) {
|
||||
void *old_e = old_b->entry;
|
||||
if (old_e == NULL) {
|
||||
continue;
|
||||
|
@ -267,7 +267,7 @@ rehash (
|
|||
|
||||
// Cannot trivially deduce hashcode from old hash fragment,
|
||||
// since we have to find its home bucket.
|
||||
unsigned long hashcode = h->entry_hash(old_e);
|
||||
unsigned long hashcode = map->entry_hash(old_e);
|
||||
size_t new_hash_idx = HASH_TO_IDX(hashcode, new_exp);
|
||||
struct bucket *new_home = new_buckets + new_hash_idx;
|
||||
|
||||
|
@ -283,10 +283,10 @@ rehash (
|
|||
new_b->entry = old_e;
|
||||
}
|
||||
|
||||
free(h->buckets);
|
||||
h->buckets = new_buckets;
|
||||
h->num_buckets = new_nbuckets;
|
||||
h->exp = new_exp;
|
||||
free(map->buckets);
|
||||
map->buckets = new_buckets;
|
||||
map->num_buckets = new_nbuckets;
|
||||
map->exp = new_exp;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -328,34 +328,34 @@ hashmap_create (
|
|||
|
||||
void
|
||||
hashmap_destroy (
|
||||
struct hashmap *h
|
||||
struct hashmap *map
|
||||
) {
|
||||
if (h == NULL) {
|
||||
if (map == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(h->buckets);
|
||||
free(h);
|
||||
free(map->buckets);
|
||||
free(map);
|
||||
}
|
||||
|
||||
void
|
||||
hashmap_foreach (
|
||||
struct hashmap const *h,
|
||||
struct hashmap const *map,
|
||||
hashmap_walk_func *walk_func,
|
||||
void *user_data
|
||||
) {
|
||||
struct bucket *end = h->buckets + h->num_buckets;
|
||||
for (struct bucket *b = h->buckets; b < end; ++b) {
|
||||
struct bucket *end = map->buckets + map->num_buckets;
|
||||
for (struct bucket *b = map->buckets; b < end; ++b) {
|
||||
void *entry = b->entry;
|
||||
if (entry == NULL) {
|
||||
continue;
|
||||
}
|
||||
walk_func(b->entry, user_data);
|
||||
walk_func(user_data, b->entry);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hashmap_entry_delete (
|
||||
hashmap_delete (
|
||||
struct hashmap *h,
|
||||
void const *entry,
|
||||
long entry_id
|
||||
|
@ -386,42 +386,44 @@ hashmap_entry_delete (
|
|||
}
|
||||
}
|
||||
|
||||
void **
|
||||
void
|
||||
hashmap_insert (
|
||||
struct hashmap *h,
|
||||
union hashmap_key key,
|
||||
unsigned long hashcode
|
||||
struct hashmap *map,
|
||||
unsigned long hashcode,
|
||||
void *entry
|
||||
) {
|
||||
unsigned exp = h->exp;
|
||||
unsigned exp = map->exp;
|
||||
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
|
||||
struct bucket *home = h->buckets + hash_idx;
|
||||
struct bucket *home = map->buckets + hash_idx;
|
||||
|
||||
int hop_idx = make_room(home, h->buckets + h->num_buckets, exp);
|
||||
int hop_idx = make_room(home, map->buckets + map->num_buckets, exp);
|
||||
if (unlikely(hop_idx < 0)) {
|
||||
debug_printf("hashmap_insert(): rehashing (%zu/%zu)",
|
||||
h->num_used, h->num_buckets - (exp - 1));
|
||||
xassert(0 == rehash(h, true));
|
||||
return hashmap_insert(h, key, hashcode);
|
||||
map->num_used, map->num_buckets - (exp - 1));
|
||||
xassert(0 == rehash(map, true));
|
||||
hashmap_insert(map, hashcode, entry);
|
||||
return;
|
||||
}
|
||||
BIT_SET(home->bits, hop_idx);
|
||||
|
||||
struct bucket *b = home + hop_idx;
|
||||
b->bits = (b->bits & BUCKET_HOP_MASK(exp)) | (hashcode << exp);
|
||||
|
||||
++h->num_used;
|
||||
return &b->entry;
|
||||
++map->num_used;
|
||||
debug_assert(entry != NULL);
|
||||
b->entry = entry;
|
||||
}
|
||||
|
||||
void *
|
||||
hashmap_search (
|
||||
struct hashmap const *h,
|
||||
struct hashmap const *map,
|
||||
union hashmap_key key,
|
||||
unsigned long hashcode,
|
||||
unsigned long *entry_id_ptr
|
||||
) {
|
||||
unsigned exp = h->exp;
|
||||
unsigned exp = map->exp;
|
||||
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
|
||||
struct bucket *home = h->buckets + hash_idx;
|
||||
struct bucket *home = map->buckets + hash_idx;
|
||||
unsigned long hop = home->bits;
|
||||
unsigned long hash_mask = BUCKET_HASH_MASK(exp);
|
||||
|
||||
|
@ -438,7 +440,7 @@ hashmap_search (
|
|||
}
|
||||
void *e = b->entry;
|
||||
debug_assert(e != NULL);
|
||||
if (0 != h->entry_comp(key, e)) {
|
||||
if (0 != map->entry_comp(key, e)) {
|
||||
continue;
|
||||
}
|
||||
if (entry_id_ptr != NULL) {
|
||||
|
|
|
@ -33,8 +33,8 @@ union hashmap_key {
|
|||
};
|
||||
|
||||
typedef void (hashmap_walk_func) (
|
||||
void *entry,
|
||||
void *user_data
|
||||
void *user_data,
|
||||
void *entry
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ hashmap_create (
|
|||
|
||||
void
|
||||
hashmap_destroy (
|
||||
struct hashmap *h
|
||||
struct hashmap *map
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -76,7 +76,7 @@ hashmap_destroy (
|
|||
*/
|
||||
void
|
||||
hashmap_foreach (
|
||||
struct hashmap const *h,
|
||||
struct hashmap const *map,
|
||||
hashmap_walk_func *walk_func,
|
||||
void *user_data
|
||||
);
|
||||
|
@ -95,7 +95,7 @@ hashmap_foreach (
|
|||
*/
|
||||
void *
|
||||
hashmap_search (
|
||||
struct hashmap const *h,
|
||||
struct hashmap const *map,
|
||||
union hashmap_key key,
|
||||
unsigned long hashcode,
|
||||
unsigned long *entry_id_ptr
|
||||
|
@ -105,16 +105,12 @@ hashmap_search (
|
|||
* Insert an entry into the hashmap.
|
||||
*
|
||||
* Invalidates all entry IDs given by previous hashmap_search() calls.
|
||||
*
|
||||
* Returns a pointer to the inserted entry.
|
||||
* The entry must be set to a non-NULL value using this pointer
|
||||
* prior to any further search/insert/delete calls on this hashmap.
|
||||
*/
|
||||
void **
|
||||
void
|
||||
hashmap_insert (
|
||||
struct hashmap *h,
|
||||
union hashmap_key key,
|
||||
unsigned long hashcode
|
||||
struct hashmap *map,
|
||||
unsigned long hashcode,
|
||||
void *entry
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -124,12 +120,10 @@ hashmap_insert (
|
|||
* The entry_id argument should either be the value given by the
|
||||
* hashmap_search() or hashmap_insert() function call where the
|
||||
* entry is returned from, or -1 (less efficient).
|
||||
*
|
||||
* Unlike hashmap_insert(), previously entry IDs are not affected.
|
||||
*/
|
||||
void
|
||||
hashmap_entry_delete (
|
||||
struct hashmap *h,
|
||||
hashmap_delete (
|
||||
struct hashmap *map,
|
||||
void const *entry,
|
||||
long entry_id
|
||||
);
|
||||
|
|
Loading…
Add table
Reference in a new issue