#include "db_config.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
#include "dbinc/mp.h"
static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
static int __bam_ca_delete_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __ram_ca_delete_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_di_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_dup_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_undodup_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_rsplit_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_split_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int __bam_ca_undosplit_func
__P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
static int
__bam_ca_delete_func(dbc, my_dbc, countp, pgno, indx, args)
DBC *dbc, *my_dbc;
u_int32_t *countp;
db_pgno_t pgno;
u_int32_t indx;
void *args;
{
BTREE_CURSOR *cp;
u_int32_t del;
COMPQUIET(my_dbc, NULL);
del = *(u_int32_t *)args;
cp = (BTREE_CURSOR *)dbc->internal;
if (cp->pgno == pgno && cp->indx == indx &&
!MVCC_SKIP_CURADJ(dbc, pgno)) {
if (del) {
F_SET(cp, C_DELETED);
cp->stream_start_pgno = PGNO_INVALID;
} else
F_CLR(cp, C_DELETED);
#ifdef HAVE_COMPRESSION
F_SET(cp, C_COMPRESS_MODIFIED);
#endif
++(*countp);
}
return (0);
}
int
__bam_ca_delete(dbp, pgno, indx, del, countp)
DB *dbp;
db_pgno_t pgno;
u_int32_t indx;
int del;
u_int32_t *countp;
{
int ret;
u_int32_t count;
if ((ret = __db_walk_cursors(dbp, NULL,
__bam_ca_delete_func, &count, pgno, indx, &del)) != 0)
return (ret);
if (countp != NULL)
*countp = count;
return (0);
}
static int
__ram_ca_delete_func(dbc, my_dbc, countp, root_pgno, indx, args)
DBC *dbc, *my_dbc;
u_int32_t *countp;
db_pgno_t root_pgno;
u_int32_t indx;
void *args;
{
COMPQUIET(indx, 0);
COMPQUIET(my_dbc, NULL);
COMPQUIET(args, NULL);
if (dbc->internal->root == root_pgno &&
!MVCC_SKIP_CURADJ(dbc, root_pgno)) {
(*countp)++;
return (EEXIST);
}
return (0);
}
int
__ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp;
db_pgno_t root_pgno;
u_int32_t *foundp;
{
int ret;
if ((ret = __db_walk_cursors(dbp, NULL, __ram_ca_delete_func,
foundp, root_pgno, 0, NULL)) != 0 && ret != EEXIST)
return (ret);
return (0);
}
struct __bam_ca_di_args {
int adjust;
DB_TXN *my_txn;
};
static int
__bam_ca_di_func(dbc, my_dbc, foundp, pgno, indx, vargs)
DBC *dbc, *my_dbc;
u_int32_t *foundp;
db_pgno_t pgno;
u_int32_t indx;
void *vargs;
{
DBC_INTERNAL *cp;
struct __bam_ca_di_args *args;
if (dbc->dbtype == DB_RECNO)
return (0);
cp = dbc->internal;
args = vargs;
if (cp->pgno == pgno && cp->indx >= indx &&
(dbc == my_dbc || !MVCC_SKIP_CURADJ(dbc, pgno))) {
DB_ASSERT(dbc->dbp->env, cp->indx != 0 || args->adjust > 0);
cp->indx += args->adjust;
if (args->my_txn != NULL && args->my_txn != dbc->txn)
*foundp = 1;
}
return (0);
}
int
__bam_ca_di(my_dbc, pgno, indx, adjust)
DBC *my_dbc;
db_pgno_t pgno;
u_int32_t indx;
int adjust;
{
DB *dbp;
DB_LSN lsn;
int ret;
u_int32_t found;
struct __bam_ca_di_args args;
dbp = my_dbc->dbp;
args.adjust = adjust;
args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
if ((ret = __db_walk_cursors(dbp, my_dbc, __bam_ca_di_func,
&found, pgno, indx, &args)) != 0)
return (ret);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0,
DB_CA_DI, pgno, 0, 0, (u_int32_t)adjust, indx, 0)) != 0)
return (ret);
}
return (0);
}
static int
__bam_opd_cursor(dbp, dbc, first, tpgno, ti)
DB *dbp;
DBC *dbc;
db_pgno_t tpgno;
u_int32_t first, ti;
{
BTREE_CURSOR *cp, *orig_cp;
DBC *dbc_nopd;
int ret;
orig_cp = (BTREE_CURSOR *)dbc->internal;
dbc_nopd = NULL;
DB_ASSERT(dbp->env, orig_cp->opd == NULL);
if ((ret = __dbc_newopd(dbc, tpgno, orig_cp->opd, &dbc_nopd)) != 0)
return (ret);
cp = (BTREE_CURSOR *)dbc_nopd->internal;
cp->pgno = tpgno;
cp->indx = ti;
if (dbp->dup_compare == NULL) {
cp->recno = ti + 1;
}
if (F_ISSET(orig_cp, C_DELETED)) {
F_SET(cp, C_DELETED);
F_CLR(orig_cp, C_DELETED);
}
orig_cp->opd = dbc_nopd;
orig_cp->indx = first;
return (0);
}
struct __bam_ca_dup_args {
db_pgno_t tpgno;
db_indx_t first, ti;
DB_TXN *my_txn;
};
static int
__bam_ca_dup_func(dbc, my_dbc, foundp, fpgno, fi, vargs)
DBC *dbc;
DBC *my_dbc;
u_int32_t *foundp;
db_pgno_t fpgno;
u_int32_t fi;
void *vargs;
{
BTREE_CURSOR *orig_cp;
DB *dbp;
int ret;
struct __bam_ca_dup_args *args;
COMPQUIET(my_dbc, NULL);
orig_cp = (BTREE_CURSOR *)dbc->internal;
if (orig_cp->opd != NULL)
return (0);
if (orig_cp->pgno != fpgno || orig_cp->indx != fi ||
MVCC_SKIP_CURADJ(dbc, fpgno))
return (0);
dbp = dbc->dbp;
args = vargs;
MUTEX_UNLOCK(dbp->env, dbp->mutex);
if ((ret = __bam_opd_cursor(dbp,
dbc, args->first, args->tpgno, args->ti)) != 0) {
MUTEX_LOCK(dbp->env, dbp->mutex);
return (ret);
}
if (args->my_txn != NULL && args->my_txn != dbc->txn)
*foundp = 1;
return (DB_LOCK_NOTGRANTED);
}
int
__bam_ca_dup(my_dbc, first, fpgno, fi, tpgno, ti)
DBC *my_dbc;
db_pgno_t fpgno, tpgno;
u_int32_t first, fi, ti;
{
DB *dbp;
DB_LSN lsn;
int ret, t_ret;
u_int32_t found;
struct __bam_ca_dup_args args;
dbp = my_dbc->dbp;
args.first = first;
args.tpgno = tpgno;
args.ti = ti;
args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
if ((ret = __db_walk_cursors(dbp,
my_dbc, __bam_ca_dup_func, &found, fpgno, fi, &args)) != 0)
return (ret);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((t_ret = __bam_curadj_log(dbp, my_dbc->txn,
&lsn, 0, DB_CA_DUP, fpgno, tpgno, 0, first, fi, ti)) != 0 &&
ret == 0)
ret = t_ret;
}
return (ret);
}
static int
__bam_ca_undodup_func(dbc, my_dbc, countp, fpgno, fi, vargs)
DBC *dbc;
DBC *my_dbc;
u_int32_t *countp;
db_pgno_t fpgno;
u_int32_t fi;
void *vargs;
{
BTREE_CURSOR *orig_cp;
DB *dbp;
int ret;
struct __bam_ca_dup_args *args;
COMPQUIET(my_dbc, NULL);
COMPQUIET(countp, NULL);
orig_cp = (BTREE_CURSOR *)dbc->internal;
dbp = dbc->dbp;
args = vargs;
if (orig_cp->pgno != fpgno ||
orig_cp->indx != args->first ||
orig_cp->opd == NULL || ((BTREE_CURSOR *)
orig_cp->opd->internal)->indx != args->ti ||
MVCC_SKIP_CURADJ(dbc, fpgno))
return (0);
MUTEX_UNLOCK(dbp->env, dbp->mutex);
if ((ret = __dbc_close(orig_cp->opd)) != 0) {
MUTEX_LOCK(dbp->env, dbp->mutex);
return (ret);
}
orig_cp->opd = NULL;
orig_cp->indx = fi;
return (DB_LOCK_NOTGRANTED);
}
int
__bam_ca_undodup(dbp, first, fpgno, fi, ti)
DB *dbp;
db_pgno_t fpgno;
u_int32_t first, fi, ti;
{
u_int32_t count;
struct __bam_ca_dup_args args;
args.first = first;
args.ti = ti;
return (__db_walk_cursors(dbp, NULL,
__bam_ca_undodup_func, &count, fpgno, fi, &args));
}
static int
__bam_ca_rsplit_func(dbc, my_dbc, foundp, fpgno, indx, args)
DBC *dbc;
DBC *my_dbc;
u_int32_t *foundp;
db_pgno_t fpgno;
u_int32_t indx;
void *args;
{
db_pgno_t tpgno;
COMPQUIET(indx, 0);
if (dbc->dbtype == DB_RECNO)
return (0);
tpgno = *(db_pgno_t *)args;
if (dbc->internal->pgno == fpgno &&
!MVCC_SKIP_CURADJ(dbc, fpgno)) {
dbc->internal->pgno = tpgno;
if (IS_SUBTRANSACTION(my_dbc->txn) && dbc->txn != my_dbc->txn)
*foundp = 1;
}
return (0);
}
int
__bam_ca_rsplit(my_dbc, fpgno, tpgno)
DBC* my_dbc;
db_pgno_t fpgno, tpgno;
{
DB *dbp;
DB_LSN lsn;
int ret;
u_int32_t found;
dbp = my_dbc->dbp;
if ((ret = __db_walk_cursors(dbp, my_dbc,
__bam_ca_rsplit_func, &found, fpgno, 0, &tpgno)) != 0)
return (ret);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
&lsn, 0, DB_CA_RSPLIT, fpgno, tpgno, 0, 0, 0, 0)) != 0)
return (ret);
}
return (0);
}
struct __bam_ca_split_args {
db_pgno_t lpgno, rpgno;
int cleft;
DB_TXN *my_txn;
};
static int
__bam_ca_split_func(dbc, my_dbc, foundp, ppgno, split_indx, vargs)
DBC *dbc;
DBC *my_dbc;
u_int32_t *foundp;
db_pgno_t ppgno;
u_int32_t split_indx;
void *vargs;
{
DBC_INTERNAL *cp;
struct __bam_ca_split_args *args;
COMPQUIET(my_dbc, NULL);
if (dbc->dbtype == DB_RECNO)
return (0);
cp = dbc->internal;
args = vargs;
if (cp->pgno == ppgno &&
!MVCC_SKIP_CURADJ(dbc, ppgno)) {
if (args->my_txn != NULL && args->my_txn != dbc->txn)
*foundp = 1;
if (cp->indx < split_indx) {
if (args->cleft)
cp->pgno = args->lpgno;
} else {
cp->pgno = args->rpgno;
cp->indx -= split_indx;
}
}
return (0);
}
int
__bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
DBC *my_dbc;
db_pgno_t ppgno, lpgno, rpgno;
u_int32_t split_indx;
int cleft;
{
DB *dbp;
DB_LSN lsn;
int ret;
u_int32_t found;
struct __bam_ca_split_args args;
dbp = my_dbc->dbp;
args.lpgno = lpgno;
args.rpgno = rpgno;
args.cleft = cleft;
args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
if ((ret = __db_walk_cursors(dbp, my_dbc,
__bam_ca_split_func, &found, ppgno, split_indx, &args)) != 0)
return (ret);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp,
my_dbc->txn, &lsn, 0, DB_CA_SPLIT, ppgno, rpgno,
cleft ? lpgno : PGNO_INVALID, 0, split_indx, 0)) != 0)
return (ret);
}
return (0);
}
static int
__bam_ca_undosplit_func(dbc, my_dbc, foundp, frompgno, split_indx, vargs)
DBC *dbc;
DBC *my_dbc;
u_int32_t *foundp;
db_pgno_t frompgno;
u_int32_t split_indx;
void *vargs;
{
DBC_INTERNAL *cp;
struct __bam_ca_split_args *args;
COMPQUIET(my_dbc, NULL);
COMPQUIET(foundp, NULL);
if (dbc->dbtype == DB_RECNO)
return (0);
cp = dbc->internal;
args = vargs;
if (cp->pgno == args->rpgno &&
!MVCC_SKIP_CURADJ(dbc, args->rpgno)) {
cp->pgno = frompgno;
cp->indx += split_indx;
} else if (cp->pgno == args->lpgno &&
!MVCC_SKIP_CURADJ(dbc, args->lpgno))
cp->pgno = frompgno;
return (0);
}
int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp;
db_pgno_t frompgno, topgno, lpgno;
u_int32_t split_indx;
{
u_int32_t count;
struct __bam_ca_split_args args;
args.lpgno = lpgno;
args.rpgno = topgno;
return (__db_walk_cursors(dbp, NULL,
__bam_ca_undosplit_func, &count, frompgno, split_indx, &args));
}