static void tochildrecurse(btIterator *iter, bt_n* self) { to_child(iter, self); if (!iter->bln->self->leaf) { // depth-first GET_NEW_CHILD(iter) tochildrecurse(iter, NODES(iter->btr, iter->bln->self)[iter->bln->in]); } }
/* copy of findnodekey */ int bt_init_iterator(struct btree *btr, bt_data_t k, struct btIterator *iter) { if (!btr->root) return -1; int i = 0; int r = 0; struct btreenode *x = btr->root; unsigned char only_right = 1; while (x != NULL) { i = findkindex(btr, x, k, &r, iter); if (i >= 0 && r == 0) return 0; if (r < 0 || i != (x->n - 1)) only_right = 0; if (x->leaf) { if (i != (x->n - 1)) only_right = 0; return only_right ? RET_ONLY_RIGHT : RET_LEAF_EXIT; } iter->bln->child = get_new_iter_child(iter); x = NODES(btr, x)[i + 1]; become_child(iter, x); } return -1; }
static int checkbtreenode(struct btree *btr, struct btreenode *x, void *kmin, void *kmax, int isroot) { int i; if (x == NULL) /* check that the two keys are in order */ if (btr->cmp(kmin, kmax) >= 0) return 0; else return 1; else { if (!isroot && (x->n < btr->t - 1 || x->n > 2 * btr->t - 1)) { printf("node, to few or to many: %d\n", x->n); bt_dumptree(btr); exit(1); } /* check subnodes */ if (x->n == 0 && !x->leaf) if (!checkbtreenode(btr, NODES(btr, x)[0], kmin, kmax, 0)) return 0; else return 1; else if (x->n == 0 && x->leaf && !isroot) { printf("leaf with no keys!!\n"); bt_dumptree(btr); if (!checkbtreenode(btr, NULL, kmin, kmax, 0)) return 0; else return 1; } if (!checkbtreenode(btr, NODES(btr, x)[0], kmin, KEYS(btr, x)[0], 0)) return 0; for (i = 1; i < x->n; i++) if (!checkbtreenode(btr, NODES(btr, x)[i], KEYS(btr, x)[i - 1], KEYS(btr, x)[i], 0)) return 0; if (!checkbtreenode(btr, NODES(btr, x)[i], KEYS(btr, x)[i - 1], kmax, 0)) return 0; } return 1; }
static void iter_node_scion(btIterator *iter) { bt *btr = iter->btr; fol_t *fl = (fol_t *)iter->data; uchar kid_in = (iter->bln->in == iter->bln->self->n) ? iter->bln->in : iter->bln->in + 1; bt_n *kid = NODES(btr, iter->bln->self)[kid_in]; bool scioned = (fl->diff > kid->scion); //DEBUG_ITER_NODE_SCION if (scioned) { fl->cnt += kid->scion + 1; // +1 for NODE itself if (btr->dirty) fl->cnt += getDR(btr, iter->bln->self, iter->bln->ik); fl->diff = fl->ofst - fl->cnt; if (fl->diff < 0) { fl->over = 0; return; } if ((iter->bln->ik + 1) < iter->bln->self->n) iter->bln->ik++; if ((iter->bln->in + 1) < iter->bln->self->n) iter->bln->in++; else toparentrecurse(iter); if (!fl->diff) { fl->over = 0; return; } } else { fl->cnt++; if (btr->dirty) fl->cnt += getDR(btr, iter->bln->self, iter->bln->ik); fl->diff = fl->ofst - fl->cnt; if (fl->diff < 0) { fl->over = 0; return; } if ((iter->bln->ik + 1) < iter->bln->self->n) iter->bln->ik++; iter->bln->in++; GET_NEW_CHILD(iter) tochildrecurse(iter, NODES(btr, iter->bln->self)[iter->bln->in]); if (!fl->diff) { fl->over = 0; return; } } }
static bt_data_t findnodekey(struct btree *btr, struct btreenode *x, bt_data_t k) { int i, r; while (x != NULL) { i = findkindex(btr, x, k, &r, NULL); if (i >= 0 && r == 0) return KEYS(btr, x)[i]; if (x->leaf) return NULL; x = NODES(btr, x)[i + 1]; } return NULL; }
static void btreeinsertnonfull(struct btree *btr, struct btreenode *x, bt_data_t k) { int i = x->n - 1; if (x->leaf) { /* we are a leaf, just add it in */ i = findkindex(btr, x, k, NULL, NULL); if (i != x->n - 1) memmove(KEYS(btr, x) + i + 2, KEYS(btr, x) + i + 1, (x->n - i - 1) * sizeof k); KEYS(btr, x)[i + 1] = k; x->n++; } else { i = findkindex(btr, x, k, NULL, NULL) + 1; /* make sure that the next node isn't full */ if (NODES(btr, x)[i]->n == n(btr->t)) { btreesplitchild(btr, x, i, NODES(btr, x)[i]); if (btr->cmp(k, KEYS(btr, x)[i]) > 0) i++; } btreeinsertnonfull(btr, NODES(btr, x)[i], k); } }
static void dumpnode(struct btree *btr, struct btreenode *n, int nn) { int i; printf("%p: leaf: %d, n: %d", n, n->leaf, n->n); for (i = 0; i < n->n; i++) printf(", key%d: %p", i, KEYS(btr, n)[i]); if (!n->leaf) { for (i = 0; i <= n->n; i++) printf(", nodeptr%d: %p", i, NODES(btr, n)[i]); puts(""); if (nn) { nn--; for (i = 0; i <= n->n; i++) dumpnode(btr, NODES(btr, n)[i], nn); } } else puts(""); }
static void iter_node_scion_rev(btIterator *iter) { bt *btr = iter->btr; fol_t *fl = (fol_t *)iter->data; bt_n *kid = NODES(iter->btr, iter->bln->self)[iter->bln->in]; bool scioned = (fl->diff > kid->scion); //DEBUG_ITER_NODE_SCION_REV if (scioned) { fl->cnt += kid->scion + 1; // +1 for NODE itself if (btr->dirty) fl->cnt += getDR(btr, iter->bln->self, iter->bln->ik); fl->diff = fl->ofst - fl->cnt; if (fl->diff < 0) { fl->over = 0; return; } if (iter->bln->ik) iter->bln->ik--; if (iter->bln->in) iter->bln->in--; else toparentrecurserev(iter); if (!fl->diff) { fl->over = 0; return; } } else { fl->cnt++; if (btr->dirty) fl->cnt += getDR(btr, iter->bln->self, iter->bln->ik); fl->diff = fl->ofst - fl->cnt; if (fl->diff < 0) { fl->over = 0; return; } GET_NEW_CHILD(iter) tochildrecurserev(iter, NODES(iter->btr, iter->bln->self)[iter->bln->in]); if (!fl->diff) { fl->over = 0; return; } } //printf("END iter_node_scion_rev: key: "); DUMP_CURR_KEY }
static void btreesplitchild(struct btree *btr, struct btreenode *x, int i, struct btreenode *y) { struct btreenode *z; int j; btr->numnodes++; if ((z = allocbtreenode(btr)) == NULL) exit(1); /* duplicate leaf setting, and store number of nodes */ z->leaf = y->leaf; z->n = btr->t - 1; /* copy the last half of y into z */ for (j = 0; j < btr->t - 1; j++) KEYS(btr, z)[j] = KEYS(btr, y)[j + btr->t]; /* if it's an internal node, copy the ptr's too */ if (!y->leaf) for (j = 0; j < btr->t; j++) NODES(btr, z)[j] = NODES(btr, y)[j + btr->t]; /* store resulting number of nodes in old part */ y->n = btr->t - 1; /* move node ptrs in parent node down one, and store new node */ for (j = x->n; j > i; j--) NODES(btr, x)[j + 1] = NODES(btr, x)[j]; NODES(btr, x)[i + 1] = z; /* adjust the keys from previous move, and store new key */ for (j = x->n - 1; j >= i; j--) KEYS(btr, x)[j + 1] = KEYS(btr, x)[j]; KEYS(btr, x)[i] = KEYS(btr, y)[btr->t - 1]; x->n++; }
static int treeheight(bt *btr) { bt_n *x = btr->root; if (!x) { return 0; } int ret = 0; while (!x->leaf) { x = NODES(btr, x)[0]; ret++; } return ++ret; }
int treeheight(struct btree *btr) { struct btreenode *x; int ret; x = btr->root; ret = 0; while (!x->leaf) { x = NODES(btr, x)[0]; ret++; } return ++ret; }
static int rdbSaveAllRows(FILE *fp, bt *btr, bt_n *x) { for (int i = 0; i < x->n; i++) { uchar *stream = (uchar *)KEYS(btr, x, i); int ssize = getStreamMallocSize(stream, btr); uchar *wstream = UU(btr) ? &stream : stream; if (rdbSaveLen(fp, ssize) == -1) return -1; if (fwrite(wstream, ssize, 1, fp) == 0) return -1; } if (!x->leaf) { for (int i = 0; i <= x->n; i++) { if (rdbSaveAllRows(fp, btr, NODES(btr, x)[i]) == -1) return -1; } } return 0; }
bt_data_t bt_delete(struct btree *btr, bt_data_t k) { struct btreenode *x; bt_data_t r; r = nodedeletekey(btr, btr->root, k, 0); /* remove an empty, non-leaf node from root, this is the ONLY * place that a tree can decrease in height */ if (btr->root->n == 0 && btr->root->leaf == 0) { btr->numnodes--; x = btr->root; btr->root = NODES(btr, x)[0]; bt_free_btreenode(x, btr); } btr->numkeys--; return r; }
void bt_insert(struct btree *btr, bt_data_t k) { struct btreenode *r, *s; btr->numkeys++; r = btr->root; if (r->n == n(btr->t)) { /* this is the ONLY place that the tree can grown in height */ btr->numnodes++; if ((s = allocbtreenode(btr)) == NULL) exit(1); btr->root = s; s->leaf = 0; s->n = 0; NODES(btr, s)[0] = r; btreesplitchild(btr, s, 0, r); r = s; } /* finally insert the new node */ btreeinsertnonfull(btr, r, k); }
static void destroy_index(bt *ibtr, bt_n *n) { if (! n->leaf) { for (int i = 0; i <= n->n; i++) { destroy_index(ibtr, NODES(ibtr, n)[i]); } } for (int i = 0; i < n->n; i++) { void *be = KEYS(ibtr, n, i); ai_nbtr *anbtr = (ai_nbtr *) parseStream(be, ibtr); if (anbtr) { if (anbtr->is_btree) { bt_destroy(anbtr->u.nbtr); } else { ai_arr_destroy(anbtr->u.arr); } cf_free(anbtr); } } }
static void iter_node(btIterator *iter) { //DEBUG_ITER_NODE if ((iter->bln->ik + 1) < iter->bln->self->n) iter->bln->ik++; if ((iter->bln->in + 1) <= iter->bln->self->n) iter->bln->in++; GET_NEW_CHILD(iter) tochildrecurse(iter, NODES(iter->btr, iter->bln->self)[iter->bln->in]); }
static bt_data_t findminnode(struct btree *btr, struct btreenode *x) { if (x->leaf) return KEYS(btr, x)[0]; else return findminnode(btr, NODES(btr, x)[0]); }
/* * remove an existing key from the tree, if the key doesn't exist in it, * unexpected results may happen. * * the s parameter is kinda special, for normal operation you need to pass * it as 0, if you want to delete the max node, pass it as 1, or if you * want to delete the min node, pass it as 2. */ static bt_data_t nodedeletekey(struct btree *btr, struct btreenode *x, bt_data_t k, int s) { int i; int r = -1; struct btreenode *xp, *y, *z; bt_data_t kp; int yn, zn; if (x == NULL) return 0; if (s) { if (!x->leaf) switch (s) { case 1: r = 1; break; case 2: r = -1; break; } else r = 0; switch (s) { case 1: i = x->n - 1; break; case 2: i = -1; break; default: i = 42; break; } } else { i = findkindex(btr, x, k, &r, NULL); } /* Case 1 * If the key k is in node x and x is a leaf, delete the key k from x. */ if (x->leaf) { if (s == 2) i++; kp = KEYS(btr, x)[i]; memmove(KEYS(btr, x) + i, KEYS(btr, x) + i + 1, (x->n - i - 1) * sizeof k); x->n--; KEYS(btr, x)[x->n] = NULL; /* JakSprats added for iterator */ return kp; } if (r == 0) { /* Case 2 * if the key k is in the node x, and x is an internal node */ if ((yn = NODES(btr, x)[i]->n) >= btr->t) { /* Case 2a * if the child y that precedes k in node x has at * least t keys, then find the predecessor k' of * k in the subtree rooted at y. Recursively delete * k', and replace k by k' in x. * * Currently the deletion isn't done in a signle * downward pass was that would require special * unwrapping of the delete function. */ xp = NODES(btr, x)[i]; kp = KEYS(btr, x)[i]; KEYS(btr, x)[i] = nodedeletekey(btr, xp, NULL, 1); return kp; } if ((zn = NODES(btr, x)[i + 1]->n) >= btr->t) { /* Case 2b * if the child z that follows k in node x has at * least t keys, then find the successor k' of * k in the subtree rooted at z. Recursively delete * k', and replace k by k' in x. * * See above for comment on single downward pass. */ xp = NODES(btr, x)[i + 1]; kp = KEYS(btr, x)[i]; KEYS(btr, x)[i] = nodedeletekey(btr, xp, NULL, 2); return kp; } if (yn == btr->t - 1 && zn == btr->t - 1) { /* Case 2c * if both y and z have only t - 1 keys, merge k * and all of z into y, so that x loses both k and * the pointer to z, and y now contains 2t - 1 * keys. */ /* JakSprats fixed a bug here, the return ptr was wrong */ y = NODES(btr, x)[i]; z = NODES(btr, x)[i + 1]; void *v = KEYS(btr, x)[i]; memmove(KEYS(btr, y) + y->n, KEYS(btr, z), (z->n + 1) * sizeof k); memmove(NODES(btr, y) + y->n, NODES(btr, z), (z->n + 1) * sizeof y); y->n += z->n; memmove(KEYS(btr, x) + i, KEYS(btr, x) + i + 1, (x->n - i - 1) * sizeof k); memmove(NODES(btr, x) + i + 1, NODES(btr, x) + i + 2, (x->n - i - 1) * sizeof k); x->n--; bt_free_btreenode(z, btr); return v; } } /* Case 3 * if k is not present in internal node x, determine the root x' of * the appropriate subtree that must contain k, if k is in the tree * at all. If x' has only t - 1 keys, execute step 3a or 3b as * necessary to guarantee that we descend to a node containing at * least t keys. Finish by recursing on the appropriate child of x. */ i++; /* !x->leaf */ if ((xp = NODES(btr, x)[i])->n == btr->t - 1) { /* Case 3a * If x' has only t - 1 keys but has a sibling with at * least t keys, give x' an extra key by moving a key * from x down into x', moving a key from x''s immediate * left or right sibling up into x, and moving the * appropriate child from the sibling into x'. */ if (i > 0 && (y = NODES(btr, x)[i - 1])->n >= btr->t) { /* left sibling has t keys */ memmove(KEYS(btr, xp) + 1, KEYS(btr, xp), xp->n * sizeof k); memmove(NODES(btr, xp) + 1, NODES(btr, xp), (xp->n + 1) * sizeof x); KEYS(btr, xp)[0] = KEYS(btr, x)[i - 1]; KEYS(btr, x)[i - 1] = KEYS(btr, y)[y->n - 1]; NODES(btr, xp)[0] = NODES(btr, y)[y->n]; y->n--; xp->n++; } else if (i < x->n && (y = NODES(btr, x)[i + 1])->n >= btr->t) { /* right sibling has t keys */ KEYS(btr, xp)[xp->n++] = KEYS(btr, x)[i]; KEYS(btr, x)[i] = KEYS(btr, y)[0]; NODES(btr, xp)[xp->n] = NODES(btr, y)[0]; y->n--; memmove(KEYS(btr, y), KEYS(btr, y) + 1, y->n * sizeof k); memmove(NODES(btr, y), NODES(btr, y) + 1, (y->n + 1) * sizeof x); } /* Case 3b * If x' and all of x''s siblings have t - 1 keys, merge * x' with one sibling, which involves moving a key from x * down into the new merged node to become the median key * for that node. */ else if (i > 0 && (y = NODES(btr, x)[i - 1])->n == btr->t - 1) { /* merge i with left sibling */ KEYS(btr, y)[y->n++] = KEYS(btr, x)[i - 1]; memmove(KEYS(btr, y) + y->n, KEYS(btr, xp), xp->n * sizeof k); memmove(NODES(btr, y) + y->n, NODES(btr, xp), (xp->n + 1) * sizeof x); y->n += xp->n; memmove(KEYS(btr, x) + i - 1, KEYS(btr, x) + i, (x->n - i) * sizeof k); memmove(NODES(btr, x) + i, NODES(btr, x) + i + 1, (x->n - i) * sizeof x); x->n--; bt_free_btreenode(xp, btr); xp = y; } else if (i < x->n && (y = NODES(btr, x)[i + 1])->n == btr->t - 1) { /* merge i with right sibling */ KEYS(btr, xp)[xp->n++] = KEYS(btr, x)[i]; memmove(KEYS(btr, xp) + xp->n, KEYS(btr, y), y->n * sizeof k); memmove(NODES(btr, xp) + xp->n, NODES(btr, y), (y->n + 1) * sizeof x); xp->n += y->n; memmove(KEYS(btr, x) + i, KEYS(btr, x) + i + 1, (x->n - i - 1) * sizeof k); memmove(NODES(btr, x) + i + 1, NODES(btr, x) + i + 2, (x->n - i - 1) * sizeof x); x->n--; bt_free_btreenode(y, btr); } } return nodedeletekey(btr, xp, k, s); }
static void iter_node_rev(btIterator *iter) { //DEBUG_ITER_NODE_REV GET_NEW_CHILD(iter) tochildrecurserev(iter, NODES(iter->btr, iter->bln->self)[iter->bln->in]); }
static bool btScionFind(btSIter *siter, bt_n *x, ulong ofst, bt *btr, bool asc, cswc_t *w, long lim) { int i = asc ? 0 : x->n; //DEBUG_SCION_PRE_LOOP1 int fin = asc ? x->n + 1 : -1;//LOOPS:(i=0,i<=x->n,i++)&(i=x->n,i>=0,i--) while (i != fin) { if (x->leaf) break; uint32_t scion = NODES(btr, x)[i]->scion; //DEBUG_SCION_LOOP_1 if (scion >= ofst) { bool i_end_n = (i == siter->x.bln->self->n); siter->x.bln->in = i; siter->x.bln->ik = (i_end_n) ? i - 1 : i; //DEBUG_SCION_LOOP_1_KID if (scion == ofst) { if (!asc) { siter->x.bln->in = siter->x.bln->ik = i - 1; } return 1; } siter->x.bln->child = get_new_iter_child(&siter->x); to_child(&siter->x, NODES(btr, x)[i]); bt_n *kid = NODES(btr, x)[i]; //DEBUG_SCION_LOOP_1_GOT_KID if (!kid->leaf) { btScionFind(siter, kid, ofst, btr, asc, w, lim); return 1; } else x = kid; break; } else ofst -= (scion + 1); // +1 for NODE itself i = asc ? i + 1 : i - 1; // loop increment } // Now Find the rest of the OFFSET (respecting DRs) uint32 n = siter->x.bln->self->n; i = asc ? 0 : n - 1; fin = asc ? MIN(ofst, n) : MAX(-1, (n - ofst)); int last = asc ? n - 1 : 0; ulong cnt = 0; //TODO findminnode() is too inefficient -> needs to be a part of btr bt_n *minx = findminnode(btr, btr->root); int btdl = btr->dirty_left; int dr = 0; //DEBUG_SCION_PRE_LOOP2 while (i != fin) { dr = getDR(btr, x, i); cnt += dr; if (!i && x == minx) cnt += btdl; //DEBUG_SCION_LOOP2 if (cnt >= ofst) break; cnt++; i = asc ? i + 1 : i - 1; // loop increment } //DEBUG_SCION_OFFSET_TOO_BIG if (i == fin && i == last) { if (cnt >= x->scion) return 0; } else if (cnt < ofst) return 0; //OFST 2big siter->x.bln->ik = i; INIT_ITER_BEENTRY(siter, btr, x, siter->x.bln->ik); if (asc) { if ((ofst + dr) != cnt) siter->missed = 1; } else { if (!i && x == minx) { if (ofst != (cnt - btdl)) siter->missed = 1; } else { if (ofst != cnt) siter->missed = 1; } } //DEBUG_SCION_POST_LOOP2 return 1; }