1*50995Sbostic /*- 2*50995Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*50995Sbostic * All rights reserved. 4*50995Sbostic * 5*50995Sbostic * This code is derived from software contributed to Berkeley by 6*50995Sbostic * Mike Olson. 7*50995Sbostic * 8*50995Sbostic * %sccs.include.redist.c% 9*50995Sbostic */ 10*50995Sbostic 11*50995Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*50995Sbostic static char sccsid[] = "@(#)rec_delete.c 5.1 (Berkeley) 09/04/91"; 13*50995Sbostic #endif /* LIBC_SCCS and not lint */ 14*50995Sbostic 15*50995Sbostic #include <sys/types.h> 16*50995Sbostic #include <errno.h> 17*50995Sbostic #include <db.h> 18*50995Sbostic #include <stdio.h> 19*50995Sbostic #include <string.h> 20*50995Sbostic #include "../btree/btree.h" 21*50995Sbostic 22*50995Sbostic static int rec_rdelete __P((BTREE *, recno_t)); 23*50995Sbostic 24*50995Sbostic /* 25*50995Sbostic * __REC_DELETE -- Delete the item(s) referenced by a key. 26*50995Sbostic * 27*50995Sbostic * Parameters: 28*50995Sbostic * dbp: pointer to access method 29*50995Sbostic * key: key to delete 30*50995Sbostic * flags: R_CURSOR if deleting what the cursor references 31*50995Sbostic * 32*50995Sbostic * Returns: 33*50995Sbostic * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 34*50995Sbostic */ 35*50995Sbostic int 36*50995Sbostic __rec_delete(dbp, key, flags) 37*50995Sbostic const DB *dbp; 38*50995Sbostic const DBT *key; 39*50995Sbostic u_int flags; 40*50995Sbostic { 41*50995Sbostic BTREE *t; 42*50995Sbostic recno_t nrec; 43*50995Sbostic int status; 44*50995Sbostic 45*50995Sbostic if ((nrec = *(recno_t *)key->data) == 0) { 46*50995Sbostic errno = EINVAL; 47*50995Sbostic return (RET_ERROR); 48*50995Sbostic } 49*50995Sbostic --nrec; 50*50995Sbostic 51*50995Sbostic t = dbp->internal; 52*50995Sbostic switch(flags) { 53*50995Sbostic case 0: 54*50995Sbostic status = rec_rdelete(t, nrec); 55*50995Sbostic break; 56*50995Sbostic case R_CURSOR: 57*50995Sbostic status = rec_rdelete(t, t->bt_rcursor); 58*50995Sbostic break; 59*50995Sbostic default: 60*50995Sbostic errno = EINVAL; 61*50995Sbostic return (RET_ERROR); 62*50995Sbostic } 63*50995Sbostic 64*50995Sbostic if (status == RET_SUCCESS) { 65*50995Sbostic --t->bt_nrecs; 66*50995Sbostic SET(t, BTF_MODIFIED); 67*50995Sbostic } 68*50995Sbostic return (status); 69*50995Sbostic } 70*50995Sbostic 71*50995Sbostic /* 72*50995Sbostic * REC_RDELETE -- Delete the data matching the specified key. 73*50995Sbostic * 74*50995Sbostic * Parameters: 75*50995Sbostic * tree: tree 76*50995Sbostic * nrec: record to delete 77*50995Sbostic * 78*50995Sbostic * Returns: 79*50995Sbostic * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 80*50995Sbostic */ 81*50995Sbostic static int 82*50995Sbostic rec_rdelete(t, nrec) 83*50995Sbostic BTREE *t; 84*50995Sbostic recno_t nrec; 85*50995Sbostic { 86*50995Sbostic EPG *e; 87*50995Sbostic EPGNO *parent; 88*50995Sbostic PAGE *h; 89*50995Sbostic int exact, status; 90*50995Sbostic 91*50995Sbostic /* Find any matching record; __rec_search pins the page. */ 92*50995Sbostic e = __rec_search(t, nrec, &exact); 93*50995Sbostic if (e == NULL || !exact) { 94*50995Sbostic mpool_put(t->bt_mp, e->page, 0); 95*50995Sbostic return (e == NULL ? RET_ERROR : RET_SPECIAL); 96*50995Sbostic } 97*50995Sbostic 98*50995Sbostic /* Delete the record. */ 99*50995Sbostic h = e->page; 100*50995Sbostic status = __rec_dleaf(t, h, e->index); 101*50995Sbostic if (status == RET_SUCCESS) 102*50995Sbostic mpool_put(t->bt_mp, h, MPOOL_DIRTY); 103*50995Sbostic else { 104*50995Sbostic mpool_put(t->bt_mp, h, 0); 105*50995Sbostic return (status); 106*50995Sbostic } 107*50995Sbostic 108*50995Sbostic /* Decrement the count on all parent pages. */ 109*50995Sbostic while ((parent = BT_POP(t)) != NULL) { 110*50995Sbostic if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) 111*50995Sbostic return (RET_ERROR); 112*50995Sbostic --GETRINTERNAL(h, parent->index)->nrecs; 113*50995Sbostic mpool_put(t->bt_mp, h, MPOOL_DIRTY); 114*50995Sbostic } 115*50995Sbostic return (RET_SUCCESS); 116*50995Sbostic } 117*50995Sbostic 118*50995Sbostic /* 119*50995Sbostic * __REC_DLEAF -- Delete a single record from a recno leaf page. 120*50995Sbostic * 121*50995Sbostic * Parameters: 122*50995Sbostic * t: tree 123*50995Sbostic * index: index on current page to delete 124*50995Sbostic * 125*50995Sbostic * Returns: 126*50995Sbostic * RET_SUCCESS, RET_ERROR. 127*50995Sbostic */ 128*50995Sbostic int 129*50995Sbostic __rec_dleaf(t, h, index) 130*50995Sbostic BTREE *t; 131*50995Sbostic PAGE *h; 132*50995Sbostic int index; 133*50995Sbostic { 134*50995Sbostic register RLEAF *rl; 135*50995Sbostic register index_t *ip, offset; 136*50995Sbostic register size_t nbytes; 137*50995Sbostic register int cnt; 138*50995Sbostic char *from; 139*50995Sbostic void *to; 140*50995Sbostic 141*50995Sbostic /* 142*50995Sbostic * Delete a record from a recno leaf page. Internal records are never 143*50995Sbostic * deleted from internal pages, regardless of the records that caused 144*50995Sbostic * them to be added being deleted. Pages made empty by deletion are 145*50995Sbostic * not reclaimed. They are, however, made available for reuse. 146*50995Sbostic * 147*50995Sbostic * Pack the remaining entries at the end of the page, shift the indices 148*50995Sbostic * down, overwriting the deleted record and its index. If the record 149*50995Sbostic * uses overflow pages, make them available for reuse. 150*50995Sbostic */ 151*50995Sbostic to = rl = GETRLEAF(h, index); 152*50995Sbostic if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) 153*50995Sbostic return (RET_ERROR); 154*50995Sbostic nbytes = NRLEAF(rl); 155*50995Sbostic 156*50995Sbostic /* 157*50995Sbostic * Compress the key/data pairs. Compress and adjust the [BR]LEAF 158*50995Sbostic * offsets. Reset the headers. 159*50995Sbostic */ 160*50995Sbostic from = (char *)h + h->upper; 161*50995Sbostic bcopy(from, from + nbytes, (char *)to - from); 162*50995Sbostic h->upper += nbytes; 163*50995Sbostic 164*50995Sbostic offset = h->linp[index]; 165*50995Sbostic for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip) 166*50995Sbostic if (ip[0] < offset) 167*50995Sbostic ip[0] += nbytes; 168*50995Sbostic for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) 169*50995Sbostic ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; 170*50995Sbostic h->lower -= sizeof(index_t); 171*50995Sbostic return (RET_SUCCESS); 172*50995Sbostic } 173