158f0484fSRodney W. Grimes /*-
2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni *
4ef5d438eSPaul Traina * Copyright (c) 1990, 1993, 1994
558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved.
658f0484fSRodney W. Grimes *
758f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by
858f0484fSRodney W. Grimes * Mike Olson.
958f0484fSRodney W. Grimes *
1058f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without
1158f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions
1258f0484fSRodney W. Grimes * are met:
1358f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer.
1558f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
1658f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
1758f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution.
18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
1958f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software
2058f0484fSRodney W. Grimes * without specific prior written permission.
2158f0484fSRodney W. Grimes *
2258f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2358f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2458f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2558f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2658f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2758f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2858f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2958f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3058f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3158f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3258f0484fSRodney W. Grimes * SUCH DAMAGE.
3358f0484fSRodney W. Grimes */
3458f0484fSRodney W. Grimes
3558f0484fSRodney W. Grimes #include <sys/types.h>
3658f0484fSRodney W. Grimes
3758f0484fSRodney W. Grimes #include <errno.h>
3858f0484fSRodney W. Grimes #include <stdio.h>
3958f0484fSRodney W. Grimes #include <string.h>
4058f0484fSRodney W. Grimes
4158f0484fSRodney W. Grimes #include <db.h>
4258f0484fSRodney W. Grimes #include "recno.h"
4358f0484fSRodney W. Grimes
44c05ac53bSDavid E. O'Brien static int rec_rdelete(BTREE *, recno_t);
4558f0484fSRodney W. Grimes
4658f0484fSRodney W. Grimes /*
4758f0484fSRodney W. Grimes * __REC_DELETE -- Delete the item(s) referenced by a key.
4858f0484fSRodney W. Grimes *
4958f0484fSRodney W. Grimes * Parameters:
5058f0484fSRodney W. Grimes * dbp: pointer to access method
5158f0484fSRodney W. Grimes * key: key to delete
5258f0484fSRodney W. Grimes * flags: R_CURSOR if deleting what the cursor references
5358f0484fSRodney W. Grimes *
5458f0484fSRodney W. Grimes * Returns:
5558f0484fSRodney W. Grimes * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
5658f0484fSRodney W. Grimes */
5758f0484fSRodney W. Grimes int
__rec_delete(const DB * dbp,const DBT * key,u_int flags)580ac22237SXin LI __rec_delete(const DB *dbp, const DBT *key, u_int flags)
5958f0484fSRodney W. Grimes {
6058f0484fSRodney W. Grimes BTREE *t;
6158f0484fSRodney W. Grimes recno_t nrec;
6258f0484fSRodney W. Grimes int status;
6358f0484fSRodney W. Grimes
6458f0484fSRodney W. Grimes t = dbp->internal;
6558f0484fSRodney W. Grimes
6658f0484fSRodney W. Grimes /* Toss any page pinned across calls. */
6758f0484fSRodney W. Grimes if (t->bt_pinned != NULL) {
6858f0484fSRodney W. Grimes mpool_put(t->bt_mp, t->bt_pinned, 0);
6958f0484fSRodney W. Grimes t->bt_pinned = NULL;
7058f0484fSRodney W. Grimes }
7158f0484fSRodney W. Grimes
7258f0484fSRodney W. Grimes switch(flags) {
7358f0484fSRodney W. Grimes case 0:
7458f0484fSRodney W. Grimes if ((nrec = *(recno_t *)key->data) == 0)
7558f0484fSRodney W. Grimes goto einval;
7658f0484fSRodney W. Grimes if (nrec > t->bt_nrecs)
7758f0484fSRodney W. Grimes return (RET_SPECIAL);
7858f0484fSRodney W. Grimes --nrec;
7958f0484fSRodney W. Grimes status = rec_rdelete(t, nrec);
8058f0484fSRodney W. Grimes break;
8158f0484fSRodney W. Grimes case R_CURSOR:
82ef5d438eSPaul Traina if (!F_ISSET(&t->bt_cursor, CURS_INIT))
8358f0484fSRodney W. Grimes goto einval;
8458f0484fSRodney W. Grimes if (t->bt_nrecs == 0)
8558f0484fSRodney W. Grimes return (RET_SPECIAL);
86ef5d438eSPaul Traina status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
8758f0484fSRodney W. Grimes if (status == RET_SUCCESS)
88ef5d438eSPaul Traina --t->bt_cursor.rcursor;
8958f0484fSRodney W. Grimes break;
9058f0484fSRodney W. Grimes default:
9158f0484fSRodney W. Grimes einval: errno = EINVAL;
9258f0484fSRodney W. Grimes return (RET_ERROR);
9358f0484fSRodney W. Grimes }
9458f0484fSRodney W. Grimes
9558f0484fSRodney W. Grimes if (status == RET_SUCCESS)
96ef5d438eSPaul Traina F_SET(t, B_MODIFIED | R_MODIFIED);
9758f0484fSRodney W. Grimes return (status);
9858f0484fSRodney W. Grimes }
9958f0484fSRodney W. Grimes
10058f0484fSRodney W. Grimes /*
10158f0484fSRodney W. Grimes * REC_RDELETE -- Delete the data matching the specified key.
10258f0484fSRodney W. Grimes *
10358f0484fSRodney W. Grimes * Parameters:
10458f0484fSRodney W. Grimes * tree: tree
10558f0484fSRodney W. Grimes * nrec: record to delete
10658f0484fSRodney W. Grimes *
10758f0484fSRodney W. Grimes * Returns:
10858f0484fSRodney W. Grimes * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
10958f0484fSRodney W. Grimes */
11058f0484fSRodney W. Grimes static int
rec_rdelete(BTREE * t,recno_t nrec)1110ac22237SXin LI rec_rdelete(BTREE *t, recno_t nrec)
11258f0484fSRodney W. Grimes {
11358f0484fSRodney W. Grimes EPG *e;
11458f0484fSRodney W. Grimes PAGE *h;
11558f0484fSRodney W. Grimes int status;
11658f0484fSRodney W. Grimes
11758f0484fSRodney W. Grimes /* Find the record; __rec_search pins the page. */
11858f0484fSRodney W. Grimes if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
11958f0484fSRodney W. Grimes return (RET_ERROR);
12058f0484fSRodney W. Grimes
12158f0484fSRodney W. Grimes /* Delete the record. */
12258f0484fSRodney W. Grimes h = e->page;
12358f0484fSRodney W. Grimes status = __rec_dleaf(t, h, e->index);
12458f0484fSRodney W. Grimes if (status != RET_SUCCESS) {
12558f0484fSRodney W. Grimes mpool_put(t->bt_mp, h, 0);
12658f0484fSRodney W. Grimes return (status);
12758f0484fSRodney W. Grimes }
12858f0484fSRodney W. Grimes mpool_put(t->bt_mp, h, MPOOL_DIRTY);
12958f0484fSRodney W. Grimes return (RET_SUCCESS);
13058f0484fSRodney W. Grimes }
13158f0484fSRodney W. Grimes
13258f0484fSRodney W. Grimes /*
13358f0484fSRodney W. Grimes * __REC_DLEAF -- Delete a single record from a recno leaf page.
13458f0484fSRodney W. Grimes *
13558f0484fSRodney W. Grimes * Parameters:
13658f0484fSRodney W. Grimes * t: tree
1374c66e4b6SXin LI * idx: index on current page to delete
13858f0484fSRodney W. Grimes *
13958f0484fSRodney W. Grimes * Returns:
14058f0484fSRodney W. Grimes * RET_SUCCESS, RET_ERROR.
14158f0484fSRodney W. Grimes */
14258f0484fSRodney W. Grimes int
__rec_dleaf(BTREE * t,PAGE * h,u_int32_t idx)1434c66e4b6SXin LI __rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)
14458f0484fSRodney W. Grimes {
145ef5d438eSPaul Traina RLEAF *rl;
146ef5d438eSPaul Traina indx_t *ip, cnt, offset;
147ef5d438eSPaul Traina u_int32_t nbytes;
14858f0484fSRodney W. Grimes char *from;
14958f0484fSRodney W. Grimes void *to;
15058f0484fSRodney W. Grimes
15158f0484fSRodney W. Grimes /*
15258f0484fSRodney W. Grimes * Delete a record from a recno leaf page. Internal records are never
15358f0484fSRodney W. Grimes * deleted from internal pages, regardless of the records that caused
15458f0484fSRodney W. Grimes * them to be added being deleted. Pages made empty by deletion are
15558f0484fSRodney W. Grimes * not reclaimed. They are, however, made available for reuse.
15658f0484fSRodney W. Grimes *
15758f0484fSRodney W. Grimes * Pack the remaining entries at the end of the page, shift the indices
15858f0484fSRodney W. Grimes * down, overwriting the deleted record and its index. If the record
15958f0484fSRodney W. Grimes * uses overflow pages, make them available for reuse.
16058f0484fSRodney W. Grimes */
1614c66e4b6SXin LI to = rl = GETRLEAF(h, idx);
16258f0484fSRodney W. Grimes if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
16358f0484fSRodney W. Grimes return (RET_ERROR);
16458f0484fSRodney W. Grimes nbytes = NRLEAF(rl);
16558f0484fSRodney W. Grimes
16658f0484fSRodney W. Grimes /*
16758f0484fSRodney W. Grimes * Compress the key/data pairs. Compress and adjust the [BR]LEAF
16858f0484fSRodney W. Grimes * offsets. Reset the headers.
16958f0484fSRodney W. Grimes */
17058f0484fSRodney W. Grimes from = (char *)h + h->upper;
17158f0484fSRodney W. Grimes memmove(from + nbytes, from, (char *)to - from);
17258f0484fSRodney W. Grimes h->upper += nbytes;
17358f0484fSRodney W. Grimes
1744c66e4b6SXin LI offset = h->linp[idx];
1754c66e4b6SXin LI for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
17658f0484fSRodney W. Grimes if (ip[0] < offset)
17758f0484fSRodney W. Grimes ip[0] += nbytes;
17858f0484fSRodney W. Grimes for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
17958f0484fSRodney W. Grimes ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
18058f0484fSRodney W. Grimes h->lower -= sizeof(indx_t);
18158f0484fSRodney W. Grimes --t->bt_nrecs;
18258f0484fSRodney W. Grimes return (RET_SUCCESS);
18358f0484fSRodney W. Grimes }
184