xref: /csrg-svn/lib/libc/db/btree/updutils.c (revision 46136)
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