Пример #1
0
static bool
ohash_table_foreach_remove_helper(void *key, void *data)
{
	struct ohash_pair *op = key;
	struct ohash_foreach_remove_ctx *ctx = data;

	return (*ctx->func)(deconstify_pointer(op->key),
		deconstify_pointer(op->value), ctx->data);
}
Пример #2
0
/**
 * 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;
}
Пример #3
0
/**
 * Check whether slist contains the `key'.
 */
bool
slist_contains_identical(const slist_t *slist, const void *key)
{
	slist_check(slist);

	return NULL != g_slist_find(slist->head, deconstify_pointer(key));
}
Пример #4
0
/**
 * Release the iterator once we're done with it.
 */
void
slist_iter_free(slist_iter_t **iter_ptr)
{
	g_assert(iter_ptr);

	if (*iter_ptr) {
		slist_iter_t *iter;
		slist_t *wslist;

		iter = *iter_ptr;
		slist_iter_check(iter);

		/*
		 * The reference count is an internal state, we're not violating
		 * the "const" contract here (the abstract data type is not  changed).
		 */

		wslist = deconstify_pointer(iter->slist);
		wslist->refcount--;
		iter->magic = 0;

		WFREE(iter);
		*iter_ptr = NULL;
	}
}
Пример #5
0
/**
 * Removes the item at the current position and moves the iterator to the
 * next item.
 */
void
slist_iter_remove(slist_iter_t *iter)
{
	GSList *item, *prev;

	slist_iter_check(iter);
	g_assert(2 == iter->slist->refcount);
	g_assert(iter->cur);
	g_assert(iter->removable);		/* Iterator allows item removal */

	item = iter->cur;
	prev = iter->prev;
	if (!slist_iter_next(iter)) {
		iter->cur = NULL;
		iter->next = NULL;
	}

	/*
	 * We can deconstify the list here because the iterator was explicitly
	 * created to allow removal of items, hence the original pointer given
	 * was not a "const".
	 */

	slist_remove_item(deconstify_pointer(iter->slist), prev, item);
	iter->prev = prev;
	iter->stamp++;
}
Пример #6
0
/**
 * Get rid of the key/value tupple in the leak table.
 */
static void
leak_free_kv(const void *key, void *value, void *unused)
{
	(void) unused;
	xfree(deconstify_pointer(key));
	xfree(value);
}
Пример #7
0
/**
 * Remove `key' from the list.
 * @return whether we found the item in the list and deleted it.
 */
bool
list_remove(list_t *list, const void *key)
{
	GList *item;

	list_check(list);

	item = g_list_find(list->head, deconstify_pointer(key));
	if (item) {

		if (item == list->head) {
			list->head = g_list_next(list->head);
		}
		if (item == list->tail) {
			list->tail = g_list_previous(list->tail);
		}
		/* @note: Return value is only assigned to "item" because
	 	 *        g_slist_delete_link is incorrectly tagged to
	 	 *        cause a GCC compiler warning otherwise.
	 	 */
		item = g_list_delete_link(item, item);

		list->length--;
		list->stamp++;

		list_regression(list);
		return TRUE;
	}
	return FALSE;
}
Пример #8
0
/**
 * Initialize internal state for our incremental zlib stream.
 *
 * @param zs		the zlib stream structure to initialize
 * @param data		input data to process; if NULL, will be incrementally given
 * @param len		length of data to process (if data not NULL) or estimation
 * @param dest		where processed data should go, or NULL if allocated
 * @param destlen	length of supplied output buffer, if dest != NULL
 */
