コード例 #1
0
/**
 * btree_insert_non_full
 * @access private
 * @param btree struct
 * @param btree node
 * @param key
 * @param data index
 * @return void
 *
 * inserts the node into the btree - either immediately if it's a leaf or find the branch, split
 * the child and call this recursively until a leaf is found
 */
static void btree_insert_non_full(btree_tree *t, btree_node *node, uint64_t key, uint32_t data_idx)
{
	uint32_t i;
	btree_node *tmp_node;

	i = node->nr_of_keys;
	if (node->leaf) {
		while (i > 0 && key < node->keys[i - 1].key) {
			node->keys[i] = node->keys[i - 1];
			i--;
		}
		node->keys[i].key = key;
		node->nr_of_keys++;

		/* Fetch data index, and set it to the idx element here too */
		node->keys[i].idx = data_idx;

		/* Do administrative jobs */
		dr_set_add(&(t->freelist), data_idx);
		t->header->item_count++;
	} else {
		tmp_node = btree_find_branch(t, node, key, &i);
		if (tmp_node->nr_of_keys == BTREE_T2(t) - 1) {
			btree_split_child(t, node, i, tmp_node);
			if (key > node->keys[i].key) {
				i++;
			}
		}
		btree_insert_non_full(t, btree_get_node(t, node->branch[i]), key, data_idx);
	}
}
コード例 #2
0
/**
 * btree_dump_node_dot
 * @access private
 * @param btree struct
 * @param btree node
 * @return void
 *
 * Outputs (using printf or php_printf) a physical representation
 * of the tree and it's data in a table format
 */
static void btree_dump_node_dot(btree_tree *t, btree_node *node)
{
	int i;

	BTREE_PRINT("\n\"IDX%d\" [\nlabel=\"{{", node->idx);
	for (i = 0; i < node->nr_of_keys; i++) {
		BTREE_PRINT("%s%lu", i ? " | " : "", node->keys[i].key);
	}
	BTREE_PRINT("} ");
	if (!node->leaf) {
		BTREE_PRINT("| {");
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			BTREE_PRINT("%s<n%d>%d", i ? " | " : "", i, node->branch[i]);
		}
		BTREE_PRINT("}}\"\n];\n");
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			BTREE_PRINT("\"IDX%d\":n%d->\"IDX%d\";\n", node->idx, i, node->branch[i]);
		}
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			btree_dump_node_dot(t, btree_get_node(t, node->branch[i]));
		}
	} else {
		BTREE_PRINT("}\"\n];\n");
	}
}
コード例 #3
0
/**
 * btree_open
 * @access public
 * @param path to the file to use for mmap, must be absolute
 * @param error code for error handling on other side
 * @return struct with open btree
 *
 * This will attempt to open an existing btree
 * Must be unmapped and freed using btree_close after use
 */
BTREE_API btree_tree *btree_open(const char *path, int *error)
{
	btree_tree *t;
	*error = 0;

	t = malloc(sizeof(btree_tree));
	if (t == NULL) {
		*error = errno;
		return NULL;
	}

	*error = btree_open_file(t, path);
	if (*error != 0) {
		free(t);
		return NULL;
	}

	t->freelist.size = t->header->max_items;
	t->freelist.setinfo = t->mmap + BTREE_HEADER_SIZE;

	t->nodes = t->mmap +
		BTREE_HEADER_SIZE +
		BTREE_FREELIST_SIZE(t->header->max_items);

	t->data = t->mmap +
		BTREE_HEADER_SIZE +
		BTREE_FREELIST_SIZE(t->header->max_items) +
		(t->header->node_count * 4096);

	t->root = btree_get_node(t, t->header->root_node_idx);

	return t;
}
コード例 #4
0
/**
 * btree_find_branch
 * @access private
 * @param btree struct
 * @param btree node
 * @param key
 * @param i
 * @return void
 *
 * finds the branch for the node and calls btree_get_node 
 */
static btree_node* btree_find_branch(btree_tree *t, btree_node *node, uint64_t key, uint32_t *i)
{
	*i = node->nr_of_keys;
	while (*i > 0 && key < node->keys[(*i) - 1].key) {
		(*i)--;
	}
	return btree_get_node(t, node->branch[*i]);
}
コード例 #5
0
/**
 * btree_find_greatest
 * @access private
 * @param btree struct
 * @param btree node
 * @return btree node
 *
 * find greatest node in a branch
 */
static btree_node *btree_find_greatest(btree_tree *t, btree_node *node)
{
	btree_node *ptr = node;
	while (!ptr->leaf) {
		ptr = btree_get_node(t, ptr->branch[ptr->nr_of_keys]);
	}
	return ptr;
}
コード例 #6
0
/**
 * btree_find_smallest
 * @access private
 * @param btree struct
 * @param btree node
 * @return btree node
 *
 * find smallest node in a branch
 */
