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