static void
zlib_stream_init(zlib_stream_t *zs,
                 const void *data, size_t len, void *dest, size_t destlen)
{
    z_streamp z;

    g_assert(size_is_non_negative(len));
    g_assert(size_is_non_negative(destlen));

    zs->in = data;
    zs->inlen = data ? len : 0;
    zs->inlen_total = zs->inlen;

    /*
     * When deflating zlib requires normally 0.1% more + 12 bytes, we use
     * 0.5% to be safe.
     *
     * When inflating, assume we'll double the input at least.
     */

    if (NULL == dest) {
        /* Processed data go to a dynamically allocated buffer */
        if (!zs->allocated) {
            if (data == NULL && len == 0)
                len = 512;

            if (ZLIB_DEFLATER_MAGIC == zs->magic) {
                zs->outlen = (len * 1.005 + 12.0);
                g_assert(zs->outlen > len);
                g_assert(zs->outlen - len >= 12);
            } else {
                zs->outlen = UNSIGNED(len) * 2;
            }

            zs->out = halloc(zs->outlen);
            zs->allocated = TRUE;
        }
    } else {
        /* Processed data go to a supplied buffer, not-resizable */
        if (zs->allocated)
            hfree(zs->out);
        zs->out = dest;
        zs->outlen = destlen;
        zs->allocated = FALSE;
    }

    /*
     * Initialize Z stream.
     */

    z = zs->z;
    g_assert(z != NULL);			/* Stream not closed yet */

    z->next_out = zs->out;
    z->avail_out = zs->outlen;
    z->next_in = deconstify_pointer(zs->in);
    z->avail_in = 0;			/* Will be set by zlib_xxx_step() */
}
Пример #9
0
/**
 * 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;
}
Пример #10
0
static void
hash_list_freecb_wrapper(void *data, void *user_data)
{
	free_fn_t freecb = cast_pointer_to_func(user_data);
	struct hash_list_item *item = data;

	(*freecb)(deconstify_pointer(item->key));
	item->key = NULL;
}
Пример #11
0
/**
 * Add value to the table.
 *
 * If it was already present, its lifetime is reset to the aging delay.
 *
 * The key argument is freed immediately if there is a free routine for
 * keys and the key was present in the table.
 *
 * The previous value is freed and replaced by the new one if there is
 * an insertion conflict and the key pointers are different.
 */
void
aging_insert(aging_table_t *ag, const void *key, void *value)
{
	bool found;
	void *ovalue;
	time_t now = tm_time();
	struct aging_value *aval;

	aging_check(ag);

	aging_synchronize(ag);

	found = hikset_lookup_extended(ag->table, key, &ovalue);
	if (found) {
		aval = ovalue;

		if (ag->kvfree != NULL) {
			/*
			 * We discard the new and keep the old key instead.
			 * That way, we don't have to update the hash table.
			 */

			(*ag->kvfree)(deconstify_pointer(key), aval->value);
		}

		/*
		 * Value existed for this key, reset its lifetime by moving the
		 * entry to the tail of the list.
		 */

		aval->value = value;
		aval->last_insert = now;
		elist_moveto_tail(&ag->list, aval);
	} else {
		WALLOC(aval);
		aval->value = value;
		aval->key = deconstify_pointer(key);
		aval->last_insert = now;
		hikset_insert(ag->table, aval);
		elist_append(&ag->list, aval);
	}

	aging_return_void(ag);
}
Пример #12
0
/**
 * @returns the first item of the list, or NULL if none.
 */
void *
hash_list_head(const hash_list_t *hl)
{
	struct hash_list_item *item;

	hash_list_check(hl);

	item = elist_head(&hl->list);
	return NULL == item ? NULL : deconstify_pointer(item->key);
}
Пример #13
0
/**
 * Iterator callback to trigger TX stack servicing.
 */
static void
udp_sched_tx_service(void *data, void *udata)
{
	struct udp_tx_stack *uts = data;
	struct udp_service_ctx *ctx = udata;

	udp_sched_log(4, "servicing TX=%p", uts->tx);
	(*uts->writable)(deconstify_pointer(uts->tx), ctx->fd, ctx->cond);
	udp_sched_log(4, "done for TX=%p", uts->tx);
}
Пример #14
0
/**
 * Get the item before a given key.
 */
