Commit 9eea3a86 authored by Dave Wells's avatar Dave Wells Committed by Yoni Fogel

logcursor changes, fix LSNs, make progress on tests [t:1926]

git-svn-id: file:///svn/toku/tokudb@13970 c7de825b-a66e-492c-adef-691d508d4ae1
parent a03138ef
......@@ -141,6 +141,7 @@ static inline int toku_logsizeof_BYTESTRING (BYTESTRING bs) {
return 4+bs.len;
}
#if 0
static inline int toku_logsizeof_LOGGEDBRTHEADER (LOGGEDBRTHEADER bs) {
int in_both = 4+4+4+8+8+4+8;
in_both += 8; // for the number of block headers
......@@ -152,6 +153,7 @@ static inline int toku_logsizeof_LOGGEDBRTHEADER (LOGGEDBRTHEADER bs) {
static inline int toku_logsizeof_INTPAIRARRAY (INTPAIRARRAY pa) {
return 4+(4+4)*pa.size;
}
#endif
static inline char *fixup_fname(BYTESTRING *f) {
assert(f->len>0);
......
......@@ -5,8 +5,10 @@
#include "includes.h"
enum lc_direction { LC_FORWARD, LC_BACKWARD, LC_FIRST, LC_LAST };
struct toku_logcursor {
char *logdir;
char *logdir; // absolute directory name
char **logfiles;
int n_logfiles;
int cur_logfiles_index;
......@@ -14,8 +16,27 @@ struct toku_logcursor {
BOOL is_open;
struct log_entry entry;
BOOL entry_valid;
LSN cur_lsn;
enum lc_direction last_direction;
};
#define LC_LSN_ERROR (-1)
static void lc_print_logcursor (TOKULOGCURSOR lc) __attribute__((unused));
static void lc_print_logcursor (TOKULOGCURSOR lc) {
printf("lc = %p\n", lc);
printf(" logdir = %s\n", lc->logdir);
printf(" logfiles = %p\n", lc->logfiles);
for (int lf=0;lf<lc->n_logfiles;lf++) {
printf(" logfile[%d] = %p (%s)\n", lf, lc->logfiles[lf], lc->logfiles[lf]);
}
printf(" n_logfiles = %d\n", lc->n_logfiles);
printf(" cur_logfiles_index = %d\n", lc->cur_logfiles_index);
printf(" cur_fp = %p\n", lc->cur_fp);
printf(" cur_lsn = %lu\n", lc->cur_lsn.lsn);
printf(" last_direction = %d\n", lc->last_direction);
}
static int lc_close_cur_logfile(TOKULOGCURSOR lc) {
int r=0;
if ( lc->is_open ) {
......@@ -28,6 +49,7 @@ static int lc_close_cur_logfile(TOKULOGCURSOR lc) {
static int lc_open_logfile(TOKULOGCURSOR lc, int index) {
int r=0;
assert( !lc->is_open );
if( index == -1 || index >= lc->n_logfiles) return DB_NOTFOUND;
lc->cur_fp = fopen(lc->logfiles[index], "r");
if ( lc->cur_fp == NULL )
return DB_NOTFOUND;
......@@ -36,13 +58,25 @@ static int lc_open_logfile(TOKULOGCURSOR lc, int index) {
r = toku_read_logmagic(lc->cur_fp, &version);
if (r!=0)
return DB_BADFORMAT;
if (version != 1)
if (version != TOKU_LOG_VERSION)
return DB_BADFORMAT;
// mark as open
lc->is_open = TRUE;
return r;
}
static int lc_check_lsn(TOKULOGCURSOR lc, int dir) {
int r=0;
LSN lsn = toku_log_entry_get_lsn(&(lc->entry));
if (((dir == LC_FORWARD) && ( lsn.lsn != lc->cur_lsn.lsn + 1 )) ||
((dir == LC_BACKWARD) && ( lsn.lsn != lc->cur_lsn.lsn - 1 ))) {
fprintf(stderr, "Bad LSN : direction = %d, lsn.lsn = %"PRIu64", cur_lsn.lsn=%"PRIu64"\n", dir, lsn.lsn, lc->cur_lsn.lsn);
return LC_LSN_ERROR;
}
lc->cur_lsn.lsn = lsn.lsn;
return r;
}
// toku_logcursor_create()
// - returns a pointer to a logcursor
int toku_logcursor_create(TOKULOGCURSOR *lc, const char *log_dir) {
......@@ -51,16 +85,38 @@ int toku_logcursor_create(TOKULOGCURSOR *lc, const char *log_dir) {
// malloc a cursor
TOKULOGCURSOR cursor = (TOKULOGCURSOR) toku_malloc(sizeof(struct toku_logcursor));
if ( NULL==cursor )
return ENOMEM;
if ( cursor == NULL ) {
failresult = ENOMEM;
goto fail;
}
// find logfiles in logdir
cursor->is_open = FALSE;
cursor->cur_logfiles_index = 0;
cursor->entry_valid = FALSE;
cursor->logdir = (char *) toku_malloc(strlen(log_dir)+1);
if ( NULL==cursor->logdir )
return ENOMEM;
strcpy(cursor->logdir, log_dir);
// cursor->logdir must be an absolute path
if ( log_dir[0]=='/' ) {
cursor->logdir = (char *) toku_malloc(strlen(log_dir)+1);
if ( cursor->logdir == NULL ) {
failresult = ENOMEM;
goto fail;
}
sprintf(cursor->logdir, "%s", log_dir);
}
else {
char *cwd = getcwd(NULL, 0);
if ( cwd == NULL ) {
failresult = -1;
goto fail;
}
cursor->logdir = (char *) toku_malloc(strlen(cwd)+strlen(log_dir)+2);
if ( cursor->logdir == NULL ) {
toku_free(cwd);
failresult = ENOMEM;
goto fail;
}
sprintf(cursor->logdir, "%s/%s", cwd, log_dir);
toku_free(cwd);
}
cursor->logfiles = NULL;
cursor->n_logfiles = 0;
r = toku_logger_find_logfiles(cursor->logdir, &(cursor->logfiles), &(cursor->n_logfiles));
......@@ -68,6 +124,8 @@ int toku_logcursor_create(TOKULOGCURSOR *lc, const char *log_dir) {
failresult=r;
goto fail;
}
cursor->cur_lsn.lsn=0;
cursor->last_direction=LC_FIRST;
*lc = cursor;
return r;
fail:
......@@ -76,6 +134,50 @@ int toku_logcursor_create(TOKULOGCURSOR *lc, const char *log_dir) {
return failresult;
}
int toku_logcursor_create_for_file(TOKULOGCURSOR *lc, const char *log_dir, const char *log_file) {
int r=0;
int failresult=0;
TOKULOGCURSOR cursor;
r = toku_logcursor_create(&cursor, log_dir);
if (r!=0)
return r;
int idx;
int found_it=0;
int fullnamelen = strlen(cursor->logdir) + strlen(log_file) + 3;
char *log_file_fullname = toku_malloc(fullnamelen);
if ( log_file_fullname == NULL ) {
failresult = ENOMEM;
goto fail;
}
sprintf(log_file_fullname, "%s/%s", cursor->logdir, log_file);
for(idx=0;idx<cursor->n_logfiles;idx++) {
if ( strcmp(log_file_fullname, cursor->logfiles[idx]) == 0 ) {
found_it = 1;
break;
}
}
if (found_it==0) {
failresult = DB_NOTFOUND;
goto fail;
}
// replace old logfile structure with single file version
int lf;
for(lf=0;lf<cursor->n_logfiles;lf++) {
toku_free(cursor->logfiles[lf]);
}
cursor->n_logfiles=1;
cursor->logfiles[0] = log_file_fullname;
*lc = cursor;
return r;
fail:
toku_free(log_file_fullname);
toku_logcursor_destroy(&cursor);
*lc = NULL;
return failresult;
}
int toku_logcursor_destroy(TOKULOGCURSOR *lc) {
int r=0;
if ( (*lc)->entry_valid ) {
......@@ -99,7 +201,13 @@ int toku_logcursor_next(TOKULOGCURSOR lc, struct log_entry **le) {
if ( lc->entry_valid ) {
toku_log_free_log_entry_resources(&(lc->entry));
lc->entry_valid = FALSE;
} else if ( !lc->entry_valid ) {
if (lc->last_direction == LC_BACKWARD) {
struct log_entry junk;
r = toku_log_fread(lc->cur_fp, &junk);
assert(r == 0);
toku_log_free_log_entry_resources(&junk);
}
} else {
r = toku_logcursor_first(lc, le);
return r;
}
......@@ -126,6 +234,10 @@ int toku_logcursor_next(TOKULOGCURSOR lc, struct log_entry **le) {
return r;
}
}
r = lc_check_lsn(lc, LC_FORWARD);
if (r!=0)
return r;
lc->last_direction = LC_FORWARD;
lc->entry_valid = TRUE;
*le = &(lc->entry);
return r;
......@@ -136,7 +248,13 @@ int toku_logcursor_prev(TOKULOGCURSOR lc, struct log_entry **le) {
if ( lc->entry_valid ) {
toku_log_free_log_entry_resources(&(lc->entry));
lc->entry_valid = FALSE;
} else if ( !lc->entry_valid ) {
if (lc->last_direction == LC_FORWARD) {
struct log_entry junk;
r = toku_log_fread_backward(lc->cur_fp, &junk);
assert(r == 0);
toku_log_free_log_entry_resources(&junk);
}
} else {
r = toku_logcursor_last(lc, le);
return r;
}
......@@ -163,6 +281,10 @@ int toku_logcursor_prev(TOKULOGCURSOR lc, struct log_entry **le) {
return r;
}
}
r = lc_check_lsn(lc, LC_BACKWARD);
if (r!=0)
return r;
lc->last_direction = LC_BACKWARD;
lc->entry_valid = TRUE;
*le = &(lc->entry);
return r;
......@@ -188,6 +310,10 @@ int toku_logcursor_first(TOKULOGCURSOR lc, struct log_entry **le) {
r = toku_log_fread(lc->cur_fp, &(lc->entry));
if (r!=0)
return r;
r = lc_check_lsn(lc, LC_FIRST);
if (r!=0)
return r;
lc->last_direction = LC_FIRST;
lc->entry_valid = TRUE;
*le = &(lc->entry);
return r;
......@@ -217,6 +343,10 @@ int toku_logcursor_last(TOKULOGCURSOR lc, struct log_entry **le) {
r = toku_log_fread_backward(lc->cur_fp, &(lc->entry));
if (r!=0)
return r;
r = lc_check_lsn(lc, LC_LAST);
if (r!=0)
return r;
lc->last_direction = LC_LAST;
lc->entry_valid = TRUE;
*le = &(lc->entry);
return r;
......
......@@ -13,11 +13,14 @@ typedef struct toku_logcursor *TOKULOGCURSOR;
// All routines return 0 on success
// toku_logcursor_create()
// - returns a pointer to a logcursor
// - creates a logcursor (lc)
// - following toku_logcursor_create()
// if toku_logcursor_next() is called, it returns the first entry in the log
// if toku_logcursor_prev() is called, it returns the last entry in the log
int toku_logcursor_create(TOKULOGCURSOR *lc, const char *log_dir);
// toku_logcursor_create_for_file()
// - creates a logcusor (lc) that only knows about the file log_file
int toku_logcursor_create_for_file(TOKULOGCURSOR *lc, const char *log_dir, const char *log_file);
// toku_logcursor_destroy()
// - frees all resources associated with the logcursor, including the log_entry
// associated with the latest cursor action
......
......@@ -48,7 +48,25 @@ int toku_logger_create (TOKULOGGER *resultp) {
int toku_logger_open (const char *directory, TOKULOGGER logger) {
if (logger->is_open) return EINVAL;
if (logger->is_panicked) return EINVAL;
int r;
TOKULOGCURSOR logcursor;
struct log_entry *le;
logger->lsn.lsn=0;
// In searching existing logfiles for last LSN, have chosen to
// ignore errors that may occur. In the event of a return error,
// revert to using LSN=0
r = toku_logcursor_create(&logcursor, directory);
if (r==0) {
r = toku_logcursor_last(logcursor, &le);
if (r==0)
logger->lsn = toku_log_entry_get_lsn(le);
toku_logcursor_destroy(&logcursor);
}
//printf("starting after LSN=%lu\n", logger->lsn.lsn);
logger->written_lsn = logger->lsn;
logger->fsynced_lsn = logger->lsn;
long long nexti;
r = toku_logger_find_next_unused_log_file(directory, &nexti);
if (r!=0) return r;
......@@ -57,10 +75,6 @@ int toku_logger_open (const char *directory, TOKULOGGER logger) {
logger->next_log_file_number = nexti;
open_logfile(logger);
logger->lsn.lsn = 0; // WRONG!!! This should actually be calculated by looking at the log file.
logger->written_lsn.lsn = 0;
logger->fsynced_lsn.lsn = 0;
logger->is_open = 1;
if (!logger->write_log_files)
toku_set_func_fsync(toku_logger_fsync_null);
......
This diff is collapsed.
......@@ -83,7 +83,8 @@ REGRESSION_TESTS_RAW = \
log-test5 \
log-test6 \
log-test7 \
log-test-timestamp \
logcursor-timestamp \
logcursor-empty-logdir \
memtest \
minicron-test \
omt-cursor-test \
......@@ -97,6 +98,7 @@ REGRESSION_TESTS_RAW = \
test-inc-split \
test-leafentry10 \
test-leafentry-nested \
test_logcursor \
test_oexcl \
test_toku_malloc_plain_free \
threadpool-test \
......
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved."
#include "test.h"
#include "includes.h"
#define dname __FILE__ ".dir"
#define rmrf "rm -rf " dname "/"
// a logcursor in an empty directory should not find any log entries
int
test_main (int argc, const char *argv[]) {
default_parse_args(argc, argv);
int r;
system(rmrf);
r = toku_os_mkdir(dname, S_IRWXU); assert(r==0);
// verify the log is empty
TOKULOGCURSOR lc = NULL;
struct log_entry *le;
r = toku_logcursor_create(&lc, dname);
assert(r == 0 && lc != NULL);
r = toku_logcursor_next(lc, &le);
assert(r != 0);
r = toku_logcursor_prev(lc, &le);
assert(r != 0);
r = toku_logcursor_destroy(&lc);
assert(r == 0 && lc == NULL);
return 0;
}
......@@ -19,8 +19,9 @@ static u_int64_t now(void) {
// a cursor through the log entries
int
test_main (int argc __attribute__((__unused__)),
const char *argv[] __attribute__((__unused__))) {
test_main (int argc, const char *argv[]) {
default_parse_args(argc, argv);
int r;
system(rmrf);
r = toku_os_mkdir(dname, S_IRWXU); assert(r==0);
......@@ -48,12 +49,13 @@ test_main (int argc __attribute__((__unused__)),
r = toku_logger_close(&logger);
assert(r == 0);
// TODO verify the log
// verify the log forwards
TOKULOGCURSOR lc = NULL;
struct log_entry *le;
r = toku_logcursor_create(&lc, dname);
assert(r == 0 && lc != NULL);
struct log_entry *le;
r = toku_logcursor_next(lc, &le);
assert(r == 0 && le->cmd == LT_timestamp);
assert(le->u.timestamp.comment.len == 5 && memcmp(le->u.timestamp.comment.data, "hello", 5) == 0);
......@@ -62,7 +64,9 @@ test_main (int argc __attribute__((__unused__)),
r = toku_logcursor_next(lc, &le);
assert(r == 0 && le->cmd == LT_timestamp);
assert(le->u.timestamp.comment.len == 5 && memcmp(le->u.timestamp.comment.data, "world", 5) == 0);
printf("%"PRId64"\n", le->u.timestamp.timestamp - t);
if (verbose)
printf("%"PRId64"\n", le->u.timestamp.timestamp - t);
assert(le->u.timestamp.timestamp - t >= 10*1000000);
r = toku_logcursor_next(lc, &le);
assert(r != 0);
......@@ -70,5 +74,27 @@ test_main (int argc __attribute__((__unused__)),
r = toku_logcursor_destroy(&lc);
assert(r == 0 && lc == NULL);
// verify the log backwards
r = toku_logcursor_create(&lc, dname);
assert(r == 0 && lc != NULL);
r = toku_logcursor_prev(lc, &le);
assert(r == 0 && le->cmd == LT_timestamp);
assert(le->u.timestamp.comment.len == 5 && memcmp(le->u.timestamp.comment.data, "world", 5) == 0);
t = le->u.timestamp.timestamp;
r = toku_logcursor_prev(lc, &le);
assert(r == 0 && le->cmd == LT_timestamp);
assert(le->u.timestamp.comment.len == 5 && memcmp(le->u.timestamp.comment.data, "hello", 5) == 0);
if (verbose)
printf("%"PRId64"\n", t - le->u.timestamp.timestamp);
assert(t - le->u.timestamp.timestamp >= 10*1000000);
r = toku_logcursor_prev(lc, &le);
assert(r != 0);
r = toku_logcursor_destroy(&lc);
assert(r == 0 && lc == NULL);
return 0;
}
......@@ -6,50 +6,116 @@
#include "includes.h"
int test_0 ();
int test_1 ();
static void usage() {
printf("test_logcursors [OPTIONS]\n");
printf("[-v]\n");
printf("[-q]\n");
}
int test_main(int argc __attribute__((unused)), const char *argv[] __attribute__((unused))) {
int r = 0;
r = test_0();
int test_main(int argc, const char *argv[]) {
int i;
for (i=1; i<argc; i++) {
const char *arg = argv[i];
if (arg[0] != '-')
break;
if (strcmp(arg, "-v")==0) {
verbose++;
} else if (strcmp(arg, "-q")==0) {
verbose = 0;
} else {
usage();
return 1;
}
}
return r
int r = 0;
if ( (r=test_0()) !=0 ) return r;
if ( (r=test_1()) !=0 ) return r;
return r;
}
int test_0 () {
int r=0;
char dbdir[100] = "./dir.test_logcursor.tdb";
char dbdir[100] = "./dir.test_logcursor";
struct toku_logcursor *cursor;
struct log_entry *entry;
r = toku_logcursor_create(&cursor, dbdir);
if ( r!=0 ) return r;
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
printf("r=%d\n", r);
r = toku_logcursor_destroy(&cursor);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir);
if ( r!=0 ) return r;
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
printf("r=%d\n", r);
r = toku_logcursor_destroy(&cursor);
r = toku_logcursor_create(&cursor, dbdir);
if ( r!=0 ) return r;
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_next(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
r = toku_logcursor_prev(cursor, &entry); printf("Entry = %c\n", entry->cmd);
if ( r == DB_NOTFOUND ) printf("PASS\n"); else printf("FAIL\n");
r = toku_logcursor_destroy(&cursor);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_first(cursor, &entry); if (verbose) printf("First Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_last(cursor, &entry); if (verbose) printf("Last Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); assert(r==DB_NOTFOUND);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); assert(r==DB_NOTFOUND);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
r = toku_logcursor_create(&cursor, dbdir); if (verbose) printf("create returns %d\n", r); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_next(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd); assert(r==0);
r = toku_logcursor_prev(cursor, &entry); if (verbose) printf("Entry = %c\n", entry->cmd);
if ( verbose) {
if ( r == DB_NOTFOUND ) printf("PASS\n");
else printf("FAIL\n");
}
assert(r==DB_NOTFOUND);
r = toku_logcursor_destroy(&cursor); if (verbose) printf("destroy returns %d\n", r); assert(r==0);
return 0;
}
// test per-file version
int test_1 () {
int r=0;
char dbdir[100] = "./dir.test_logcursor";
char logfile[100] = "log000000000000.tokulog";
struct toku_logcursor *cursor;
struct log_entry *entry;
r = toku_logcursor_create_for_file(&cursor, dbdir, logfile);
if (verbose) printf("create returns %d\n", r);
assert(r==0);
r = toku_logcursor_last(cursor, &entry);
if (verbose) printf("entry = %c\n", entry->cmd);
assert(r==0);
assert(entry->cmd =='C');
r = toku_logcursor_destroy(&cursor);
if (verbose) printf("destroy returns %d\n", r);
assert(r==0);
return 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