home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
DOOG
/
CBASE09.ZIP
/
BTREE.ZIP
/
BTINSERT.C
< prev
next >
Wrap
Text File
|
1989-08-31
|
6KB
|
284 lines
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "btinsert.c 1.1 - 89/07/03" */
#include <blkio.h>
#include <bool.h>
#include <errno.h>
/* #include <stdlib.h> */
/* #include <string.h> */
#include "btree_.h"
/*man---------------------------------------------------------------------------
NAME
btinsert - btree insert
SYNOPSIS
#include <btree.h>
int btinsert(btp, buf)
btree_t *btp;
void *buf;
DESCRIPTION
The btinsert function inserts the key pointed to by buf into btree
btp. The cursor is positioned to the inserted key. If the insertion
fails, the position of the cursor is undefined.
btinsert will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] buf is the NULL pointer.
[BTEDUPKEY] The key at buf is already in btree btp.
[BTELOCK] btp is not write locked.
[BTENOPEN] btp is not open.
SEE ALSO
btdelete, btsearch.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned and errno is set to indicate the error.
------------------------------------------------------------------------------*/
int btinsert(btp, buf)
btree_t * btp;
void * buf;
{
int rs = 0;
int rt = 0;
int spi = 0; /* search path index */
btnode_t * btnp = NULL; /* node receiving new key */
btnode_t * rbtnp = NULL; /* right sibling node */
bttuple_t bttuple;
bool grow = FALSE;
errno = 0;
/* initialize storage */
memset((void *)&bttuple, 0, sizeof(bttuple));
/* validate arguments */
if ((!bt_valid(btp)) || (buf == NULL)) {
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
errno = BTENOPEN;
return -1;
}
/* check locks */
if (!(btp->flags & BTWRLCK)) {
errno = BTELOCK;
return -1;
}
/* locate slot for key */
rs = bt_search(btp, buf);
if (rs == -1) {
BTEPRINT;
return -1;
}
if (rs == 1) { /* check for duplicate key */
errno = BTEDUPKEY;
return -1;
}
/* initialize working nodes */
btnp = bt_ndalloc(btp);
if (btnp == NULL) {
BTEPRINT;
return -1;
}
rbtnp = bt_ndalloc(btp);
if (rbtnp == NULL) {
BTEPRINT;
bt_ndfree(btnp);
return -1;
}
rs = bt_ndcopy(btp, btnp, btp->cbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(btnp);
return -1;
}
/* initialize bttuple */
bttuple.key_p = calloc(1, btp->bthdr.keysize);
if (bttuple.key_p == NULL) {
BTEPRINT;
bt_ndfree(rbtnp);
bt_ndfree(btnp);
errno = ENOMEM;
return -1;
}
memcpy(bttuple.key_p, buf, btp->bthdr.keysize);
bttuple.child = 0;
if (btp->bthdr.height == 0) {
grow = TRUE;
}
/* set modify bit in header */
btp->bthdr.flags |= BTHMOD;
rs = bputh(btp->bp, (void *)&btp->bthdr);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
bt_ndfree(rbtnp);
bt_ndfree(btnp);
return -1;
}
rs = bsync(btp->bp);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
bt_ndfree(rbtnp);
bt_ndfree(btnp);
return -1;
}
/* loop from leaf node to root */
for (spi = btp->bthdr.height; spi > 0; spi--) {
/* insert new key into node */
rs = bt_ndinskey(btp, btnp, btp->sp[spi].key, &bttuple);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
/* write to disk if node not too big */
if (btnp->n <= bt_ndmax(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;
}
memcpy((void *)&btp->cbtpos,
(void *)&btp->sp[btp->bthdr.height],
sizeof(btp->cbtpos));
}
break;
}
/* node must be split */
rs = bt_ndsplit(btp, btp->sp[spi].node, btnp, rbtnp, &bttuple);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
/* write split nodes */
rs = bt_ndput(btp, btp->sp[spi].node, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
rs = bt_ndput(btp, bttuple.child, rbtnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
/* update right sibling node */
if (rbtnp->rsib != 0) {
rs = bputbf(btp->bp, rbtnp->rsib, offsetof(btnode_t, lsib), (void *)&bttuple.child, sizeof(rbtnp->lsib));
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
}
/* check if at top of tree */
if (spi == 1) {
grow = TRUE;
} else { /* read new parent node */
rs = bt_ndget(btp, btp->sp[spi - 1].node, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
}
/* update cursor, first, and last */
if (spi == btp->bthdr.height) {
if (rbtnp->rsib == 0) { /* new last key node */
btp->bthdr.last = bttuple.child;
}
if (btp->sp[btp->bthdr.height].key <= btnp->n) {
rs = bt_ndcopy(btp, btp->cbtnp, btnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
memcpy((void *)&btp->cbtpos,
(void *)&btp->sp[btp->bthdr.height],
sizeof(btp->cbtpos));
} else {
rs = bt_ndcopy(btp, btp->cbtnp, rbtnp);
if (rs == -1) {
BTEPRINT;
rt = -1;
break;
}
memcpy((void *)&btp->cbtpos,
(void *)&btp->sp[btp->bthdr.height],
sizeof(btp->cbtpos));
}
}
}
if (rt == -1) {
BTEPRINT;
free(bttuple.key_p);
bt_ndfree(rbtnp);
bt_ndfree(btnp);
return -1;
}
bt_ndfree(rbtnp);
bt_ndfree(btnp);
/* check if the tree grew */
if (grow) {
rs = bt_grow(btp, &bttuple);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
return -1;
}
}
free(bttuple.key_p);
/* increment key count */
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;
}