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