xref: /csrg-svn/lib/libc/db/btree/updutils.c (revision 46561)
146136Smao /*-
246136Smao  * Copyright (c) 1990 The Regents of the University of California.
346136Smao  * All rights reserved.
446136Smao  *
546136Smao  * This code is derived from software contributed to Berkeley by
646136Smao  * Mike Olson.
746136Smao  *
846136Smao  * %sccs.include.redist.c%
946136Smao  */
1046136Smao 
1146136Smao #if defined(LIBC_SCCS) && !defined(lint)
12*46561Sbostic static char sccsid[] = "@(#)updutils.c	5.2 (Berkeley) 02/22/91";
1346136Smao #endif /* LIBC_SCCS and not lint */
1446136Smao 
1546136Smao #include <sys/types.h>
1646136Smao #include <db.h>
17*46561Sbostic #include <stdlib.h>
18*46561Sbostic #include <string.h>
1946136Smao #include "btree.h"
2046136Smao 
2146136Smao /*
2246136Smao  *  _BT_FIXSCAN -- Adjust a scan to cope with a change in tree structure.
2346136Smao  *
2446136Smao  *	If the user has an active scan on the database, and we delete an
2546136Smao  *	item from the page the cursor is pointing at, we need to figure
2646136Smao  *	out what to do about it.  Basically, the solution is to point
2746136Smao  *	"between" keys in the tree, using the CRSR_BEFORE flag.  The
2846136Smao  *	requirement is that the user should not miss any data in the
2946136Smao  *	tree during a scan, just because he happened to do some deletions
3046136Smao  *	or insertions while it was active.
3146136Smao  *
3246136Smao  *	In order to guarantee that the scan progresses properly, we need
3346136Smao  *	to save the key of any deleted item we were pointing at, so that
3446136Smao  *	we can check later insertions against it.
3546136Smao  *
3646136Smao  *	Parameters:
3746136Smao  *		t -- tree to adjust
3846136Smao  *		index -- index of item at which change was made
3946136Smao  *		newd -- new datum (for insertions only)
4046136Smao  *		op -- operation (DELETE or INSERT) causing change
4146136Smao  *
4246136Smao  *	Returns:
4346136Smao  *		RET_SUCCESS, RET_ERROR (errno is set).
4446136Smao  *
4546136Smao  *	Side Effects:
4646136Smao  *		None.
4746136Smao  */
4846136Smao 
4946136Smao int
_bt_fixscan(t,index,newd,op)5046136Smao _bt_fixscan(t, index, newd, op)
5146136Smao 	BTREE_P t;
5246136Smao 	index_t index;
5346136Smao 	DATUM *newd;
5446136Smao 	int op;
5546136Smao {
5646136Smao 	CURSOR *c;
5746136Smao 	DATUM *d;
5846136Smao 
5946136Smao 	c = &(t->bt_cursor);
6046136Smao 
6146136Smao 	if (op == DELETE) {
6246136Smao 		if (index < c->c_index)
6346136Smao 			c->c_index--;
6446136Smao 		else if (index == c->c_index) {
6546136Smao 			if (!(c->c_flags & CRSR_BEFORE)) {
6646136Smao 				if (_bt_crsrkey(t) == RET_ERROR)
6746136Smao 					return (RET_ERROR);
6846136Smao 				c->c_flags |= CRSR_BEFORE;
6946136Smao 			}
7046136Smao 		}
7146136Smao 	} else {
7246136Smao 		/*
7346136Smao 		 *  If we previously deleted the object at this location,
7446136Smao 		 *  and now we're inserting a new one, we need to do the
7546136Smao 		 *  right thing -- the cursor should come either before
7646136Smao 		 *  or after the new item, depending on the key that was
7746136Smao 		 *  here, and the new one.
7846136Smao 		 */
7946136Smao 
8046136Smao 		if (c->c_flags & CRSR_BEFORE) {
8146136Smao 			if (index <= c->c_index) {
8246136Smao 				char *tmp;
8346136Smao 				int itmp;
8446136Smao 				pgno_t chain;
8546136Smao 				int r;
8646136Smao 
8746136Smao 				d = (DATUM *) GETDATUM(t->bt_curpage, index);
8846136Smao 				if (d->d_flags & D_BIGKEY) {
8946136Smao 					bcopy(&(newd->d_bytes[0]),
9046136Smao 					      (char *) &chain,
9146136Smao 					      sizeof(chain));
9246136Smao 					if (_bt_getbig(t, chain, &tmp, &itmp)
9346136Smao 					     == RET_ERROR)
9446136Smao 						return (RET_ERROR);
9546136Smao 				} else
9646136Smao 					tmp = &(newd->d_bytes[0]);
9746136Smao 
9846136Smao 				r = (*(t->bt_compare))(tmp, c->c_key);
9946136Smao 				if (r < 0)
10046136Smao 					c->c_index++;
10146136Smao 
10246136Smao 				if (d->d_flags & D_BIGKEY)
10346136Smao 					(void) free (tmp);
10446136Smao 			}
10546136Smao 		} else if (index <= c->c_index)
10646136Smao 			c->c_index++;
10746136Smao 	}
10846136Smao 	return (RET_SUCCESS);
10946136Smao }
11046136Smao 
11146136Smao /*
11246136Smao  *  _BT_CRSRKEY -- Save a copy of the key of the record that the cursor
11346136Smao  *		   is pointing to.  The record is about to be deleted.
11446136Smao  *
11546136Smao  *	Parameters:
11646136Smao  *		t -- btree
11746136Smao  *
11846136Smao  *	Returns:
11946136Smao  *		RET_SUCCESS, RET_ERROR.
12046136Smao  *
12146136Smao  *	Side Effects:
12246136Smao  *		Allocates memory for the copy which should be released when
12346136Smao  *		it is no longer needed.
12446136Smao  */
12546136Smao 
12646136Smao int
_bt_crsrkey(t)12746136Smao _bt_crsrkey(t)
12846136Smao 	BTREE_P t;
12946136Smao {
13046136Smao 	CURSOR *c;
13146136Smao 	DATUM *d;
13246136Smao 	pgno_t pgno;
13346136Smao 	int ignore;
13446136Smao 
13546136Smao 	c = &(t->bt_cursor);
13646136Smao 	d = (DATUM *) GETDATUM(t->bt_curpage, c->c_index);
13746136Smao 
13846136Smao 	if (d->d_flags & D_BIGKEY) {
13946136Smao 		bcopy(&(d->d_bytes[0]), (char *) &pgno, sizeof(pgno));
14046136Smao 		return (_bt_getbig(t, pgno, &(c->c_key), &ignore));
14146136Smao 	} else {
14246136Smao 		if ((c->c_key = (char *) malloc(d->d_ksize)) == (char *) NULL)
14346136Smao 			return (RET_ERROR);
14446136Smao 
14546136Smao 		bcopy(&(d->d_bytes[0]), c->c_key, (size_t) (d->d_ksize));
14646136Smao 	}
14746136Smao 	return (RET_SUCCESS);
14846136Smao }
149