예제 #1
0
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]);
	}
}
예제 #2
0
/* 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;
}
예제 #3
0
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;
}
예제 #4
0
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;
		}
	}
}
예제 #5
0
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;
}
예제 #6
0
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);
    }
}
예제 #7
0
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("");
}
예제 #8
0
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
}
예제 #9
0
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++;
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
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;
}
예제 #14
0
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);
}
예제 #15
0
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);                                                     
		}                                                                       
	}                                                                           
}                 
예제 #16
0
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]);
}
예제 #17
0
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]);
}
예제 #18
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);
}
예제 #19
0
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]);
}
예제 #20
0
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;
}