/** * Replace a key/value pair in the table. * * If the key already existed, the old key/values are replaced by the new ones, * at the same position. Otherwise, the key is appended. * * @return TRUE when replacement occurred (the key existed). */ bool ohash_table_replace(ohash_table_t *oh, const void *key, const void *value) { struct ohash_pair pk; struct ohash_pair *op; const void *hkey; void *pos = NULL; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (hash_list_find(oh->hl, &pk, &hkey)) { op = deconstify_pointer(hkey); g_assert(op->oh == oh); pos = hash_list_remove_position(oh->hl, &pk); } else { WALLOC(op); op->oh = oh; op->key = key; } op->value = value; if (pos != NULL) { hash_list_insert_position(oh->hl, op, pos); } else { hash_list_append(oh->hl, op); } return pos != NULL; }
/** * Lookup an attribute in the table. * * The key is only used for lookups, only the hashed elements need to be * filled in. */ static struct xattr * xattr_table_lookup_key(const xattr_table_t *xat, const struct xattr *key) { const void *it; xattr_table_check(xat); return hash_list_find(xat->hl, key, &it) ? deconstify_pointer(it) : NULL; }
/** * Detach a UDP TX scheduling layer from a TX stack. * * @param us the UDP TX scheduler to detach from * @param tx the TX driver detaching from the scheduler */ void udp_sched_detach(udp_sched_t *us, const txdrv_t *tx) { struct udp_tx_stack key, *uts; const void *oldkey; udp_sched_check(us); key.tx = tx; g_assert(hash_list_contains(us->stacks, &key)); hash_list_find(us->stacks, &key, &oldkey); uts = deconstify_pointer(oldkey); hash_list_remove(us->stacks, uts); WFREE(uts); }
/** * Lookup a key in the table. */ void * ohash_table_lookup(const ohash_table_t *oh, const void *key) { struct ohash_pair pk; const void *hkey; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (hash_list_find(oh->hl, &pk, &hkey)) { const struct ohash_pair *op = hkey; g_assert(op->oh == oh); return deconstify_pointer(op->value); } else { return NULL; } }
/** * Extended lookup of a key in the table, returning both key/value pointers. */ bool ohash_table_lookup_extended(const ohash_table_t *oh, const void *key, void *okey, void *oval) { struct ohash_pair pk; const void *hkey; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (hash_list_find(oh->hl, &pk, &hkey)) { const struct ohash_pair *op = hkey; g_assert(op->oh == oh); if (okey != NULL) *(void **) okey = deconstify_pointer(op->key); if (oval != NULL) *(void **) oval = deconstify_pointer(op->value); return TRUE; } else { return FALSE; } }
/** * Locate statistics structure for the file. * * If a SHA1 is given, we search by SHA1. Otherwise we search by (name, size) * and if the record is missing the SHA1, probably because it was not * available at the time of insertion, then it is added to the structure * and recorded as such. */ static struct ul_stats * upload_stats_find(const struct sha1 *sha1, const char *pathname, guint64 size) { struct ul_stats *s = NULL; if (upload_stats_list) { static const struct ul_stats zero_stats; struct ul_stats key; gconstpointer orig_key; g_assert(upload_stats_by_sha1); if (sha1) { s = g_hash_table_lookup(upload_stats_by_sha1, sha1); if (s) goto done; /* Found it by SHA1 */ } key = zero_stats; key.pathname = atom_str_get(pathname); key.size = size; if (hash_list_find(upload_stats_list, &key, &orig_key)) s = deconstify_gpointer(orig_key); atom_str_free_null(&key.pathname); if (s && sha1) { /* Was missing from the by-SHA1 table */ if (NULL == s->sha1) { /* SHA1 was unknown */ s->sha1 = atom_sha1_get(sha1); } else { /* SHA1 changed, file was modified */ struct ul_stats *old = g_hash_table_lookup(upload_stats_by_sha1, s->sha1); g_assert(old == s); /* Must be the same filename entry */ g_hash_table_remove(upload_stats_by_sha1, s->sha1); atom_sha1_free(s->sha1); s->sha1 = atom_sha1_get(sha1); } gm_hash_table_insert_const(upload_stats_by_sha1, s->sha1, s); } } done: /* We guarantee the SHA1 is present in the record if known */ g_assert(!(s && sha1) || s->sha1); /* Postcondition: if we return something, it must be "correct" */ if (s != NULL) { g_assert(atom_is_str(s->pathname)); g_assert(atom_is_str(s->filename)); g_assert(s->norm >= 0.0); } return s; }