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