/**
 * 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);
}
Beispiel #3
0
/**
 * 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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
	}
}