Commit 06dfd4f0 authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

Work on transactions rollback. Also Fixes #254. Addresess #253.

git-svn-id: file:///svn/tokudb@1572 c7de825b-a66e-492c-adef-691d508d4ae1
parent 12c0d219
......@@ -27,7 +27,7 @@ void test_env_exceptions (void) {
DbEnv env(0);
TC(env.open(".", DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0777), 0);
DbTxn *txn;
TC(env.txn_begin(0, &txn, 0), EINVAL); // not configured for transations
TC(env.txn_begin(0, &txn, 0), EINVAL); // not configured for transactions
}
{
DbEnv env(0);
......
......@@ -44,7 +44,7 @@ typedef struct loggedbrtheader {
u_int32_t nodesize;
DISKOFF freelist;
DISKOFF unused_memory;
u_int32_t n_named_roots;
u_int32_t n_named_roots; // -1 for the union below to be "one".
union {
struct {
char **names;
......
......@@ -91,6 +91,8 @@ int toku_logger_open (const char *directory, TOKULOGGER logger) {
logger->lsn.lsn = 0; // WRONG!!! This should actually be calculated by looking at the log file.
logger->is_open = 1;
return toku_logger_log_bytes(logger, 0, "");
}
......@@ -102,6 +104,10 @@ int toku_logger_panicked(TOKULOGGER logger) {
if (logger==0) return 0;
return logger->is_panicked;
}
int toku_logger_is_open(TOKULOGGER logger) {
if (logger==0) return 0;
return logger->is_open;
}
static int log_format_version=0;
......@@ -291,6 +297,7 @@ int toku_logger_txn_begin (TOKUTXN parent_tokutxn, TOKUTXN *tokutxn, TXNID txnid
result->txnid64 = txnid64;
result->logger = logger;
result->parent = parent_tokutxn;
result->oldest_logentry = result->newest_logentry = 0;
*tokutxn = result;
return 0;
}
......
......@@ -6,6 +6,8 @@
#include "../include/db.h"
#include "brttypes.h"
#include "kv-pair.h"
#include <errno.h>
int toku_logger_create(TOKULOGGER */*resultp*/);
int toku_logger_open(const char */*directory*/, TOKULOGGER);
int toku_logger_log_bytes(TOKULOGGER logger, int nbytes, void *bytes);
......@@ -13,6 +15,7 @@ int toku_logger_close(TOKULOGGER *logger);
int toku_logger_log_checkpoint (TOKULOGGER, LSN*);
void toku_logger_panic(TOKULOGGER, int/*err*/);
int toku_logger_panicked(TOKULOGGER /*logger*/);
int toku_logger_is_open(TOKULOGGER);
int toku_logger_log_phys_add_or_delete_in_leaf (DB *db, TOKUTXN txn, DISKOFF diskoff, int is_add, const struct kv_pair *pair);
......@@ -62,4 +65,70 @@ int toku_read_and_print_logmagic (FILE *f, u_int32_t *version);
TXNID toku_txn_get_txnid (TOKUTXN);
LSN toku_txn_get_last_lsn (TOKUTXN);
static inline int toku_copy_FILENUM(FILENUM *target, FILENUM val) { *target = val; return 0; }
static inline void toku_free_FILENUM(FILENUM val __attribute__((__unused__))) {}
static inline int toku_copy_DISKOFF(DISKOFF *target, DISKOFF val) { *target = val; return 0; }
static inline void toku_free_DISKOFF(DISKOFF val __attribute__((__unused__))) {}
static inline int toku_copy_TXNID(TXNID *target, TXNID val) { *target = val; return 0; }
static inline void toku_free_TXNID(TXNID val __attribute__((__unused__))) {}
static inline int toku_copy_u_int8_t(u_int8_t *target, u_int8_t val) { *target = val; return 0; }
static inline void toku_free_u_int8_t(u_int8_t val __attribute__((__unused__))) {}
static inline int toku_copy_u_int32_t(u_int32_t *target, u_int32_t val) { *target = val; return 0; }
static inline void toku_free_u_int32_t(u_int32_t val __attribute__((__unused__))) {}
static inline int toku_copy_INTPAIRARRAY(INTPAIRARRAY *target, INTPAIRARRAY val) {
target->size = val.size;
target->array = toku_memdup(val.array, val.size*sizeof(val.array[0]));
if (target->array==0) return errno;
return 0;
}
static inline void toku_free_INTPAIRARRAY(INTPAIRARRAY val) {
toku_free(val.array);
}
static inline int toku_copy_BYTESTRING(BYTESTRING *target, BYTESTRING val) {
target->len = val.len;
target->data = toku_memdup(val.data, val.len);
if (target->data==0) return errno;
return 0;
}
static inline void toku_free_BYTESTRING(BYTESTRING val) {
toku_free(val.data);
}
static inline int toku_copy_LOGGEDBRTHEADER(LOGGEDBRTHEADER *target, LOGGEDBRTHEADER val) {
*target = val;
if ((int32_t)val.n_named_roots!=-1) {
int r;
target->u.many.names = toku_memdup(target->u.many.names, val.n_named_roots*sizeof(target->u.many.names[0]));
if (target->u.many.names==0) { r=errno; if (0) { died0: toku_free(target->u.many.names); } return r; }
target->u.many.roots = toku_memdup(target->u.many.roots, val.n_named_roots*sizeof(target->u.many.roots[0]));
if (target->u.many.roots==0) { r=errno; if (0) { died1: toku_free(target->u.many.names); } goto died0; }
u_int32_t i;
for (i=0; i<val.n_named_roots; i++) {
target->u.many.names[i] = toku_strdup(target->u.many.names[i]);
if (target->u.many.names[i]==0) {
u_int32_t j;
r=errno;
for (j=0; j<i; j++) toku_free(target->u.many.names[j]);
goto died1;
}
}
}
return 0;
}
static inline void toku_free_LOGGEDBRTHEADER(LOGGEDBRTHEADER val) {
if ((int32_t)val.n_named_roots==-1) return;
u_int32_t i;
for (i=0; i<val.n_named_roots; i++) {
toku_free(val.u.many.names[i]);
}
toku_free(val.u.many.names);
toku_free(val.u.many.roots);
}
#endif
......@@ -197,6 +197,22 @@ void generate_log_writer (void) {
fprintf(cf, " }\n");
fprintf(cf, " return 0;\n");
} else {
int i=0;
fprintf(cf, " struct log_entry *MALLOC(lentry);\n");
fprintf(cf, " if (lentry==0) return errno;\n");
fprintf(cf, " if (0) { died0: toku_free(lentry); return r; }\n");
fprintf(cf, " lentry->cmd = %d;\n", lt->command);
DO_FIELDS(ft, lt,
({
fprintf(cf, " r=toku_copy_%s(&lentry->u.%s.%s, %s);\n", ft->type, lt->name, ft->name, ft->name);
fprintf(cf, " if (r!=0) { if(0) { died%d: toku_free_%s(lentry->u.%s.%s); } goto died%d; }\n", i+1, ft->type, lt->name, ft->name, i);
i++;
}));
fprintf(cf, " if (0) { goto died%d; }\n", i); // Need to use that label.
fprintf(cf, " lentry->next = 0;\n");
fprintf(cf, " if (txn->oldest_logentry==0) txn->oldest_logentry = lentry;\n");
fprintf(cf, " else txn->newest_logentry->next = lentry;\n");
fprintf(cf, " txn->newest_logentry = lentry;\n");
fprintf(cf, " return r;\n");
}
fprintf(cf, "}\n\n");
......
......@@ -700,7 +700,7 @@ static int toku_txn_abort(DB_TXN * txn) {
static int toku_txn_begin(DB_ENV * env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags) {
HANDLE_PANICKED_ENV(env);
if (!env->i->logger) return EINVAL;
if (!toku_logger_is_open(env->i->logger)) return do_error(env, EINVAL, "Environment does not have logging enabled\n");
flags=flags;
DB_TXN *MALLOC(result);
if (result == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment