150995Sbostic /*- 261207Sbostic * Copyright (c) 1990, 1993 361207Sbostic * The Regents of the University of California. All rights reserved. 450995Sbostic * 550995Sbostic * This code is derived from software contributed to Berkeley by 650995Sbostic * Mike Olson. 750995Sbostic * 850995Sbostic * %sccs.include.redist.c% 950995Sbostic */ 1050995Sbostic 1150995Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*66140Sbostic static char sccsid[] = "@(#)rec_delete.c 8.3 (Berkeley) 02/17/94"; 1350995Sbostic #endif /* LIBC_SCCS and not lint */ 1450995Sbostic 1550995Sbostic #include <sys/types.h> 1656756Sbostic 1750995Sbostic #include <errno.h> 1850995Sbostic #include <stdio.h> 1950995Sbostic #include <string.h> 2056756Sbostic 2157933Sbostic #include <db.h> 2251088Sbostic #include "recno.h" 2350995Sbostic 2450995Sbostic static int rec_rdelete __P((BTREE *, recno_t)); 2550995Sbostic 2650995Sbostic /* 2750995Sbostic * __REC_DELETE -- Delete the item(s) referenced by a key. 2850995Sbostic * 2950995Sbostic * Parameters: 3050995Sbostic * dbp: pointer to access method 3150995Sbostic * key: key to delete 3250995Sbostic * flags: R_CURSOR if deleting what the cursor references 3350995Sbostic * 3450995Sbostic * Returns: 3550995Sbostic * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 3650995Sbostic */ 3750995Sbostic int 3850995Sbostic __rec_delete(dbp, key, flags) 3950995Sbostic const DB *dbp; 4050995Sbostic const DBT *key; 4150995Sbostic u_int flags; 4250995Sbostic { 4350995Sbostic BTREE *t; 4450995Sbostic recno_t nrec; 4550995Sbostic int status; 4650995Sbostic 4750995Sbostic t = dbp->internal; 4864461Sbostic 4964461Sbostic /* Toss any page pinned across calls. */ 5064461Sbostic if (t->bt_pinned != NULL) { 5164461Sbostic mpool_put(t->bt_mp, t->bt_pinned, 0); 5264461Sbostic t->bt_pinned = NULL; 5364461Sbostic } 5464461Sbostic 5550995Sbostic switch(flags) { 5650995Sbostic case 0: 5756756Sbostic if ((nrec = *(recno_t *)key->data) == 0) 5856756Sbostic goto einval; 5951088Sbostic if (nrec > t->bt_nrecs) 6051088Sbostic return (RET_SPECIAL); 6151088Sbostic --nrec; 6250995Sbostic status = rec_rdelete(t, nrec); 6350995Sbostic break; 6450995Sbostic case R_CURSOR: 6560052Sbostic if (!ISSET(t, B_SEQINIT)) 6656756Sbostic goto einval; 6756756Sbostic if (t->bt_nrecs == 0) 6851088Sbostic return (RET_SPECIAL); 6951088Sbostic status = rec_rdelete(t, t->bt_rcursor - 1); 7056756Sbostic if (status == RET_SUCCESS) 7151088Sbostic --t->bt_rcursor; 7250995Sbostic break; 7350995Sbostic default: 7456756Sbostic einval: errno = EINVAL; 7550995Sbostic return (RET_ERROR); 7650995Sbostic } 7750995Sbostic 7854281Sbostic if (status == RET_SUCCESS) 7960052Sbostic SET(t, B_MODIFIED | R_MODIFIED); 8050995Sbostic return (status); 8150995Sbostic } 8250995Sbostic 8350995Sbostic /* 8450995Sbostic * REC_RDELETE -- Delete the data matching the specified key. 8550995Sbostic * 8650995Sbostic * Parameters: 8750995Sbostic * tree: tree 8850995Sbostic * nrec: record to delete 8950995Sbostic * 9050995Sbostic * Returns: 9150995Sbostic * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 9250995Sbostic */ 9350995Sbostic static int 9450995Sbostic rec_rdelete(t, nrec) 9550995Sbostic BTREE *t; 9650995Sbostic recno_t nrec; 9750995Sbostic { 9850995Sbostic EPG *e; 9950995Sbostic PAGE *h; 10051088Sbostic int status; 10150995Sbostic 10251088Sbostic /* Find the record; __rec_search pins the page. */ 103*66140Sbostic if ((e = __rec_search(t, nrec, SDELETE)) == NULL) 10451088Sbostic return (RET_ERROR); 10550995Sbostic 10650995Sbostic /* Delete the record. */ 10750995Sbostic h = e->page; 10850995Sbostic status = __rec_dleaf(t, h, e->index); 10951088Sbostic if (status != RET_SUCCESS) { 11050995Sbostic mpool_put(t->bt_mp, h, 0); 11150995Sbostic return (status); 11250995Sbostic } 11351088Sbostic mpool_put(t->bt_mp, h, MPOOL_DIRTY); 11450995Sbostic return (RET_SUCCESS); 11550995Sbostic } 11650995Sbostic 11750995Sbostic /* 11850995Sbostic * __REC_DLEAF -- Delete a single record from a recno leaf page. 11950995Sbostic * 12050995Sbostic * Parameters: 12150995Sbostic * t: tree 12250995Sbostic * index: index on current page to delete 12350995Sbostic * 12450995Sbostic * Returns: 12550995Sbostic * RET_SUCCESS, RET_ERROR. 12650995Sbostic */ 12750995Sbostic int 12850995Sbostic __rec_dleaf(t, h, index) 12950995Sbostic BTREE *t; 13050995Sbostic PAGE *h; 13150995Sbostic int index; 13250995Sbostic { 13350995Sbostic register RLEAF *rl; 13457988Sbostic register indx_t *ip, offset; 13550995Sbostic register size_t nbytes; 13650995Sbostic register int cnt; 13750995Sbostic char *from; 13850995Sbostic void *to; 13950995Sbostic 14050995Sbostic /* 14150995Sbostic * Delete a record from a recno leaf page. Internal records are never 14250995Sbostic * deleted from internal pages, regardless of the records that caused 14350995Sbostic * them to be added being deleted. Pages made empty by deletion are 14450995Sbostic * not reclaimed. They are, however, made available for reuse. 14550995Sbostic * 14650995Sbostic * Pack the remaining entries at the end of the page, shift the indices 14750995Sbostic * down, overwriting the deleted record and its index. If the record 14850995Sbostic * uses overflow pages, make them available for reuse. 14950995Sbostic */ 15050995Sbostic to = rl = GETRLEAF(h, index); 15150995Sbostic if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) 15250995Sbostic return (RET_ERROR); 15350995Sbostic nbytes = NRLEAF(rl); 15450995Sbostic 15550995Sbostic /* 15650995Sbostic * Compress the key/data pairs. Compress and adjust the [BR]LEAF 15750995Sbostic * offsets. Reset the headers. 15850995Sbostic */ 15950995Sbostic from = (char *)h + h->upper; 16058015Sbostic memmove(from + nbytes, from, (char *)to - from); 16150995Sbostic h->upper += nbytes; 16250995Sbostic 16350995Sbostic offset = h->linp[index]; 16450995Sbostic for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip) 16550995Sbostic if (ip[0] < offset) 16650995Sbostic ip[0] += nbytes; 16750995Sbostic for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) 16850995Sbostic ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; 16957988Sbostic h->lower -= sizeof(indx_t); 17054281Sbostic --t->bt_nrecs; 17150995Sbostic return (RET_SUCCESS); 17250995Sbostic } 173