void *
hash_list_previous(hash_list_t *hl, const void *key)
{
	struct hash_list_item *item;

	hash_list_check(hl);

	item = hikset_lookup(hl->ht, key);
	item = item ? elist_data(&hl->list, elist_prev(&item->lnk)) : NULL;
	return item ? deconstify_pointer(item->key) : NULL;
}
Пример #15
0
static bool
cq_free_periodic(const void *key, void *data)
{
	cperiodic_t *cp = deconstify_pointer(key);

	(void) data;

	cperiodic_check(cp);
	cp->magic = 0;
	WFREE(cp);
	return TRUE;
}
Пример #16
0
/**
 * Frees the key/values from the headers hash.
 */
static bool
free_header_data(const void *key, void *value, void *unused_udata)
{
	void *k;

	(void) unused_udata;

	k = deconstify_pointer(key);
	hfree(k);					/* XXX if shared, don't do that */
	str_destroy(value);
	return TRUE;
}
Пример #17
0
static bool
cq_free_idle(const void *key, void *data)
{
	cidle_t *ci = deconstify_pointer(key);

	(void) data;

	cidle_check(ci);
	ci->magic = 0;
	WFREE(ci);
	return TRUE;
}
Пример #18
0
static bool
free_hash_entry(const void *key, void *value, void *unused_data)
{
    struct term_counts *val = value;
    char *s = deconstify_pointer(key);

    (void) unused_data;

    wfree(s, 1 + strlen(s));
    WFREE(val);
    return TRUE;
}
Пример #19
0
/**
 * 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;
	}
}
Пример #20
0
/**
 * Apply `func' to all the items in the structure.
 */
void
hash_list_foreach(const hash_list_t *hl, data_fn_t func, void *user_data)
{
	link_t *lk;
	
	hash_list_check(hl);
	g_assert(NULL != func);

	for (lk = elist_first(&hl->list); lk != NULL; lk = elist_next(lk)) {
		struct hash_list_item *item = ITEM(lk);
		(*func)(deconstify_pointer(item->key), user_data);
	}

	hash_list_regression(hl);
}
Пример #21
0
/**
 * Remove current iterator item, returned by hikset_iter_next().
 */
void
hikset_iter_remove(hikset_iter_t *hxi)
{
	hikset_t *hx;
	size_t idx;

	hikset_iter_check(hxi);
	g_assert(size_is_positive(hxi->pos));		/* Called _next() once */
	g_assert(hxi->pos <= hxi->hx->kset.size);

	hx = deconstify_pointer(hxi->hx);
	idx = hxi->pos - 1;		/* Current item */
	if (hash_keyset_erect_tombstone(&hx->kset, idx))
		hx->kset.items--;
	hxi->deleted = TRUE;
}
Пример #22
0
/**
 * Prepend `key' to the list.
 */
void
list_prepend(list_t *list, const void *key)
{
	list_check(list);
	g_assert(1 == list->refcount);

	list->head = g_list_prepend(list->head, deconstify_pointer(key));
	if (!list->tail) {
		list->tail = list->head;
	}

	list->length++;
	list->stamp++;

	list_regression(list);
}
Пример #23
0
/**
 * Extract the list of items so that the caller can iterate at will over
 * it as sort it.  The caller must dispose of that list via g_list_free().
 * The underlying data is not copied so it must NOT be freed.
 *
 * @returns a shallow copy of the underlying list.
 */
GList *
hash_list_list(hash_list_t *hl)
{
	GList *l = NULL;
	link_t *lk;

	hash_list_check(hl);

	for (lk = elist_last(&hl->list); lk != NULL; lk = elist_prev(lk)) {
		struct hash_list_item *item = ITEM(lk);

		l = g_list_prepend(l, deconstify_pointer(item->key));
	}

	return l;
}
Пример #24
0
/**
 * 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);
}
Пример #25
0
/**
 * Remove specified item.
 *
 * @return the original key.
 */