static btree_node *btree_find_smallest(btree_tree *t, btree_node *node)
{
	btree_node *ptr = node;
	while (!ptr->leaf) {
		ptr = btree_get_node(t, ptr->branch[0]);
	}
	return ptr;
}
コード例 #7
0
ファイル: tree.c プロジェクト: Arkaniad/libtree
// Get a specific node from a tree
btree_node *btree_get_node(btree *tree, int num){
  btree_node *root;
  root = tree->root;
  if(root->num == num){
    return root;
  } else {
    if(root->num < num){
      if(root->right != NULL) {
        return btree_get_node((btree_node *)root->right, num);
      } else {
        return (btree_node*) NULL;
      }
    } else {
      if(root->left != NULL) {
        return btree_get_node(root->left, num);
      } else {
        return (btree_node*) NULL;
      }
    }
  }
}
コード例 #8
0
/**
 * btree_dump_node
 * @access private
 * @param btree struct
 * @return void
 *
 * Recursive helper for printing out the contents of a node,
 * used by btree_dump
 */
static void btree_dump_node(btree_tree *t, btree_node *node)
{
	int i;

	BTREE_PRINT("\nIDX: %d\n", node->idx);
	for (i = 0; i < node->nr_of_keys; i++) {
		BTREE_PRINT("%9lu ", node->keys[i].key);
	}
	if (!node->leaf) {
		BTREE_PRINT("\n");
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			BTREE_PRINT("%9d ", node->branch[i]);
		}
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			btree_dump_node(t, btree_get_node(t, node->branch[i]));
		}
	}
}
コード例 #9
0
/**
 * btree_dump_node_test
 * @access private
 * @param btree struct
 * @param btree node
 * @param level to output
 * @return void
 *
 * Recursive helper for printing out the contents of a node,
 * used by btree_dump_test - provides more information than the normal dump
 */
static void btree_dump_node_test(btree_tree *t, btree_node *node, int level)
{
	int i;

	BTREE_PRINT("\n%*sIDX: %d: ", level * 2, "", node->idx);
	if (!node->leaf) {
		BTREE_PRINT("(%d) ", node->branch[0]);
	}
	for (i = 0; i < node->nr_of_keys; i++) {
		BTREE_PRINT("%lu ", node->keys[i].key);
		if (!node->leaf) {
			BTREE_PRINT("(%d) ", node->branch[i+1]);
		}
	}
	if (!node->leaf) {
		for (i = 0; i < node->nr_of_keys + 1; i++) {
			btree_dump_node_test(t, btree_get_node(t, node->branch[i]), level + 1);
		}
	}
}
コード例 #10
0
/**
 * btree_search_internal
 * @access private
 * @param btree struct
 * @param btree node
 * @param key
 * @param index to fill
 * @return 1 if found, 0 if not
 *
 * does the actual search of the tree to find an index location
 * can be called recursively as the nodes are walked
 */
static int btree_search_internal(btree_tree *t, btree_node *node, uint64_t key, uint32_t *idx)
{
	int i = 0;
	while (i < node->nr_of_keys && key > node->keys[i].key) {
		i++;
	}

	if (i < node->nr_of_keys && key == node->keys[i].key) {
		if (idx) {
			*idx = node->keys[i].idx;
		}
		return 1;
	}

	if (node->leaf) {
		return 0;
	} else {
		btree_node *tmp_node = btree_get_node(t, node->branch[i]);
		return btree_search_internal(t, tmp_node, key, idx);
	}
}
コード例 #11
0
/**
 * btree_delete_internal
 * @access private
 * @param btree struct
 * @param btree node
 * @param key that was requested for deletion
 * @param current key
 * @param data index
 * @return int 1 on success, 0 on failure
 *
 * Removes a node at key from the btree
 * Locks the entire tree until complete
 */
