#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));
int
__bam_ca_delete(dbp, pgno, indx, delete, countp)
DB *dbp;
db_pgno_t pgno;
u_int32_t indx;
int delete, *countp;
{
BTREE_CURSOR *cp;
DB *ldbp;
DB_ENV *dbenv;
DBC *dbc;
int count;
dbenv = dbp->dbenv;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (count = 0;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
cp = (BTREE_CURSOR *)dbc->internal;
if (cp->pgno == pgno && cp->indx == indx &&
!MVCC_SKIP_CURADJ(dbc, pgno)) {
if (delete)
F_SET(cp, C_DELETED);
else
F_CLR(cp, C_DELETED);
++count;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (countp != NULL)
*countp = count;
return (0);
}
int
__ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp;
db_pgno_t root_pgno;
int *foundp;
{
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
int found;
dbenv = dbp->dbenv;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (found = 0;
found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links)
if (dbc->internal->root == root_pgno &&
!MVCC_SKIP_CURADJ(dbc, root_pgno)) {
found = 1;
break;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
*foundp = found;
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, *ldbp;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
DBC *dbc;
DBC_INTERNAL *cp;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (found = 0;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == pgno && cp->indx >= indx &&
(dbc == my_dbc || !MVCC_SKIP_CURADJ(dbc, pgno))) {
DB_ASSERT(dbenv, cp->indx != 0 || adjust > 0);
cp->indx += adjust;
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
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->dbenv, 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);
}
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;
{
BTREE_CURSOR *orig_cp;
DB *dbp, *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret, t_ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
ret = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (found = 0;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
orig_cp = (BTREE_CURSOR *)dbc->internal;
if (orig_cp->pgno != fpgno || orig_cp->indx != fi ||
MVCC_SKIP_CURADJ(dbc, fpgno))
continue;
if (orig_cp->opd != NULL)
continue;
MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __bam_opd_cursor(dbp,
dbc, first, tpgno, ti)) != 0)
goto err;
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
goto loop;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
err: MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
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);
}
int
__bam_ca_undodup(dbp, first, fpgno, fi, ti)
DB *dbp;
db_pgno_t fpgno;
u_int32_t first, fi, ti;
{
BTREE_CURSOR *orig_cp;
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
int ret;
dbenv = dbp->dbenv;
ret = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
orig_cp = (BTREE_CURSOR *)dbc->internal;
if (orig_cp->pgno != fpgno ||
orig_cp->indx != first ||
orig_cp->opd == NULL || ((BTREE_CURSOR *)
orig_cp->opd->internal)->indx != ti ||
MVCC_SKIP_CURADJ(dbc, fpgno))
continue;
MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __dbc_close(orig_cp->opd)) != 0)
goto err;
orig_cp->opd = NULL;
orig_cp->indx = fi;
goto loop;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
err: MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (ret);
}
int
__bam_ca_rsplit(my_dbc, fpgno, tpgno)
DBC* my_dbc;
db_pgno_t fpgno, tpgno;
{
DB *dbp, *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (found = 0;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
if (dbc->dbtype == DB_RECNO)
continue;
if (dbc->internal->pgno == fpgno &&
!MVCC_SKIP_CURADJ(dbc, fpgno)) {
dbc->internal->pgno = tpgno;
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
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);
}
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, *ldbp;
DBC *dbc;
DBC_INTERNAL *cp;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (found = 0;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == ppgno &&
!MVCC_SKIP_CURADJ(dbc, ppgno)) {
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
if (cp->indx < split_indx) {
if (cleft)
cp->pgno = lpgno;
} else {
cp->pgno = rpgno;
cp->indx -= split_indx;
}
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
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);
}
int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp;
db_pgno_t frompgno, topgno, lpgno;
u_int32_t split_indx;
{
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DBC_INTERNAL *cp;
dbenv = dbp->dbenv;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp);
for (;
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_FOREACH(dbc, &ldbp->active_queue, links) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == topgno &&
!MVCC_SKIP_CURADJ(dbc, topgno)) {
cp->pgno = frompgno;
cp->indx += split_indx;
} else if (cp->pgno == lpgno &&
!MVCC_SKIP_CURADJ(dbc, lpgno))
cp->pgno = frompgno;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}