static void * 
hash_list_remove_item(hash_list_t *hl, struct hash_list_item *item)
{
	void *key;

	g_assert(item);

	key = deconstify_pointer(item->key);
	hikset_remove(hl->ht, key);
	elist_link_remove(&hl->list, &item->lnk);
	WFREE(item);

	hl->stamp++;		/* Unsafe operation when iterating */

	hash_list_regression(hl);
	return key;
}
Пример #26
0
/**
 * Get the previous data item from the iterator, or NULL if none.
 */
G_GNUC_HOT void *
hash_list_iter_previous(hash_list_iter_t *iter)
{
	link_t *prev;

	hash_list_iter_check(iter);

	prev = iter->prev;
	if (prev != NULL) {
		iter->item = ITEM(prev);
		iter->next = elist_next(prev);
		iter->prev = elist_prev(prev);
		return deconstify_pointer(iter->item->key);
	} else {
		return NULL;
	}
}
Пример #27
0
/**
 * Fetch value from the hash set.
 *
 * @param ht		the hash table
 * @param key		the key being looked up
 *
 * @return found value, or NULL if not found.
 */
void *
hevset_lookup(const hevset_t *ht, const void *key)
{
	size_t idx;
	void *kptr;

	hevset_check(ht);
	g_assert(key != NULL);

	idx = hash_lookup_key(HASH(ht), key);

	if ((size_t) -1 == idx)
		return NULL;

	kptr = deconstify_pointer(ht->kset.keys[idx]);
	return ptr_add_offset(kptr, -ht->offset);
}
Пример #28
0
/**
 * Get the next data item from the iterator, or NULL if none.
 */
G_GNUC_HOT void *
hash_list_iter_next(hash_list_iter_t *iter)
{
	link_t *next;

	hash_list_iter_check(iter);

	next = iter->next;
	if (next != NULL) {
		iter->item = ITEM(next);
		iter->prev = elist_prev(next);
		iter->next = elist_next(next);
		return deconstify_pointer(iter->item->key);
	} else {
		return NULL;
	}
}
Пример #29
0
/**
 * @return last sibling of node, NULL if node is NULL.
 */
static node_t *
etree_node_last_sibling(const node_t *n)
{
	const node_t *sn, *next;

	if (NULL == n)
		return NULL;

	for (sn = n; /* empty */; sn = next) {
		next = sn->sibling;
		if (NULL == next)
			break;
	}

	g_assert(sn != NULL);	/* Found last sibling */

	return deconstify_pointer(sn);
}
Пример #30
0
/**
 * Creates an iovec from a singly-linked list of pmsg_t buffers.
 * It should be freed via hfree().
 *
 * NOTE: The iovec will hold no more than MAX_IOV_COUNT items. That means
 *       the iovec might not cover the whole buffered data. This limit
 *		 is applied because writev() could fail with EINVAL otherwise
 *		 which would simply add more unnecessary complexity.
 */
iovec_t *
pmsg_slist_to_iovec(slist_t *slist, int *iovcnt_ptr, size_t *size_ptr)
{
	iovec_t *iov;
	size_t held = 0;
	int n;

	g_assert(slist);

	n = slist_length(slist);

	if (n > 0) {
		slist_iter_t *iter;
		int i;

		n = MIN(n, MAX_IOV_COUNT);
		iov = halloc(n * sizeof *iov);

		iter = slist_iter_before_head(slist);
		for (i = 0; i < n; i++) {
			pmsg_t *mb;
			size_t size;

			mb = slist_iter_next(iter);
			pmsg_check_consistency(mb);

			size = pmsg_size(mb);
			g_assert(size > 0);
			held += size;

			iovec_set(&iov[i], deconstify_pointer(pmsg_read_base(mb)), size);
		}
		slist_iter_free(&iter);
	} else {
		iov = NULL;
	}
	if (iovcnt_ptr) {
		*iovcnt_ptr = MAX(0, n);
	}
	if (size_ptr) {
		*size_ptr = held;
	}
	return iov;
}