staticint keyzero(struct btree_geo *geo, unsignedlong *key)
{ int i;
for (i = 0; i < geo->keylen; i++) if (key[i]) return0;
return1;
}
staticvoid *btree_lookup_node(struct btree_head *head, struct btree_geo *geo, unsignedlong *key)
{ int i, height = head->height; unsignedlong *node = head->node;
if (height == 0) return NULL;
for ( ; height > 1; height--) { for (i = 0; i < geo->no_pairs; i++) if (keycmp(geo, node, i, key) <= 0) break; if (i == geo->no_pairs) return NULL;
node = bval(geo, node, i); if (!node) return NULL;
} return node;
}
node = btree_lookup_node(head, geo, key); if (!node) return NULL;
for (i = 0; i < geo->no_pairs; i++) if (keycmp(geo, node, i, key) == 0) return bval(geo, node, i); return NULL;
}
EXPORT_SYMBOL_GPL(btree_lookup);
int btree_update(struct btree_head *head, struct btree_geo *geo, unsignedlong *key, void *val)
{ int i; unsignedlong *node;
node = btree_lookup_node(head, geo, key); if (!node) return -ENOENT;
for (i = 0; i < geo->no_pairs; i++) if (keycmp(geo, node, i, key) == 0) {
setval(geo, node, i, val); return0;
} return -ENOENT;
}
EXPORT_SYMBOL_GPL(btree_update);
for (i = 0; i < geo->no_pairs; i++) { if (keycmp(geo, node, i, key) <= 0) break;
} return i;
}
staticint getfill(struct btree_geo *geo, unsignedlong *node, int start)
{ int i;
for (i = start; i < geo->no_pairs; i++) if (!bval(geo, node, i)) break; return i;
}
/* *locatethecorrectleafnodeinthebtree
*/ staticunsignedlong *find_level(struct btree_head *head, struct btree_geo *geo, unsignedlong *key, int level)
{ unsignedlong *node = head->node; int i, height;
for (height = head->height; height > level; height--) { for (i = 0; i < geo->no_pairs; i++) if (keycmp(geo, node, i, key) <= 0) break;
if ((i == geo->no_pairs) || !bval(geo, node, i)) { /* right-most key is too large, update it */ /* FIXME: If the right-most key on higher levels is
* always zero, this wouldn't be necessary. */
i--;
setkey(geo, node, i, key);
}
BUG_ON(i < 0);
node = bval(geo, node, i);
}
BUG_ON(!node); return node;
}
staticint btree_insert_level(struct btree_head *head, struct btree_geo *geo, unsignedlong *key, void *val, int level,
gfp_t gfp)
{ unsignedlong *node; int i, pos, fill, err;
BUG_ON(!val); if (head->height < level) {
err = btree_grow(head, geo, gfp); if (err) return err;
}
retry:
node = find_level(head, geo, key, level);
pos = getpos(geo, node, key);
fill = getfill(geo, node, pos); /* two identical keys are not allowed */
BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);
if (fill == geo->no_pairs) { /* need to split node */ unsignedlong *new;
new = btree_node_alloc(head, gfp); if (!new) return -ENOMEM;
err = btree_insert_level(head, geo,
bkey(geo, node, fill / 2 - 1), new, level + 1, gfp); if (err) {
mempool_free(new, head->mempool); return err;
} for (i = 0; i < fill / 2; i++) {
setkey(geo, new, i, bkey(geo, node, i));
setval(geo, new, i, bval(geo, node, i));
setkey(geo, node, i, bkey(geo, node, i + fill / 2));
setval(geo, node, i, bval(geo, node, i + fill / 2));
clearpair(geo, node, i + fill / 2);
} if (fill & 1) {
setkey(geo, node, i, bkey(geo, node, fill - 1));
setval(geo, node, i, bval(geo, node, fill - 1));
clearpair(geo, node, fill - 1);
} goto retry;
}
BUG_ON(fill >= geo->no_pairs);
/* shift and insert */ for (i = fill; i > pos; i--) {
setkey(geo, node, i, bkey(geo, node, i - 1));
setval(geo, node, i, bval(geo, node, i - 1));
}
setkey(geo, node, pos, key);
setval(geo, node, pos, val);
staticvoid *btree_remove_level(struct btree_head *head, struct btree_geo *geo, unsignedlong *key, int level); staticvoid merge(struct btree_head *head, struct btree_geo *geo, int level, unsignedlong *left, int lfill, unsignedlong *right, int rfill, unsignedlong *parent, int lpos)
{ int i;
for (i = 0; i < rfill; i++) { /* Move all keys to the left */
setkey(geo, left, lfill + i, bkey(geo, right, i));
setval(geo, left, lfill + i, bval(geo, right, i));
} /* Exchange left and right child in parent */
setval(geo, parent, lpos, right);
setval(geo, parent, lpos + 1, left); /* Remove left (formerly right) child from parent */
btree_remove_level(head, geo, bkey(geo, parent, lpos), level + 1);
mempool_free(right, head->mempool);
}
staticvoid rebalance(struct btree_head *head, struct btree_geo *geo, unsignedlong *key, int level, unsignedlong *child, int fill)
{ unsignedlong *parent, *left = NULL, *right = NULL; int i, no_left, no_right;
if (fill == 0) { /* Because we don't steal entries from a neighbour, this case *canhappen.Parentnodecontainsasinglechild,this *node,somergingwithasiblingneverhappens.
*/
btree_remove_level(head, geo, key, level + 1);
mempool_free(child, head->mempool); return;
}
/* remove and shift */ for (i = pos; i < fill - 1; i++) {
setkey(geo, node, i, bkey(geo, node, i + 1));
setval(geo, node, i, bval(geo, node, i + 1));
}
clearpair(geo, node, fill - 1);
if (fill - 1 < geo->no_pairs / 2) { if (level < head->height)
rebalance(head, geo, key, level, node, fill - 1); elseif (fill - 1 == 1)
btree_shrink(head, geo);
}
if (!(target->node)) { /* target is empty, just copy fields over */
target->node = victim->node;
target->height = victim->height;
__btree_init(victim); return0;
}
/* TODO: This needs some optimizations. Currently we do three tree *walkstoremoveasingleobjectfromthevictim.
*/ for (;;) { if (!btree_last(victim, geo, key)) break;
val = btree_lookup(victim, geo, key);
err = btree_insert(target, geo, key, val, gfp); if (err) return err; /* We must make a copy of the key, as the original will get
* mangled inside btree_remove. */
longcpy(dup, key, geo->keylen);
btree_remove(victim, geo, dup);
} return0;
}
EXPORT_SYMBOL_GPL(btree_merge);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.