/** * Check whether a key is contained in the table. */ bool ohash_table_contains(const ohash_table_t *oh, const void *key) { struct ohash_pair pk; ohash_table_check(oh); pk.oh = oh; pk.key = key; return hash_list_contains(oh->hl, &pk); }
/** * 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); }
/** * Allocate a new entry in the cache to hold the deserialized value. * * @param dw the DBM wrapper * @param key key we want a cache entry for * @param filled optionally, a new cache entry already filled with the data * * @attention * An older cache entry structure can be returned, and it will still * point to the previous data. Caller should normally invoke fill_entry() * immediately to make sure these stale data are not associated wrongly * with the new key, or supply his own filled structure directly. * * @return a cache entry object that can be filled with the value. */ static struct cached * allocate_entry(dbmw_t *dw, gconstpointer key, struct cached *filled) { struct cached *entry; gpointer saved_key; g_assert(!hash_list_contains(dw->keys, key)); g_assert(!map_contains(dw->values, key)); g_assert(!filled || (!filled->len == !filled->data)); saved_key = wcopy(key, dbmw_keylen(dw, key)); /* * If we have less keys cached than our maximum, add it. * Otherwise evict the least recently used key, at the head. */ if (hash_list_length(dw->keys) < dw->max_cached) { if (filled) entry = filled; else WALLOC0(entry); } else { gpointer head; g_assert(hash_list_length(dw->keys) == dw->max_cached); head = hash_list_head(dw->keys); entry = remove_entry(dw, head, filled != NULL, TRUE); g_assert(filled != NULL || entry != NULL); if (filled) entry = filled; } /* * Add entry into cache. */ g_assert(entry); hash_list_append(dw->keys, saved_key); map_insert(dw->values, saved_key, entry); return entry; }
/** * Attach a UDP TX scheduling layer to a TX stack. * * @param us the UDP TX scheduler to use * @param tx the TX driver attaching to the scheduler * @param writable TX handler to invoke when we can write new data */ void udp_sched_attach(udp_sched_t *us, const txdrv_t *tx, inputevt_handler_t writable) { struct udp_tx_stack key, *uts; udp_sched_check(us); key.tx = tx; g_assert(!hash_list_contains(us->stacks, &key)); WALLOC(uts); uts->tx = tx; uts->writable = writable; hash_list_append(us->stacks, uts); }
static bool udp_ping_register(const struct guid *muid, host_addr_t addr, uint16 port, udp_ping_cb_t cb, void *data, bool multiple) { struct udp_ping *ping; uint length; g_assert(muid); g_return_val_if_fail(udp_pings, FALSE); if (hash_list_contains(udp_pings, muid)) { /* Probably a duplicate */ return FALSE; } /* random early drop */ length = hash_list_length(udp_pings); if (length >= UDP_PING_MAX) { return FALSE; } else if (length > (UDP_PING_MAX / 4) * 3) { if (random_value(UDP_PING_MAX - 1) < length) return FALSE; } WALLOC(ping); ping->muid = *muid; ping->added = tm_time(); { gnet_host_t host; gnet_host_set(&host, addr, port); ping->host = atom_host_get(&host); } if (cb != NULL) { WALLOC0(ping->callback); ping->callback->cb = cb; ping->callback->data = data; ping->callback->multiple = booleanize(multiple); } else { ping->callback = NULL; } hash_list_append(udp_pings, ping); return TRUE; }
static void uhc_list_append(const char *host) { struct uhc *uhc; g_return_if_fail(host); uhc = uhc_new(host); if (hash_list_contains(uhc_list, uhc)) { g_warning("duplicate bootstrap UHC: \"%s\"", uhc->host); uhc_free(&uhc); return; } if (GNET_PROPERTY(bootstrap_debug) > 1) g_debug("adding UHC %s", host); hash_list_append(uhc_list, uhc); }
/** * Remove a key from the table. * * @return TRUE if the key was found and removed. */ bool ohash_table_remove(ohash_table_t *oh, const void *key) { struct ohash_pair pk; struct ohash_pair *op; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (!hash_list_contains(oh->hl, &pk)) return FALSE; op = hash_list_remove(oh->hl, &pk); g_assert(op->oh == oh); ohash_free_kv(op); return TRUE; }
/** * Insert a key/value pair in the table. * * If the key already exists, the value is replaced (but the old key is kept). * * For ordering purposes, the key is appended to the list of keys, unless it * already existed in which case its position is unchanged. */ void ohash_table_insert(ohash_table_t *oh, const void *key, const void *value) { struct ohash_pair pk; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (!hash_list_contains(oh->hl, &pk)) { struct ohash_pair *op; WALLOC(op); op->key = key; op->value = value; op->oh = oh; hash_list_append(oh->hl, op); } }