/* * NAME: node->insert() * DESCRIPTION: insert a new record into a node; return a record for parent */ int n_insert(node *np, unsigned char *record, int *reclen) { n_compact(np); /* check for free space */ if (np->nd.ndNRecs >= HFS_MAXRECS || *reclen + 2 > (int)NODESPACE(*np)) return n_split(np, record, reclen); n_insertx(np, record, *reclen); *reclen = 0; return bt_putnode(np); }
/* * NAME: node->delete() * DESCRIPTION: remove a record from a node */ int n_delete(node *np, unsigned char *record, int *flag) { node left; unsigned char *rec; rec = HFS_NODEREC(*np, np->rnum); HFS_RECKEYLEN(rec) = 0; n_compact(np); /* see if we can merge with our left sibling */ left.bt = np->bt; left.nnum = np->nd.ndBLink; if (left.nnum > 0) { if (bt_getnode(&left) < 0) return -1; if ((int)(np->nd.ndNRecs + left.nd.ndNRecs) <= HFS_MAXRECS && (int)(np->roff[np->nd.ndNRecs] - np->roff[0] + 2 * np->nd.ndNRecs) <= (int)NODESPACE(left)) return n_merge(np, &left, record, flag); } if (np->rnum == 0) { /* special case: first record changed; update parent record key */ n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0); *flag = 1; } return bt_putnode(np); }
/* * NAME: node->split() * DESCRIPTION: divide a node into two and insert a record */ int n_split(node *left, unsigned char *record, int *reclen) { node right; int nrecs, i, mid; unsigned char *rec; right = *left; right.nd.ndBLink = left->nnum; if (n_new(&right) < 0) return -1; left->nd.ndFLink = right.nnum; nrecs = left->nd.ndNRecs; /* * Ensure node split leaves enough room for new record. * The size calculations used are based on the NODESPACE() macro, but * I don't know what the extra 2's and 1's are needed for. * John Witford <*****@*****.**> */ n_search(&right, record); mid = nrecs/2; for(;;) { if (right.rnum < mid) { if ( mid > 0 && (int)left->roff[mid] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1)) { --mid; if (mid > 0) continue; } } else { if ( mid < nrecs && (int)right.roff[nrecs] - (int)right.roff[mid] + (int)left->roff[0] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1)) { ++mid; if (mid < nrecs) continue; } } break; } for (i = 0; i < nrecs; ++i) { if (i < mid) rec = HFS_NODEREC(right, i); else rec = HFS_NODEREC(*left, i); HFS_RECKEYLEN(rec) = 0; } /* original code ... for (i = 0; i < nrecs; ++i) { if (i < nrecs / 2) rec = HFS_NODEREC(right, i); else rec = HFS_NODEREC(*left, i); HFS_RECKEYLEN(rec) = 0; } */ n_compact(left); n_compact(&right); n_search(&right, record); if (right.rnum >= 0) n_insertx(&right, record, *reclen); else { n_search(left, record); n_insertx(left, record, *reclen); } /* store the new/modified nodes */ if (bt_putnode(left) < 0 || bt_putnode(&right) < 0) return -1; /* create an index record for the new node in the parent */ n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen); /* update link pointers */ if (left->bt->hdr.bthLNode == left->nnum) { left->bt->hdr.bthLNode = right.nnum; left->bt->flags |= HFS_UPDATE_BTHDR; } if (right.nd.ndFLink) { node n; n.bt = right.bt; n.nnum = right.nd.ndFLink; if (bt_getnode(&n) < 0) return -1; n.nd.ndBLink = right.nnum; if (bt_putnode(&n) < 0) return -1; } return 0; }
/* * NAME: node->split() * DESCRIPTION: divide a node into two and insert a record */ int n_split(node *left, unsigned char *record, int *reclen) { node right; int nrecs, i; unsigned char *rec; right = *left; right.nd.ndBLink = left->nnum; if (n_new(&right) < 0) return -1; left->nd.ndFLink = right.nnum; nrecs = left->nd.ndNRecs; for (i = 0; i < nrecs; ++i) { if (i < nrecs / 2) rec = HFS_NODEREC(right, i); else rec = HFS_NODEREC(*left, i); HFS_RECKEYLEN(rec) = 0; } n_compact(left); n_compact(&right); n_search(&right, record); if (right.rnum >= 0) n_insertx(&right, record, *reclen); else { n_search(left, record); n_insertx(left, record, *reclen); } /* store the new/modified nodes */ if (bt_putnode(left) < 0 || bt_putnode(&right) < 0) return -1; /* create an index record for the new node in the parent */ n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen); /* update link pointers */ if (left->bt->hdr.bthLNode == left->nnum) { left->bt->hdr.bthLNode = right.nnum; left->bt->flags |= HFS_UPDATE_BTHDR; } if (right.nd.ndFLink) { node n; n.bt = right.bt; n.nnum = right.nd.ndFLink; if (bt_getnode(&n) < 0) return -1; n.nd.ndBLink = right.nnum; if (bt_putnode(&n) < 0) return -1; } return 0; }