Exemplo n.º 1
0
Arquivo: index.c Projeto: Tigro/eblob
static int eblob_key_range_cmp(const void *k1, const void *k2)
{
	const struct eblob_key *key = k1;
	const struct eblob_index_block *index = k2;
	int cmp;

	/* compare key against start of the [start_key, end_key] range */
	cmp = eblob_id_cmp(key->id, index->start_key.id);

	/* our key is less than the start, skip */
	if (cmp < 0)
		return -1;

	/* our key belongs to the range - it is equal to the start of the range - accept */
	if (cmp == 0)
		return 0;

	/* compare key against end of the [start_key, end_key] range
	 * our key is already bigger than start of the range
	 */
	cmp = eblob_id_cmp(key->id, index->end_key.id);

	/* our key is less or equal than the end of the range - accept */
	if (cmp < 0)
		return 0;
	if (cmp == 0)
		return 0;

	/* key is bigger than the end of the range - skip */
	return 1;
}
Exemplo n.º 2
0
/**
 * __eblob_l2hash_collision_walk() - internal function that walks collision
 * tree getting as close to key as possible.
 * @parent:	pointer to pointer to parent tree node (can be NULL)
 * @node:	pointer to pointer to pointer to last leaf (can be NULL)
 *
 * @parent and @node are needed for subsequent rb_link_node()
 */
static struct rb_node *
__eblob_l2hash_collision_walk(struct rb_root *root, struct eblob_key *key,
		struct rb_node  **parent, struct rb_node ***node)
{
	struct eblob_l2hash_collision *e;
	struct rb_node **n = &root->rb_node;
	int cmp;

	if (parent != NULL)
		*parent = NULL;

	while (*n) {
		if (parent != NULL)
			*parent = *n;

		e = rb_entry(*n, struct eblob_l2hash_collision, node);
		cmp = eblob_id_cmp(key->id, e->key.id);
		if (cmp < 0)
			n = &(*n)->rb_left;
		else if (cmp > 0)
			n = &(*n)->rb_right;
		else
			return *n;
	}
	if (node != NULL)
		*node = n;

	return NULL;
}
Exemplo n.º 3
0
Arquivo: index.c Projeto: Tigro/eblob
int eblob_disk_control_sort(const void *d1, const void *d2)
{
	const struct eblob_disk_control *dc1 = d1;
	const struct eblob_disk_control *dc2 = d2;

	return eblob_id_cmp(dc1->key.id, dc2->key.id);
}
Exemplo n.º 4
0
/**
 * eblob_l2hash_compare_index() - goes to index and compares @key with data in disk
 * control.
 * Index has higher probability to be in memory so use if instead of data file.
 *
 * Returns:
 *	0:	@key belongs to @rctl
 *	1:	@key does not belong to @rctl
 *	Other:	Error
 */
static int eblob_l2hash_compare_index(struct eblob_key *key, struct eblob_ram_control *rctl)
{
	struct eblob_disk_control dc;
	ssize_t err;

	assert(key != NULL);
	assert(rctl != NULL);
	assert(rctl->index_fd >= 0);

	/* Got to disk for index header */
	if ((err = __eblob_l2hash_index_hdr(rctl, &dc)) != 0)
		return err;

	/* Compare given @key with index */
	return !!(eblob_id_cmp(dc.key.id, key->id));
}
Exemplo n.º 5
0
Arquivo: index.c Projeto: Tigro/eblob
int eblob_disk_control_sort_with_flags(const void *d1, const void *d2)
{
	const struct eblob_disk_control *dc1 = d1;
	const struct eblob_disk_control *dc2 = d2;

	int cmp = eblob_id_cmp(dc1->key.id, dc2->key.id);

	if (cmp == 0) {
		if ((dc1->flags & BLOB_DISK_CTL_REMOVE) && !(dc2->flags & BLOB_DISK_CTL_REMOVE))
			cmp = -1;

		if (!(dc1->flags & BLOB_DISK_CTL_REMOVE) && (dc2->flags & BLOB_DISK_CTL_REMOVE))
			cmp = 1;
	}

	return cmp;
}
Exemplo n.º 6
0
/**
 * __eblob_l2hash_insert() - inserts @rctl entry into l2hash.
 * @type:	changes behaviour depending on existence of @key in cache.
 *
 * This is very complicated routine - should be modified with care.
 *
 * Returns:
 *	0:	Success
 *	Other:	Error
 */
static int __eblob_l2hash_insert(struct eblob_l2hash *l2h, struct eblob_key *key,
		struct eblob_ram_control *rctl, unsigned int type)
{
	struct eblob_l2hash_collision *collision;
	struct eblob_l2hash_entry *e;
	struct rb_node *n, *parent, **node;
	int err = 0;

	assert(l2h != NULL);
	assert(key != NULL);
	assert(rctl != NULL);
	assert(pthread_mutex_trylock(&l2h->root_lock) == EBUSY);

	if (type <= EBLOB_L2HASH_TYPE_FIRST)
		return -EINVAL;
	if (type >= EBLOB_L2HASH_TYPE_LAST)
		return -EINVAL;

