/* This is information from the last page of the pair. */
n = bp[0];
pageno = bp[n - 1];
/* Now, bp is the first page of the pair. */
bp = (uint16 *)bufp->page; if (n > 2) { /* There is an overflow page. */
bp[1] = pageno;
bp[2] = OVFLPAGE;
bufp->ovfl = rbufp->ovfl;
} else /* This is the last page. */
bufp->ovfl = NULL;
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
OFFSET(bp) = hashp->BSIZE - 1;
bufp->flags |= BUF_MOD; if (rbufp)
dbm_free_ovflpage(hashp, rbufp); if (last_bfp != rbufp)
dbm_free_ovflpage(hashp, last_bfp);
/* *Returnthedataforthekey/datapairthatbeginsonthispageatthis *index(indexshouldalwaysbe1).
*/ externint
dbm_big_return(
HTAB *hashp,
BUFHEAD *bufp, int ndx,
DBT *val, int set_current)
{
BUFHEAD *save_p;
uint16 *bp, len, off, save_addr; char *tp; int save_flags;
bp = (uint16 *)bufp->page; while (bp[ndx + 1] == PARTIAL_KEY) {
bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1);
bp = (uint16 *)bufp->page;
ndx = 1;
}
if (bp[ndx + 1] == FULL_KEY) {
bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1);
bp = (uint16 *)bufp->page;
save_p = bufp;
save_addr = save_p->addr;
off = bp[1];
len = 0;
} elseif (!FREESPACE(bp)) { /* *Thisisahack.Wecan'tdistinguishbetween *FULL_KEY_DATAthatcontainscompletedataor *incompletedata,sowerequirethatifthedata *iscomplete,thereisatleast1byteoffree *spaceleft.
*/
off = bp[bp[0]];
len = bp[1] - off;
save_p = bufp;
save_addr = bufp->addr;
bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1);
bp = (uint16 *)bufp->page;
} else { /* The data is all on one page. */
tp = (char *)bp;
off = bp[bp[0]];
val->data = (uint8 *)tp + off;
val->size = bp[1] - off; if (set_current) { if (bp[0] == 2) { /* No more buckets in
* chain */
hashp->cpage = NULL;
hashp->cbucket++;
hashp->cndx = 1;
} else {
hashp->cpage = dbm_get_buf(hashp,
bp[bp[0] - 1], bufp, 0); if (!hashp->cpage) return (-1);
hashp->cndx = 1; if (!((uint16 *)
hashp->cpage->page)[0]) {
hashp->cbucket++;
hashp->cpage = NULL;
}
}
} return (0);
}
/* pin our saved buf so that we don't lose if
* we run out of buffers */
save_flags = save_p->flags;
save_p->flags |= BUF_PIN;
val->size = collect_data(hashp, bufp, (int)len, set_current);
save_p->flags = save_flags; if (val->size == (size_t)-1) return (-1); if (save_p->addr != save_addr) { /* We are pretty short on buffers. */
errno = EINVAL; /* OUT OF BUFFERS */ return (-1);
}
memmove(hashp->tmp_buf, (save_p->page) + off, len);
val->data = (uint8 *)hashp->tmp_buf; return (0);
}
/* *Counthowbigthetotaldatasizeisbyloopingthroughthepages.Then *allocateabufferandcopythedatainthesecondloop.NOTE:Ourcaller *mayalreadyhaveabpwhichitisholdingonto.Thecalleris *responsibleforcopyingthatbpintoourtempbuffer.'len'ishowmuch *spacetoreserveforthatbuffer.
*/ staticint
collect_data(
HTAB *hashp,
BUFHEAD *bufp, int len, int set)
{ register uint16 *bp;
BUFHEAD *save_bufp; int save_flags; int mylen, totlen;
/* read the length of the buffer */ for (totlen = len; bufp; bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0)) {
bp = (uint16 *)bufp->page;
mylen = hashp->BSIZE - bp[1];
/* if mylen ever goes negative it means that the *pageisscrewedup.
*/ if (mylen < 0) {
save_bufp->flags = save_flags; return (-1);
}
totlen += mylen; if (bp[2] == FULL_KEY_DATA) { /* End of Data */ break;
}
}
if (!bufp) {
save_bufp->flags = save_flags; return (-1);
}
/* allocate a temp buf */ if (hashp->tmp_buf)
free(hashp->tmp_buf); if ((hashp->tmp_buf = (char *)malloc((size_t)totlen)) == NULL) {
save_bufp->flags = save_flags; return (-1);
}
/* copy the buffers back into temp buf */ for (bufp = save_bufp; bufp;
bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0)) {
bp = (uint16 *)bufp->page;
mylen = hashp->BSIZE - bp[1];
memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], (size_t)mylen);
len += mylen; if (bp[2] == FULL_KEY_DATA) { break;
}
}
/* 'clear' the pin flags */
save_bufp->flags = save_flags;
/* update the database cursor */ if (set) {
hashp->cndx = 1; if (bp[0] == 2) { /* No more buckets in chain */
hashp->cpage = NULL;
hashp->cbucket++;
} else {
hashp->cpage = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!hashp->cpage) return (-1); elseif (!((uint16 *)hashp->cpage->page)[0]) {
hashp->cbucket++;
hashp->cpage = NULL;
}
}
} return (totlen);
}
/* *Counthowbigthetotalkeysizeisbyrecursingthroughthepages.Then *collectthedata,allocateabufferandcopythekeyasyourecurseup.
*/ staticint
collect_key(
HTAB *hashp,
BUFHEAD *bufp, int len,
DBT *val, int set)
{
BUFHEAD *xbp; char *p; int mylen, totlen;
uint16 *bp, save_addr;
p = bufp->page;
bp = (uint16 *)p;
mylen = hashp->BSIZE - bp[1];
save_addr = bufp->addr;
totlen = len + mylen; if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ if (hashp->tmp_key != NULL)
free(hashp->tmp_key); if ((hashp->tmp_key = (char *)malloc((size_t)totlen)) == NULL) return (-1); if (dbm_big_return(hashp, bufp, 1, val, set)) return (-1);
} else {
xbp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!xbp || ((totlen =
collect_key(hashp, xbp, totlen, val, set)) < 1)) return (-1);
} if (bufp->addr != save_addr) {
errno = EINVAL; /* MIS -- OUT OF BUFFERS */ return (-1);
}
memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], (size_t)mylen); return (totlen);
}
/* *Returns: *0=>OK *-1=>error
*/ externint
dbm_big_split(
HTAB *hashp,
BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
BUFHEAD *np, /* Pointer to new bucket page */ /* Pointer to first page containing the big key/data */
BUFHEAD *big_keyp,
uint32 addr, /* Address of big_keyp */
uint32 obucket, /* Old Bucket */
SPLIT_RETURN *ret)
{ register BUFHEAD *tmpp; register uint16 *tp;
BUFHEAD *bp;
DBT key, val;
uint32 change;
uint16 free_space, n, off;
bp = big_keyp;
/* Now figure out where the big key/data goes */ if (dbm_big_keydata(hashp, big_keyp, &key, &val, 0)) return (-1);
change = (dbm_call_hash(hashp, (char *)key.data, key.size) != obucket);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.