#include "db_config.h"
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/db_page.h"
#include "dbinc/db_am.h"
#include "dbinc/btree.h"
#include "dbinc/hash.h"
#include "dbinc/qam.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h"
#include "dbinc/fop.h"
#include "dbinc/log_verify.h"
#define BDBOP(op) do { \
ret = (op); \
if (ret != 0) { \
__lv_on_bdbop_err(ret); \
goto err; \
} \
} while (0)
#define BDBOP2(dbenv, op, funct) do { \
ret = (op); \
if (ret != 0) { \
__lv_on_bdbop_err(ret); \
__db_err(dbenv->env, ret, "\n%s", funct); \
return (ret); \
} \
} while (0)
#define BDBOP3(dbenv, op, excpt, funct) do { \
ret = (op); \
if (ret != 0) { \
__lv_on_bdbop_err(ret); \
if (ret != excpt) { \
__db_err(dbenv->env, ret, "\n%s", funct); \
return (ret); \
} \
} \
} while (0)
typedef int (*btcmp_funct)(DB *, const DBT *, const DBT *);
typedef int (*dupcmp_funct)(DB *, const DBT *, const DBT *);
static int __lv_add_recycle_handler __P((
DB_LOG_VRFY_INFO *, VRFY_TXN_INFO *, void *));
static int __lv_add_recycle_lsn __P((VRFY_TXN_INFO *, const DB_LSN *));
static size_t __lv_dbt_arrsz __P((const DBT *, u_int32_t));
static int __lv_fidpgno_cmp __P((DB *, const DBT *, const DBT *));
static int __lv_i32_cmp __P((DB *, const DBT *, const DBT *));
static int __lv_lsn_cmp __P((DB *, const DBT *, const DBT *));
static void __lv_on_bdbop_err __P((int));
static int __lv_open_db __P((DB_ENV *, DB **, DB_THREAD_INFO *,
const char *, int, btcmp_funct, u_int32_t, dupcmp_funct));
static int __lv_pack_filereg __P((const VRFY_FILEREG_INFO *, DBT *));
static int __lv_pack_txn_vrfy_info __P((
const VRFY_TXN_INFO *, DBT *, DBT *data));
static int __lv_seccbk_fname __P((DB *, const DBT *, const DBT *, DBT *));
static int __lv_seccbk_lsn __P((DB *, const DBT *, const DBT *, DBT *));
static int __lv_seccbk_txnpg __P((DB *, const DBT *, const DBT *, DBT *));
static void __lv_setup_logtype_names __P((DB_LOG_VRFY_INFO *lvinfo));
static int __lv_txnrgns_lsn_cmp __P((DB *, const DBT *, const DBT *));
static int __lv_ui32_cmp __P((DB *, const DBT *, const DBT *));
static int __lv_unpack_txn_vrfy_info __P((VRFY_TXN_INFO **, const DBT *));
static int __lv_unpack_filereg __P((const DBT *, VRFY_FILEREG_INFO **));
static void __lv_on_bdbop_err(ret)
int ret;
{
COMPQUIET(ret, 0);
}
int
__create_log_vrfy_info(cfg, lvinfopp, ip)
const DB_LOG_VERIFY_CONFIG *cfg;
DB_LOG_VRFY_INFO **lvinfopp;
DB_THREAD_INFO *ip;
{
const char *envhome;
int inmem, ret;
u_int32_t cachesz, envflags;
const char *dbf1, *dbf2, *dbf3, *dbf4, *dbf5, *dbf6, *dbf7, *dbf8,
*dbf9, *dbf10, *dbf11;
DB_LOG_VRFY_INFO *lvinfop;
dbf1 = "__db_log_vrfy_txninfo.db";
dbf2 = "__db_log_vrfy_fileregs.db";
dbf3 = "__db_log_vrfy_pgtxn.db";
dbf4 = "__db_log_vrfy_lsntime.db";
dbf5 = "__db_log_vrfy_timelsn.db";
dbf6 = "__db_log_vrfy_ckps.db";
dbf7 = "__db_log_vrfy_dbregids.db";
dbf8 = "__db_log_vrfy_fnameuid.db";
dbf9 = "__db_log_vrfy_timerange.db";
dbf10 = "__db_log_vrfy_txnaborts.db";
dbf11 = "__db_log_vrfy_txnpg.db";
envhome = cfg->temp_envhome;
lvinfop = NULL;
cachesz = cfg->cachesize;
if (cachesz== 0)
cachesz = 1024 * 1024 * 256;
BDBOP(__os_malloc(NULL, sizeof(DB_LOG_VRFY_INFO), &lvinfop));
memset(lvinfop, 0, sizeof(DB_LOG_VRFY_INFO));
lvinfop->ip = ip;
__lv_setup_logtype_names(lvinfop);
lvinfop->valid_lsn.file = lvinfop->valid_lsn.offset = (u_int32_t)-1;
if (envhome == NULL) {
envflags = DB_PRIVATE;
inmem = 1;
} else {
envflags = 0;
inmem = 0;
}
BDBOP(db_env_create(&lvinfop->dbenv, 0));
BDBOP(__memp_set_cachesize(lvinfop->dbenv, 0, cachesz, 1));
BDBOP(__env_open(lvinfop->dbenv, envhome,
envflags | DB_CREATE | DB_INIT_MPOOL, 0666));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->txninfo, ip, dbf1,
inmem, __lv_ui32_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->fileregs, ip, dbf2,
inmem, NULL, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->dbregids, ip, dbf7,
inmem, __lv_i32_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->pgtxn, ip, dbf3,
inmem, __lv_fidpgno_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->txnpg, ip, dbf11,
inmem, __lv_ui32_cmp, DB_DUP | DB_DUPSORT, __lv_fidpgno_cmp));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->lsntime, ip, dbf4,
inmem, __lv_lsn_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->timelsn, ip, dbf5,
inmem, __lv_i32_cmp, DB_DUP | DB_DUPSORT, __lv_lsn_cmp));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->txnaborts, ip, dbf10,
inmem, __lv_lsn_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->ckps, ip, dbf6,
inmem, __lv_lsn_cmp, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->fnameuid, ip, dbf8,
inmem, NULL, 0, NULL));
BDBOP(__lv_open_db(lvinfop->dbenv, &lvinfop->txnrngs, ip, dbf9,
inmem, __lv_ui32_cmp, DB_DUP | DB_DUPSORT, __lv_txnrgns_lsn_cmp));
BDBOP(__db_associate(lvinfop->lsntime, ip, NULL,
lvinfop->timelsn, __lv_seccbk_lsn, DB_CREATE));
BDBOP(__db_associate(lvinfop->fileregs, ip, NULL,
lvinfop->fnameuid, __lv_seccbk_fname, DB_CREATE));
BDBOP(__db_associate(lvinfop->pgtxn, ip, NULL,
lvinfop->txnpg, __lv_seccbk_txnpg, DB_CREATE));
*lvinfopp = lvinfop;
return (0);
err:
if (lvinfop->dbenv && ret != 0)
__db_err(lvinfop->dbenv->env, ret, "__create_log_vrfy_info");
(void)__destroy_log_vrfy_info(lvinfop);
return (ret);
}
int
__destroy_log_vrfy_info(lvinfop)
DB_LOG_VRFY_INFO *lvinfop;
{
int ret;
ret = 0;
if (lvinfop == NULL)
return (0);
if (lvinfop->txnaborts != NULL &&
(ret = __db_close(lvinfop->txnaborts, NULL, 0)) != 0)
goto err;
if (lvinfop->txninfo != NULL &&
(ret = __db_close(lvinfop->txninfo, NULL, 0)) != 0)
goto err;
if (lvinfop->dbregids != NULL &&
(ret = __db_close(lvinfop->dbregids, NULL, 0)) != 0)
goto err;
if (lvinfop->fileregs != NULL &&
(ret = __db_close(lvinfop->fileregs, NULL, 0)) != 0)
goto err;
if (lvinfop->pgtxn != NULL &&
(ret = __db_close(lvinfop->pgtxn, NULL, 0)) != 0)
goto err;
if (lvinfop->lsntime != NULL &&
(ret = __db_close(lvinfop->lsntime, NULL, 0)) != 0)
goto err;
if (lvinfop->ckps != NULL &&
(ret = __db_close(lvinfop->ckps, NULL, 0)) != 0)
goto err;
if (lvinfop->txnrngs != NULL &&
(ret = __db_close(lvinfop->txnrngs, NULL, 0)) != 0)
goto err;
if (lvinfop->fnameuid != NULL &&
(ret = __db_close(lvinfop->fnameuid, NULL, 0)) != 0)
goto err;
if (lvinfop->timelsn != NULL &&
(ret = __db_close(lvinfop->timelsn, NULL, 0)) != 0)
goto err;
if (lvinfop->txnpg != NULL &&
(ret = __db_close(lvinfop->txnpg, NULL, 0)) != 0)
goto err;
if (lvinfop->dbenv != NULL &&
(ret = __env_close(lvinfop->dbenv, 0)) != 0)
goto err;
err:
__os_free(NULL, lvinfop);
return (ret);
}
static int
__lv_seccbk_fname(secdb, key, data, result)
DB *secdb;
const DBT *key;
const DBT *data;
DBT *result;
{
int ret, tret;
VRFY_FILEREG_INFO *freg;
char *buf;
size_t buflen, slen;
ret = tret = 0;
COMPQUIET(key, NULL);
if ((ret = __lv_unpack_filereg(data, &freg)) != 0)
goto out;
if (freg->fname == NULL || (slen = strlen(freg->fname)) == 0) {
ret = DB_DONOTINDEX;
goto out;
}
buflen = (slen + 1) * sizeof(char);
if ((ret = __os_umalloc(secdb->dbenv->env, buflen, &buf)) != 0)
goto out;
(void)strcpy(buf, freg->fname);
result->size = (u_int32_t)buflen;
result->flags |= DB_DBT_APPMALLOC;
result->data = buf;
out:
if (freg != NULL && (tret = __free_filereg_info(freg)) != 0 && ret == 0)
ret = tret;
return (ret);
}
static int
__lv_seccbk_txnpg(secdb, key, data, result)
DB *secdb;
const DBT *key;
const DBT *data;
DBT *result;
{
COMPQUIET(key, NULL);
COMPQUIET(secdb, NULL);
result->data = data->data;
result->size = data->size;
return (0);
}
static int
__lv_seccbk_lsn(secdb, key, data, result)
DB *secdb;
const DBT *key;
const DBT *data;
DBT *result;
{
VRFY_TIMESTAMP_INFO *lvti;
COMPQUIET(key, NULL);
COMPQUIET(secdb, NULL);
lvti = (VRFY_TIMESTAMP_INFO *)data->data;
result->data = &(lvti->timestamp);
result->size = sizeof(lvti->timestamp);
return (0);
}
static int
__lv_open_db(dbenv, dbpp, ip, name, inmem, cmpf, sflags, dupcmpf)
DB_ENV *dbenv;
DB **dbpp;
const char *name;
int inmem;
btcmp_funct cmpf;
u_int32_t sflags;
dupcmp_funct dupcmpf;
DB_THREAD_INFO *ip;
{
int ret;
const char *dbfname, *dbname;
DB *dbp;
dbp = NULL;
ret = 0;
if (inmem) {
dbfname = NULL;
dbname = name;
} else {
dbfname = name;
dbname = NULL;
}
BDBOP(db_create(&dbp, dbenv, 0));
if (cmpf != NULL)
BDBOP(__bam_set_bt_compare(dbp, cmpf));
if (dupcmpf != NULL)
dbp->dup_compare = dupcmpf;
if (sflags != 0)
BDBOP(__db_set_flags(dbp, sflags));
BDBOP(__db_set_pagesize(dbp, 16 * 1024));
BDBOP(__db_open(dbp, ip, NULL, dbfname, dbname, DB_BTREE, DB_CREATE,
0666, PGNO_BASE_MD));
*dbpp = dbp;
return (0);
err:
if (dbenv != NULL && ret != 0)
__db_err(dbenv->env, ret, "__lv_open_db");
if (dbp != NULL)
(void)__db_close(dbp, NULL, 0);
return (ret);
}
static int
__lv_fidpgno_cmp(db, dbt1, dbt2)
DB *db;
const DBT *dbt1;
const DBT *dbt2;
{
db_pgno_t pgno1, pgno2;
int ret;
size_t len;
COMPQUIET(db, NULL);
len = DB_FILE_ID_LEN;
ret = memcmp(dbt1->data, dbt2->data, len);
if (ret == 0) {
memcpy(&pgno1, (u_int8_t *)dbt1->data + len,
sizeof(pgno1));
memcpy(&pgno2, (u_int8_t *)dbt2->data + len,
sizeof(pgno2));
ret = NUMCMP(pgno1, pgno2);
}
return (ret);
}
static int
__lv_i32_cmp(db, dbt1, dbt2)
DB *db;
const DBT *dbt1;
const DBT *dbt2;
{
int32_t k1, k2;
COMPQUIET(db, NULL);
memcpy(&k1, dbt1->data, sizeof(k1));
memcpy(&k2, dbt2->data, sizeof(k2));
return (NUMCMP(k1, k2));
}
static int
__lv_ui32_cmp(db, dbt1, dbt2)
DB *db;
const DBT *dbt1;
const DBT *dbt2;
{
u_int32_t k1, k2;
COMPQUIET(db, NULL);
memcpy(&k1, dbt1->data, sizeof(k1));
memcpy(&k2, dbt2->data, sizeof(k2));
return (NUMCMP(k1, k2));
}
static int
__lv_lsn_cmp(db, dbt1, dbt2)
DB *db;
const DBT *dbt1;
const DBT *dbt2;
{
DB_LSN lsn1, lsn2;
DB_ASSERT(db->env, dbt1->size == sizeof(DB_LSN));
DB_ASSERT(db->env, dbt2->size == sizeof(DB_LSN));
memcpy(&lsn1, dbt1->data, sizeof(DB_LSN));
memcpy(&lsn2, dbt2->data, sizeof(DB_LSN));
return (LOG_COMPARE(&lsn1, &lsn2));
}
int
__put_txn_vrfy_info (lvinfo, txninfop)
const DB_LOG_VRFY_INFO *lvinfo;
const VRFY_TXN_INFO *txninfop;
{
int ret;
DBT key, data;
ret = __lv_pack_txn_vrfy_info(txninfop, &key, &data);
DB_ASSERT(lvinfo->dbenv->env, ret == 0);
BDBOP2(lvinfo->dbenv, __db_put(lvinfo->txninfo, lvinfo->ip, NULL,
&key, &data, 0), "__put_txn_vrfy_info");
__os_free(lvinfo->dbenv->env, data.data);
return (0);
}
static int
__lv_pack_txn_vrfy_info(txninfop, key, data)
const VRFY_TXN_INFO *txninfop;
DBT *key, *data;
{
int ret;
char *buf, *p;
size_t bufsz, len;
u_int32_t i;
DBT *pdbt;
memset(key, 0, sizeof(DBT));
memset(data, 0, sizeof(DBT));
ret = 0;
bufsz = TXN_VERIFY_INFO_TOTSIZE(*txninfop);
if ((ret = __os_malloc(NULL, bufsz, &buf)) != 0)
goto err;
memset(buf, 0, bufsz);
memcpy(buf, txninfop, TXN_VERIFY_INFO_FIXSIZE);
p = buf + TXN_VERIFY_INFO_FIXSIZE;
memcpy(p, txninfop->recycle_lsns, len = sizeof(DB_LSN) *
txninfop->num_recycle);
p += len;
for (i = 0; i < txninfop->filenum; i++) {
pdbt = &(txninfop->fileups[i]);
memcpy(p, &(pdbt->size), sizeof(pdbt->size));
p += sizeof(pdbt->size);
memcpy(p, pdbt->data, pdbt->size);
p += pdbt->size;
}
key->data = (void *)&txninfop->txnid;
key->size = sizeof(txninfop->txnid);
data->data = buf;
data->size = (u_int32_t)bufsz;
data->flags |= DB_DBT_MALLOC;
err:
return (ret);
}
static size_t
__lv_dbt_arrsz(arr, arrlen)
const DBT *arr;
u_int32_t arrlen;
{
u_int32_t i;
size_t sz;
sz = 0;
for (i = 0; i < arrlen; i++)
sz += arr[i].size + sizeof(arr[i].size);
return sz;
}
int
__get_txn_vrfy_info (lvinfo, txnid, txninfopp)
const DB_LOG_VRFY_INFO *lvinfo;
u_int32_t txnid;
VRFY_TXN_INFO **txninfopp;
{
int ret;
DBT key, data;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &txnid;
key.size = sizeof(txnid);
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->txninfo, lvinfo->ip, NULL,
&key, &data, 0), DB_NOTFOUND, "__get_txn_vrfy_info");
if (ret != DB_NOTFOUND)
ret = __lv_unpack_txn_vrfy_info(txninfopp, &data);
return (ret);
}
static int
__lv_unpack_txn_vrfy_info(txninfopp, data)
VRFY_TXN_INFO **txninfopp;
const DBT *data;
{
size_t bufsz;
VRFY_TXN_INFO *buf, *txninfop;
DB_LSN *lsns, *p;
u_int32_t i, sz;
char *pb, *q;
int ret;
ret = 0;
i = sz = 0;
lsns = p = NULL;
pb = q = NULL;
txninfop = (VRFY_TXN_INFO *)data->data;
lsns = (DB_LSN *)((char *)data->data + TXN_VERIFY_INFO_FIXSIZE);
pb = (char *)lsns + txninfop->num_recycle * sizeof(DB_LSN);
if ((ret = __os_malloc(NULL, bufsz = sizeof(VRFY_TXN_INFO), &buf)) != 0)
goto err;
memset(buf, 0, bufsz);
memcpy(buf, data->data, TXN_VERIFY_INFO_FIXSIZE);
if (txninfop->num_recycle != 0) {
if ((ret = __os_malloc(NULL,
txninfop->num_recycle * sizeof(DB_LSN), &p)) != 0)
goto err;
memcpy(p, lsns, txninfop->num_recycle * sizeof(DB_LSN));
buf->recycle_lsns = p;
}
if (txninfop->filenum != 0) {
if ((ret = __os_malloc(NULL,
txninfop->filenum * sizeof(DBT), &q)) != 0)
goto err;
memset(q, 0, txninfop->filenum * sizeof(DBT));
buf->fileups = (DBT *)q;
for (i = 0; i < txninfop->filenum; i++) {
memcpy(&sz, pb, sizeof(sz));
pb += sizeof(sz);
if ((ret = __os_malloc(NULL, sz, &q)) != 0)
goto err;
memcpy(q, pb, sz);
pb += sz;
buf->fileups[i].data = q;
buf->fileups[i].size = sz;
}
}
*txninfopp = buf;
err:
return (ret);
}
static int
__lv_add_recycle_lsn (txninfop, lsn)
VRFY_TXN_INFO *txninfop;
const DB_LSN *lsn;
{
int ret;
ret = 0;
txninfop->num_recycle++;
if ((ret = __os_realloc(NULL, txninfop->num_recycle * sizeof(DB_LSN),
&(txninfop->recycle_lsns))) != 0)
goto err;
txninfop->recycle_lsns[txninfop->num_recycle - 1] = *lsn;
err:
return (ret);
}
int
__add_recycle_lsn_range(lvinfo, lsn, min, max)
DB_LOG_VRFY_INFO *lvinfo;
const DB_LSN *lsn;
u_int32_t min, max;
{
DBC *csr;
int ret, tret;
u_int32_t i;
DBT key2, data2;
struct __add_recycle_params param;
csr = NULL;
ret = tret = 0;
memset(&key2, 0, sizeof(DBT));
memset(&data2, 0, sizeof(DBT));
memset(¶m, 0, sizeof(param));
if ((ret = __os_malloc(lvinfo->dbenv->env, sizeof(VRFY_TXN_INFO *) *
(param.ti2ul = 1024), &(param.ti2u))) != 0)
goto err;
param.ti2ui = 0;
param.recycle_lsn = *lsn;
param.min = min;
param.max = max;
if ((ret = __iterate_txninfo(lvinfo, min, max, __lv_add_recycle_handler,
¶m)) != 0)
goto err;
BDBOP(__db_cursor(lvinfo->txninfo, lvinfo->ip, NULL, &csr, DBC_BULK));
for (i = 0; i < param.ti2ui; i++) {
ret = __lv_pack_txn_vrfy_info(param.ti2u[i], &key2, &data2);
DB_ASSERT(lvinfo->dbenv->env, ret == 0);
BDBOP(__dbc_put(csr, &key2, &data2, DB_KEYLAST));
if ((ret = __free_txninfo(param.ti2u[i])) != 0)
goto err;
}
err:
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
__os_free(lvinfo->dbenv->env, param.ti2u);
if (ret != 0)
__db_err(lvinfo->dbenv->env, ret,
"__add_recycle_lsn_range");
return (ret);
}
int
__iterate_txninfo(lvinfo, min, max, handler, param)
DB_LOG_VRFY_INFO *lvinfo;
u_int32_t min, max;
TXNINFO_HANDLER handler;
void *param;
{
ENV *env;
VRFY_TXN_INFO *txninfop;
int ret, tret;
u_int32_t bufsz, pgsz, txnid;
size_t retkl, retdl;
char *btbuf;
u_int8_t *retk, *retd;
DBT key, data, data2;
DBC *csr;
void *p;
csr = NULL;
env = lvinfo->dbenv->env;
txninfop = NULL;
ret = tret = 0;
txnid = 0;
retkl = retdl = 0;
bufsz = 64 * 1024;
btbuf = NULL;
retk = retd = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&data2, 0, sizeof(DBT));
pgsz = lvinfo->txninfo->pgsize;
DB_ASSERT(env, ret == 0);
if (bufsz % pgsz != 0)
bufsz = pgsz * (bufsz / pgsz);
if ((ret = __os_malloc(env, bufsz, &btbuf)) != 0)
goto err;
BDBOP(__db_cursor(lvinfo->txninfo, lvinfo->ip, NULL, &csr, DBC_BULK));
data.data = btbuf;
data.ulen = bufsz;
data.flags |= DB_DBT_USERMEM;
for (ret = __dbc_get(csr, &key, &data, DB_FIRST | DB_MULTIPLE_KEY) ;;
ret = __dbc_get(csr, &key, &data, DB_NEXT | DB_MULTIPLE_KEY)) {
switch (ret) {
case 0:
break;
case DB_NOTFOUND:
goto out;
case DB_BUFFER_SMALL:
if ((ret = __os_realloc(lvinfo->dbenv->env,
bufsz *= 2, &btbuf)) != 0)
goto out;
data.ulen = bufsz;
data.data = btbuf;
continue;
default:
goto err;
}
DB_MULTIPLE_INIT(p, &data);
while (1) {
DB_MULTIPLE_KEY_NEXT(p, &data,
retk, retkl, retd, retdl);
if (p == NULL)
break;
DB_ASSERT(env, retkl == sizeof(txnid) && retk != NULL);
memcpy(&txnid, retk, retkl);
if ((min != 0 && txnid >= min && max != 0 &&
txnid <= max) || (min == 0 && max == 0)) {
data2.data = retd;
data2.size = (u_int32_t)retdl;
if ((ret = __lv_unpack_txn_vrfy_info(
&txninfop, &data2)) != 0)
goto out;
if ((ret = handler(lvinfo, txninfop,
param)) != 0)
goto out;
}
}
}
out:
if (ret == DB_NOTFOUND)
ret = 0;
err:
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
__os_free(lvinfo->dbenv->env, btbuf);
return (ret);
}
static int
__lv_add_recycle_handler(lvinfo, txninfop, params)
DB_LOG_VRFY_INFO *lvinfo;
VRFY_TXN_INFO *txninfop;
void *params;
{
int ret;
struct __add_recycle_params *param;
ret = 0;
param = (struct __add_recycle_params *)params;
if (txninfop->txnid < param->min && txninfop->txnid > param->max) {
ret = __free_txninfo(txninfop);
return (ret);
}
ret = __lv_add_recycle_lsn(txninfop, &(param->recycle_lsn));
if (ret != 0)
goto err;
if (txninfop->status == TXN_STAT_PREPARE) {
__db_errx(lvinfo->dbenv->env,
"[ERROR] Transaction with ID %u is prepared and not "
"committed, but its ID is recycled by log record [%u, %u].",
txninfop->txnid, param->recycle_lsn.file,
param->recycle_lsn.offset);
}
param->ti2u[(param->ti2ui)++] = txninfop;
if (param->ti2ui == param->ti2ul)
BDBOP(__os_realloc(lvinfo->dbenv->env,
sizeof(VRFY_TXN_INFO *) * (param->ti2ul *= 2),
&(param->ti2u)));
err:
return (ret);
}
int
__rem_last_recycle_lsn(txninfop)
VRFY_TXN_INFO *txninfop;
{
int ret;
ret = 0;
if (txninfop->num_recycle == 0)
return (0);
txninfop->num_recycle--;
if (txninfop->num_recycle > 0)
BDBOP(__os_realloc(NULL, txninfop->num_recycle * sizeof(DB_LSN),
&(txninfop->recycle_lsns)));
else {
__os_free(NULL, txninfop->recycle_lsns);
txninfop->recycle_lsns = NULL;
}
err:
return (ret);
}
int
__add_file_updated (txninfop, fileid, dbregid)
VRFY_TXN_INFO *txninfop;
const DBT *fileid;
int32_t dbregid;
{
int ret;
DBT *pdbt, *p;
u_int32_t found, i;
ret = 0;
p = pdbt = NULL;
for (found = 0, i = 0; i < txninfop->filenum; i++) {
p = &(txninfop->fileups[i]);
if (p->size == fileid->size &&
memcmp(p->data, fileid->data, p->size) == 0) {
found = 1;
break;
}
}
if (found)
return (0);
txninfop->filenum++;
if ((ret = __os_realloc(NULL, txninfop->filenum *
sizeof(DBT), &(txninfop->fileups))) != 0)
goto err;
pdbt = &(txninfop->fileups[txninfop->filenum - 1]);
memset(pdbt, 0, sizeof(DBT));
if ((ret = __os_malloc(NULL,
pdbt->size = fileid->size, &(pdbt->data))) != 0)
goto err;
memcpy(pdbt->data, fileid->data, fileid->size);
BDBOP(__os_realloc(NULL, txninfop->filenum *
sizeof(int32_t), &(txninfop->dbregid)));
txninfop->dbregid[txninfop->filenum - 1] = dbregid;
err:
return (ret);
}
int
__del_file_updated (txninfop, fileid)
VRFY_TXN_INFO *txninfop;
const DBT *fileid;
{
u_int32_t found, i;
int ret;
DBT *p;
void *pdbtdata;
ret = 0;
if (txninfop->filenum == 0)
return (0);
for (found = 0, i = 0, pdbtdata = NULL; i < txninfop->filenum; i++) {
p = &(txninfop->fileups[i]);
if (p->size == fileid->size &&
memcmp(p->data, fileid->data, p->size) == 0) {
pdbtdata = p->data;
if (txninfop->filenum > 1) {
memmove(txninfop->fileups + i, txninfop->
fileups + i + 1, sizeof(DBT) * (txninfop->
filenum - (i + 1)));
memmove(txninfop->dbregid + i, txninfop->
dbregid + i + 1, sizeof(int32_t) *
(txninfop->filenum - (i + 1)));
} else {
__os_free(NULL, txninfop->fileups);
__os_free(NULL, txninfop->dbregid);
txninfop->fileups = NULL;
txninfop->dbregid = NULL;
}
found = 1;
break;
}
}
if (found) {
txninfop->filenum--;
if (txninfop->filenum) {
BDBOP(__os_realloc(NULL, sizeof(DBT) *
txninfop->filenum, &(txninfop->fileups)));
BDBOP(__os_realloc(NULL, sizeof(int32_t) *
txninfop->filenum, &(txninfop->dbregid)));
}
__os_free(NULL, pdbtdata);
}
err:
return (ret);
}
int
__clear_fileups(txninfop)
VRFY_TXN_INFO *txninfop;
{
u_int32_t i;
for (i = 0; i < txninfop->filenum; i++)
__os_free(NULL, txninfop->fileups[i].data);
__os_free(NULL, txninfop->fileups);
__os_free(NULL, txninfop->dbregid);
txninfop->fileups = NULL;
txninfop->dbregid = NULL;
txninfop->filenum = 0;
return (0);
}
int
__free_txninfo_stack (p)
VRFY_TXN_INFO *p;
{
u_int32_t i;
if (p == NULL)
return (0);
if (p->fileups != NULL) {
for (i = 0; i < p->filenum; i++)
__os_free(NULL, p->fileups[i].data);
__os_free(NULL, p->fileups);
}
if (p->dbregid != NULL)
__os_free(NULL, p->dbregid);
if (p->recycle_lsns != NULL)
__os_free(NULL, p->recycle_lsns);
return (0);
}
int
__free_txninfo(p)
VRFY_TXN_INFO *p;
{
(void)__free_txninfo_stack(p);
__os_free(NULL, p);
return (0);
}
static int
__lv_pack_filereg(freginfo, data)
const VRFY_FILEREG_INFO *freginfo;
DBT *data;
{
char *buf, *p;
size_t bufsz, offset;
int ret;
ret = 0;
if ((ret = __os_malloc(NULL,
bufsz = FILE_REG_INFO_TOTSIZE(*freginfo), &buf)) != 0)
goto err;
memset(buf, 0, bufsz);
memcpy(buf, freginfo, FILE_REG_INFO_FIXSIZE);
p = buf + FILE_REG_INFO_FIXSIZE;
offset = sizeof(int32_t) * freginfo->regcnt;
memcpy(p, freginfo->dbregids, offset);
p += offset;
memcpy(p, &(freginfo->fileid.size), sizeof(freginfo->fileid.size));
p += sizeof(freginfo->fileid.size);
memcpy(p, freginfo->fileid.data, freginfo->fileid.size);
p += freginfo->fileid.size;
(void)strcpy(p, freginfo->fname);
data->data = buf;
data->size = (u_int32_t)bufsz;
err:
return (ret);
}
int __put_filereg_info (lvinfo, freginfo)
const DB_LOG_VRFY_INFO *lvinfo;
const VRFY_FILEREG_INFO *freginfo;
{
int ret;
DBT data;
memset(&data, 0, sizeof(DBT));
if ((ret = __lv_pack_filereg(freginfo, &data)) != 0)
goto err;
BDBOP2(lvinfo->dbenv, __db_put(lvinfo->fileregs, lvinfo->ip, NULL,
(DBT *)&(freginfo->fileid), &data, 0), "__put_filereg_info");
err:
if (data.data != NULL)
__os_free(lvinfo->dbenv->env, data.data);
return (ret);
}
int
__del_filelife(lvinfo, dbregid)
const DB_LOG_VRFY_INFO *lvinfo;
int32_t dbregid;
{
int ret;
DBT key;
memset(&key, 0, sizeof(DBT));
key.data = &(dbregid);
key.size = sizeof(dbregid);
if ((ret = __db_del(lvinfo->dbregids, lvinfo->ip, NULL,
&key, 0)) != 0)
goto err;
err:
return (ret);
}
int
__put_filelife (lvinfo, pflife)
const DB_LOG_VRFY_INFO *lvinfo;
VRFY_FILELIFE *pflife;
{
int ret;
DBT key, data;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &(pflife->dbregid);
key.size = sizeof(pflife->dbregid);
data.data = pflife;
data.size = sizeof(VRFY_FILELIFE);
if ((ret = __db_put(lvinfo->dbregids, lvinfo->ip, NULL,
&key, &data, 0)) != 0)
goto err;
err:
return (ret);
}
int
__get_filelife (lvinfo, dbregid, flifepp)
const DB_LOG_VRFY_INFO *lvinfo;
int32_t dbregid;
VRFY_FILELIFE **flifepp;
{
int ret;
DBT key, data;
VRFY_FILELIFE *flifep;
ret = 0;
flifep = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &dbregid;
key.size = sizeof(dbregid);
if ((ret = __db_get(lvinfo->dbregids, lvinfo->ip, NULL,
&key, &data, 0)) != 0)
goto err;
if ((ret = __os_malloc(lvinfo->dbenv->env,
sizeof(VRFY_FILELIFE), &flifep)) != 0)
goto err;
DB_ASSERT(lvinfo->dbenv->env, flifep != NULL);
memcpy(flifep, data.data, sizeof(VRFY_FILELIFE));
*flifepp = flifep;
err:
return (ret);
}
int
__get_filereg_by_dbregid(lvinfo, dbregid, freginfopp)
const DB_LOG_VRFY_INFO *lvinfo;
int32_t dbregid;
VRFY_FILEREG_INFO **freginfopp;
{
int ret;
DBT key, data;
char uid[DB_FILE_ID_LEN];
VRFY_FILELIFE *pflife;
memset(&data, 0, sizeof(DBT));
memset(&key, 0, sizeof(DBT));
key.data = &dbregid;
key.size = sizeof(dbregid);
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->dbregids, lvinfo->ip, NULL,
&key, &data, 0), DB_NOTFOUND, "__get_filereg_by_dbregid");
if (ret == DB_NOTFOUND)
goto err;
pflife = (VRFY_FILELIFE *)data.data;
memcpy((void *)uid, (void *)pflife->fileid, key.size = DB_FILE_ID_LEN);
key.data = (void *)uid;
memset(&data, 0, sizeof(DBT));
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->fileregs, lvinfo->ip, NULL,
&key, &data, 0), DB_NOTFOUND, "__get_filereg_by_dbregid");
if (ret == DB_NOTFOUND)
goto err;
if ((ret = __lv_unpack_filereg(&data, freginfopp)) != 0)
goto err;
err:
return (ret);
}
int
__add_dbregid(lvh, freg, dbregid, opcode, lsn, dbtype, meta_pgno, addp)
DB_LOG_VRFY_INFO *lvh;
VRFY_FILEREG_INFO *freg;
int32_t dbregid;
u_int32_t opcode;
DB_LSN lsn;
DBTYPE dbtype;
db_pgno_t meta_pgno;
int *addp;
{
int inarray, ret, tret;
u_int32_t i, j;
VRFY_FILELIFE flife;
inarray = ret = tret = 0;
for (i = 0; i < freg->regcnt; i++) {
if (freg->dbregids[i] == dbregid) {
if (!IS_DBREG_CLOSE(opcode)) {
if (IS_DBREG_OPEN(opcode) &&
(opcode != DBREG_CHKPNT &&
opcode != DBREG_XCHKPNT)) {
tret = 2;
goto err;
}
tret = 0;
inarray = 1;
} else
tret = -1;
break;
}
}
if (IS_DBREG_OPEN(opcode))
tret = 1;
if (tret == -1) {
for (j = i; j < freg->regcnt - 1; j++)
freg->dbregids[j] = freg->dbregids[j + 1];
freg->regcnt--;
BDBOP(__os_realloc(lvh->dbenv->env,
sizeof(int32_t) * freg->regcnt, &(freg->dbregids)));
} else if (tret == 1) {
if (!inarray) {
freg->regcnt++;
BDBOP(__os_realloc(lvh->dbenv->env,
sizeof(int32_t) * freg->regcnt, &(freg->dbregids)));
freg->dbregids[freg->regcnt - 1] = dbregid;
}
flife.dbregid = dbregid;
memcpy(flife.fileid, freg->fileid.data, freg->fileid.size);
flife.lifetime = opcode;
flife.dbtype = dbtype;
flife.lsn = lsn;
flife.meta_pgno = meta_pgno;
if ((ret = __put_filelife(lvh, &flife)) != 0)
goto err;
}
err:
*addp = tret;
return (ret);
}
int
__get_filereg_info (lvinfo, fuid, freginfopp)
const DB_LOG_VRFY_INFO *lvinfo;
const DBT *fuid;
VRFY_FILEREG_INFO **freginfopp;
{
int ret;
DBT data;
memset(&data, 0, sizeof(DBT));
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->fileregs, lvinfo->ip, NULL,
(DBT *)fuid, &data, 0), DB_NOTFOUND, "__get_filereg_info");
if (ret == DB_NOTFOUND)
goto err;
if ((ret = __lv_unpack_filereg(&data, freginfopp)) != 0)
goto err;
err:
return (ret);
}
static int
__lv_unpack_filereg(data, freginfopp)
const DBT *data;
VRFY_FILEREG_INFO **freginfopp;
{
char *p, *q;
u_int32_t fidsz, arrsz;
VRFY_FILEREG_INFO *buf;
int ret;
ret = 0;
p = q = NULL;
fidsz = arrsz = 0;
buf = NULL;
if ((ret = __os_malloc(NULL, sizeof(VRFY_FILEREG_INFO), &buf)) != 0)
goto err;
memset(buf, 0, sizeof(VRFY_FILEREG_INFO));
memcpy(buf, data->data, FILE_REG_INFO_FIXSIZE);
*freginfopp = (VRFY_FILEREG_INFO *)buf;
p = ((char *)(data->data)) + FILE_REG_INFO_FIXSIZE;
if ((ret = __os_malloc(NULL, arrsz = (*freginfopp)->regcnt *
sizeof(int32_t), &((*freginfopp)->dbregids))) != 0)
goto err;
memcpy((*freginfopp)->dbregids, p, arrsz);
p += arrsz;
memcpy(&fidsz, p, sizeof(fidsz));
p += sizeof(fidsz);
if ((ret = __os_malloc(NULL, fidsz, &q)) != 0)
goto err;
memcpy(q, p, fidsz);
(*freginfopp)->fileid.data = q;
(*freginfopp)->fileid.size = fidsz;
p += fidsz;
if ((ret = __os_malloc(NULL, sizeof(char) * (strlen(p) + 1), &q)) != 0)
goto err;
(void)strcpy(q, p);
(*freginfopp)->fname = q;
err:
return (ret);
}
int
__free_filereg_info(p)
VRFY_FILEREG_INFO *p;
{
if (p == NULL)
return (0);
if (p ->fname != NULL)
__os_free(NULL, (void *)(p->fname));
if (p->fileid.data != NULL)
__os_free(NULL, p->fileid.data);
if (p->dbregids != NULL)
__os_free(NULL, p->dbregids);
__os_free(NULL, p);
return (0);
}
int
__get_ckp_info (lvinfo, lsn, ckpinfopp)
const DB_LOG_VRFY_INFO *lvinfo;
DB_LSN lsn;
VRFY_CKP_INFO **ckpinfopp;
{
int ret;
DBT key, data;
VRFY_CKP_INFO *ckpinfo;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &lsn;
key.size = sizeof(DB_LSN);
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->ckps, lvinfo->ip, NULL,
&key, &data, 0), DB_NOTFOUND, "__get_ckp_info");
if (ret == DB_NOTFOUND)
goto err;
if ((ret = __os_malloc(lvinfo->dbenv->env,
sizeof(VRFY_CKP_INFO), &ckpinfo)) != 0)
goto err;
memcpy(ckpinfo, data.data, sizeof(VRFY_CKP_INFO));
*ckpinfopp = ckpinfo;
err:
return (ret);
}
int
__get_last_ckp_info (lvinfo, ckpinfopp)
const DB_LOG_VRFY_INFO *lvinfo;
VRFY_CKP_INFO **ckpinfopp;
{
int ret, tret;
DBT key, data;
VRFY_CKP_INFO *ckpinfo;
DBC *csr;
csr = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
BDBOP(__db_cursor(lvinfo->ckps, lvinfo->ip, NULL, &csr, 0));
if ((ret = __dbc_get(csr, &key, &data, DB_LAST)) != 0)
goto err;
if ((ret = __os_malloc(lvinfo->dbenv->env,
sizeof(VRFY_CKP_INFO), &ckpinfo)) != 0)
goto err;
DB_ASSERT(lvinfo->dbenv->env, sizeof(VRFY_CKP_INFO) == data.size);
memcpy(ckpinfo, data.data, sizeof(VRFY_CKP_INFO));
*ckpinfopp = ckpinfo;
err:
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
if (ret != 0 && ret != DB_NOTFOUND)
__db_err(lvinfo->dbenv->env, ret, "__get_last_ckp_info");
return (ret);
}
int __put_ckp_info (lvinfo, ckpinfo)
const DB_LOG_VRFY_INFO *lvinfo;
const VRFY_CKP_INFO *ckpinfo;
{
int ret;
DBT key, data;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = (void *)&ckpinfo->lsn;
key.size = sizeof(DB_LSN);
data.data = (void *)ckpinfo;
data.size = sizeof(VRFY_CKP_INFO);
BDBOP2(lvinfo->dbenv, __db_put(lvinfo->ckps, lvinfo->ip,
NULL, &key, &data, 0), "__put_ckp_info");
return (0);
}
int __get_timestamp_info (lvinfo, lsn, tsinfopp)
const DB_LOG_VRFY_INFO *lvinfo;
DB_LSN lsn;
VRFY_TIMESTAMP_INFO **tsinfopp;
{
int ret;
DBT key, data;
VRFY_TIMESTAMP_INFO *tsinfo;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &lsn;
key.size = sizeof(DB_LSN);
BDBOP3(lvinfo->dbenv, __db_get(lvinfo->lsntime, lvinfo->ip, NULL,
&key, &data, 0), DB_NOTFOUND, "__get_timestamp_info");
if (ret == DB_NOTFOUND)
goto err;
if ((ret = __os_malloc(lvinfo->dbenv->env,
sizeof(VRFY_TIMESTAMP_INFO), &tsinfo)) != 0)
goto err;
memcpy(tsinfo, data.data, sizeof(VRFY_TIMESTAMP_INFO));
*tsinfopp = tsinfo;
err:
return (ret);
}
int __get_latest_timestamp_info(lvinfo, lsn, tsinfopp)
const DB_LOG_VRFY_INFO *lvinfo;
DB_LSN lsn;
VRFY_TIMESTAMP_INFO **tsinfopp;
{
int ret, tret;
DBT key, data;
VRFY_TIMESTAMP_INFO *tsinfo;
DBC *csr;
csr = NULL;
ret = tret = 0;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &lsn;
key.size = sizeof(lsn);
BDBOP(__db_cursor(lvinfo->lsntime, lvinfo->ip, NULL, &csr, 0));
BDBOP(__dbc_get(csr, &key, &data, DB_SET));
BDBOP(__dbc_get(csr, &key, &data, DB_PREV));
if ((ret = __os_malloc(lvinfo->dbenv->env, sizeof(VRFY_TIMESTAMP_INFO),
&tsinfo)) != 0)
goto err;
memcpy(tsinfo, data.data, sizeof(VRFY_TIMESTAMP_INFO));
*tsinfopp = tsinfo;
err:
if (ret != 0 && ret != DB_NOTFOUND)
__db_err(lvinfo->dbenv->env,
ret, "__get_latest_timestamp_info");
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int __put_timestamp_info (lvinfo, tsinfo)
const DB_LOG_VRFY_INFO *lvinfo;
const VRFY_TIMESTAMP_INFO *tsinfo;
{
int ret;
DBT key, data;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = (void *)&(tsinfo->lsn);
key.size = sizeof(DB_LSN);
data.data = (void *)tsinfo;
data.size = sizeof(VRFY_TIMESTAMP_INFO);
BDBOP2(lvinfo->dbenv, __db_put(lvinfo->lsntime, lvinfo->ip, NULL,
&key, &data, 0), "__put_timestamp_info");
return (0);
}
static int
__lv_txnrgns_lsn_cmp (db, d1, d2)
DB *db;
const DBT *d1, *d2;
{
struct __lv_txnrange r1, r2;
DB_ASSERT(db->env, d1->size == sizeof(r1));
DB_ASSERT(db->env, d2->size == sizeof(r2));
memcpy(&r1, d1->data, d1->size);
memcpy(&r2, d2->data, d2->size);
return (LOG_COMPARE(&(r1.end), &(r2.end)));
}
int
__find_lsnrg_by_timerg(lvinfo, begin, end, startlsn, endlsn)
DB_LOG_VRFY_INFO *lvinfo;
time_t begin, end;
DB_LSN *startlsn, *endlsn;
{
int ret, tret;
DBC *csr;
struct __lv_timestamp_info *t1, *t2;
DBT key, data;
ret = tret = 0;
csr = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
BDBOP(__db_cursor(lvinfo->timelsn, lvinfo->ip, NULL, &csr, 0));
key.data = &begin;
key.size = sizeof(begin);
BDBOP(__dbc_get(csr, &key, &data, DB_SET_RANGE));
if ((ret = __dbc_get(csr, &key, &data, DB_PREV)) != 0 &&
ret != DB_NOTFOUND)
goto err;
if (ret == DB_NOTFOUND)
startlsn->file = startlsn->offset = 0;
else {
t1 = (struct __lv_timestamp_info *)data.data;
*startlsn = t1->lsn;
}
key.data = &end;
key.size = sizeof(end);
if ((ret = __dbc_get(csr, &key, &data, DB_SET_RANGE)) != 0 &&
ret != DB_NOTFOUND)
goto err;
if (ret == DB_NOTFOUND) {
endlsn->file = endlsn->offset = (u_int32_t)-1;
ret = 0;
goto err;
}
if ((ret = __dbc_get(csr, &key, &data, DB_NEXT_NODUP)) != 0 &&
ret != DB_NOTFOUND)
goto err;
if (ret == DB_NOTFOUND)
BDBOP(__dbc_get(csr, &key, &data, DB_LAST));
else
BDBOP(__dbc_get(csr, &key, &data, DB_PREV));
t2 = (struct __lv_timestamp_info *)data.data;
*endlsn = t2->lsn;
err:
if (ret == DB_NOTFOUND)
ret = 0;
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int __add_txnrange (lvinfo, txnid, lsn, when, ishead)
DB_LOG_VRFY_INFO *lvinfo;
u_int32_t txnid;
DB_LSN lsn;
int32_t when;
int ishead;
{
int ret, tret;
DBC *csr;
struct __lv_txnrange tr, *ptr;
DBT key, data;
csr = NULL;
ret = 0;
ptr = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&tr, 0, sizeof(tr));
key.data = &txnid;
key.size = sizeof(txnid);
tr.txnid = txnid;
BDBOP(__db_cursor(lvinfo->txnrngs, lvinfo->ip, NULL, &csr, 0));
if (!ishead) {
tr.end = lsn;
tr.when_commit = when;
data.data = &tr;
data.size = sizeof(tr);
BDBOP(__dbc_put(csr, &key, &data, DB_KEYFIRST));
} else {
BDBOP(__dbc_get(csr, &key, &data, DB_SET));
ptr = (struct __lv_txnrange *)data.data;
DB_ASSERT(lvinfo->dbenv->env, IS_ZERO_LSN(ptr->begin));
ptr->begin = lsn;
BDBOP(__dbc_put(csr, &key, &data, DB_CURRENT));
}
err:
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int
__get_aborttxn(lvinfo, lsn)
DB_LOG_VRFY_INFO *lvinfo;
DB_LSN lsn;
{
int ret, tret;
u_int32_t txnid;
DBC *csr;
DBT key, data;
csr = NULL;
txnid = 0;
ret = tret = 0;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &lsn;
key.size = sizeof(lsn);
BDBOP(__db_cursor(lvinfo->txnaborts, lvinfo->ip, NULL, &csr, 0));
BDBOP(__dbc_get(csr, &key, &data, DB_SET));
memcpy(&txnid, data.data, data.size);
lvinfo->aborted_txnid = txnid;
lvinfo->aborted_txnlsn = lsn;
err:
if (ret == DB_NOTFOUND)
ret = 0;
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int
__txn_started(lvinfo, lsn, txnid, res)
DB_LOG_VRFY_INFO *lvinfo;
DB_LSN lsn;
u_int32_t txnid;
int *res;
{
int ret, tret;
DBC *csr;
DBT key, data;
struct __lv_txnrange *ptr, tr;
ret = *res = 0;
csr = NULL;
memset(&tr, 0, sizeof(tr));
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &txnid;
key.size = sizeof(txnid);
BDBOP(__db_cursor(lvinfo->txnrngs, lvinfo->ip, NULL, &csr, 0));
BDBOP(__dbc_get(csr, &key, &data, DB_SET));
for (;ret == 0; ret = __dbc_get(csr, &key, &data, DB_NEXT_DUP)) {
ptr = (struct __lv_txnrange *)data.data;
if (LOG_COMPARE(&lsn, &(ptr->begin)) > 0 &&
LOG_COMPARE(&lsn, &(ptr->end)) <= 0) {
*res = 1;
break;
}
}
err:
if (ret == DB_NOTFOUND)
ret = 0;
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int
__set_logvrfy_dbfuid(lvinfo)
DB_LOG_VRFY_INFO *lvinfo;
{
int ret;
const char *p;
DBT key, data;
size_t buflen;
p = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
p = lvinfo->lv_config->dbfile;
buflen = sizeof(char) * (strlen(p) + 1);
key.data = (char *)p;
key.size = (u_int32_t)buflen;
BDBOP2(lvinfo->dbenv, __db_get(lvinfo->fnameuid, lvinfo->ip, NULL,
&key, &data, 0), "__set_logvrfy_dbfuid");
memcpy(lvinfo->target_dbid, data.data, DB_FILE_ID_LEN);
return (ret);
}
int
__add_page_to_txn (lvinfo, dbregid, pgno, txnid, otxn, result)
DB_LOG_VRFY_INFO *lvinfo;
int32_t dbregid;
db_pgno_t pgno;
u_int32_t txnid, *otxn;
int *result;
{
int ret;
u_int8_t *buf;
DBT key, data;
size_t buflen;
u_int32_t txnid2;
VRFY_FILELIFE *pff;
if (txnid < TXN_MINIMUM) {
*result = 0;
return (0);
}
buf = NULL;
ret = 0;
txnid2 = 0;
pff = NULL;
buflen = sizeof(u_int8_t) * DB_FILE_ID_LEN + sizeof(db_pgno_t);
BDBOP(__os_malloc(lvinfo->dbenv->env, buflen, &buf));
memset(buf, 0, buflen);
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &dbregid;
key.size = sizeof(dbregid);
if ((ret = __db_get(lvinfo->dbregids, lvinfo->ip, NULL,
&key, &data, 0)) != 0) {
if (ret == DB_NOTFOUND) {
if (F_ISSET(lvinfo, DB_LOG_VERIFY_PARTIAL)) {
ret = 0;
goto out;
} else
F_SET(lvinfo, DB_LOG_VERIFY_INTERR);
}
goto err;
}
pff = (VRFY_FILELIFE *)data.data;
memcpy(buf, pff->fileid, DB_FILE_ID_LEN);
memcpy(buf + DB_FILE_ID_LEN, (u_int8_t *)&pgno, sizeof(pgno));
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = buf;
key.size = (u_int32_t)buflen;
if ((ret = __db_get(lvinfo->pgtxn, lvinfo->ip, NULL,
&key, &data, 0)) != 0) {
if (ret == DB_NOTFOUND) {
data.data = &txnid;
data.size = sizeof(txnid);
BDBOP(__db_put(lvinfo->pgtxn, lvinfo->ip, NULL, &key,
&data, 0));
*result = 1;
ret = 0;
}
goto err;
}
DB_ASSERT(lvinfo->dbenv->env, data.size == sizeof(txnid2));
memcpy(&txnid2, data.data, data.size);
if (txnid == txnid2)
*result = 0;
else {
*result = -1;
*otxn = txnid2;
}
out:
err:
if (buf != NULL)
__os_free(lvinfo->dbenv->env, buf);
return (ret);
}
int
__del_txn_pages(lvinfo, txnid)
DB_LOG_VRFY_INFO *lvinfo;
u_int32_t txnid;
{
int ret;
DBT key;
ret = 0;
memset(&key, 0, sizeof(DBT));
key.data = &txnid;
key.size = sizeof(txnid);
BDBOP(__db_del(lvinfo->txnpg, lvinfo->ip, NULL, &key, 0));
err:
return (ret);
}
int
__is_ancestor_txn (lvinfo, ptxnid, txnid, lsn, res)
DB_LOG_VRFY_INFO *lvinfo;
u_int32_t ptxnid, txnid;
DB_LSN lsn;
int *res;
{
u_int32_t ptid;
int ret, tret;
DBC *csr;
DB *pdb;
DBT key, data;
struct __lv_txnrange tr;
ret = 0;
ptid = txnid;
csr = NULL;
pdb = lvinfo->txnrngs;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
*res = 0;
BDBOP(__db_cursor(pdb, lvinfo->ip, NULL, &csr, 0));
do {
key.data = &ptid;
key.size = sizeof(ptid);
BDBOP(__dbc_get(csr, &key, &data, DB_SET));
for (;ret == 0;
ret = __dbc_get(csr, &key, &data, DB_NEXT_DUP)) {
DB_ASSERT(pdb->env, sizeof(tr) == data.size);
memcpy(&tr, data.data, data.size);
if (tr.ptxnid > 0 &&
LOG_COMPARE(&lsn, &(tr.begin)) >= 0 &&
LOG_COMPARE(&lsn, &(tr.end)) <= 0)
break;
}
if (tr.ptxnid == ptxnid) {
*res = 1;
goto out;
} else
ptid = tr.ptxnid;
} while (ptid != 0);
out:
err:
if (ret == DB_NOTFOUND)
ret = 0;
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
int __return_txn_pages(lvh, ctxn, ptxn)
DB_LOG_VRFY_INFO *lvh;
u_int32_t ctxn, ptxn;
{
int ret, tret;
DBC *csr;
DB *pdb, *sdb;
DBT key, key2, data, data2;
char buf[DB_FILE_ID_LEN + sizeof(db_pgno_t)];
ret = tret = 0;
csr = NULL;
sdb = lvh->txnpg;
pdb = lvh->pgtxn;
memset(&key, 0, sizeof(DBT));
memset(&key2, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&data2, 0, sizeof(DBT));
BDBOP(__db_cursor(sdb, lvh->ip, NULL, &csr, 0));
key.data = &ctxn;
key.size = sizeof(ctxn);
key2.data = &ptxn;
key2.size = sizeof(ptxn);
data2.data = buf;
data2.ulen = DB_FILE_ID_LEN + sizeof(db_pgno_t);
data2.flags = DB_DBT_USERMEM;
for (ret = __dbc_pget(csr, &key, &data2, &data, DB_SET); ret == 0;
ret = __dbc_pget(csr, &key, &data2, &data, DB_NEXT_DUP))
BDBOP(__db_put(pdb, lvh->ip, NULL, &data2, &key2, 0));
if ((ret = __del_txn_pages(lvh, ctxn)) != 0 && ret != DB_NOTFOUND)
goto err;
err:
if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0)
ret = tret;
return (ret);
}
#define ADD_ITEM(lvh, logtype) ((lvh)->logtype_names[(logtype)] = (#logtype))
static void
__lv_setup_logtype_names(lvinfo)
DB_LOG_VRFY_INFO *lvinfo;
{
ADD_ITEM(lvinfo, DB___bam_irep);
ADD_ITEM(lvinfo, DB___bam_split_42);
ADD_ITEM(lvinfo, DB___bam_split);
ADD_ITEM(lvinfo, DB___bam_rsplit);
ADD_ITEM(lvinfo, DB___bam_adj);
ADD_ITEM(lvinfo, DB___bam_cadjust);
ADD_ITEM(lvinfo, DB___bam_cdel);
ADD_ITEM(lvinfo, DB___bam_repl);
ADD_ITEM(lvinfo, DB___bam_root);
ADD_ITEM(lvinfo, DB___bam_curadj);
ADD_ITEM(lvinfo, DB___bam_rcuradj);
ADD_ITEM(lvinfo, DB___bam_relink_43);
ADD_ITEM(lvinfo, DB___bam_merge_44);
ADD_ITEM(lvinfo, DB___crdel_metasub);
ADD_ITEM(lvinfo, DB___crdel_inmem_create);
ADD_ITEM(lvinfo, DB___crdel_inmem_rename);
ADD_ITEM(lvinfo, DB___crdel_inmem_remove);
ADD_ITEM(lvinfo, DB___dbreg_register);
ADD_ITEM(lvinfo, DB___db_addrem);
ADD_ITEM(lvinfo, DB___db_big);
ADD_ITEM(lvinfo, DB___db_ovref);
ADD_ITEM(lvinfo, DB___db_relink_42);
ADD_ITEM(lvinfo, DB___db_debug);
ADD_ITEM(lvinfo, DB___db_noop);
ADD_ITEM(lvinfo, DB___db_pg_alloc_42);
ADD_ITEM(lvinfo, DB___db_pg_alloc);
ADD_ITEM(lvinfo, DB___db_pg_free_42);
ADD_ITEM(lvinfo, DB___db_pg_free);
ADD_ITEM(lvinfo, DB___db_cksum);
ADD_ITEM(lvinfo, DB___db_pg_freedata_42);
ADD_ITEM(lvinfo, DB___db_pg_freedata);
ADD_ITEM(lvinfo, DB___db_pg_init);
ADD_ITEM(lvinfo, DB___db_pg_sort_44);
ADD_ITEM(lvinfo, DB___db_pg_trunc);
ADD_ITEM(lvinfo, DB___db_realloc);
ADD_ITEM(lvinfo, DB___db_relink);
ADD_ITEM(lvinfo, DB___db_merge);
ADD_ITEM(lvinfo, DB___db_pgno);
#ifdef HAVE_HASH
ADD_ITEM(lvinfo, DB___ham_insdel);
ADD_ITEM(lvinfo, DB___ham_newpage);
ADD_ITEM(lvinfo, DB___ham_splitdata);
ADD_ITEM(lvinfo, DB___ham_replace);
ADD_ITEM(lvinfo, DB___ham_copypage);
ADD_ITEM(lvinfo, DB___ham_metagroup_42);
ADD_ITEM(lvinfo, DB___ham_metagroup);
ADD_ITEM(lvinfo, DB___ham_groupalloc_42);
ADD_ITEM(lvinfo, DB___ham_groupalloc);
ADD_ITEM(lvinfo, DB___ham_changeslot);
ADD_ITEM(lvinfo, DB___ham_contract);
ADD_ITEM(lvinfo, DB___ham_curadj);
ADD_ITEM(lvinfo, DB___ham_chgpg);
#endif
#ifdef HAVE_QUEUE
ADD_ITEM(lvinfo, DB___qam_incfirst);
ADD_ITEM(lvinfo, DB___qam_mvptr);
ADD_ITEM(lvinfo, DB___qam_del);
ADD_ITEM(lvinfo, DB___qam_add);
ADD_ITEM(lvinfo, DB___qam_delext);
#endif
ADD_ITEM(lvinfo, DB___txn_regop_42);
ADD_ITEM(lvinfo, DB___txn_regop);
ADD_ITEM(lvinfo, DB___txn_ckp_42);
ADD_ITEM(lvinfo, DB___txn_ckp);
ADD_ITEM(lvinfo, DB___txn_child);
ADD_ITEM(lvinfo, DB___txn_xa_regop_42);
ADD_ITEM(lvinfo, DB___txn_prepare);
ADD_ITEM(lvinfo, DB___txn_recycle);
ADD_ITEM(lvinfo, DB___fop_create_42);
ADD_ITEM(lvinfo, DB___fop_create);
ADD_ITEM(lvinfo, DB___fop_remove);
ADD_ITEM(lvinfo, DB___fop_write_42);
ADD_ITEM(lvinfo, DB___fop_write);
ADD_ITEM(lvinfo, DB___fop_rename_42);
ADD_ITEM(lvinfo, DB___fop_rename_noundo_46);
ADD_ITEM(lvinfo, DB___fop_rename);
ADD_ITEM(lvinfo, DB___fop_rename_noundo);
ADD_ITEM(lvinfo, DB___fop_file_remove);
}