xref: /csrg-svn/lib/libc/db/recno/rec_delete.c (revision 51088)
150995Sbostic /*-
250995Sbostic  * Copyright (c) 1990 The Regents of the University of California.
350995Sbostic  * 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*51088Sbostic static char sccsid[] = "@(#)rec_delete.c	5.2 (Berkeley) 09/11/91";
1350995Sbostic #endif /* LIBC_SCCS and not lint */
1450995Sbostic 
1550995Sbostic #include <sys/types.h>
1650995Sbostic #include <errno.h>
1750995Sbostic #include <db.h>
1850995Sbostic #include <stdio.h>
1950995Sbostic #include <string.h>
20*51088Sbostic #include "recno.h"
2150995Sbostic 
2250995Sbostic static int rec_rdelete __P((BTREE *, recno_t));
2350995Sbostic 
2450995Sbostic /*
2550995Sbostic  * __REC_DELETE -- Delete the item(s) referenced by a key.
2650995Sbostic  *
2750995Sbostic  * Parameters:
2850995Sbostic  *	dbp:	pointer to access method
2950995Sbostic  *	key:	key to delete
3050995Sbostic  *	flags:	R_CURSOR if deleting what the cursor references
3150995Sbostic  *
3250995Sbostic  * Returns:
3350995Sbostic  *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
3450995Sbostic  */
3550995Sbostic int
3650995Sbostic __rec_delete(dbp, key, flags)
3750995Sbostic 	const DB *dbp;
3850995Sbostic 	const DBT *key;
3950995Sbostic 	u_int flags;
4050995Sbostic {
4150995Sbostic 	BTREE *t;
4250995Sbostic 	recno_t nrec;
4350995Sbostic 	int status;
4450995Sbostic 
4550995Sbostic 	t = dbp->internal;
4650995Sbostic 	switch(flags) {
4750995Sbostic 	case 0:
48*51088Sbostic 		if ((nrec = *(recno_t *)key->data) == 0) {
49*51088Sbostic 			errno = EINVAL;
50*51088Sbostic 			return (RET_ERROR);
51*51088Sbostic 		}
52*51088Sbostic 		if (nrec > t->bt_nrecs)
53*51088Sbostic 			return (RET_SPECIAL);
54*51088Sbostic 		--nrec;
5550995Sbostic 		status = rec_rdelete(t, nrec);
5650995Sbostic 		break;
5750995Sbostic 	case R_CURSOR:
58*51088Sbostic 		if (ISSET(t, BTF_DELCRSR))
59*51088Sbostic 			return (RET_SPECIAL);
60*51088Sbostic 		status = rec_rdelete(t, t->bt_rcursor - 1);
61*51088Sbostic 		if (status == RET_SUCCESS) {
62*51088Sbostic 			--t->bt_rcursor;
63*51088Sbostic 			SET(t, BTF_DELCRSR);
64*51088Sbostic 		}
6550995Sbostic 		break;
6650995Sbostic 	default:
6750995Sbostic 		errno = EINVAL;
6850995Sbostic 		return (RET_ERROR);
6950995Sbostic 	}
7050995Sbostic 
7150995Sbostic 	if (status == RET_SUCCESS) {
7250995Sbostic 		--t->bt_nrecs;
7350995Sbostic 		SET(t, BTF_MODIFIED);
7450995Sbostic 	}
7550995Sbostic 	return (status);
7650995Sbostic }
7750995Sbostic 
7850995Sbostic /*
7950995Sbostic  * REC_RDELETE -- Delete the data matching the specified key.
8050995Sbostic  *
8150995Sbostic  * Parameters:
8250995Sbostic  *	tree:	tree
8350995Sbostic  *	nrec:	record to delete
8450995Sbostic  *
8550995Sbostic  * Returns:
8650995Sbostic  *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
8750995Sbostic  */
8850995Sbostic static int
8950995Sbostic rec_rdelete(t, nrec)
9050995Sbostic 	BTREE *t;
9150995Sbostic 	recno_t nrec;
9250995Sbostic {
9350995Sbostic 	EPG *e;
9450995Sbostic 	PAGE *h;
95*51088Sbostic 	int status;
9650995Sbostic 
97*51088Sbostic 	/* Find the record; __rec_search pins the page. */
98*51088Sbostic 	if ((e = __rec_search(t, nrec, SDELETE)) == NULL) {
9950995Sbostic 		mpool_put(t->bt_mp, e->page, 0);
100*51088Sbostic 		return (RET_ERROR);
10150995Sbostic 	}
10250995Sbostic 
10350995Sbostic 	/* Delete the record. */
10450995Sbostic 	h = e->page;
10550995Sbostic 	status = __rec_dleaf(t, h, e->index);
106*51088Sbostic 	if (status != RET_SUCCESS) {
10750995Sbostic 		mpool_put(t->bt_mp, h, 0);
10850995Sbostic 		return (status);
10950995Sbostic 	}
110*51088Sbostic 	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
11150995Sbostic 	return (RET_SUCCESS);
11250995Sbostic }
11350995Sbostic 
11450995Sbostic /*
11550995Sbostic  * __REC_DLEAF -- Delete a single record from a recno leaf page.
11650995Sbostic  *
11750995Sbostic  * Parameters:
11850995Sbostic  *	t:	tree
11950995Sbostic  *	index:	index on current page to delete
12050995Sbostic  *
12150995Sbostic  * Returns:
12250995Sbostic  *	RET_SUCCESS, RET_ERROR.
12350995Sbostic  */
12450995Sbostic int
12550995Sbostic __rec_dleaf(t, h, index)
12650995Sbostic 	BTREE *t;
12750995Sbostic 	PAGE *h;
12850995Sbostic 	int index;
12950995Sbostic {
13050995Sbostic 	register RLEAF *rl;
13150995Sbostic 	register index_t *ip, offset;
13250995Sbostic 	register size_t nbytes;
13350995Sbostic 	register int cnt;
13450995Sbostic 	char *from;
13550995Sbostic 	void *to;
13650995Sbostic 
13750995Sbostic 	/*
13850995Sbostic 	 * Delete a record from a recno leaf page.  Internal records are never
13950995Sbostic 	 * deleted from internal pages, regardless of the records that caused
14050995Sbostic 	 * them to be added being deleted.  Pages made empty by deletion are
14150995Sbostic 	 * not reclaimed.  They are, however, made available for reuse.
14250995Sbostic 	 *
14350995Sbostic 	 * Pack the remaining entries at the end of the page, shift the indices
14450995Sbostic 	 * down, overwriting the deleted record and its index.  If the record
14550995Sbostic 	 * uses overflow pages, make them available for reuse.
14650995Sbostic 	 */
14750995Sbostic 	to = rl = GETRLEAF(h, index);
14850995Sbostic 	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
14950995Sbostic 		return (RET_ERROR);
15050995Sbostic 	nbytes = NRLEAF(rl);
15150995Sbostic 
15250995Sbostic 	/*
15350995Sbostic 	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
15450995Sbostic 	 * offsets.  Reset the headers.
15550995Sbostic 	 */
15650995Sbostic 	from = (char *)h + h->upper;
15750995Sbostic 	bcopy(from, from + nbytes, (char *)to - from);
15850995Sbostic 	h->upper += nbytes;
15950995Sbostic 
16050995Sbostic 	offset = h->linp[index];
16150995Sbostic 	for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
16250995Sbostic 		if (ip[0] < offset)
16350995Sbostic 			ip[0] += nbytes;
16450995Sbostic 	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
16550995Sbostic 		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
16650995Sbostic 	h->lower -= sizeof(index_t);
16750995Sbostic 	return (RET_SUCCESS);
16850995Sbostic }
169