2008-01-11 03:09:14 +00:00
|
|
|
/* -*- mode: C; c-basic-offset: 4 -*- */
|
2008-01-24 15:10:32 +00:00
|
|
|
#ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved."
|
2008-01-11 03:09:14 +00:00
|
|
|
|
|
|
|
/* rollback and rollforward routines. */
|
|
|
|
|
2013-04-16 23:57:20 -04:00
|
|
|
#include "includes.h"
|
2008-01-11 03:09:14 +00:00
|
|
|
|
2008-07-01 19:52:35 +00:00
|
|
|
// these flags control whether or not we send commit messages for
|
|
|
|
// various operations
|
|
|
|
#define TOKU_DO_COMMIT_CMD_INSERT 0
|
|
|
|
#define TOKU_DO_COMMIT_CMD_DELETE 1
|
|
|
|
#define TOKU_DO_COMMIT_CMD_DELETE_BOTH 1
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
typedef void (*YIELDF)(void*);
|
|
|
|
|
|
|
|
int
|
|
|
|
toku_commit_fcreate (TXNID UU(xid),
|
2013-04-16 23:57:40 -04:00
|
|
|
FILENUM UU(filenum),
|
2013-04-16 23:57:38 -04:00
|
|
|
BYTESTRING UU(bs_fname),
|
|
|
|
TOKUTXN UU(txn),
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void *UU(yield_v))
|
|
|
|
{
|
2008-04-07 01:30:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_fcreate (TXNID UU(xid),
|
2013-04-16 23:57:40 -04:00
|
|
|
FILENUM filenum,
|
2013-04-16 23:57:38 -04:00
|
|
|
BYTESTRING bs_fname,
|
2013-04-16 23:57:40 -04:00
|
|
|
TOKUTXN txn,
|
2013-04-16 23:57:38 -04:00
|
|
|
YIELDF UU(yield),
|
|
|
|
void* UU(yield_v))
|
|
|
|
{
|
2008-02-14 19:23:25 +00:00
|
|
|
char *fname = fixup_fname(&bs_fname);
|
2008-01-12 12:21:07 +00:00
|
|
|
char *directory = txn->logger->directory;
|
|
|
|
int full_len=strlen(fname)+strlen(directory)+2;
|
|
|
|
char full_fname[full_len];
|
|
|
|
int l = snprintf(full_fname,full_len, "%s/%s", directory, fname);
|
|
|
|
assert(l<=full_len);
|
2013-04-16 23:57:27 -04:00
|
|
|
//Remove reference to the fd in the cachetable
|
|
|
|
CACHEFILE cf;
|
|
|
|
int r = toku_cachefile_of_filenum(txn->logger->ct, filenum, &cf);
|
|
|
|
if (r == 0) {
|
|
|
|
r = toku_cachefile_redirect_nullfd(cf);
|
|
|
|
assert(r==0);
|
|
|
|
}
|
2013-04-16 23:57:40 -04:00
|
|
|
r = unlink(full_fname);
|
2008-01-12 12:21:07 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:39 -04:00
|
|
|
r = toku_graceful_delete(full_fname);
|
|
|
|
assert(r==0);
|
2013-04-16 23:57:33 -04:00
|
|
|
toku_free(fname);
|
2008-01-12 12:21:07 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-27 12:34:50 +00:00
|
|
|
static int find_brt_from_filenum (OMTVALUE v, void *filenumvp) {
|
|
|
|
FILENUM *filenump=filenumvp;
|
|
|
|
BRT brt = v;
|
|
|
|
FILENUM thisfnum = toku_cachefile_filenum(brt->cf);
|
|
|
|
if (thisfnum.fileid<filenump->fileid) return -1;
|
|
|
|
if (thisfnum.fileid>filenump->fileid) return +1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-27 15:12:25 +00:00
|
|
|
static int do_insertion (enum brt_cmd_type type, TXNID xid, FILENUM filenum, BYTESTRING key, BYTESTRING *data,TOKUTXN txn) {
|
2008-04-07 01:30:25 +00:00
|
|
|
CACHEFILE cf;
|
|
|
|
//printf("%s:%d committing insert %s %s\n", __FILE__, __LINE__, key.data, data.data);
|
2008-04-09 02:45:27 +00:00
|
|
|
int r = toku_cachefile_of_filenum(txn->logger->ct, filenum, &cf);
|
2008-03-28 20:49:50 +00:00
|
|
|
assert(r==0);
|
2008-04-27 12:34:50 +00:00
|
|
|
|
2008-04-07 01:30:25 +00:00
|
|
|
DBT key_dbt,data_dbt;
|
2008-04-27 15:12:25 +00:00
|
|
|
BRT_CMD_S brtcmd = { type, xid,
|
2008-04-07 01:30:25 +00:00
|
|
|
.u.id={toku_fill_dbt(&key_dbt, key.data, key.len),
|
2008-04-27 15:12:25 +00:00
|
|
|
data
|
|
|
|
? toku_fill_dbt(&data_dbt, data->data, data->len)
|
|
|
|
: toku_init_dbt(&data_dbt) }};
|
2008-06-02 20:52:12 +00:00
|
|
|
OMTVALUE brtv=NULL;
|
2008-05-30 20:41:12 +00:00
|
|
|
r = toku_omt_find_zero(txn->open_brts, find_brt_from_filenum, &filenum, &brtv, NULL, NULL);
|
2008-04-27 12:34:50 +00:00
|
|
|
|
|
|
|
if (r==DB_NOTFOUND) {
|
|
|
|
r = toku_cachefile_root_put_cmd(cf, &brtcmd, toku_txn_logger(txn));
|
|
|
|
if (r!=0) return r;
|
|
|
|
} else {
|
|
|
|
assert(r==0);
|
|
|
|
BRT brt = brtv;
|
|
|
|
r = toku_brt_root_put_cmd(brt, &brtcmd, txn->logger);
|
|
|
|
}
|
2013-04-16 23:57:38 -04:00
|
|
|
return toku_cachefile_close(&cf, toku_txn_logger(txn), 0);
|
2008-04-27 15:12:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-03 12:43:25 +00:00
|
|
|
static int do_nothing_with_filenum(TOKUTXN txn, FILENUM filenum) {
|
|
|
|
CACHEFILE cf;
|
|
|
|
int r = toku_cachefile_of_filenum(txn->logger->ct, filenum, &cf);
|
|
|
|
assert(r==0);
|
2013-04-16 23:57:38 -04:00
|
|
|
return toku_cachefile_close(&cf, toku_txn_logger(txn), 0);
|
2008-05-03 12:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int toku_commit_cmdinsert (TXNID xid, FILENUM filenum, BYTESTRING key, TOKUTXN txn, YIELDF UU(yield), void *UU(yieldv)) {
|
2013-04-16 23:57:34 -04:00
|
|
|
#if TOKU_DO_COMMIT_CMD_INSERT
|
|
|
|
return do_insertion (BRT_COMMIT_ANY, xid, filenum, key, 0, txn);
|
|
|
|
#else
|
|
|
|
xid = xid; key = key;
|
|
|
|
return do_nothing_with_filenum(txn, filenum);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_commit_cmdinsertboth (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
BYTESTRING data,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-07-01 19:52:35 +00:00
|
|
|
#if TOKU_DO_COMMIT_CMD_INSERT
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_COMMIT_BOTH, xid, filenum, key, &data, txn);
|
2008-07-01 19:52:35 +00:00
|
|
|
#else
|
|
|
|
xid = xid; key = key; data = data;
|
|
|
|
return do_nothing_with_filenum(txn, filenum);
|
|
|
|
#endif
|
2008-03-28 20:49:50 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_cmdinsert (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2013-04-16 23:57:34 -04:00
|
|
|
return do_insertion (BRT_ABORT_ANY, xid, filenum, key, 0, txn);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_cmdinsertboth (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
BYTESTRING data,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_ABORT_BOTH, xid, filenum, key, &data, txn);
|
2008-04-07 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_commit_cmddeleteboth (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
BYTESTRING data,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-07-01 19:52:35 +00:00
|
|
|
#if TOKU_DO_COMMIT_CMD_DELETE_BOTH
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_COMMIT_BOTH, xid, filenum, key, &data, txn);
|
2008-07-01 19:52:35 +00:00
|
|
|
#else
|
|
|
|
xid = xid; key = key; data = data;
|
|
|
|
return do_nothing_with_filenum(txn, filenum);
|
|
|
|
#endif
|
2008-04-07 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_cmddeleteboth (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
BYTESTRING data,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_ABORT_BOTH, xid, filenum, key, &data, txn);
|
2008-01-25 21:50:07 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_commit_cmddelete (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-07-01 19:52:35 +00:00
|
|
|
#if TOKU_DO_COMMIT_CMD_DELETE
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_COMMIT_ANY, xid, filenum, key, 0, txn);
|
2008-07-01 19:52:35 +00:00
|
|
|
#else
|
|
|
|
xid = xid; key = key;
|
|
|
|
return do_nothing_with_filenum(txn, filenum);
|
|
|
|
#endif
|
2008-02-27 07:14:03 +00:00
|
|
|
}
|
2008-03-19 19:23:45 +00:00
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_cmddelete (TXNID xid,
|
|
|
|
FILENUM filenum,
|
|
|
|
BYTESTRING key,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF UU(yield),
|
|
|
|
void * UU(yieldv))
|
|
|
|
{
|
2008-04-27 15:12:25 +00:00
|
|
|
return do_insertion (BRT_ABORT_ANY, xid, filenum, key, 0, txn);
|
2008-03-19 19:23:45 +00:00
|
|
|
}
|
2008-04-22 17:09:24 +00:00
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_commit_fileentries (int fd,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF yield,
|
|
|
|
void * yieldv)
|
|
|
|
{
|
2013-04-16 23:57:38 -04:00
|
|
|
BREAD f = create_bread_from_fd_initialize_at(fd);
|
2008-07-09 12:00:26 +00:00
|
|
|
int r=0;
|
2008-07-11 22:00:06 +00:00
|
|
|
MEMARENA ma = memarena_create();
|
2013-04-16 23:57:38 -04:00
|
|
|
int count=0;
|
2008-07-09 12:00:26 +00:00
|
|
|
while (bread_has_more(f)) {
|
2008-04-22 17:09:24 +00:00
|
|
|
struct roll_entry *item;
|
2008-07-11 22:00:06 +00:00
|
|
|
r = toku_read_rollback_backwards(f, &item, ma);
|
2008-07-09 12:00:26 +00:00
|
|
|
if (r!=0) goto finish;
|
2013-04-16 23:57:38 -04:00
|
|
|
r = toku_commit_rollback_item(txn, item, yield, yieldv);
|
2008-07-09 12:00:26 +00:00
|
|
|
if (r!=0) goto finish;
|
2008-07-11 22:00:06 +00:00
|
|
|
memarena_clear(ma);
|
2013-04-16 23:57:38 -04:00
|
|
|
count++;
|
|
|
|
if (count%2==0) yield(yieldv);
|
2008-04-22 17:09:24 +00:00
|
|
|
}
|
2008-07-09 12:00:26 +00:00
|
|
|
finish:
|
|
|
|
{ int r2 = close_bread_without_closing_fd(f); assert(r2==0); }
|
2008-07-11 22:00:06 +00:00
|
|
|
memarena_close(&ma);
|
2008-07-09 12:00:26 +00:00
|
|
|
return r;
|
2008-04-22 17:09:24 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_fileentries (int fd,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF yield,
|
|
|
|
void * yieldv)
|
|
|
|
{
|
2013-04-16 23:57:38 -04:00
|
|
|
BREAD f = create_bread_from_fd_initialize_at(fd);
|
2008-07-09 12:00:26 +00:00
|
|
|
assert(f);
|
|
|
|
int r=0;
|
2008-07-11 22:00:06 +00:00
|
|
|
MEMARENA ma = memarena_create();
|
2013-04-16 23:57:38 -04:00
|
|
|
int count=0;
|
2008-07-09 12:00:26 +00:00
|
|
|
while (bread_has_more(f)) {
|
2008-04-22 17:09:24 +00:00
|
|
|
struct roll_entry *item;
|
2008-07-11 22:00:06 +00:00
|
|
|
r = toku_read_rollback_backwards(f, &item, ma);
|
2008-07-09 12:00:26 +00:00
|
|
|
if (r!=0) goto finish;
|
2013-04-16 23:57:38 -04:00
|
|
|
r = toku_abort_rollback_item(txn, item, yield, yieldv);
|
2008-07-09 12:00:26 +00:00
|
|
|
if (r!=0) goto finish;
|
2008-07-11 22:00:06 +00:00
|
|
|
memarena_clear(ma);
|
2013-04-16 23:57:38 -04:00
|
|
|
count++;
|
|
|
|
if (count%2==0) yield(yieldv);
|
2008-04-22 17:09:24 +00:00
|
|
|
}
|
2008-07-09 12:00:26 +00:00
|
|
|
finish:
|
|
|
|
{ int r2 = close_bread_without_closing_fd(f); assert(r2==0); }
|
2008-07-11 22:00:06 +00:00
|
|
|
memarena_close(&ma);
|
2008-07-09 12:00:26 +00:00
|
|
|
return r;
|
2008-04-22 17:09:24 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_commit_rollinclude (BYTESTRING bs,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF yield,
|
|
|
|
void * yieldv) {
|
2008-04-22 17:09:24 +00:00
|
|
|
int r;
|
|
|
|
char *fname = fixup_fname(&bs);
|
2013-04-16 23:57:27 -04:00
|
|
|
int fd = open(fname, O_RDONLY+O_BINARY);
|
2008-04-22 17:09:24 +00:00
|
|
|
assert(fd>=0);
|
2013-04-16 23:57:38 -04:00
|
|
|
r = toku_commit_fileentries(fd, txn, yield, yieldv);
|
2008-04-22 17:09:24 +00:00
|
|
|
assert(r==0);
|
|
|
|
r = close(fd);
|
|
|
|
assert(r==0);
|
|
|
|
unlink(fname);
|
2013-04-16 23:57:33 -04:00
|
|
|
toku_free(fname);
|
2008-04-22 17:09:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
int
|
|
|
|
toku_rollback_rollinclude (BYTESTRING bs,
|
|
|
|
TOKUTXN txn,
|
|
|
|
YIELDF yield,
|
|
|
|
void * yieldv)
|
|
|
|
{
|
2008-04-22 17:09:24 +00:00
|
|
|
int r;
|
|
|
|
char *fname = fixup_fname(&bs);
|
2013-04-16 23:57:27 -04:00
|
|
|
int fd = open(fname, O_RDONLY+O_BINARY);
|
2008-04-22 17:09:24 +00:00
|
|
|
assert(fd>=0);
|
2013-04-16 23:57:38 -04:00
|
|
|
r = toku_rollback_fileentries(fd, txn, yield, yieldv);
|
2008-04-22 17:09:24 +00:00
|
|
|
assert(r==0);
|
|
|
|
r = close(fd);
|
|
|
|
assert(r==0);
|
|
|
|
unlink(fname);
|
2013-04-16 23:57:33 -04:00
|
|
|
toku_free(fname);
|
2008-04-22 17:09:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2013-04-16 23:57:38 -04:00
|
|
|
|
|
|
|
int
|
|
|
|
toku_rollback_tablelock_on_empty_table (FILENUM filenum, TOKUTXN txn, YIELDF UU(yield), void* UU(yield_v))
|
|
|
|
{
|
|
|
|
// on rollback we have to make the file be empty, since we locked an empty table, and then may have done things to it.
|
|
|
|
|
|
|
|
CACHEFILE cf;
|
|
|
|
//printf("%s:%d committing insert %s %s\n", __FILE__, __LINE__, key.data, data.data);
|
|
|
|
int r = toku_cachefile_of_filenum(txn->logger->ct, filenum, &cf);
|
|
|
|
assert(r==0);
|
|
|
|
|
|
|
|
OMTVALUE brtv=NULL;
|
|
|
|
r = toku_omt_find_zero(txn->open_brts, find_brt_from_filenum, &filenum, &brtv, NULL, NULL);
|
2013-04-16 23:57:40 -04:00
|
|
|
if (r==0) {
|
|
|
|
// If r!=0 it could be because we grabbed a log on an empty table that doesn't even exist, and we never put anything into it.
|
|
|
|
// So, just don't do anything in this case.
|
|
|
|
BRT brt = brtv;
|
|
|
|
r = toku_brt_truncate(brt);
|
|
|
|
assert(r==0);
|
|
|
|
}
|
2013-04-16 23:57:38 -04:00
|
|
|
|
2013-04-16 23:57:38 -04:00
|
|
|
return toku_cachefile_close(&cf, toku_txn_logger(txn), 0);
|
2013-04-16 23:57:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
toku_commit_tablelock_on_empty_table (FILENUM filenum, TOKUTXN txn, YIELDF UU(yield), void* UU(yield_v))
|
|
|
|
{
|
|
|
|
return do_nothing_with_filenum(txn, filenum);
|
|
|
|
}
|