• Home
  • History
  • Annotate
  • only in /fuchsia/zircon/third_party/ulib/musl/src/math/
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Mike Olson.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)rec_delete.c	8.7 (Berkeley) 7/14/94";
37#endif /* LIBC_SCCS and not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD$");
40
41#include <sys/types.h>
42
43#include <errno.h>
44#include <stdio.h>
45#include <string.h>
46
47#include <db.h>
48#include "recno.h"
49
50static int rec_rdelete(BTREE *, recno_t);
51
52/*
53 * __REC_DELETE -- Delete the item(s) referenced by a key.
54 *
55 * Parameters:
56 *	dbp:	pointer to access method
57 *	key:	key to delete
58 *	flags:	R_CURSOR if deleting what the cursor references
59 *
60 * Returns:
61 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
62 */
63int
64__rec_delete(const DB *dbp, const DBT *key, u_int flags)
65{
66	BTREE *t;
67	recno_t nrec;
68	int status;
69
70	t = dbp->internal;
71
72	/* Toss any page pinned across calls. */
73	if (t->bt_pinned != NULL) {
74		mpool_put(t->bt_mp, t->bt_pinned, 0);
75		t->bt_pinned = NULL;
76	}
77
78	switch(flags) {
79	case 0:
80		if ((nrec = *(recno_t *)key->data) == 0)
81			goto einval;
82		if (nrec > t->bt_nrecs)
83			return (RET_SPECIAL);
84		--nrec;
85		status = rec_rdelete(t, nrec);
86		break;
87	case R_CURSOR:
88		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
89			goto einval;
90		if (t->bt_nrecs == 0)
91			return (RET_SPECIAL);
92		status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
93		if (status == RET_SUCCESS)
94			--t->bt_cursor.rcursor;
95		break;
96	default:
97einval:		errno = EINVAL;
98		return (RET_ERROR);
99	}
100
101	if (status == RET_SUCCESS)
102		F_SET(t, B_MODIFIED | R_MODIFIED);
103	return (status);
104}
105
106/*
107 * REC_RDELETE -- Delete the data matching the specified key.
108 *
109 * Parameters:
110 *	tree:	tree
111 *	nrec:	record to delete
112 *
113 * Returns:
114 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
115 */
116static int
117rec_rdelete(BTREE *t, recno_t nrec)
118{
119	EPG *e;
120	PAGE *h;
121	int status;
122
123	/* Find the record; __rec_search pins the page. */
124	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
125		return (RET_ERROR);
126
127	/* Delete the record. */
128	h = e->page;
129	status = __rec_dleaf(t, h, e->index);
130	if (status != RET_SUCCESS) {
131		mpool_put(t->bt_mp, h, 0);
132		return (status);
133	}
134	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
135	return (RET_SUCCESS);
136}
137
138/*
139 * __REC_DLEAF -- Delete a single record from a recno leaf page.
140 *
141 * Parameters:
142 *	t:	tree
143 *	idx:	index on current page to delete
144 *
145 * Returns:
146 *	RET_SUCCESS, RET_ERROR.
147 */
148int
149__rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)
150{
151	RLEAF *rl;
152	indx_t *ip, cnt, offset;
153	u_int32_t nbytes;
154	char *from;
155	void *to;
156
157	/*
158	 * Delete a record from a recno leaf page.  Internal records are never
159	 * deleted from internal pages, regardless of the records that caused
160	 * them to be added being deleted.  Pages made empty by deletion are
161	 * not reclaimed.  They are, however, made available for reuse.
162	 *
163	 * Pack the remaining entries at the end of the page, shift the indices
164	 * down, overwriting the deleted record and its index.  If the record
165	 * uses overflow pages, make them available for reuse.
166	 */
167	to = rl = GETRLEAF(h, idx);
168	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
169		return (RET_ERROR);
170	nbytes = NRLEAF(rl);
171
172	/*
173	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
174	 * offsets.  Reset the headers.
175	 */
176	from = (char *)h + h->upper;
177	memmove(from + nbytes, from, (char *)to - from);
178	h->upper += nbytes;
179
180	offset = h->linp[idx];
181	for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
182		if (ip[0] < offset)
183			ip[0] += nbytes;
184	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
185		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
186	h->lower -= sizeof(indx_t);
187	--t->bt_nrecs;
188	return (RET_SUCCESS);
189}
190