📄 bt_delete.c
字号:
/*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Olson. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";#endif /* LIBC_SCCS and not lint */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#include <errno.h>#include <stdio.h>#ifdef HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include "db.h"#include "btree.h"static int __bt_bdelete(BTREE *, const DBT *);static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int);static int __bt_pdelete(BTREE *, PAGE *);static int __bt_relink(BTREE *, PAGE *);static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);/* * __bt_delete * Delete the item(s) referenced by a key. * * Return RET_SPECIAL if the key is not found. */int__bt_delete(dbp, key, flags) const DB *dbp; const DBT *key; u_int flags;{ BTREE *t; CURSOR *c; PAGE *h; int status; t = dbp->internal; /* Toss any page pinned across calls. */ if (t->bt_pinned != NULL) { mpool_put(t->bt_mp, t->bt_pinned, 0); t->bt_pinned = NULL; } /* Check for change to a read-only tree. */ if (F_ISSET(t, B_RDONLY)) { errno = EPERM; return (RET_ERROR); } switch (flags) { case 0: status = __bt_bdelete(t, key); break; case R_CURSOR: /* * If flags is R_CURSOR, delete the cursor. Must already * have started a scan and not have already deleted it. */ c = &t->bt_cursor; if (F_ISSET(c, CURS_INIT)) { if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) return (RET_SPECIAL); if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) return (RET_ERROR); /* * If the page is about to be emptied, we'll need to * delete it, which means we have to acquire a stack. */ if (NEXTINDEX(h) == 1) if (__bt_stkacq(t, &h, &t->bt_cursor)) return (RET_ERROR); status = __bt_dleaf(t, NULL, h, c->pg.index); if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) { if (__bt_pdelete(t, h)) return (RET_ERROR); } else mpool_put(t->bt_mp, h, status == RET_SUCCESS ? MPOOL_DIRTY : 0); break; } /* FALLTHROUGH */ default: errno = EINVAL; return (RET_ERROR); } if (status == RET_SUCCESS) F_SET(t, B_MODIFIED); return (status);}/* * __bt_stkacq -- * Acquire a stack so we can delete a cursor entry. * * Parameters: * t: tree * hp: pointer to current, pinned PAGE pointer * c: pointer to the cursor * * Returns: * 0 on success, 1 on failure */static int__bt_stkacq(t, hp, c) BTREE *t; PAGE **hp; CURSOR *c;{ BINTERNAL *bi; EPG *e; EPGNO *parent; PAGE *h; indx_t index = 0; pgno_t pgno; recno_t nextpg, prevpg; int exact, level; /* * Find the first occurrence of the key in the tree. Toss the * currently locked page so we don't hit an already-locked page. */ h = *hp; mpool_put(t->bt_mp, h, 0); if ((e = __bt_search(t, &c->key, &exact)) == NULL) return (1); h = e->page; /* See if we got it in one shot. */ if (h->pgno == c->pg.pgno) goto ret; /* * Move right, looking for the page. At each move we have to move * up the stack until we don't have to move to the next page. If * we have to change pages at an internal level, we have to fix the * stack back up. */ while (h->pgno != c->pg.pgno) { if ((nextpg = h->nextpg) == P_INVALID) break; mpool_put(t->bt_mp, h, 0); /* Move up the stack. */ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { /* Get the parent page. */ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) return (1); /* Move to the next index. */ if (parent->index != NEXTINDEX(h) - 1) { index = parent->index + 1; BT_PUSH(t, h->pgno, index); break; } mpool_put(t->bt_mp, h, 0); } /* Restore the stack. */ while (level--) { /* Push the next level down onto the stack. */ bi = GETBINTERNAL(h, index); pgno = bi->pgno; BT_PUSH(t, pgno, 0); /* Lose the currently pinned page. */ mpool_put(t->bt_mp, h, 0); /* Get the next level down. */ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) return (1); index = 0; } mpool_put(t->bt_mp, h, 0); if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL) return (1); } if (h->pgno == c->pg.pgno) goto ret; /* Reacquire the original stack. */ mpool_put(t->bt_mp, h, 0); if ((e = __bt_search(t, &c->key, &exact)) == NULL) return (1); h = e->page; /* * Move left, looking for the page. At each move we have to move * up the stack until we don't have to change pages to move to the * next page. If we have to change pages at an internal level, we * have to fix the stack back up. */ while (h->pgno != c->pg.pgno) { if ((prevpg = h->prevpg) == P_INVALID) break; mpool_put(t->bt_mp, h, 0); /* Move up the stack. */ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { /* Get the parent page. */ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) return (1); /* Move to the next index. */ if (parent->index != 0) { index = parent->index - 1; BT_PUSH(t, h->pgno, index); break; } mpool_put(t->bt_mp, h, 0); } /* Restore the stack. */ while (level--) { /* Push the next level down onto the stack. */ bi = GETBINTERNAL(h, index); pgno = bi->pgno; /* Lose the currently pinned page. */ mpool_put(t->bt_mp, h, 0); /* Get the next level down. */ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) return (1); index = NEXTINDEX(h) - 1; BT_PUSH(t, pgno, index); } mpool_put(t->bt_mp, h, 0); if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL) return (1); } ret: mpool_put(t->bt_mp, h, 0); return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);}/* * __bt_bdelete -- * Delete all key/data pairs matching the specified key. * * Parameters: * t: tree * key: key to delete * * Returns: * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. */static int__bt_bdelete(t, key) BTREE *t; const DBT *key;{ EPG *e; PAGE *h; int deleted, exact, redo; deleted = 0; /* Find any matching record; __bt_search pins the page. */loop: if ((e = __bt_search(t, key, &exact)) == NULL) return (deleted ? RET_SUCCESS : RET_ERROR); if (!exact) { mpool_put(t->bt_mp, e->page, 0); return (deleted ? RET_SUCCESS : RET_SPECIAL); } /* * Delete forward, then delete backward, from the found key. If * there are duplicates and we reach either side of the page, do * the key search again, so that we get them all. */ redo = 0; h = e->page; do { if (__bt_dleaf(t, key, h, e->index)) { mpool_put(t->bt_mp, h, 0); return (RET_ERROR); } if (F_ISSET(t, B_NODUPS)) { if (NEXTINDEX(h) == 0) { if (__bt_pdelete(t, h)) return (RET_ERROR); } else mpool_put(t->bt_mp, h, MPOOL_DIRTY); return (RET_SUCCESS); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -