You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
7.4 KiB
305 lines
7.4 KiB
3 years ago
|
/*-
|
||
|
* See the file LICENSE for redistribution information.
|
||
|
*
|
||
|
* Copyright (c) 1996, 1997, 1998, 1999
|
||
|
* Sleepycat Software. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#include "db_config.h"
|
||
|
|
||
|
#ifndef lint
|
||
|
static const char sccsid[] = "@(#)bt_curadj.c 11.5 (Sleepycat) 11/10/99";
|
||
|
#endif /* not lint */
|
||
|
|
||
|
#ifndef NO_SYSTEM_INCLUDES
|
||
|
#include <sys/types.h>
|
||
|
#endif
|
||
|
|
||
|
#include "db_int.h"
|
||
|
#include "db_page.h"
|
||
|
#include "btree.h"
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
/*
|
||
|
* CDB___bam_cprint --
|
||
|
* Display the current cursor list.
|
||
|
*
|
||
|
* PUBLIC: int CDB___bam_cprint __P((DB *));
|
||
|
*/
|
||
|
int
|
||
|
CDB___bam_cprint(dbp)
|
||
|
DB *dbp;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
fprintf(stderr,
|
||
|
"%#0x->%#0x: page: %lu index: %lu dpage %lu dindex: %lu recno: %lu",
|
||
|
(u_int)dbc, (u_int)cp, (u_long)cp->pgno, (u_long)cp->indx,
|
||
|
(u_long)cp->dpgno, (u_long)cp->dindx, (u_long)cp->recno);
|
||
|
if (F_ISSET(cp, C_DELETED))
|
||
|
fprintf(stderr, " (deleted)");
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
|
||
|
return (0);
|
||
|
}
|
||
|
#endif /* DEBUG */
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_delete --
|
||
|
* Update the cursors when items are deleted and when already deleted
|
||
|
* items are overwritten. Return the number of relevant cursors found.
|
||
|
*
|
||
|
* PUBLIC: int CDB___bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int));
|
||
|
*/
|
||
|
int
|
||
|
CDB___bam_ca_delete(dbp, pgno, indx, delete)
|
||
|
DB *dbp;
|
||
|
db_pgno_t pgno;
|
||
|
u_int32_t indx;
|
||
|
int delete;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
int count; /* !!!: Has to contain max number of cursors. */
|
||
|
|
||
|
/* Recno is responsible for its own adjustments. */
|
||
|
if (dbp->type == DB_RECNO)
|
||
|
return (0);
|
||
|
|
||
|
/*
|
||
|
* Adjust the cursors. We don't have to review the cursors for any
|
||
|
* thread of control other than the current one, because we have the
|
||
|
* page write locked at this point, and any other thread of control
|
||
|
* had better be using a different locker ID, meaning only cursors in
|
||
|
* our thread of control can be on the page.
|
||
|
*
|
||
|
* It's possible for multiple cursors within the thread to have write
|
||
|
* locks on the same page, but, cursors within a thread must be single
|
||
|
* threaded, so all we're locking here is the cursor linked list.
|
||
|
*/
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (count = 0, dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
|
||
|
if ((cp->pgno == pgno && cp->indx == indx) ||
|
||
|
(cp->dpgno == pgno && cp->dindx == indx)) {
|
||
|
if (delete)
|
||
|
F_SET(cp, C_DELETED);
|
||
|
else
|
||
|
F_CLR(cp, C_DELETED);
|
||
|
++count;
|
||
|
}
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
|
||
|
return (count);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_di --
|
||
|
* Adjust the cursors during a delete or insert.
|
||
|
*
|
||
|
* PUBLIC: void CDB___bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int));
|
||
|
*/
|
||
|
void
|
||
|
CDB___bam_ca_di(dbp, pgno, indx, adjust)
|
||
|
DB *dbp;
|
||
|
db_pgno_t pgno;
|
||
|
u_int32_t indx;
|
||
|
int adjust;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
/* Recno is responsible for its own adjustments. */
|
||
|
if (dbp->type == DB_RECNO)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Adjust the cursors. See the comment in CDB___bam_ca_delete().
|
||
|
*/
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
if (cp->pgno == pgno && cp->indx >= indx) {
|
||
|
/* Cursor indices should never be negative. */
|
||
|
DB_ASSERT(cp->indx != 0 || adjust > 0);
|
||
|
cp->indx += adjust;
|
||
|
}
|
||
|
if (cp->dpgno == pgno && cp->dindx >= indx) {
|
||
|
/* Cursor indices should never be negative. */
|
||
|
DB_ASSERT(cp->dindx != 0 || adjust > 0);
|
||
|
cp->dindx += adjust;
|
||
|
}
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_dup --
|
||
|
* Adjust the cursors when moving items from a leaf page to a duplicates
|
||
|
* page.
|
||
|
*
|
||
|
* PUBLIC: void CDB___bam_ca_dup __P((DB *,
|
||
|
* PUBLIC: db_pgno_t, u_int32_t, u_int32_t, db_pgno_t, u_int32_t));
|
||
|
*/
|
||
|
void
|
||
|
CDB___bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti)
|
||
|
DB *dbp;
|
||
|
db_pgno_t fpgno, tpgno;
|
||
|
u_int32_t first, fi, ti;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
/* Recno is responsible for its own adjustments. */
|
||
|
if (dbp->type == DB_RECNO)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Adjust the cursors. See the comment in CDB___bam_ca_delete().
|
||
|
*/
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
/*
|
||
|
* Ignore matching entries that have already been moved,
|
||
|
* we move from the same location on the leaf page more
|
||
|
* than once.
|
||
|
*/
|
||
|
if (cp->dpgno == PGNO_INVALID &&
|
||
|
cp->pgno == fpgno && cp->indx == fi) {
|
||
|
cp->indx = first;
|
||
|
cp->dpgno = tpgno;
|
||
|
cp->dindx = ti;
|
||
|
}
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_rsplit --
|
||
|
* Adjust the cursors when doing reverse splits.
|
||
|
*
|
||
|
* PUBLIC: void CDB___bam_ca_rsplit __P((DB *, db_pgno_t, db_pgno_t));
|
||
|
*/
|
||
|
void
|
||
|
CDB___bam_ca_rsplit(dbp, fpgno, tpgno)
|
||
|
DB *dbp;
|
||
|
db_pgno_t fpgno, tpgno;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
/* Recno is responsible for its own adjustments. */
|
||
|
if (dbp->type == DB_RECNO)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Adjust the cursors. See the comment in CDB___bam_ca_delete().
|
||
|
*/
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
if (cp->pgno == fpgno)
|
||
|
cp->pgno = tpgno;
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_split --
|
||
|
* Adjust the cursors when splitting a page.
|
||
|
*
|
||
|
* PUBLIC: void CDB___bam_ca_split __P((DB *,
|
||
|
* PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
|
||
|
*/
|
||
|
void
|
||
|
CDB___bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft)
|
||
|
DB *dbp;
|
||
|
db_pgno_t ppgno, lpgno, rpgno;
|
||
|
u_int32_t split_indx;
|
||
|
int cleft;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
/* Recno is responsible for its own adjustments. */
|
||
|
if (dbp->type == DB_RECNO)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Adjust the cursors. See the comment in CDB___bam_ca_delete().
|
||
|
*
|
||
|
* If splitting the page that a cursor was on, the cursor has to be
|
||
|
* adjusted to point to the same record as before the split. Most
|
||
|
* of the time we don't adjust pointers to the left page, because
|
||
|
* we're going to copy its contents back over the original page. If
|
||
|
* the cursor is on the right page, it is decremented by the number of
|
||
|
* records split to the left page.
|
||
|
*/
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
if (cp->pgno == ppgno) {
|
||
|
if (cp->indx < split_indx) {
|
||
|
if (cleft)
|
||
|
cp->pgno = lpgno;
|
||
|
} else {
|
||
|
cp->pgno = rpgno;
|
||
|
cp->indx -= split_indx;
|
||
|
}
|
||
|
}
|
||
|
if (cp->dpgno == ppgno) {
|
||
|
if (cp->dindx < split_indx) {
|
||
|
if (cleft)
|
||
|
cp->dpgno = lpgno;
|
||
|
} else {
|
||
|
cp->dpgno = rpgno;
|
||
|
cp->dindx -= split_indx;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CDB___bam_ca_repl --
|
||
|
* Adjust the cursors when when doing a replace.
|
||
|
*
|
||
|
* PUBLIC: void CDB___bam_ca_repl __P((DB *,
|
||
|
* PUBLIC: db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
|
||
|
*/
|
||
|
void
|
||
|
CDB___bam_ca_repl(dbp, dpgno, dindx, newpgno, newindx)
|
||
|
DB *dbp;
|
||
|
db_pgno_t dpgno, newpgno;
|
||
|
u_int32_t dindx, newindx;
|
||
|
{
|
||
|
BTREE_CURSOR *cp;
|
||
|
DBC *dbc;
|
||
|
|
||
|
MUTEX_THREAD_LOCK(dbp->mutexp);
|
||
|
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||
|
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||
|
cp = (BTREE_CURSOR *)dbc->internal;
|
||
|
if (cp->dpgno == dpgno && cp->dindx == dindx) {
|
||
|
cp->dpgno = newpgno;
|
||
|
cp->dindx = newindx;
|
||
|
}
|
||
|
}
|
||
|
MUTEX_THREAD_UNLOCK(dbp->mutexp);
|
||
|
}
|