146130Smao /*- 246130Smao * Copyright (c) 1990 The Regents of the University of California. 346130Smao * All rights reserved. 446130Smao * 546130Smao * This code is derived from software contributed to Berkeley by 646130Smao * Mike Olson. 746130Smao * 846130Smao * %sccs.include.redist.c% 946130Smao */ 1046130Smao 1146130Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46561Sbostic static char sccsid[] = "@(#)bt_delete.c 5.2 (Berkeley) 02/22/91"; 1346130Smao #endif /* LIBC_SCCS and not lint */ 1446130Smao 1546130Smao #include <sys/types.h> 1646130Smao #include <db.h> 17*46561Sbostic #include <errno.h> 18*46561Sbostic #include <string.h> 1946130Smao #include "btree.h" 2046130Smao 2146130Smao /* 2246130Smao * _BT_CRSRDEL -- Delete the item pointed to by the cursor. 2346130Smao * 2446130Smao * This routine deletes the item most recently returned by a scan 2546130Smao * through the tree. Since it only makes sense to delete the current 2646130Smao * record once, we make sure that we don't try to delete twice without 2746130Smao * advancing the scan. 2846130Smao * 2946130Smao * Parameters: 3046130Smao * t -- tree in which to do deletion 3146130Smao * 3246130Smao * Returns: 3346130Smao * RET_SUCCESS, RET_ERROR. 3446130Smao * 3546130Smao * Side Effects: 3646130Smao * The call to _bt_delone marks the cursor, so we can tell that 3746130Smao * the current record has been deleted. 3846130Smao */ 3946130Smao 4046130Smao int 4146130Smao _bt_crsrdel(t) 4246130Smao BTREE_P t; 4346130Smao { 4446130Smao CURSOR *c; 4546130Smao 4646130Smao c = &(t->bt_cursor); 4746130Smao 4846130Smao /* a cursor must exist, and can't have deleted the current key yet */ 4946130Smao if (!(t->bt_flags & BTF_SEQINIT) || (c->c_flags & CRSR_BEFORE)) { 5046130Smao errno = EINVAL; 5146130Smao return (RET_ERROR); 5246130Smao } 5346130Smao 5446130Smao if (_bt_getpage(t, c->c_pgno) == RET_ERROR) 5546130Smao return (RET_ERROR); 5646130Smao 5746130Smao if (c->c_index >= NEXTINDEX(t->bt_curpage)) { 5846130Smao errno = EINVAL; 5946130Smao return (RET_ERROR); 6046130Smao } 6146130Smao 6246130Smao return (_bt_delone(t, c->c_index)); 6346130Smao } 6446130Smao 6546130Smao /* 6646130Smao * _BT_DELONE -- Delete a single entry from a btree. 6746130Smao * 6846130Smao * This routine physically removes a btree entry from a leaf page. 6946130Smao * IDATUM items are *never* removed from internal nodes, regardless 7046130Smao * of whether the entries that originally caused them to be added 7146130Smao * are removed from the tree or not. In addition, pages made empty 7246130Smao * by element deletion are not actually reclaimed. They are, 7346130Smao * however, made available for reuse. 7446130Smao * 7546130Smao * To delete an item from a page, we pack the remaining items at 7646130Smao * the end of the page, overwriting the deleted item's entry. We 7746130Smao * move the line pointers backward on the page, overwriting the 7846130Smao * original item's line pointer. This guarantees that the space in 7946130Smao * the middle of the page is free -- a property that our insertion 8046130Smao * strategy relies on. 8146130Smao * 8246130Smao * This routine doesn't reclaim pages all of whose entries have 8346130Smao * been deleted. These pages are available for reuse, however. 8446130Smao * If an item is deleted that was too big to fit on a page, then 8546130Smao * the blocks that it occupies are put on a free list for reuse. 8646130Smao * 8746130Smao * Parameters: 8846130Smao * t -- btree from which to delete item 8946130Smao * index -- index of entry on current page to delete 9046130Smao * 9146130Smao * Returns: 9246130Smao * RET_SUCCESS, RET_ERROR. 9346130Smao * 9446130Smao * Side Effects: 9546130Smao * Physically changes page layout, adjusts internal page 9646130Smao * state to reflect the deletion of the item, and updates 9746130Smao * the list of free pages for this tree. 9846130Smao */ 9946130Smao 10046130Smao int 10146130Smao _bt_delone(t, index) 10246130Smao BTREE_P t; 10346130Smao index_t index; 10446130Smao { 10546130Smao char *src, *dest; 10646130Smao int nbytes, nmoved; 10746130Smao index_t off; 10846130Smao index_t top; 10946130Smao index_t i; 11046130Smao pgno_t chain; 11146130Smao BTHEADER *h; 11246130Smao CURSOR *c; 11346130Smao DATUM *d; 11446130Smao 11546130Smao /* deletion may confuse an active scan. fix it. */ 11646130Smao c = &(t->bt_cursor); 11746130Smao if (t->bt_flags & BTF_SEQINIT && t->bt_curpage->h_pgno == c->c_pgno) 11846130Smao if (_bt_fixscan(t, index, (DATUM *) NULL, DELETE) == RET_ERROR) 11946130Smao return (RET_ERROR); 12046130Smao 12146130Smao h = t->bt_curpage; 12246130Smao off = h->h_linp[index]; 12346130Smao d = (DATUM *) GETDATUM(h, index); 12446130Smao 12546130Smao /* if this is a big item, reclaim the space it occupies */ 12646130Smao if (d->d_flags & D_BIGKEY) { 12746130Smao bcopy(&(d->d_bytes[0]), 12846130Smao (char *) &chain, 12946130Smao sizeof(chain)); 13046130Smao if (_bt_delindir(t, chain) == RET_ERROR) 13146130Smao return (RET_ERROR); 13246130Smao h = t->bt_curpage; 13346130Smao d = (DATUM *) GETDATUM(h, index); 13446130Smao } 13546130Smao if (d->d_flags & D_BIGDATA) { 13646130Smao bcopy(&(d->d_bytes[d->d_ksize]), 13746130Smao (char *) &chain, 13846130Smao sizeof(chain)); 13946130Smao if (_bt_delindir(t, chain) == RET_ERROR) 14046130Smao return (RET_ERROR); 14146130Smao h = t->bt_curpage; 14246130Smao d = (DATUM *) GETDATUM(h, index); 14346130Smao } 14446130Smao 14546130Smao /* move the data down on the page */ 14646130Smao nbytes = d->d_ksize + d->d_dsize 14746130Smao + (sizeof(DATUM) - sizeof(char)); 14846130Smao nbytes = LONGALIGN(nbytes); 14946130Smao src = ((char *) h) + h->h_upper; 15046130Smao dest = src + nbytes; 15146130Smao nmoved = (int) (((char *) d) - src); 15246130Smao (void) bcopy(src, dest, nmoved); 15346130Smao 15446130Smao /* next move the line pointers up */ 15546130Smao src = (char *) &(h->h_linp[index + 1]); 15646130Smao dest = (char *) &(h->h_linp[index]); 15746130Smao nmoved = (int) (((char *) &(h->h_linp[NEXTINDEX(h)])) - src); 15846130Smao (void) bcopy(src, dest, nmoved); 15946130Smao 16046130Smao /* remember that we freed up some space */ 16146130Smao h->h_upper += nbytes; 16246130Smao h->h_lower -= sizeof(index_t); 16346130Smao 16446130Smao /* adjust offsets in line pointers affected by moving the data */ 16546130Smao top = NEXTINDEX(h); 16646130Smao for (i = 0; i < top; i++) { 16746130Smao if (h->h_linp[i] < off) 16846130Smao h->h_linp[i] += nbytes; 16946130Smao } 17046130Smao 17146130Smao /* it's gone */ 17246130Smao h->h_flags |= F_DIRTY; 17346130Smao 17446130Smao return (RET_SUCCESS); 17546130Smao } 176