|
|
researchv10 Norman
#include "cbt.h"
#include "pr.h"
typedef union {
ndaddr na;
lfaddr la;
} addr;
static char splitting[MXHT+1];
extern bfile *curbf;
extern ndaddr oldnode(), newnode();
extern char *malloc();
extern long brecwrite();
bwrite(bf, key, rec) mbuf key, rec; bfile *bf;
{ addr u;
int n;
if(bf == NULL)
return(EOF);
if(!bf->rdwrt) {
errno = BNOWRITE;
return(EOF);
}
if(notran(bf))
return(EOF);
if(key.mlen > MAXKLEN)
return(EOF);
if(!treeonly(bf)) {
u.la.llen = rec.mlen;
u.la.lloc = brecwrite(rec);
if(u.la.lloc == EOF)
return(EOF);
}
if(desce(bf, key, (private *)NULL) == EOF)
return(EOF);
n = xinsert(0, key, u);
(void) bseek(bf, key);
return(n);
}
fixpath(bf)
bfile *bf;
{ addr u;
hdr *b;
int i, n, j;
for(i = 0; i < bf->height; i++) {
if(!mustwrite(bf, i))
continue;
n = bf->loc[i];
if((u.na = oldnode(i)) == EOF)
return(EOF);
b = bf->path[i+1];
for(j = 0; j <= b->kcnt; j++)
if(*ndadr(b, j) == n)
break;
if(j > b->kcnt){ /* curtains, the parent doesn't point to us */
errno = BFATAL;
return(EOF);
}
*ndadr(b, j) = u.na;
mustwrite(bf, i + 1) = 1;
}
return(0);
}
xinsert(lev, key, u) mbuf key; addr u;
{ private x;
int n, dellen;
hdr *b = curbf->path[lev];
char ba[NDSZ], bb[NDSZ];
dkey *dx, *dy;
if(splitting[lev])
if(desce(curbf, key, (private *)NULL) == EOF)
return(EOF);
n = xscan(b, key, &x);
if(x.match == FOUND) {
if(treeonly(curbf))
return(FOUND);
else if(lev)
*ndadr(b, n) = u.na;
else
*lfadr(b, n) = u.la;
mustwrite(curbf, lev) = 1;
return(FOUND);
}
dx = (dkey *)ba;
dy = (dkey *)bb;
dellen = newx(&x, key, dx, dy);
if(lev)
dellen += sizeof(ndaddr);
else if(!treeonly(curbf))
dellen += sizeof(lfaddr);
if(dellen > nfree(b)) {
if(nsplit(lev) == EOF)
return(EOF);
splitting[lev] = 1;
n = xinsert(lev, key, u);
splitting[lev] = 0;
return(n);
}
b = curbf->path[lev]; /* with thanks to brian meekings */
addaddr(b, n, u);
newkeys(b, &x, dx, dy);
b->kcnt++;
nfree(b) -= dellen;
mustwrite(curbf, lev) = 1;
return(NOTFOUND);
}
newx(x, key, c, d) private *x; mbuf key; dkey *c, *d;
{ int i, j;
if(x->match != EOF)
c->dcom = x->ocom;
else c->dcom = x->ncom;
i = key.mlen - c->dcom;
c->dlen = DKEYSZ + i;
mvgbt(c->dkey, key.mdata + c->dcom, i);
if(x->match == EOF)
return(c->dlen);
j = x->ncom - x->d->dcom;
d->dcom = x->ncom;
d->dlen = x->d->dlen - j;
mvgbt(d->dkey, x->d->dkey + j, d->dlen - DKEYSZ);
return(c->dlen - j);
}
addaddr(b, n, u)
hdr *b;
addr u;
{
if(b->hlev) {
mvgbt((char *)ndadr(b, b->kcnt + 1),
(char *)ndadr(b, b->kcnt),
sizeof(ndaddr) * (b->kcnt + 1 - n) );
*ndadr(b, n) = u.na;
return;
}
if(treeonly(curbf))
return;
mvgbt((char *)lfadr(b, b->kcnt), (char *)lfadr(b, b->kcnt - 1),
sizeof(lfaddr) * (b->kcnt - n));
*lfadr(b, n) = u.la;
}
newkeys(b, x, c, d)
hdr *b;
private *x;
dkey *c, *d;
{ int n;
char *ffree;
if(b->hlev)
ffree = (char *)ndadr(b, b->kcnt) - nfree(b);
else if(treeonly(curbf))
ffree = (char *)&nfree(b) - nfree(b);
else
ffree = (char *)lfadr(b, b->kcnt - 1) - nfree(b);
if(x->match != EOF) {
n = c->dlen + d->dlen;
n -= x->d->dlen;
mvgbt((char *)x->d + n, (char *)x->d, ffree - (char *)x->d);
mvgbt((char *)x->d, (char *)c, c->dlen);
mvgbt((char *)x->d + c->dlen, (char *)d, d->dlen);
}
else if(b->kcnt > 0)
mvgbt((char *)x->d + x->d->dlen, (char *)c, c->dlen);
else
mvgbt((char *)x->d, (char *)c, c->dlen);
}
nsplit(lev)
{ dkey *tod, *fromd;
char prefix[MAXKLEN + 10];
hdr *b = curbf->path[lev];
mbuf key;
addr u;
union {
lfaddr *la;
ndaddr *na;
} from, to;
int mvd, x, i, count, n;
hdr *ha;
char a[NDSZ];
x = (NDSZ - sizeof(hdr) - sizeof(trailer)) / 2;
ha = (hdr *) a;
mvd = count = 0;
tod = (dkey *)(ha + 1);
fromd = (dkey *)(b + 1);
if(lev == 0) {
to.la = lfadr(ha, 0);
from.la = lfadr(b, 0);
}
else {
to.na = ndadr(ha, 0);
from.na = ndadr(b, 0);
}
*ha = *b;
n = (b->kcnt + 1)/2;
if(lev && b->kcnt - n <= 1)
n--;
for(; count < n && mvd <= x; count++) {
mvgbt((char *)tod, (char *)fromd, fromd->dlen);
mvd += fromd->dlen;
tod = (dkey *)((char *)tod + fromd->dlen);
fromd = (dkey *)((char *)fromd + fromd->dlen);
if(lev) {
*to.na-- = *from.na--;
mvd += sizeof(ndaddr);
}
else if(!treeonly(curbf)) {
*to.la-- = *from.la--;
mvd += sizeof(lfaddr);
}
}
if(lev) { /* another pointer for non-leaves */
*to.na-- = *from.na--;
mvd += sizeof(ndaddr);
}
ha->kcnt = count;
nfree(ha) = NDSZ - sizeof(hdr) - sizeof(trailer) - mvd;
/* if lev == 0, we promote the last key, else the next key */
key.mlen = lastkey(ha, prefix);
if(lev) {
mvgbt(prefix + fromd->dcom, fromd->dkey, fromd->dlen - DKEYSZ);
key.mlen = fromd->dcom + fromd->dlen - DKEYSZ;
count++;
fromd = (dkey *)((char *)fromd + fromd->dlen);
}
u.na = newnode(ha);
if(u.na == EOF) { /* error while splitting */
curbf->fatal++;
return(EOF);
}
key.mdata = prefix;
/* other half */
if(lev == 0)
to.la = lfadr(ha, 0);
else
to.na = ndadr(ha, 0);
tod = (dkey *)(ha + 1);
tod->dcom = 0;
tod->dlen = fromd->dlen + fromd->dcom;
mvgbt(tod->dkey, prefix, fromd->dcom);
mvgbt(tod->dkey + fromd->dcom, fromd->dkey, fromd->dlen - DKEYSZ);
mvd = tod->dlen;
fromd = (dkey *)((char *)fromd + fromd->dlen);
tod = (dkey *)((char *)tod + tod->dlen);
if(lev) {
*to.na-- = *from.na--;
mvd += sizeof(ndaddr);
}
else if(!treeonly(curbf)) {
*to.la-- = *from.la--;
mvd += sizeof(lfaddr);
}
count++;
for(i = 1; count < b->kcnt; i++, count++) {
mvgbt((char *)tod, (char *)fromd, fromd->dlen);
mvd += fromd->dlen;
tod = (dkey *)((char *)tod + tod->dlen);
fromd = (dkey *)((char *)fromd + fromd->dlen);
if(lev) {
*to.na-- = *from.na--;
mvd += sizeof(ndaddr);
}
else if(!treeonly(curbf)) {
*to.la-- = *from.la--;
mvd += sizeof(lfaddr);
}
}
if(lev) {
*to.na-- = *from.na--;
mvd += sizeof(ndaddr);
}
ha->kcnt = i;
nfree(ha) = NDSZ - sizeof(hdr) - sizeof(trailer) - mvd;
mvgbt((char *)b, (char *)ha, NDSZ);
mustwrite(curbf, lev) = 1;
if(lev < curbf->height) {
if(xinsert(lev + 1, key, u) == EOF) {
curbf->fatal++;
return(EOF);
}
}
else
return(newroot(u, key, b));
return(0);
}
newroot(u, key, b)
addr u;
mbuf key;
hdr *b;
{ hdr *x;
dkey *d;
if(curbf->height >= MXHT) {
errno = BTALL;
curbf->fatal++;
return(EOF);
}
if((x = curbf->path[b->hlev + 1] = (hdr *)malloc(NDSZ)) == NULL) {
errno = BNOMEM;
curbf->fatal++;
return(EOF);
}
*x = *b;
x->hlev++;
d = (dkey *)(x + 1);
d->dlen = DKEYSZ + key.mlen;
d->dcom = 0;
mvgbt(d->dkey, key.mdata, key.mlen);
*ndadr(x, 0) = u.na;
*ndadr(x, 1) = curbf->loc[b->hlev] = newnode(b);
x->kcnt = 1;
nfree(x) = NDSZ - sizeof(hdr) - sizeof(trailer) - DKEYSZ
- key.mlen - 2 * sizeof(ndaddr);
mustwrite(curbf, ++curbf->height) = 1;
return(0);
}
lastkey(b, s)
hdr *b;
char *s;
{ int i, n;
dkey *p;
p = (dkey *)(b + 1);
for(n = i = 0; i < b->kcnt; i++) {
mvgbt(s + p->dcom, p->dkey, p->dlen - DKEYSZ);
n = p->dlen + p->dcom - DKEYSZ;
p = (dkey *)((char *) p + p->dlen);
}
return(n);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.