1*46136Smao /*- 2*46136Smao * Copyright (c) 1990 The Regents of the University of California. 3*46136Smao * All rights reserved. 4*46136Smao * 5*46136Smao * This code is derived from software contributed to Berkeley by 6*46136Smao * Mike Olson. 7*46136Smao * 8*46136Smao * %sccs.include.redist.c% 9*46136Smao */ 10*46136Smao 11*46136Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46136Smao static char sccsid[] = "@(#)updutils.c 5.1 (Berkeley) 01/23/91"; 13*46136Smao #endif /* LIBC_SCCS and not lint */ 14*46136Smao 15*46136Smao #include <sys/types.h> 16*46136Smao #include <db.h> 17*46136Smao #include "btree.h" 18*46136Smao 19*46136Smao /* 20*46136Smao * _BT_FIXSCAN -- Adjust a scan to cope with a change in tree structure. 21*46136Smao * 22*46136Smao * If the user has an active scan on the database, and we delete an 23*46136Smao * item from the page the cursor is pointing at, we need to figure 24*46136Smao * out what to do about it. Basically, the solution is to point 25*46136Smao * "between" keys in the tree, using the CRSR_BEFORE flag. The 26*46136Smao * requirement is that the user should not miss any data in the 27*46136Smao * tree during a scan, just because he happened to do some deletions 28*46136Smao * or insertions while it was active. 29*46136Smao * 30*46136Smao * In order to guarantee that the scan progresses properly, we need 31*46136Smao * to save the key of any deleted item we were pointing at, so that 32*46136Smao * we can check later insertions against it. 33*46136Smao * 34*46136Smao * Parameters: 35*46136Smao * t -- tree to adjust 36*46136Smao * index -- index of item at which change was made 37*46136Smao * newd -- new datum (for insertions only) 38*46136Smao * op -- operation (DELETE or INSERT) causing change 39*46136Smao * 40*46136Smao * Returns: 41*46136Smao * RET_SUCCESS, RET_ERROR (errno is set). 42*46136Smao * 43*46136Smao * Side Effects: 44*46136Smao * None. 45*46136Smao */ 46*46136Smao 47*46136Smao int 48*46136Smao _bt_fixscan(t, index, newd, op) 49*46136Smao BTREE_P t; 50*46136Smao index_t index; 51*46136Smao DATUM *newd; 52*46136Smao int op; 53*46136Smao { 54*46136Smao CURSOR *c; 55*46136Smao DATUM *d; 56*46136Smao 57*46136Smao c = &(t->bt_cursor); 58*46136Smao 59*46136Smao if (op == DELETE) { 60*46136Smao if (index < c->c_index) 61*46136Smao c->c_index--; 62*46136Smao else if (index == c->c_index) { 63*46136Smao if (!(c->c_flags & CRSR_BEFORE)) { 64*46136Smao if (_bt_crsrkey(t) == RET_ERROR) 65*46136Smao return (RET_ERROR); 66*46136Smao c->c_flags |= CRSR_BEFORE; 67*46136Smao } 68*46136Smao } 69*46136Smao } else { 70*46136Smao /* 71*46136Smao * If we previously deleted the object at this location, 72*46136Smao * and now we're inserting a new one, we need to do the 73*46136Smao * right thing -- the cursor should come either before 74*46136Smao * or after the new item, depending on the key that was 75*46136Smao * here, and the new one. 76*46136Smao */ 77*46136Smao 78*46136Smao if (c->c_flags & CRSR_BEFORE) { 79*46136Smao if (index <= c->c_index) { 80*46136Smao char *tmp; 81*46136Smao int itmp; 82*46136Smao pgno_t chain; 83*46136Smao int r; 84*46136Smao 85*46136Smao d = (DATUM *) GETDATUM(t->bt_curpage, index); 86*46136Smao if (d->d_flags & D_BIGKEY) { 87*46136Smao bcopy(&(newd->d_bytes[0]), 88*46136Smao (char *) &chain, 89*46136Smao sizeof(chain)); 90*46136Smao if (_bt_getbig(t, chain, &tmp, &itmp) 91*46136Smao == RET_ERROR) 92*46136Smao return (RET_ERROR); 93*46136Smao } else 94*46136Smao tmp = &(newd->d_bytes[0]); 95*46136Smao 96*46136Smao r = (*(t->bt_compare))(tmp, c->c_key); 97*46136Smao if (r < 0) 98*46136Smao c->c_index++; 99*46136Smao 100*46136Smao if (d->d_flags & D_BIGKEY) 101*46136Smao (void) free (tmp); 102*46136Smao } 103*46136Smao } else if (index <= c->c_index) 104*46136Smao c->c_index++; 105*46136Smao } 106*46136Smao return (RET_SUCCESS); 107*46136Smao } 108*46136Smao 109*46136Smao /* 110*46136Smao * _BT_CRSRKEY -- Save a copy of the key of the record that the cursor 111*46136Smao * is pointing to. The record is about to be deleted. 112*46136Smao * 113*46136Smao * Parameters: 114*46136Smao * t -- btree 115*46136Smao * 116*46136Smao * Returns: 117*46136Smao * RET_SUCCESS, RET_ERROR. 118*46136Smao * 119*46136Smao * Side Effects: 120*46136Smao * Allocates memory for the copy which should be released when 121*46136Smao * it is no longer needed. 122*46136Smao */ 123*46136Smao 124*46136Smao int 125*46136Smao _bt_crsrkey(t) 126*46136Smao BTREE_P t; 127*46136Smao { 128*46136Smao CURSOR *c; 129*46136Smao DATUM *d; 130*46136Smao pgno_t pgno; 131*46136Smao int ignore; 132*46136Smao 133*46136Smao c = &(t->bt_cursor); 134*46136Smao d = (DATUM *) GETDATUM(t->bt_curpage, c->c_index); 135*46136Smao 136*46136Smao if (d->d_flags & D_BIGKEY) { 137*46136Smao bcopy(&(d->d_bytes[0]), (char *) &pgno, sizeof(pgno)); 138*46136Smao return (_bt_getbig(t, pgno, &(c->c_key), &ignore)); 139*46136Smao } else { 140*46136Smao if ((c->c_key = (char *) malloc(d->d_ksize)) == (char *) NULL) 141*46136Smao return (RET_ERROR); 142*46136Smao 143*46136Smao bcopy(&(d->d_bytes[0]), c->c_key, (size_t) (d->d_ksize)); 144*46136Smao } 145*46136Smao return (RET_SUCCESS); 146*46136Smao } 147