home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
DOOG
/
CBASE09.ZIP
/
BTREE.ZIP
/
NDOPS.C
< prev
Wrap
Text File
|
1989-08-31
|
23KB
|
1,044 lines
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "ndops.c 1.1 - 89/07/03" */
#include <blkio.h>
#include <bool.h>
#include <errno.h>
/* #include <stdlib.h> */
#include "btree_.h"
/*man---------------------------------------------------------------------------
NAME
bt_ndalloc - allocate memory for node
SYNOPSIS
#include "btree_.h"
btnode_t *bt_ndalloc(btp)
btree_t *btp;
DESCRIPTION
The bt_ndalloc function creates a node of the appropriate configuration
for btree btp and initializes it. The address of the node created is
returned.
bt_ndalloc will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[ENOMEM] Not enough memory is available for the
calling process to allocate.
[BTENOPEN] btp is not open.
SEE ALSO
bt_ndfree, bt_ndinit.
DIAGNOSTICS
On failure, a value of NULL is returned, and errno set to indicate
the error.
------------------------------------------------------------------------------*/
btnode_t *bt_ndalloc(btp)
btree_t *btp;
{
btnode_t * btnp = NULL;
bttuple_t bttuple; /* used only for sizeof */
errno = 0;
/* initialize storage */
memset((void *)&bttuple, 0, sizeof(bttuple));
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return NULL;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return NULL;
}
#endif
/* allocate storage for main node structure */
/* (calloc is used throughout to automatically set all bits 0) */
btnp = (btnode_t *)calloc(1, sizeof(btnode_t));
if (btnp == NULL) {
BTEPRINT;
errno = ENOMEM;
return NULL;
}
btnp->n = 0;
btnp->lsib = 0;
btnp->rsib = 0;
/* key array [1..(m - 1)] plus one extra for overflow */
btnp->key_p = calloc(btp->bthdr.m, btp->bthdr.keysize);
if (btnp->key_p == NULL) {
BTEPRINT;
free(btnp);
errno = ENOMEM;
return NULL;
}
/* child node file postion array [0..m] plus one extra for overflow */
btnp->child_p = (size_t *)calloc(btp->bthdr.m + 1, sizeof(bttuple.child));
if (btnp->child_p == NULL) {
BTEPRINT;
free(btnp->key_p);
free(btnp);
errno = ENOMEM;
return NULL;
}
errno = 0;
return btnp;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndcopy - copy btree node
SYNOPSIS
#include "btree_.h"
int bt_ndcopy(btp, tbtnp, sbtnp)
btree_t *btp;
btnode_t *tbtnp;
btnode_t *sbtnp;
DESCRIPTION
The bt_ndcopy function makes an exact copy of source node sbtnp in
target node tbtnp.
bt_ndcopy will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] tbtnp or sbtnp is the NULL pointer.
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 bt_ndcopy(btp, tbtnp, sbtnp)
btree_t * btp;
btnode_t * tbtnp;
btnode_t * sbtnp;
{
bttuple_t bttuple; /* only used for sizeof */
errno = 0;
/* initialize storage */
memset((void *)&bttuple, 0, sizeof(bttuple));
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (tbtnp == NULL) || (sbtnp == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
#endif
/* copy node sbtnp into tbtnp */
tbtnp->n = sbtnp->n;
tbtnp->lsib = sbtnp->lsib;
tbtnp->rsib = sbtnp->rsib;
memcpy(bt_kykey_p(btp, tbtnp, 1), bt_kykey_p(btp, sbtnp, 1), btp->bthdr.m * btp->bthdr.keysize);
memcpy((void *)bt_kychild_p(tbtnp, 0), (void *)bt_kychild_p(sbtnp, 0), (btp->bthdr.m + 1) * sizeof(bttuple.child));
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_nddelkey - delete key from btree node
SYNOPSIS
#include "btree_.h"
int bt_nddelkey(btp, btnp, kn)
btree_t *btp;
btnode_t *btnp;
size_t kn;
DESCRIPTION
The bt_nddelkey function deletes the knth tuple from node btnp.
bt_nddelkey will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] btnp is the NULL pointer.
SEE ALSO
bt_ndinskey.
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 bt_nddelkey(btp, btnp, kn)
btree_t * btp;
btnode_t * btnp;
size_t kn;
{
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
#endif
return bt_kyshift(btp, btnp, kn + 1, -1);
}
/*man---------------------------------------------------------------------------
NAME
bt_ndfree - free memory allocated for btree node
SYNOPSIS
#include "btree_.h"
void bt_ndfree(btnp)
btnode_t *btnp;
DESCRIPTION
The bt_ndfree function frees all memory allocated for btree node
btnp.
SEE ALSO
bt_ndalloc.
------------------------------------------------------------------------------*/
void bt_ndfree(btnp)
btnode_t *btnp; /* <--> */
{
if (btnp == NULL) {
return;
}
free(btnp->child_p);
btnp->child_p = NULL;
free(btnp->key_p);
btnp->key_p = NULL;
free(btnp);
return;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndfuse - btree node fuse
SYNOPSIS
#include "btree_.h"
int bt_ndfuse(btp, lbtnp, rbtnp, pbtnp, pkn)
btree_t *btp;
btnode_t *lbtnp;
btnode_t *rbtnp;
btnode_t *pbtnp;
size_t pkn;
DESCRIPTION
The bt_ndfuse function fuses nodes lbtnp and rbtnp into a single
node in lbtnp. pbtnp is the parent of both nodes and pkn is the
key in the parent node between the two children being fused. All
sibling connections are handled. The right node is placed back
in the free list. The parent is modified for the effect of the
fusion.
bt_ndfuse will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] btnp, rbtnp, or pbtnp is NULL.
[BTENOPEN] btp is not open.
SEE ALSO
bt_ndshift, bt_ndsplit.
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 bt_ndfuse(btp, lbtnp, rbtnp, pbtnp, pkn)
btree_t * btp;
btnode_t * lbtnp;
btnode_t * rbtnp;
btnode_t * pbtnp;
size_t pkn;
{
int rs = 0;
bool leaf = FALSE;
bttuple_t bttuple;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return NULL;
}
if ((lbtnp == NULL) || (rbtnp == NULL) || (pbtnp == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
if ((pkn == 0) || (pkn > pbtnp->n)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
#endif
/* check if leaf */
if (*bt_kychild_p(lbtnp, 0) == 0) {
leaf = TRUE;
}
/* check if too many keys for fusion */
if ((lbtnp->n + rbtnp->n) > (bt_ndmax(btp) - (leaf ? 0 : 1))) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* bring down parent key pkn if internal node */
if (!leaf) {
bttuple.key_p = calloc(1, btp->bthdr.keysize);
if (bttuple.key_p == NULL) {
BTEPRINT;
errno = ENOMEM;
return -1;
}
rs = bt_kyread(btp, pbtnp, pkn, &bttuple);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
return -1;
}
bttuple.child = *bt_kychild_p(rbtnp, (size_t)0);
rs = bt_ndinskey(btp, lbtnp, lbtnp->n + 1, &bttuple);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
return -1;
}
free(bttuple.key_p);
}
/* move keys from rbtnp to lbtnp */
rs = bt_kymvleft(btp, lbtnp, rbtnp, rbtnp->n);
if (rs == -1) {
BTEPRINT;
return -1;
}
/* put right node back on free list */
rs = bflpush(btp->bp, &lbtnp->rsib);
if (rs == -1) {
BTEPRINT;
return -1;
}
/* fix sibling connections */
lbtnp->rsib = rbtnp->rsib;
if (lbtnp->rsib != 0) {
rs = bputbf(btp->bp, lbtnp->rsib, offsetof(btnode_t, lsib), (void *)&rbtnp->lsib, sizeof(rbtnp->lsib));
if (rs == -1) {
BTEPRINT;
return -1;
}
} else if (leaf) {
btp->bthdr.last = rbtnp->lsib;
}
bt_ndinit(btp, rbtnp);
/* fix parent */
rs = bt_nddelkey(btp, pbtnp, pkn);
if (rs == -1) {
BTEPRINT;
return -1;
}
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndget - btree node get
SYNOPSIS
#include "btree_.h"
int bt_ndget(btp, node, btnp)
btree_t *btp;
bpos_t node;
btnode_t *btnp;
DESCRIPTION
SEE ALSO
bt_ndput.
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 bt_ndget(btp, node, btnp)
btree_t * btp;
bpos_t node;
btnode_t * btnp;
{
int rs = 0;
void * buf = NULL;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL) || (node == 0)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return -1;
}
#endif
/* read node from file */
buf = calloc(1, bt_blksize(btp));
if (buf == NULL) {
BTEPRINT;
errno = ENOMEM;
return -1;
}
rs = bgetb(btp->bp, node, buf);
if (rs == -1) {
BTEPRINT;
free(buf);
return -1;
}
/* convert node from file format */
memcpy((void *)btnp, buf, offsetof(btnode_t, key_p));
memcpy(btnp->key_p,
(void *)((char *)buf + offsetof(btnode_t, key_p)),
((btp->bthdr.m - 1) * btp->bthdr.keysize));
memcpy(btnp->child_p,
(void *)((char *)buf + offsetof(btnode_t, key_p) +
((btp->bthdr.m - 1) * btp->bthdr.keysize)),
((btp->bthdr.m) * sizeof(size_t)));
/* free buffer */
free(buf);
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndinit - initialize node
SYNOPSIS
#include "btree_.h"
void bt_ndinit(btp, btnp)
btree_t *btp;
btnode_t *btnp;
DESCRIPTION
The bt_ndinit function initializes node btnp.
------------------------------------------------------------------------------*/
void bt_ndinit(btp, btnp)
btree_t * btp;
btnode_t * btnp;
{
bttuple_t bttuple; /* used only for sizeof */
/* initialize storage */
memset((void *)&bttuple, 0, sizeof(bttuple));
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL)) {
BTEPRINT;
return;
}
#endif
/* initialize btnp */
btnp->n = 0;
btnp->lsib = 0;
btnp->rsib = 0;
memset(btnp->key_p, 0, btp->bthdr.m * btp->bthdr.keysize);
memset((void *)btnp->child_p, 0, (btp->bthdr.m + 1) * sizeof(bttuple.child));
return;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndinskey - insete key into btree node
SYNOPSIS
#include "btree_.h"
int bt_ndinskey(btp, btnp, kn, bttuple_p)
btree_t *btp;
btnode_t *btnp;
size_t kn;
bttuple_t *bttuple_p;
DESCRIPTION
The bt_ndinskey function inserts bttuple_p into the knth slot in
btree node btnp.
bt_ndinskey will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] btnp is the NULL pointer.
[EINVAL] kn is greater than then number of
keys is btnp plus one.
SEE ALSO
bt_nddelkey.
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 bt_ndinskey(btp, btnp, kn, bttuple_p)
btree_t * btp;
btnode_t * btnp;
size_t kn;
bttuple_t * bttuple_p;
{
int rs = 0;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL) || (bttuple_p == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
if (kn > (btnp->n + 1)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
#endif
/* check if room to insert */
if (btnp->n >= btp->bthdr.m) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* make an empty slot */
rs = bt_kyshift(btp, btnp, kn, 1);
if (rs == -1) {
BTEPRINT;
return -1;
}
/* write new key into empty slot */
rs = bt_kywrite(btp, btnp, kn, bttuple_p);
if (rs == -1) {
BTEPRINT;
return -1;
}
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_ndmax - maximum keys per node
SYNOPSIS
#include "btree_.h"
int bt_ndmax(btp)
btree_t *btp;
DESCRIPTION
SEE ALSO
bt_ndmin.
------------------------------------------------------------------------------*/
/* bt_ndmax is #defined in btree_.h. */
/*man---------------------------------------------------------------------------
NAME
bt_ndmin - minimum keys per node
SYNOPSIS
#include "btree_.h"
int bt_ndmin(btp)
btree_t *btp;
DESCRIPTION
SEE ALSO
bt_ndmax.
------------------------------------------------------------------------------*/
/* bt_ndmin is #defined in btree_.h. */
/*man---------------------------------------------------------------------------
NAME
bt_ndput - put btree node to file
SYNOPSIS
#include "btree_.h"
int bt_ndput(btp, node, btnp)
btree_t *btp;
bpos_t node;
btnode_t *btnp;
DESCRIPTION
SEE ALSO
bt_ndget.
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 bt_ndput(btp, node, btnp)
btree_t * btp;
bpos_t node;
btnode_t * btnp;
{
int rs = 0;
void * buf = NULL;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL) || (node == 0)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return -1;
}
#endif
/* convert node to file format */
buf = calloc(1, bt_blksize(btp));
if (buf == NULL) {
BTEPRINT;
errno = ENOMEM;
return -1;
}
memcpy(buf, (void *)btnp, offsetof(btnode_t, key_p));
memcpy((void *)((char *)buf + offsetof(btnode_t, key_p)), btnp->key_p,
((btp->bthdr.m - 1) * btp->bthdr.keysize));
memcpy((void *)((char *)buf + offsetof(btnode_t, key_p) +
((btp->bthdr.m - 1) * btp->bthdr.keysize)),
btnp->child_p,
((btp->bthdr.m) * sizeof(size_t)));
/* write node to file */
rs = bputb(btp->bp, node, buf);
if (rs == -1) {
BTEPRINT;
free(buf);
return -1;
}
/* free buffer */
free(buf);
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
SYNOPSIS
#include "btree_.h"
int bt_ndsearch(btp, btnp, key_p, kn_p)
btree_t *btp;
btnode_t *btnp;
void *key_p;
size_t *kn_p;
DESCRIPTION
Function searches node btnp for key key_p. The location of the smallest
key >= key_p is returned in kn_p.
Returns: 0 - not found
1 - found
-1 - error
SEE ALSO
DIAGNOSTICS
------------------------------------------------------------------------------*/
int bt_ndsearch(btp, btnp, key_p, kn_p)
btree_t * btp;
btnode_t * btnp;
void * key_p;
size_t * kn_p;
{
int rs = 0;
int i = 0;
bool found = FALSE;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (btnp == NULL) || (key_p == NULL) || (kn_p == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
#endif
/* initialize return value */
*kn_p = 0;
/* locate key */
for (i = 1; (i <= btnp->n); i++) {
rs = (*btp->cmp_p)(bt_kykey_p(btp, btnp, i), key_p, btp->bthdr.keysize);
if (rs == 0) {
found = TRUE;
break;
}
if (rs > 0) {
break;
}
}
*kn_p = i;
errno = 0;
return (found ? 1 : 0);
}
/*man---------------------------------------------------------------------------
NAME
bt_ndshift - node shift
SYNOPSIS
#include "btree_.h"
int bt_ndshift(btp, lbtnp, rbtnp, pbtnp, pkn)
btree_t *btp;
btnode_t *lbtnp;
btnode_t *rbtnp;
btnode_t *pbtnp;
size_t pkn;
DESCRIPTION
The bt_ndshift function shifts keys between the two sibling nodes lbtnp
and rbtnp to give them both the same number of keys (+/- 1). The
key in slot pkn in node pbtnp is the parent of the right node rbtnp.
It is updated for the shift.
bt_ndshift will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] btnp, rbtnp, or pbtnp is NULL.
[EINVAL] pkn is 0 or greater than pbtnp->n.
[BTENOPEN] btp is not open.
SEE ALSO
bt_ndfuse, bt_ndsplit.
DIAGNOSTICS
Upon successful completion, the number of keys shifted is returned.
Otherwise, a value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int bt_ndshift(btp, lbtnp, rbtnp, pbtnp, pkn)
btree_t * btp;
btnode_t * lbtnp;
btnode_t * rbtnp;
btnode_t * pbtnp;
size_t pkn;
{
int rs = 0;
int ns = 0;
bool leaf = FALSE;
bttuple_t bttuple;
errno = 0;
/* initialize storage */
memset((void *)&bttuple, 0, sizeof(bttuple));
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return NULL;
}
if ((lbtnp == NULL) || (rbtnp == NULL) || (pbtnp == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
if ((pkn == 0) || (pkn > pbtnp->n)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return NULL;
}
#endif
/* check if leaf */
if (*bt_kychild_p(lbtnp, (size_t)0) == 0) {
leaf = TRUE;
}
/* check if enough keys to shift */
if ((((lbtnp->n + rbtnp->n) / 2) < bt_ndmin(btp))) {
errno = BTEPANIC;
return -1;
}
/* calculate number of keys to shift */
ns = ((int)lbtnp->n - (int)rbtnp->n) / 2;
if (ns == 0) {
return 0;
}
/* bring down parent key pkn if internal node */
if (!leaf) {
bttuple.key_p = calloc(1, btp->bthdr.keysize);
if (bttuple.key_p == NULL) {
BTEPRINT;
errno = ENOMEM;
return -1;
}
rs = bt_kyread(btp, pbtnp, pkn, &bttuple);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
return -1;
}
bttuple.child = *bt_kychild_p(rbtnp, 0);
rs = bt_ndinskey(btp, lbtnp, lbtnp->n + 1, &bttuple);
if (rs == -1) {
BTEPRINT;
free(bttuple.key_p);
return -1;
}
free(bttuple.key_p);
bttuple.key_p = NULL;
}
/* shift keys */
if (ns > 0) {
rs = bt_kymvright(btp, lbtnp, rbtnp, (size_t)ns);
if (rs == -1) {
BTEPRINT;
return -1;
}
} else {
rs = bt_kymvleft(btp, lbtnp, rbtnp, (size_t)(-ns));
if (rs == -1) {
BTEPRINT;
return -1;
}
}
if (!leaf) {
memcpy(bt_kykey_p(btp, pbtnp, pkn), bt_kykey_p(btp, lbtnp, lbtnp->n), btp->bthdr.keysize);
rs = bt_nddelkey(btp, lbtnp, lbtnp->n);
if (rs == -1) {
BTEPRINT;
return -1;
}
} else {
memcpy(bt_kykey_p(btp, pbtnp, pkn), bt_kykey_p(btp, rbtnp, 1), btp->bthdr.keysize);
}
errno = 0;
return ((ns >= 0) ? ns : -ns);
}
/*man---------------------------------------------------------------------------
NAME
bt_ndsplit - split btree node
SYNOPSIS
#include "btree_.h"
int bt_ndsplit(btp, node, btnp, rbtnp, bttuple_p)
btree_t *btp;
bpos_t node;
btnode_t *btnp;
btnode_t *rbtnp;
bttuple_t *bttuple_p;
DESCRIPTION
The bt_ndsplit function splits node btnp located in the indicated
node block into left and right nodes. btnp becomes the left node
and rbtnp the right. The key to be inserted in the parent node is
returned in bttuple_p; the address of the new node rbtnp is in
bttuple_p->child.
bt_ndsplit will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] btnp, rbtnp, or bttuple_p is NULL.
[EINVAL] btnp and rbtnp point to the same node.
[BTENOPEN] btp is not open.
SEE ALSO
bt_ndfuse, bt_ndshift.
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 bt_ndsplit(btp, node, btnp, rbtnp, bttuple_p)
btree_t * btp;
bpos_t node;
btnode_t * btnp;
btnode_t * rbtnp;
bttuple_t * bttuple_p;
{
int rs = 0;
bool leaf = FALSE;
int midkey = 0; /* middle key */
bpos_t rnode = 0; /* right node block number */
errno = 0;
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return NULL;
}
if ((btnp == NULL) || (rbtnp == NULL) || (bttuple_p == NULL) || (btnp == rbtnp)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return NULL;
}
#endif
/* check if node not full */
if (btnp->n < (btp->bthdr.m - 1)) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* check if leaf node */
if (*bt_kychild_p(btnp, (size_t)0) == 0) {
leaf = TRUE;
}
/* find center node */
midkey = (btnp->n / 2) + 1;
/* get new node for right sibling */
bt_ndinit(btp, rbtnp);
rs = bflpop(btp->bp, &rnode);
if (rs == -1) {
BTEPRINT;
return -1;
}
/* make nodes siblings */
rbtnp->rsib = btnp->rsib;
btnp->rsib = rnode;
rbtnp->lsib = node;
/* load bttuple_p */
rs = bt_kyread(btp, btnp, midkey, bttuple_p);
if (rs == -1) {
BTEPRINT;
return -1;
}
bttuple_p->child = rnode;
/* move keys midkey through n to the right sibling */
if (leaf) {
rs = bt_kymvright(btp, btnp, rbtnp, btnp->n - midkey + 1);
if (rs == -1) {
BTEPRINT;
return -1;
}
} else {
rs = bt_kymvright(btp, btnp, rbtnp, btnp->n - midkey);
if (rs == -1) {
BTEPRINT;
return -1;
}
rs = bt_nddelkey(btp, btnp, btnp->n);
if (rs == -1) {
BTEPRINT;
return -1;
}
}
errno = 0;
return 0;
}