xref: /csrg-svn/lib/libc/db/recno/rec_delete.c (revision 50995)
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