home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
DOOG
/
CBASE09.ZIP
/
BTREE.ZIP
/
BTDELCUR.C
< prev
next >
Wrap
Text File
|
1989-08-31
|
11KB
|
495 lines
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "btdelcur.c 1.1 - 89/07/03" */
#include <blkio.h>
#include <errno.h>
#include "btree_.h"
static int dshuffle(/* btree_t *btp, btnode_t *btnp, btpos_t *btpos_p, btnode_t *pbtnp, size_t pkn */);
/*man---------------------------------------------------------------------------
NAME
btdelcur - delete current btree key
SYNOPSIS
#include <btree.h>
int btdelcur(btp)
btree_t *btp;
DESCRIPTION
The btdelcur function deletes the current key from btree btp. The
cursor is positioned to the key following the one deleted.
btdelcur will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[BTELOCK] btree btp is not write locked.
[BTENKEY] The cursor is null.
[BTENOPEN] btree btp is not open.
SEE ALSO
btdelete, btinsert, btsearch.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int btdelcur(btp)
btree_t *btp;
{
int rt = 0;
int rs = 0;
int spi = 0; /* search path index */
btnode_t * btnp = NULL; /* node losing key */
btnode_t * pbtnp = NULL; /* parent node */
/* validate arguments */
if (!bt_valid(btp)) {
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
errno = BTENOPEN;
return -1;
}
/* check if not write locked */
if (!(btp->flags & BTWRLCK)) {
errno = BTELOCK;
return -1;
}
/* check if cursor is null */
if (btcursor(btp) == NULL) {
errno = BTENKEY;
return -1;
}
/* generate search path if necessary */
if (btp->sp[btp->bthdr.height].node == btp->cbtpos.node) {
btp->sp[btp->bthdr.height].key = btp->cbtpos.key;
} else {
rs = btsearch(btp, bt_kykey_p(btp, btp->cbtnp, btp->cbtpos.key));
if (rs == -1) {
BTEPRINT;
return -1;
}
if (rs == 0) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
}
/* initialize working nodes */
btnp = bt_ndalloc(btp);
if (btnp == NULL) {
BTEPRINT;
return -1;
}
pbtnp = bt_ndalloc(btp);
if (pbtnp == NULL) {
BTEPRINT;
bt_ndfree(btnp);
return -1;
}
rs = bt_ndcopy(btp, btnp, btp->cbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(pbtnp);
bt_ndfree(btnp);
return -1;
}
/* delete key from node */
rs = bt_nddelkey(btp, btnp, btp->cbtpos.key);
if (rs == -1) {
BTEPRINT;
bt_ndfree(pbtnp);
bt_ndfree(btnp);
return -1;
}
/* set modify bit in header */
btp->bthdr.flags |= BTHMOD;
rs = bputh(btp->bp, (void *)&btp->bthdr);
if (rs == -1) {
BTEPRINT;
bt_ndfree(pbtnp);
bt_ndfree(btnp);
return -1;
}
rs = bsync(btp->bp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(pbtnp);
bt_ndfree(btnp);
return -1;
}
for (spi = btp->bthdr.height; spi > 0; spi--) {
/* write to disk if node not too small */
if (btnp->n >= bt_ndmin(btp)) {
rs = bt_ndput(btp, btp->sp[spi].node, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
/* set cursor */
if (spi == btp->bthdr.height) {
rs = bt_ndcopy(btp, btp->cbtnp, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
}
break;
}
/* write to disk if root */
if (spi == 1) {
if (btnp->n != 0) {
rs = bt_ndput(btp, btp->sp[spi].node, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
} else {
rs = bt_shrink(btp, *bt_kychild_p(btnp, 0));
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
}
break;
}
/* node needs more keys */
/* read in parent node */
rs = bt_ndget(btp, btp->sp[spi - 1].node, pbtnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
rs = dshuffle(btp, btnp, &btp->sp[spi], pbtnp, btp->sp[spi - 1].key);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
rs = bt_ndcopy(btp, btnp, pbtnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
}
if (rt == -1) {
BTEPRINT;
bt_ndfree(pbtnp);
bt_ndfree(btnp);
return -1;
}
bt_ndfree(pbtnp);
bt_ndfree(btnp);
/* decrement key count in header */
btp->bthdr.keycnt--;
/* clear modify bit in header */
btp->bthdr.flags &= ~BTHMOD;
rs = bputh(btp->bp, (void *)&btp->bthdr);
if (rs == -1) {
BTEPRINT;
return -1;
}
rs = bsync(btp->bp);
if (rs == -1) {
BTEPRINT;
return -1;
}
errno = 0;
return 0;
}
/*------------------------------------------------------------------------------
NAME
dshuffle - delete shuffle
SYNOPSIS
#include <btree.h>
static int dshuffle(btp, btnp, btpos_p, pbtnp, pkn)
btree_t * btp;
btnode_t * btnp;
btpos_t * btpos_p;
btnode_t * pbtnp;
size_t pkn;
DESCRIPTION
The dshuffle function shuffles keys to give btree node btnp at least
the minimum necessary for a btree btp. It first tries to shift some
over from one of the siblings. If neither sibling can provide enough
keys, it will fuse btnp with one of the siblings. The parent node
pbtnp is adjusted for each operation. All child nodes modified are
written to the file, but the parent node is not.
btpos_p points to the btree position of the key just deleted from
node btnp. pkn is the number of the key in the parent node which
was traversed in the search path.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
static int dshuffle(btp, btnp, btpos_p, pbtnp, pkn)
btree_t * btp;
btnode_t * btnp;
btpos_t * btpos_p;
btnode_t * pbtnp;
size_t pkn;
{
int rs = 0;
bool leaf = FALSE;
size_t lsib = 0;
size_t rsib = 0;
btnode_t * lbtnp = NULL;
btnode_t * rbtnp = NULL;
int ns = 0;
errno = 0;
/* validate arguments */
if ((pkn == 0) || (pkn > (pbtnp->n + 1))) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* check if leaf or internal node */
if (*bt_kychild_p(btnp, 0) == 0) {
leaf = TRUE;
}
/* find parent key */
if (pkn == (pbtnp->n + 1)) {
pkn = pbtnp->n;
} else if (*bt_kychild_p(pbtnp, pkn) != btpos_p->node) {
pkn--;
}
if (*bt_kychild_p(pbtnp, pkn) != btpos_p->node) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* find block numbers of siblings nodes */
if (pkn == 0) {
lsib = 0;
} else {
/* lsib = btnp->lsib; */
lsib = *bt_kychild_p(pbtnp, pkn - 1);
}
if (pkn == pbtnp->n) {
rsib = 0;
} else {
/* rsib = btnp->rsib; */
rsib = *bt_kychild_p(pbtnp, pkn + 1);
}
/* read sibling nodes */
lbtnp = bt_ndalloc(btp);
if (lbtnp == NULL) {
BTEPRINT;
return -1;
}
rbtnp = bt_ndalloc(btp);
if (rbtnp == NULL) {
BTEPRINT;
bt_ndfree(lbtnp);
return -1;
}
if (lsib != 0) {
rs = bt_ndget(btp, lsib, lbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
if (rsib != 0) {
rs = bt_ndget(btp, rsib, rbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
/* first try shifting keys from the right sibling */
if ((rsib != 0) && (((btnp->n + rbtnp->n) / 2) >= bt_ndmin(btp))) {
ns = bt_ndshift(btp, btnp, rbtnp, pbtnp, pkn + 1);
if (ns == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* position cursor */
if (leaf) {
btp->cbtpos.node = btpos_p->node;
btp->cbtpos.key = btpos_p->key;
rs = bt_ndcopy(btp, btp->cbtnp, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
rs = bt_ndput(btp, btpos_p->node, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
rs = bt_ndput(btp, rsib, rbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* then from the left sibling */
} else if ((lsib != 0) && (((btnp->n + lbtnp->n) / 2) >= bt_ndmin(btp))) {
ns = bt_ndshift(btp, lbtnp, btnp, pbtnp, pkn);
if (ns == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* position cursor */
if (leaf) {
btp->cbtpos.node = btpos_p->node;
btp->cbtpos.key = btpos_p->key + ns;
rs = bt_ndcopy(btp, btp->cbtnp, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
rs = bt_ndput(btp, lsib, lbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
rs = bt_ndput(btp, btpos_p->node, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* then try to fuse nodes */
} else {
/* first try to fuse with the right node */
if (rsib != 0) {
rs = bt_ndfuse(btp, btnp, rbtnp, pbtnp, pkn + 1);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* position cursor */
if (leaf) {
btp->cbtpos.node = btpos_p->node;
btp->cbtpos.key = btpos_p->key;
if (btnp->rsib == 0) {
btp->bthdr.last = btpos_p->node;
}
rs = bt_ndcopy(btp, btp->cbtnp, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
rs = bt_ndput(btp, btpos_p->node, btnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* then with the left node */
} else if (lsib != 0) {
/* position cursor */
if (leaf) {
btp->cbtpos.key = lbtnp->n + btpos_p->key;
btp->cbtpos.node = lsib;
}
rs = bt_ndfuse(btp, lbtnp, btnp, pbtnp, pkn);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
/* copy current node */
if (leaf) {
if (lbtnp->rsib == 0) {
btp->bthdr.last = lsib;
}
rs = bt_ndcopy(btp, btp->cbtnp, lbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
}
rs = bt_ndput(btp, lsib, lbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
return -1;
}
} else {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
errno = BTEPANIC;
return -1;
}
}
bt_ndfree(rbtnp);
bt_ndfree(lbtnp);
errno = 0;
return 0;
}