static int btree_delete_internal(btree_tree *t, btree_node *node, uint64_t key_to_delete, uint64_t key, uint32_t *data_idx_to_free)
{
	uint32_t idx;
	uint32_t data_idx;

	/* if x is a leaf then
	 *   if k is in x then
	 *     delete k from x and return true
	 *   else return false //k is not in subtree
	 */
	if (node->leaf) {
		if (btree_check_key_in_node(node, key, &idx, &data_idx)) {
			btree_delete_key_idx_from_node(node, idx);
			btree_delete_branch_idx_from_node(node, idx);
			if (key == key_to_delete) {
				*data_idx_to_free = data_idx;
			}
			return 1;
		} else {
			return 0;
		}
	} else {
		/* if k is in x then */
		if (btree_check_key_in_node(node, key, &idx, &data_idx)) {
			btree_node *y, *node_with_prev_key;
			/* Record the data_idx for this key */
			if (key == key_to_delete) {
				*data_idx_to_free = data_idx;
			}
			/*   y = the child of x that precedes k
			 *   if y has at least t keys then
			 *     k' = the predecessor of k (use B-Tree-FindLargest)
			 *     Copy k' over k //i.e., replace k with k'
			 *     B-Tree-Delete(y, k') //Note: recursive call
			 */
			y = btree_get_node(t, node->branch[idx]);
			if (y->nr_of_keys >= BTREE_T(t)) {
				node_with_prev_key = btree_find_greatest(t, y);
				node->keys[idx] = node_with_prev_key->keys[y->nr_of_keys-1];
				return btree_delete_internal(t, y, key_to_delete, node_with_prev_key->keys[y->nr_of_keys-1].key, data_idx_to_free);
			} else {
				btree_node *z, *node_with_next_key;
			/*   else //y has t-1 keys
			 *     z = the child of x that follows k
			 *     if z has at least t keys then
			 *       k' = the successor of k
			 *       Copy k' over k //i.e., replace k with k'
			 *       B-Tree-Delete(z, k') //Note: recursive call
			 */
				z = btree_get_node(t, node->branch[idx + 1]);
				if (z->nr_of_keys >= BTREE_T(t)) {
					node_with_next_key = btree_find_smallest(t, z);
					node->keys[idx] = node_with_next_key->keys[0];
					btree_delete_internal(t, z, key_to_delete, node_with_next_key->keys[0].key, data_idx_to_free);
				} else {
			/*     else //both y and z have t-1 keys
			 *       merge k and all of z into y //y now contains 2t-1 keys.
			 *       //k and the pointer to z will be deleted from x.
			 *       B-Tree-Delete(y, k) //Note: recursive call
			 */
					btree_merge(t, y, node, idx, z);
					btree_delete_key_idx_from_node(node, idx);
					btree_delete_branch_idx_from_node(node, idx + 1);
					btree_delete_internal(t, y, key_to_delete, key, data_idx_to_free);
					if (t->root->nr_of_keys == 0 && !t->root->leaf) {
						t->root = btree_get_node(t, t->root->branch[0]);
					}
				}
			}
		} else {
			btree_node *c;
			uint32_t i;

			c = btree_find_branch(t, node, key, &i);
			if (c->nr_of_keys <= BTREE_T(t) - 1) {
				btree_node *z, *node_with_prev_key, *node_with_next_key;
				btree_key tmp_key;

				/* Is there a left sibling with T or more keys? */
				if (i > 0) { /* otherwise there is no left sibling */
					z = btree_get_node(t, node->branch[i - 1]);
					if (z->nr_of_keys > BTREE_T(t) - 1) {
						node_with_prev_key = btree_find_greatest(t, z);
						btree_node_insert_key(t, c, 0, node_with_prev_key->keys[z->nr_of_keys-1]);
						btree_delete_internal(t, z, key_to_delete, node_with_prev_key->keys[z->nr_of_keys-1].key, data_idx_to_free);

						/* Swap parent and first key in C */
						tmp_key = node->keys[i-1];
						node->keys[i-1] = c->keys[0];
						c->keys[0] = tmp_key;
						goto proceed;
					}
				}

				/* Is there a left sibling with T or more keys? */
				if (i < node->nr_of_keys) { /* otherwise there is no right sibling */
					z = btree_get_node(t, node->branch[i + 1]);
					if (z->nr_of_keys > BTREE_T(t) - 1) {
						node_with_next_key = btree_find_smallest(t, z);
						btree_node_insert_key(t, c, c->nr_of_keys, node_with_next_key->keys[0]);
						btree_delete_internal(t, z, key_to_delete, node_with_next_key->keys[0].key, data_idx_to_free);

						/* Swap parent and last key in C */
						tmp_key = node->keys[i];
						node->keys[i] = c->keys[c->nr_of_keys - 1];
						c->keys[c->nr_of_keys - 1] = tmp_key;
						goto proceed;
					}
				}

				/* No siblings, so we need to merge. */
				/* Is there a left sibling? */
				if (i > 0) { /* otherwise there is no left sibling */
					z = btree_get_node(t, node->branch[i - 1]);
					btree_merge(t, z, node, i - 1, c);
					btree_delete_branch_idx_from_node(node, i);
					btree_delete_key_idx_from_node(node, i - 1);
					if (t->root->nr_of_keys == 0 && !t->root->leaf) {
						t->root = btree_get_node(t, t->root->branch[0]);
					}
					return btree_delete_internal(t, z, key_to_delete, key, data_idx_to_free);
				}
				/* Is there a right sibling? */
				if (i < node->nr_of_keys) { /* otherwise there is no right sibling */
					z = btree_get_node(t, node->branch[i + 1]);
					btree_merge(t, c, node, i, z);
					btree_delete_branch_idx_from_node(node, i + 1);
					btree_delete_key_idx_from_node(node, i);
					if (t->root->nr_of_keys == 0 && !t->root->leaf) {
						t->root = btree_get_node(t, t->root->branch[0]);
					}
					return btree_delete_internal(t, c, key_to_delete, key, data_idx_to_free);
				}
			}
proceed:
			return btree_delete_internal(t, c, key_to_delete, key, data_idx_to_free);
		}
	}
	return 0;
}