Commit | Line | Data |
---|---|---|
7467df92 MO |
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) | |
fb91cf55 | 12 | static char sccsid[] = "@(#)updutils.c 5.2 (Berkeley) %G%"; |
7467df92 MO |
13 | #endif /* LIBC_SCCS and not lint */ |
14 | ||
15 | #include <sys/types.h> | |
16 | #include <db.h> | |
fb91cf55 KB |
17 | #include <stdlib.h> |
18 | #include <string.h> | |
7467df92 MO |
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 | } |