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