	/* Search tree for matching entry */
	e = __eblob_l2hash_lookup(l2h, key);
	if (e == NULL) {
		/* No entry with matching l2hash - inserting */
		if (type == EBLOB_L2HASH_TYPE_UPDATE)
			return -ENOENT;
		return __eblob_l2hash_noncollision_insert(&l2h->root, key, rctl);
	}
	/* There is already entry with matching l2hash */
	if (e->collision == 0) {
		struct eblob_disk_control dc;

		/* No collisions - only one entry to check */
		if ((err = __eblob_l2hash_index_hdr(&e->rctl, &dc)) != 0)
			return err;
		if (eblob_id_cmp(key->id, dc.key.id) == 0) {
			/* Not a collision - updating in-place */
			if (type == EBLOB_L2HASH_TYPE_INSERT)
				return -EEXIST;
			e->rctl = *rctl;
			return 0;
		}

		/* This is a collision */
		if (type == EBLOB_L2HASH_TYPE_UPDATE)
			return -ENOENT;

		/* Move old entry to collision tree */
		err = __eblob_l2hash_collision_insert(&l2h->collisions, &dc.key, &e->rctl);
		if (err != 0)
			return err;

		e->collision = 1;
		memset(&e->rctl, 0, sizeof(struct eblob_ram_control));
		return __eblob_l2hash_collision_insert(&l2h->collisions, key, rctl);
	}

	/* Search tree of collisions for matching entry */
	n = __eblob_l2hash_collision_walk(&l2h->collisions, key, &parent, &node);
	if (n == NULL) {
		/* No entry found - inserting one */
		if (type == EBLOB_L2HASH_TYPE_UPDATE)
			return -ENOENT;
		return __eblob_l2hash_collision_insert(&l2h->collisions, key, rctl);
	}

	/* Entry found - modifying in-place  */
	if (type == EBLOB_L2HASH_TYPE_INSERT)
		return -EEXIST;
	collision = rb_entry(n, struct eblob_l2hash_collision, node);
	collision->rctl = *rctl;
	return 0;
}
Exemplo n.º 7
0
Arquivo: index.c Projeto: Tigro/eblob
int eblob_key_sort(const void *key1, const void *key2)
{
	return eblob_id_cmp(((struct eblob_key *)key1)->id, ((struct eblob_key *)key2)->id);
}
Exemplo n.º 8
0
/**
 * _eblob_l2hash_insert() - inserts @rctl entry into l2hash.
 * @flavor:	changes behaviour depending on existence of @key in cache.
 * @replaced:	set to 1 if entry was replaced, to 0 otherwise.
 *
 * This is very complicated routine - should be modified with care.
 *
 * Returns:
 *	0:	Success
 *	Other:	Error
 */
static int _eblob_l2hash_insert(struct eblob_l2hash *l2h,
		const struct eblob_key *key,
		const struct eblob_ram_control *rctl,
		const unsigned int flavor,
		int *replaced)
{
	struct eblob_l2hash_collision *collision;
	struct eblob_l2hash_entry *e;
	struct rb_node *n, *parent, **node;
	int err = 0;

	if (l2h == NULL || key == NULL || rctl == NULL)
		return -EINVAL;

	if (flavor <= EBLOB_L2HASH_FLAVOR_FIRST)
		return -EINVAL;
	if (flavor >= EBLOB_L2HASH_FLAVOR_LAST)
		return -EINVAL;

	if (replaced != NULL)
		*replaced = 0;

	/* Search tree for matching entry */
	e = __eblob_l2hash_lookup(l2h, key);
	if (e == NULL) {
		/* No entry with matching l2hash - inserting */
		if (flavor == EBLOB_L2HASH_FLAVOR_UPDATE)
			return -ENOENT;
		return __eblob_l2hash_noncollision_insert(&l2h->root, key, rctl);
	}
	/* There is already entry with matching l2hash */
	if (e->collision == 0) {
		struct eblob_disk_control dc;

		/* No collisions - only one entry to check */
		if ((err = __eblob_l2hash_index_hdr(&e->rctl, &dc)) != 0)
			return err;
		if (eblob_id_cmp(key->id, dc.key.id) == 0) {
			/* Not a collision - updating in-place */
			if (flavor == EBLOB_L2HASH_FLAVOR_INSERT)
				return -EEXIST;

			/* If entry was replaced - notify caller */
			if (replaced != NULL)
				*replaced = 1;

			e->rctl = *rctl;
			return 0;
		}

		/* This is a collision */
		if (flavor == EBLOB_L2HASH_FLAVOR_UPDATE)
			return -ENOENT;

		/* Move old entry to collision tree */
		err = __eblob_l2hash_collision_insert(&l2h->collisions, &dc.key, &e->rctl);
		if (err != 0)
			return err;

		e->collision = 1;
		memset(&e->rctl, 0, sizeof(struct eblob_ram_control));
		return __eblob_l2hash_collision_insert(&l2h->collisions, key, rctl);
	}

	/* Search tree of collisions for matching entry */
	n = __eblob_l2hash_collision_walk(&l2h->collisions, key, &parent, &node);
	if (n == NULL) {
		/* No entry found - inserting one */
		if (flavor == EBLOB_L2HASH_FLAVOR_UPDATE)
			return -ENOENT;
		return __eblob_l2hash_collision_insert(&l2h->collisions, key, rctl);
	}

	/* Entry found - modifying in-place  */
	if (flavor == EBLOB_L2HASH_FLAVOR_INSERT)
		return -EEXIST;
	collision = rb_entry(n, struct eblob_l2hash_collision, node);
	collision->rctl = *rctl;

	/* If entry was replaced - notify caller */
	if (replaced != NULL)
		*replaced = 1;

	return 0;
}