2007-11-29 14:18:54 +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."
2007-11-29 14:18:54 +00:00
2007-11-23 18:27:50 +00:00
/* Recover an env. The logs are in argv[1]. The new database is created in the cwd. */
// Test:
// cd ../src/tests/tmpdir
// ../../../newbrt/recover ../dir.test_log2.c.tdb
2007-11-23 20:36:03 +00:00
# include "cachetable.h"
# include "key.h"
2008-04-25 13:45:55 +00:00
# include "brt-internal.h"
2008-02-08 03:17:38 +00:00
# include "log-internal.h"
# include "log_header.h"
# include "toku_assert.h"
2008-04-02 23:40:36 +00:00
# include "kv-pair.h"
2008-04-25 13:45:55 +00:00
2008-03-12 19:40:38 +00:00
2008-02-08 03:17:38 +00:00
# include <fcntl.h>
# include <stdlib.h>
2008-03-12 19:40:38 +00:00
# include <sys/file.h>
# include <sys/stat.h>
2008-02-08 03:17:38 +00:00
# include <unistd.h>
2007-11-23 20:36:03 +00:00
2008-04-07 01:30:25 +00:00
//#define DO_VERIFY_COUNTS
2008-03-14 19:14:31 +00:00
# ifdef DO_VERIFY_COUNTS
# define VERIFY_COUNTS(n) toku_verify_counts(n)
# else
# define VERIFY_COUNTS(n) ((void)0)
# endif
static DB * const null_db = 0 ;
// These data structures really should be part of a recovery data structure. Recovery could be multithreaded (on different environments...) But this is OK since recovery can only happen in one
static CACHETABLE ct ;
static struct cf_pair {
FILENUM filenum ;
CACHEFILE cf ;
BRT brt ; // set to zero on an fopen, but filled in when an fheader is seen.
} * cf_pairs ;
2013-04-16 23:57:20 -04:00
static int n_cf_pairs = 0 , max_cf_pairs = 0 ;
2008-03-14 19:14:31 +00:00
int toku_recover_init ( void ) {
int r = toku_create_cachetable ( & ct , 1 < < 25 , ( LSN ) { 0 } , 0 ) ;
return r ;
}
void toku_recover_cleanup ( void ) {
int i ;
for ( i = 0 ; i < n_cf_pairs ; i + + ) {
if ( cf_pairs [ i ] . brt ) {
2008-04-17 03:11:55 +00:00
int r = toku_close_brt ( cf_pairs [ i ] . brt , 0 ) ;
2008-03-14 19:14:31 +00:00
//r = toku_cachefile_close(&cf_pairs[i].cf);
assert ( r = = 0 ) ;
}
}
toku_free ( cf_pairs ) ;
{
int r = toku_cachetable_close ( & ct ) ;
assert ( r = = 0 ) ;
}
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_commit ( LSN UU ( lsn ) , TXNID UU ( txnid ) ) {
2008-03-14 19:14:31 +00:00
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_xabort ( LSN UU ( lsn ) , TXNID UU ( txnid ) ) {
2008-04-21 04:22:45 +00:00
}
2008-03-14 19:14:31 +00:00
2013-04-16 23:57:20 -04:00
static void
create_dir_from_file ( const char * fname ) {
2008-04-18 14:45:04 +00:00
int i ;
char * tmp = toku_strdup ( fname ) ;
char ch ;
for ( i = 0 ; ( ch = fname [ i ] ) ; i + + ) {
if ( ch = = ' / ' ) {
if ( i > 0 ) {
tmp [ i ] = 0 ;
mode_t oldu = umask ( 0 ) ;
int r = mkdir ( tmp , 0700 ) ;
if ( r ! = 0 & & errno ! = EEXIST ) {
printf ( " error: %s \n " , strerror ( errno ) ) ;
}
assert ( r = = 0 | | ( errno = = EEXIST ) ) ;
umask ( oldu ) ;
tmp [ i ] = ch ;
}
}
}
toku_free ( tmp ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_fcreate ( LSN UU ( lsn ) , TXNID UU ( txnid ) , BYTESTRING fname , u_int32_t mode ) {
2008-03-14 19:14:31 +00:00
char * fixed_fname = fixup_fname ( & fname ) ;
2008-04-18 14:45:04 +00:00
create_dir_from_file ( fixed_fname ) ;
2008-03-14 19:14:31 +00:00
int fd = creat ( fixed_fname , mode ) ;
assert ( fd > = 0 ) ;
toku_free ( fixed_fname ) ;
toku_free_BYTESTRING ( fname ) ;
}
2013-04-16 23:57:20 -04:00
static int
toku_recover_note_cachefile ( FILENUM fnum , CACHEFILE cf , BRT brt ) {
2008-03-14 19:14:31 +00:00
if ( max_cf_pairs = = 0 ) {
n_cf_pairs = 1 ;
max_cf_pairs = 2 ;
MALLOC_N ( max_cf_pairs , cf_pairs ) ;
if ( cf_pairs = = 0 ) return errno ;
} else {
if ( n_cf_pairs > = max_cf_pairs ) {
max_cf_pairs * = 2 ;
cf_pairs = toku_realloc ( cf_pairs , max_cf_pairs * sizeof ( * cf_pairs ) ) ;
}
n_cf_pairs + + ;
}
cf_pairs [ n_cf_pairs - 1 ] . filenum = fnum ;
cf_pairs [ n_cf_pairs - 1 ] . cf = cf ;
cf_pairs [ n_cf_pairs - 1 ] . brt = brt ;
return 0 ;
}
static int find_cachefile ( FILENUM fnum , struct cf_pair * * cf_pair ) {
int i ;
for ( i = 0 ; i < n_cf_pairs ; i + + ) {
if ( fnum . fileid = = cf_pairs [ i ] . filenum . fileid ) {
* cf_pair = cf_pairs + i ;
return 0 ;
}
}
return 1 ;
}
static void toku_recover_fheader ( LSN UU ( lsn ) , TXNID UU ( txnid ) , FILENUM filenum , LOGGEDBRTHEADER header ) {
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
struct brt_header * MALLOC ( h ) ;
assert ( h ) ;
h - > dirty = 0 ;
2008-05-22 21:28:00 +00:00
h - > flags_array [ 0 ] = header . flags ;
2008-03-14 19:14:31 +00:00
h - > nodesize = header . nodesize ;
2013-04-16 23:57:18 -04:00
h - > free_blocks = header . free_blocks ;
h - > unused_blocks = header . unused_blocks ;
2008-03-14 19:14:31 +00:00
h - > n_named_roots = header . n_named_roots ;
2008-04-09 02:45:27 +00:00
r = toku_fifo_create ( & h - > fifo ) ;
assert ( r = = 0 ) ;
2008-03-14 19:14:31 +00:00
if ( ( signed ) header . n_named_roots = = - 1 ) {
2008-06-18 21:38:01 +00:00
MALLOC_N ( 1 , h - > roots ) ; assert ( h - > roots ) ;
MALLOC_N ( 1 , h - > root_hashes ) ; assert ( h - > root_hashes ) ;
2008-05-22 21:28:00 +00:00
h - > roots [ 0 ] = header . u . one . root ;
2008-06-18 21:38:01 +00:00
h - > root_hashes [ 0 ] . valid = FALSE ;
2008-03-14 19:14:31 +00:00
} else {
assert ( 0 ) ;
}
2013-04-16 23:57:18 -04:00
//toku_cachetable_put(pair->cf, header_blocknum, fullhash, h, 0, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
2008-03-14 19:14:31 +00:00
if ( pair - > brt ) {
2008-04-18 14:45:04 +00:00
toku_free ( pair - > brt - > h ) ;
2008-03-14 19:14:31 +00:00
} else {
2008-05-03 17:34:14 +00:00
r = toku_brt_create ( & pair - > brt ) ;
assert ( r = = 0 ) ;
2008-03-14 19:14:31 +00:00
pair - > brt - > cf = pair - > cf ;
pair - > brt - > database_name = 0 ; // Special case, we don't know or care what the database name is for recovery.
list_init ( & pair - > brt - > cursors ) ;
pair - > brt - > compare_fun = 0 ;
pair - > brt - > dup_compare = 0 ;
pair - > brt - > db = 0 ;
pair - > brt - > skey = pair - > brt - > sval = 0 ;
}
pair - > brt - > h = h ;
pair - > brt - > nodesize = h - > nodesize ;
pair - > brt - > flags = h - > nodesize ;
2013-04-16 23:57:18 -04:00
toku_cachefile_set_userdata ( pair - > cf , pair - > brt - > h , toku_brtheader_close ) ;
2008-03-14 19:14:31 +00:00
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_newbrtnode ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t height , u_int32_t nodesize , u_int8_t is_dup_sort , u_int32_t rand4fingerprint ) {
2008-03-14 19:14:31 +00:00
int r ;
struct cf_pair * pair = NULL ;
r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
TAGMALLOC ( BRTNODE , n ) ;
n - > nodesize = nodesize ;
2013-04-16 23:57:18 -04:00
n - > thisnodename = blocknum ;
2008-03-14 19:14:31 +00:00
n - > log_lsn = n - > disk_lsn = lsn ;
//printf("%s:%d %p->disk_lsn=%"PRId64"\n", __FILE__, __LINE__, n, n->disk_lsn.lsn);
2013-04-16 23:57:18 -04:00
n - > layout_version = BRT_LAYOUT_VERSION ;
2008-03-14 19:14:31 +00:00
n - > height = height ;
n - > rand4fingerprint = rand4fingerprint ;
n - > flags = is_dup_sort ? TOKU_DB_DUPSORT : 0 ; // Don't have TOKU_DB_DUP ???
n - > local_fingerprint = 0 ; // nothing there yet
n - > dirty = 1 ;
if ( height = = 0 ) {
2008-04-22 20:39:50 +00:00
r = toku_omt_create ( & n - > u . l . buffer ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
n - > u . l . n_bytes_in_buffer = 0 ;
2008-04-02 23:40:36 +00:00
{
2008-04-03 22:27:32 +00:00
u_int32_t mpsize = n - > nodesize + n - > nodesize / 4 ;
void * mp = toku_malloc ( mpsize ) ;
2008-04-02 23:40:36 +00:00
assert ( mp ) ;
2008-04-03 22:27:32 +00:00
toku_mempool_init ( & n - > u . l . buffer_mempool , mp , mpsize ) ;
2008-04-02 23:40:36 +00:00
}
2008-03-14 19:14:31 +00:00
} else {
n - > u . n . n_children = 0 ;
n - > u . n . totalchildkeylens = 0 ;
n - > u . n . n_bytes_in_buffers = 0 ;
MALLOC_N ( 3 , n - > u . n . childinfos ) ;
MALLOC_N ( 2 , n - > u . n . childkeys ) ;
}
// Now put it in the cachetable
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
2008-06-17 17:05:19 +00:00
n - > fullhash = fullhash ;
2013-04-16 23:57:18 -04:00
toku_cachetable_put ( pair - > cf , blocknum , fullhash , n , toku_serialize_brtnode_size ( n ) , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , 0 ) ;
2008-03-14 19:14:31 +00:00
VERIFY_COUNTS ( n ) ;
n - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , fullhash , 1 , toku_serialize_brtnode_size ( n ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:18 -04:00
static void recover_setup_node ( FILENUM filenum , BLOCKNUM blocknum , CACHEFILE * cf , BRTNODE * resultnode ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
assert ( pair - > brt ) ;
void * node_v ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash ,
2008-06-17 17:05:19 +00:00
& node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( fullhash = = node - > fullhash ) ;
2008-03-14 19:14:31 +00:00
* resultnode = node ;
* cf = pair - > cf ;
}
2008-05-02 14:38:35 +00:00
static void toku_recover_deqrootentry ( LSN lsn __attribute__ ( ( __unused__ ) ) , FILENUM filenum ) {
2008-04-09 02:45:27 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
//void *h_v;
//r = toku_cachetable_get_and_pin(pair->cf, header_blocknum, fullhash,
// &h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
struct brt_header * h = 0 ;
2008-04-09 02:45:27 +00:00
bytevec storedkey , storeddata ;
ITEMLEN storedkeylen , storeddatalen ;
TXNID storedxid ;
u_int32_t storedtype ;
r = toku_fifo_peek ( h - > fifo , & storedkey , & storedkeylen , & storeddata , & storeddatalen , & storedtype , & storedxid ) ;
assert ( r = = 0 ) ;
r = toku_fifo_deq ( h - > fifo ) ;
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
//r = toku_cachetable_unpin(pair->cf, header_blocknum, fullhash, 1, 0);
//assert(r==0);
2008-04-09 02:45:27 +00:00
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_enqrootentry ( LSN lsn __attribute__ ( ( __unused__ ) ) , FILENUM filenum , TXNID xid , u_int32_t typ , BYTESTRING key , BYTESTRING val ) {
2008-04-09 02:45:27 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * h_v ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , header_blocknum ) ;
2013-04-16 23:57:18 -04:00
if ( 0 ) {
//r = toku_cachetable_get_and_pin(pair->cf, header_blocknum, fullhash, &h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
} else {
h_v = 0 ;
assert ( 0 ) ;
}
2008-04-09 02:45:27 +00:00
assert ( r = = 0 ) ;
struct brt_header * h = h_v ;
r = toku_fifo_enq ( h - > fifo , key . data , key . len , val . data , val . len , typ , xid ) ;
assert ( r = = 0 ) ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , header_blocknum , fullhash , 1 , 0 ) ;
2008-04-09 02:45:27 +00:00
assert ( r = = 0 ) ;
toku_free ( key . data ) ;
toku_free ( val . data ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_brtdeq ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum ) {
2008-03-17 18:56:12 +00:00
CACHEFILE cf ;
BRTNODE node ;
int r ;
2013-04-16 23:57:18 -04:00
recover_setup_node ( filenum , blocknum , & cf , & node ) ;
2008-03-17 18:56:12 +00:00
assert ( node - > height > 0 ) ;
2008-03-18 10:19:41 +00:00
//printf("deq: %lld expected_old_fingerprint=%08x actual=%08x new=%08x\n", diskoff, oldfingerprint, node->local_fingerprint, newfingerprint);
2008-05-04 16:56:15 +00:00
bytevec actual_key = 0 , actual_data = 0 ;
ITEMLEN actual_keylen = 0 , actual_datalen = 0 ;
u_int32_t actual_type = 0 ;
TXNID actual_xid = 0 ;
2008-03-18 11:01:44 +00:00
assert ( childnum < ( u_int32_t ) node - > u . n . n_children ) ;
2008-03-18 10:19:41 +00:00
r = toku_fifo_peek ( BNC_BUFFER ( node , childnum ) , & actual_key , & actual_keylen , & actual_data , & actual_datalen , & actual_type , & actual_xid ) ;
2008-03-17 18:56:12 +00:00
assert ( r = = 0 ) ;
2008-05-02 14:38:35 +00:00
u_int32_t sizediff = actual_keylen + actual_datalen + KEY_VALUE_OVERHEAD + BRT_CMD_OVERHEAD ;
2008-07-27 22:16:49 +00:00
node - > local_fingerprint - = node - > rand4fingerprint * toku_calc_fingerprint_cmd ( actual_type , actual_xid , actual_key , actual_keylen , actual_data , actual_datalen ) ;
2008-03-17 18:56:12 +00:00
node - > log_lsn = lsn ;
2008-03-18 10:19:41 +00:00
node - > u . n . n_bytes_in_buffers - = sizediff ;
BNC_NBYTESINBUF ( node , childnum ) - = sizediff ;
r = toku_fifo_deq ( BNC_BUFFER ( node , childnum ) ) ; // don't deq till were' done looking at the data.
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-17 18:56:12 +00:00
assert ( r = = 0 ) ;
}
2008-03-14 19:14:31 +00:00
2013-04-16 23:57:20 -04:00
static void
toku_recover_brtenq ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , TXNID xid , u_int32_t typ , BYTESTRING key , BYTESTRING data ) {
2008-03-17 18:56:12 +00:00
CACHEFILE cf ;
BRTNODE node ;
int r ;
2013-04-16 23:57:18 -04:00
recover_setup_node ( filenum , blocknum , & cf , & node ) ;
2008-03-17 18:56:12 +00:00
assert ( node - > height > 0 ) ;
2013-04-16 23:57:18 -04:00
//printf("enq: %lld expected_old_fingerprint=%08x actual=%08x new=%08x\n", blocknum, oldfingerprint, node->local_fingerprint, newfingerprint);
2008-03-17 18:56:12 +00:00
r = toku_fifo_enq ( BNC_BUFFER ( node , childnum ) , key . data , key . len , data . data , data . len , typ , xid ) ;
assert ( r = = 0 ) ;
2008-07-27 22:16:49 +00:00
node - > local_fingerprint + = node - > rand4fingerprint * toku_calc_fingerprint_cmd ( typ , xid , key . data , key . len , data . data , data . len ) ;
2008-03-17 18:56:12 +00:00
node - > log_lsn = lsn ;
2008-03-18 10:19:41 +00:00
u_int32_t sizediff = key . len + data . len + KEY_VALUE_OVERHEAD + BRT_CMD_OVERHEAD ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-17 18:56:12 +00:00
assert ( r = = 0 ) ;
2008-03-18 10:19:41 +00:00
node - > u . n . n_bytes_in_buffers + = sizediff ;
BNC_NBYTESINBUF ( node , childnum ) + = sizediff ;
2008-03-17 18:56:12 +00:00
toku_free ( key . data ) ;
toku_free ( data . data ) ;
}
2008-03-14 19:14:31 +00:00
2013-04-16 23:57:20 -04:00
static void
toku_recover_addchild ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , BLOCKNUM child , u_int32_t childfingerprint ) {
2008-03-14 19:14:31 +00:00
CACHEFILE cf ;
BRTNODE node ;
2013-04-16 23:57:18 -04:00
recover_setup_node ( filenum , blocknum , & cf , & node ) ;
2008-03-14 19:14:31 +00:00
assert ( node - > height > 0 ) ;
assert ( childnum < = ( unsigned ) node - > u . n . n_children ) ;
unsigned int i ;
REALLOC_N ( node - > u . n . n_children + 1 , node - > u . n . childinfos ) ;
REALLOC_N ( node - > u . n . n_children , node - > u . n . childkeys ) ;
for ( i = node - > u . n . n_children ; i > childnum ; i - - ) {
node - > u . n . childinfos [ i ] = node - > u . n . childinfos [ i - 1 ] ;
BNC_NBYTESINBUF ( node , i ) = BNC_NBYTESINBUF ( node , i - 1 ) ;
assert ( i > = 2 ) ;
node - > u . n . childkeys [ i - 1 ] = node - > u . n . childkeys [ i - 2 ] ;
}
if ( childnum > 0 ) {
node - > u . n . childkeys [ childnum - 1 ] = 0 ;
}
2013-04-16 23:57:18 -04:00
BNC_BLOCKNUM ( node , childnum ) = child ;
2008-03-14 19:14:31 +00:00
BNC_SUBTREE_FINGERPRINT ( node , childnum ) = childfingerprint ;
2008-05-06 13:58:08 +00:00
BNC_SUBTREE_LEAFENTRY_ESTIMATE ( node , childnum ) = 0 ;
2008-03-14 19:14:31 +00:00
int r = toku_fifo_create ( & BNC_BUFFER ( node , childnum ) ) ; assert ( r = = 0 ) ;
BNC_NBYTESINBUF ( node , childnum ) = 0 ;
node - > u . n . n_children + + ;
node - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_delchild ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , BLOCKNUM child , u_int32_t childfingerprint , BYTESTRING pivotkey ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
assert ( node - > height > 0 ) ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-03-14 19:14:31 +00:00
assert ( childnum < ( unsigned ) node - > u . n . n_children ) ;
assert ( node - > u . n . childinfos [ childnum ] . subtree_fingerprint = = childfingerprint ) ;
2013-04-16 23:57:18 -04:00
assert ( BNC_BLOCKNUM ( node , childnum ) . b = = child . b ) ;
2008-03-14 19:14:31 +00:00
assert ( toku_fifo_n_entries ( BNC_BUFFER ( node , childnum ) ) = = 0 ) ;
assert ( BNC_NBYTESINBUF ( node , childnum ) = = 0 ) ;
assert ( node - > u . n . n_children > 2 ) ; // Must be at least two children.
u_int32_t i ;
assert ( childnum > 0 ) ;
node - > u . n . totalchildkeylens - = toku_brt_pivot_key_len ( pair - > brt , node - > u . n . childkeys [ childnum - 1 ] ) ;
toku_free ( ( void * ) node - > u . n . childkeys [ childnum - 1 ] ) ;
toku_fifo_free ( & BNC_BUFFER ( node , childnum ) ) ;
for ( i = childnum + 1 ; i < ( unsigned ) node - > u . n . n_children ; i + + ) {
node - > u . n . childinfos [ i - 1 ] = node - > u . n . childinfos [ i ] ;
BNC_NBYTESINBUF ( node , i - 1 ) = BNC_NBYTESINBUF ( node , i ) ;
node - > u . n . childkeys [ i - 2 ] = node - > u . n . childkeys [ i - 1 ] ;
}
node - > u . n . n_children - - ;
node - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
toku_free ( pivotkey . data ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_setchild ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , BLOCKNUM UU ( oldchild ) , BLOCKNUM newchild ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-03-14 19:14:31 +00:00
assert ( node - > height > 0 ) ;
assert ( childnum < ( unsigned ) node - > u . n . n_children ) ;
2013-04-16 23:57:18 -04:00
BNC_BLOCKNUM ( node , childnum ) = newchild ;
2008-03-14 19:14:31 +00:00
node - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_setpivot ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , BYTESTRING pivotkey ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-03-14 19:14:31 +00:00
assert ( node - > height > 0 ) ;
struct kv_pair * new_pivot = kv_pair_malloc ( pivotkey . data , pivotkey . len , 0 , 0 ) ;
node - > u . n . childkeys [ childnum ] = new_pivot ;
node - > u . n . totalchildkeylens + = toku_brt_pivot_key_len ( pair - > brt , node - > u . n . childkeys [ childnum ] ) ;
node - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
toku_free ( pivotkey . data ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_changechildfingerprint ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t childnum , u_int32_t UU ( oldfingerprint ) , u_int32_t newfingerprint ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-03-14 19:14:31 +00:00
assert ( node - > height > 0 ) ;
2008-03-17 14:24:01 +00:00
assert ( ( signed ) childnum < = node - > u . n . n_children ) ; // we allow the childnum to be one too large.
2008-03-14 19:14:31 +00:00
BNC_SUBTREE_FINGERPRINT ( node , childnum ) = newfingerprint ;
node - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_fopen ( LSN UU ( lsn ) , TXNID UU ( txnid ) , BYTESTRING fname , FILENUM filenum ) {
2008-03-14 19:14:31 +00:00
char * fixedfname = fixup_fname ( & fname ) ;
CACHEFILE cf ;
int fd = open ( fixedfname , O_RDWR , 0 ) ;
assert ( fd > = 0 ) ;
2008-05-04 16:56:15 +00:00
BRT brt = 0 ;
2008-05-03 17:34:14 +00:00
int r = toku_brt_create ( & brt ) ;
assert ( r = = 0 ) ;
2008-04-17 03:11:55 +00:00
brt - > fname = fixedfname ;
brt - > database_name = 0 ;
2008-03-14 19:14:31 +00:00
brt - > h = 0 ;
brt - > compare_fun = 0 ;
brt - > dup_compare = 0 ;
brt - > db = 0 ;
2008-05-03 17:34:14 +00:00
r = toku_cachetable_openfd ( & cf , ct , fd , fixedfname ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
brt - > skey = brt - > sval = 0 ;
brt - > cf = cf ;
toku_recover_note_cachefile ( filenum , cf , brt ) ;
toku_free_BYTESTRING ( fname ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_brtclose ( LSN UU ( lsn ) , BYTESTRING UU ( fname ) , FILENUM filenum ) {
2008-04-17 03:11:55 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
// Bump up the reference count
toku_cachefile_refup ( pair - > cf ) ;
r = toku_close_brt ( pair - > brt , 0 ) ;
assert ( r = = 0 ) ;
pair - > brt = 0 ;
toku_free_BYTESTRING ( fname ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_cfclose ( LSN UU ( lsn ) , BYTESTRING UU ( fname ) , FILENUM filenum ) {
2008-04-17 03:11:55 +00:00
int i ;
for ( i = 0 ; i < n_cf_pairs ; i + + ) {
if ( filenum . fileid = = cf_pairs [ i ] . filenum . fileid ) {
int r = toku_cachefile_close ( & cf_pairs [ i ] . cf , 0 ) ;
assert ( r = = 0 ) ;
cf_pairs [ i ] = cf_pairs [ n_cf_pairs - 1 ] ;
n_cf_pairs - - ;
break ;
}
}
toku_free_BYTESTRING ( fname ) ;
}
2008-04-25 13:45:55 +00:00
static int fill_buf ( OMTVALUE lev , u_int32_t idx , void * varray ) {
LEAFENTRY le = lev ;
2008-04-23 04:17:28 +00:00
LEAFENTRY * array = varray ;
array [ idx ] = le ;
return 0 ;
}
2008-04-22 20:39:50 +00:00
// The memory for the new node should have already been allocated.
2013-04-16 23:57:20 -04:00
static void
toku_recover_leafsplit ( LSN lsn , FILENUM filenum , BLOCKNUM old_blocknum , BLOCKNUM new_blocknum , u_int32_t old_n , u_int32_t new_n , u_int32_t new_node_size , u_int32_t new_rand4 , u_int8_t is_dup_sort ) {
2008-04-22 20:39:50 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
void * nodeA_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t oldn_fullhash = toku_cachetable_hash ( pair - > cf , old_blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , old_blocknum , oldn_fullhash , & nodeA_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-04-22 20:39:50 +00:00
assert ( r = = 0 ) ;
BRTNODE oldn = nodeA_v ;
2008-06-17 17:05:19 +00:00
assert ( oldn - > fullhash = = oldn_fullhash ) ;
2008-04-22 20:39:50 +00:00
assert ( oldn - > height = = 0 ) ;
TAGMALLOC ( BRTNODE , newn ) ;
2008-04-23 04:17:28 +00:00
assert ( newn ) ;
2013-04-16 23:57:18 -04:00
//printf("%s:%d leafsplit %p (%lld) %p (%lld)\n", __FILE__, __LINE__, oldn, old_blocknum, newn, new_blocknum);
2008-04-23 04:17:28 +00:00
2013-04-16 23:57:18 -04:00
newn - > fullhash = toku_cachetable_hash ( pair - > cf , new_blocknum ) ;
2008-04-22 20:39:50 +00:00
newn - > nodesize = new_node_size ;
2013-04-16 23:57:18 -04:00
newn - > thisnodename = new_blocknum ;
2008-04-22 20:39:50 +00:00
newn - > log_lsn = newn - > disk_lsn = lsn ;
//printf("%s:%d %p->disk_lsn=%"PRId64"\n", __FILE__, __LINE__, n, n->disk_lsn.lsn);
2013-04-16 23:57:18 -04:00
newn - > layout_version = BRT_LAYOUT_VERSION ;
2008-04-22 20:39:50 +00:00
newn - > height = 0 ;
newn - > rand4fingerprint = new_rand4 ;
newn - > flags = is_dup_sort ? TOKU_DB_DUPSORT : 0 ; // Don't have TOKU_DB_DUP ???
newn - > dirty = 1 ;
2008-04-23 04:17:28 +00:00
{
u_int32_t mpsize = newn - > nodesize + newn - > nodesize / 4 ;
void * mp = toku_malloc ( mpsize ) ;
assert ( mp ) ;
toku_mempool_init ( & newn - > u . l . buffer_mempool , mp , mpsize ) ;
}
2008-04-22 20:39:50 +00:00
assert ( toku_omt_size ( oldn - > u . l . buffer ) = = old_n ) ;
2008-04-23 04:17:28 +00:00
u_int32_t n_leafentries = old_n ;
2008-04-25 13:45:55 +00:00
OMTVALUE * MALLOC_N ( n_leafentries , leafentries ) ;
2008-04-23 04:17:28 +00:00
assert ( leafentries ) ;
toku_omt_iterate ( oldn - > u . l . buffer , fill_buf , leafentries ) ;
{
u_int32_t i ;
u_int32_t new_fp = 0 , new_size = 0 ;
for ( i = new_n ; i < n_leafentries ; i + + ) {
LEAFENTRY oldle = leafentries [ i ] ;
LEAFENTRY newle = toku_mempool_malloc ( & newn - > u . l . buffer_mempool , leafentry_memsize ( oldle ) , 1 ) ;
assert ( newle ) ;
new_fp + = toku_le_crc ( oldle ) ;
new_size + = OMT_ITEM_OVERHEAD + leafentry_disksize ( oldle ) ;
memcpy ( newle , oldle , leafentry_memsize ( oldle ) ) ;
toku_mempool_mfree ( & oldn - > u . l . buffer_mempool , oldle , leafentry_memsize ( oldle ) ) ;
leafentries [ i ] = newle ;
}
toku_omt_destroy ( & oldn - > u . l . buffer ) ;
r = toku_omt_create_from_sorted_array ( & newn - > u . l . buffer , leafentries + new_n , n_leafentries - new_n ) ;
assert ( r = = 0 ) ;
newn - > u . l . n_bytes_in_buffer = new_size ;
newn - > local_fingerprint = newn - > rand4fingerprint * new_fp ;
}
{
u_int32_t i ;
u_int32_t old_fp = 0 , old_size = 0 ;
for ( i = 0 ; i < new_n ; i + + ) {
LEAFENTRY oldle = leafentries [ i ] ;
old_fp + = toku_le_crc ( oldle ) ;
old_size + = OMT_ITEM_OVERHEAD + leafentry_disksize ( oldle ) ;
}
r = toku_omt_create_from_sorted_array ( & oldn - > u . l . buffer , leafentries , new_n ) ;
oldn - > u . l . n_bytes_in_buffer = old_size ;
oldn - > local_fingerprint = oldn - > rand4fingerprint * old_fp ;
}
toku_free ( leafentries ) ;
//r = toku_omt_split_at(oldn->u.l.buffer, &newn->u.l.buffer, new_n);
toku_verify_all_in_mempool ( oldn ) ; toku_verify_counts ( oldn ) ;
toku_verify_all_in_mempool ( newn ) ; toku_verify_counts ( newn ) ;
2013-04-16 23:57:18 -04:00
toku_cachetable_put ( pair - > cf , new_blocknum , newn - > fullhash ,
2008-06-17 17:05:19 +00:00
newn , toku_serialize_brtnode_size ( newn ) , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , 0 ) ;
2008-04-23 04:17:28 +00:00
newn - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , new_blocknum , newn - > fullhash , 1 , toku_serialize_brtnode_size ( newn ) ) ;
2008-04-23 04:17:28 +00:00
assert ( r = = 0 ) ;
oldn - > log_lsn = lsn ;
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , old_blocknum , oldn - > fullhash , 1 , toku_serialize_brtnode_size ( oldn ) ) ;
2008-04-23 04:17:28 +00:00
assert ( r = = 0 ) ;
2008-04-22 20:39:50 +00:00
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_insertleafentry ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t idx , LEAFENTRY newleafentry ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-03-14 19:14:31 +00:00
assert ( node - > height = = 0 ) ;
VERIFY_COUNTS ( node ) ;
2008-04-07 01:30:25 +00:00
node - > log_lsn = lsn ;
{
int memsize = leafentry_memsize ( newleafentry ) ;
2008-04-22 20:39:50 +00:00
void * mem = mempool_malloc_from_omt ( node - > u . l . buffer , & node - > u . l . buffer_mempool , memsize ) ;
2008-04-17 03:11:55 +00:00
assert ( mem ) ;
2008-04-07 01:30:25 +00:00
memcpy ( mem , newleafentry , memsize ) ;
2008-04-22 20:39:50 +00:00
r = toku_omt_insert_at ( node - > u . l . buffer , mem , idx ) ;
assert ( r = = 0 ) ;
node - > u . l . n_bytes_in_buffer + = OMT_ITEM_OVERHEAD + leafentry_disksize ( newleafentry ) ;
2008-04-07 01:30:25 +00:00
node - > local_fingerprint + = node - > rand4fingerprint * toku_le_crc ( newleafentry ) ;
}
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-04-07 01:30:25 +00:00
assert ( r = = 0 ) ;
toku_free_LEAFENTRY ( newleafentry ) ;
}
2008-03-17 02:40:59 +00:00
2013-04-16 23:57:20 -04:00
static void
toku_recover_deleteleafentry ( LSN lsn , FILENUM filenum , BLOCKNUM blocknum , u_int32_t idx ) {
2008-04-07 01:30:25 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
void * node_v ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
u_int32_t fullhash = toku_cachetable_hash ( pair - > cf , blocknum ) ;
r = toku_cachetable_get_and_pin ( pair - > cf , blocknum , fullhash , & node_v , NULL , toku_brtnode_flush_callback , toku_brtnode_fetch_callback , pair - > brt ) ;
2008-04-07 01:30:25 +00:00
assert ( r = = 0 ) ;
BRTNODE node = node_v ;
2008-06-17 17:05:19 +00:00
assert ( node - > fullhash = = fullhash ) ;
2008-04-07 01:30:25 +00:00
assert ( node - > height = = 0 ) ;
2008-03-14 19:14:31 +00:00
VERIFY_COUNTS ( node ) ;
node - > log_lsn = lsn ;
2008-04-07 01:30:25 +00:00
{
2008-05-12 18:39:21 +00:00
OMTVALUE data = 0 ;
2008-05-30 20:41:12 +00:00
r = toku_omt_fetch ( node - > u . l . buffer , idx , & data , NULL ) ;
2008-04-07 01:30:25 +00:00
assert ( r = = 0 ) ;
2008-05-07 00:40:45 +00:00
LEAFENTRY oldleafentry = data ;
2008-04-22 20:39:50 +00:00
u_int32_t len = leafentry_memsize ( oldleafentry ) ;
2008-04-07 01:30:25 +00:00
assert ( memcmp ( oldleafentry , data , len ) = = 0 ) ;
2008-05-07 00:40:45 +00:00
node - > u . l . n_bytes_in_buffer - = OMT_ITEM_OVERHEAD + leafentry_disksize ( oldleafentry ) ;
node - > local_fingerprint - = node - > rand4fingerprint * toku_le_crc ( oldleafentry ) ;
toku_mempool_mfree ( & node - > u . l . buffer_mempool , oldleafentry , len ) ;
2008-04-22 20:39:50 +00:00
r = toku_omt_delete_at ( node - > u . l . buffer , idx ) ;
assert ( r = = 0 ) ;
2008-04-07 01:30:25 +00:00
}
2013-04-16 23:57:18 -04:00
r = toku_cachetable_unpin ( pair - > cf , blocknum , node - > fullhash , 1 , toku_serialize_brtnode_size ( node ) ) ;
2008-03-14 19:14:31 +00:00
assert ( r = = 0 ) ;
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_changeunnamedroot ( LSN UU ( lsn ) , FILENUM filenum , BLOCKNUM UU ( oldroot ) , BLOCKNUM newroot ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
assert ( pair - > brt - > h ) ;
2008-05-22 21:28:00 +00:00
pair - > brt - > h - > roots [ 0 ] = newroot ;
2008-06-18 21:38:01 +00:00
pair - > brt - > h - > root_hashes [ 0 ] . valid = FALSE ;
2008-03-14 19:14:31 +00:00
}
2013-04-16 23:57:20 -04:00
static void
toku_recover_changenamedroot ( LSN UU ( lsn ) , FILENUM UU ( filenum ) , BYTESTRING UU ( name ) , BLOCKNUM UU ( oldroot ) , BLOCKNUM UU ( newroot ) ) { assert ( 0 ) ; }
2008-03-14 19:14:31 +00:00
2013-04-16 23:57:20 -04:00
static void
toku_recover_changeunusedmemory ( LSN UU ( lsn ) , FILENUM filenum , BLOCKNUM UU ( oldunused ) , BLOCKNUM newunused ) {
2008-03-14 19:14:31 +00:00
struct cf_pair * pair = NULL ;
int r = find_cachefile ( filenum , & pair ) ;
assert ( r = = 0 ) ;
assert ( pair - > brt ) ;
2013-04-16 23:57:18 -04:00
assert ( pair - > brt - > h ) ;
2013-04-16 23:57:18 -04:00
pair - > brt - > h - > unused_blocks = newunused ;
2008-03-14 19:14:31 +00:00
}
2008-03-21 19:40:32 +00:00
static int toku_recover_checkpoint ( LSN UU ( lsn ) ) {
return 0 ;
}
2008-03-14 19:14:31 +00:00
2008-03-21 21:02:30 +00:00
static int toku_recover_xbegin ( LSN UU ( lsn ) , TXNID UU ( parent ) ) {
return 0 ;
}
2008-03-12 19:40:38 +00:00
int tokudb_recover ( const char * data_dir , const char * log_dir ) {
2007-11-23 18:27:50 +00:00
int r ;
2007-12-26 16:52:55 +00:00
int entrycount = 0 ;
2007-11-23 18:27:50 +00:00
char * * logfiles ;
2008-03-12 19:40:38 +00:00
int lockfd ;
{
int namelen = strlen ( data_dir ) ;
char lockfname [ namelen + 20 ] ;
snprintf ( lockfname , sizeof ( lockfname ) , " %s/__recoverylock_dont_delete_me " , data_dir ) ;
lockfd = open ( lockfname , O_RDWR | O_CREAT , S_IRUSR | S_IWUSR ) ;
if ( lockfd < 0 ) {
printf ( " Couldn't open %s \n " , lockfname ) ;
2008-03-14 11:02:28 +00:00
return errno ;
2008-03-12 19:40:38 +00:00
}
r = flock ( lockfd , LOCK_EX | LOCK_NB ) ;
if ( r ! = 0 ) {
printf ( " Couldn't run recovery because some other process holds the recovery lock %s \n " , lockfname ) ;
2008-03-14 11:02:28 +00:00
return errno ;
2008-03-12 19:40:38 +00:00
}
}
2008-03-21 19:40:32 +00:00
r = toku_logger_find_logfiles ( log_dir , & logfiles ) ;
2008-03-14 11:02:28 +00:00
if ( r ! = 0 ) return r ;
2007-11-23 18:27:50 +00:00
int i ;
2008-01-11 03:09:14 +00:00
toku_recover_init ( ) ;
2008-03-12 19:40:38 +00:00
char org_wd [ 1000 ] ;
{
char * wd = getcwd ( org_wd , sizeof ( org_wd ) ) ;
assert ( wd ! = 0 ) ;
//printf("%s:%d org_wd=\"%s\"\n", __FILE__, __LINE__, org_wd);
}
char data_wd [ 1000 ] ;
{
r = chdir ( data_dir ) ; assert ( r = = 0 ) ;
char * wd = getcwd ( data_wd , sizeof ( data_wd ) ) ;
assert ( wd ! = 0 ) ;
//printf("%s:%d data_wd=\"%s\"\n", __FILE__, __LINE__, data_wd);
}
2008-03-21 19:40:32 +00:00
for ( i = 0 ; logfiles [ i ] ; i + + ) {
2007-12-22 20:56:20 +00:00
//fprintf(stderr, "Opening %s\n", logfiles[i]);
2008-03-12 19:40:38 +00:00
r = chdir ( org_wd ) ;
assert ( r = = 0 ) ;
2007-11-23 18:27:50 +00:00
FILE * f = fopen ( logfiles [ i ] , " r " ) ;
struct log_entry le ;
u_int32_t version ;
2008-03-17 02:40:59 +00:00
//printf("Reading file %s\n", logfiles[i]);
2007-11-28 19:09:24 +00:00
r = toku_read_and_print_logmagic ( f , & version ) ;
2007-11-23 18:27:50 +00:00
assert ( r = = 0 & & version = = 0 ) ;
2008-03-12 19:40:38 +00:00
r = chdir ( data_wd ) ;
assert ( r = = 0 ) ;
2007-11-29 18:14:40 +00:00
while ( ( r = toku_log_fread ( f , & le ) ) = = 0 ) {
2008-03-17 02:40:59 +00:00
//printf("%lld: Got cmd %c\n", (long long)le.u.commit.lsn.lsn, le.cmd);
2008-02-08 22:16:02 +00:00
logtype_dispatch_args ( & le , toku_recover_ ) ;
2007-12-29 19:27:01 +00:00
entrycount + + ;
2007-11-23 18:27:50 +00:00
}
if ( r ! = EOF ) {
if ( r = = DB_BADFORMAT ) {
2008-01-25 21:50:07 +00:00
fprintf ( stderr , " Bad log format at record %d \n " , entrycount ) ;
2008-03-14 11:02:28 +00:00
return r ;
2007-11-23 18:27:50 +00:00
} else {
fprintf ( stderr , " Huh? %s \n " , strerror ( r ) ) ;
2008-03-14 11:02:28 +00:00
return r ;
2007-11-23 18:27:50 +00:00
}
}
fclose ( f ) ;
}
2008-01-11 03:09:14 +00:00
toku_recover_cleanup ( ) ;
2008-03-21 19:40:32 +00:00
for ( i = 0 ; logfiles [ i ] ; i + + ) {
2007-11-23 18:27:50 +00:00
toku_free ( logfiles [ i ] ) ;
}
toku_free ( logfiles ) ;
2008-03-12 19:40:38 +00:00
r = flock ( lockfd , LOCK_UN ) ;
2008-03-14 11:02:28 +00:00
if ( r ! = 0 ) return errno ;
r = chdir ( org_wd ) ;
if ( r ! = 0 ) return errno ;
2008-03-12 19:40:38 +00:00
//printf("%s:%d recovery successful! ls -l says\n", __FILE__, __LINE__);
//system("ls -l");
2007-11-23 18:27:50 +00:00
return 0 ;
}