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
_bt_fixscan(t,index,newd,op)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
_bt_crsrkey(t)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