Commit 0a5a3951 authored by Rich Prohaska's avatar Rich Prohaska Committed by Yoni Fogel

merge brt_truncate into 1032b. addresses #1032

git-svn-id: file:///svn/toku/tokudb.1032b@7803 c7de825b-a66e-492c-adef-691d508d4ae1
parent 75bfcdc1
......@@ -529,7 +529,22 @@ void toku_brtnode_free (BRTNODE *nodep) {
*nodep=0;
}
void toku_brtheader_free (struct brt_header *h) {
static void
brtheader_init(struct brt_header *h) {
memset(h, 0, sizeof *h);
}
static void
brtheader_partial_destroy(struct brt_header *h) {
toku_free(h->block_translation);
h->block_translation = 0;
toku_fifo_free(&h->fifo);
destroy_block_allocator(&h->block_allocator);
}
static void
brtheader_destroy(struct brt_header *h) {
brtheader_partial_destroy(h);
if (h->n_named_roots>0) {
int i;
for (i=0; i<h->n_named_roots; i++) {
......@@ -537,14 +552,35 @@ void toku_brtheader_free (struct brt_header *h) {
}
toku_free(h->names);
}
toku_fifo_free(&h->fifo);
toku_free(h->roots);
toku_free(h->root_hashes);
toku_free(h->flags_array);
toku_free(h->block_translation);
destroy_block_allocator(&h->block_allocator);
}
static int
brtheader_alloc(struct brt_header **hh) {
int r;
if ((MALLOC(*hh))==0) {
assert(errno==ENOMEM);
r = ENOMEM;
} else {
brtheader_init(*hh);
r = 0;
}
return r;
}
static void
brtheader_free(struct brt_header *h)
{
brtheader_destroy(h);
toku_free(h);
}
void
toku_brtheader_free (struct brt_header *h) {
brtheader_free(h);
}
void
extend_block_translation (BLOCKNUM blocknum, struct brt_header *h)
......@@ -2639,22 +2675,14 @@ static int brt_open_file(BRT brt, const char *fname, int is_create, int *fdp, BO
return 0;
}
// allocate and initialize a brt header.
// t->cf is not set to anything.
static int brt_alloc_init_header(BRT t, const char *dbname, TOKUTXN txn) {
static int brt_init_header(BRT t, TOKUTXN txn) {
int r;
BLOCKNUM root = make_blocknum(1);
assert(t->h == 0);
if ((MALLOC(t->h))==0) {
assert(errno==ENOMEM);
r = ENOMEM;
if (0) { died2: toku_free(t->h); }
t->h=0;
return r;
}
t->h->roots[0] = root;
compute_and_fill_remembered_hash(t, 0);
t->h->dirty=1;
if ((MALLOC_N(1, t->h->flags_array))==0) { r = errno; if (0) { died3: toku_free(t->h->flags_array); } goto died2; }
t->h->flags_array[0] = t->flags;
t->h->nodesize=t->nodesize;
t->h->free_blocks = make_blocknum(-1);
......@@ -2667,22 +2695,6 @@ static int brt_alloc_init_header(BRT t, const char *dbname, TOKUTXN txn) {
create_block_allocator(&t->h->block_allocator, BLOCK_ALLOCATOR_HEADER_RESERVE, BLOCK_ALLOCATOR_ALIGNMENT);
toku_fifo_create(&t->h->fifo);
t->h->root_put_counter = global_root_put_counter++;
if (dbname) {
t->h->n_named_roots = 1;
if ((MALLOC_N(1, t->h->names))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died4: if (dbname) toku_free(t->h->names); } goto died3; }
if ((MALLOC_N(1, t->h->roots))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died5: if (dbname) toku_free(t->h->roots); } goto died4; }
if ((MALLOC_N(1, t->h->root_hashes))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died6: if (dbname) toku_free(t->h->root_hashes); } goto died5; }
if ((t->h->names[0] = toku_strdup(dbname))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died7: if (dbname) toku_free(t->h->names[0]); } goto died6; }
t->h->roots[0] = root; // Block 0 is the header. Block 1 is the root.
compute_and_fill_remembered_hash(t, 0);
} else {
MALLOC_N(1, t->h->roots); assert(t->h->roots);
MALLOC_N(1, t->h->root_hashes); assert(t->h->root_hashes);
t->h->roots[0] = root;
compute_and_fill_remembered_hash(t, 0);
t->h->n_named_roots = -1;
t->h->names=0;
}
{
LOGGEDBRTHEADER lh = {.size= toku_serialize_brt_header_size(t->h),
......@@ -2697,9 +2709,9 @@ static int brt_alloc_init_header(BRT t, const char *dbname, TOKUTXN txn) {
} else {
lh.u.one.root = t->h->roots[0];
}
if ((r=toku_log_fheader(toku_txn_logger(txn), (LSN*)0, 0, toku_txn_get_txnid(txn), toku_cachefile_filenum(t->cf), lh))) { goto died7; }
if ((r=toku_log_fheader(toku_txn_logger(txn), (LSN*)0, 0, toku_txn_get_txnid(txn), toku_cachefile_filenum(t->cf), lh))) { return r; }
}
if ((r=setup_initial_brt_root_node(t, root, toku_txn_logger(txn)))!=0) { goto died7; }
if ((r=setup_initial_brt_root_node(t, root, toku_txn_logger(txn)))!=0) { return r; }
//printf("%s:%d putting %p (%d)\n", __FILE__, __LINE__, t->h, 0);
assert(t->h->free_blocks.b==-1);
toku_cachefile_set_userdata(t->cf, t->h, toku_brtheader_close);
......@@ -2707,6 +2719,38 @@ static int brt_alloc_init_header(BRT t, const char *dbname, TOKUTXN txn) {
return r;
}
// allocate and initialize a brt header.
// t->cf is not set to anything.
static int brt_alloc_init_header(BRT t, const char *dbname, TOKUTXN txn) {
int r;
r = brtheader_alloc(&t->h);
if (r != 0) {
if (0) { died2: toku_free(t->h); }
t->h=0;
return r;
}
if ((MALLOC_N(1, t->h->flags_array))==0) { r = errno; if (0) { died3: toku_free(t->h->flags_array); } goto died2; }
if (dbname) {
t->h->n_named_roots = 1;
if ((MALLOC_N(1, t->h->names))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died4: if (dbname) toku_free(t->h->names); } goto died3; }
if ((MALLOC_N(1, t->h->roots))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died5: if (dbname) toku_free(t->h->roots); } goto died4; }
if ((MALLOC_N(1, t->h->root_hashes))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died6: if (dbname) toku_free(t->h->root_hashes); } goto died5; }
if ((t->h->names[0] = toku_strdup(dbname))==0) { assert(errno==ENOMEM); r=ENOMEM; if (0) { died7: if (dbname) toku_free(t->h->names[0]); } goto died6; }
} else {
MALLOC_N(1, t->h->roots); assert(t->h->roots);
MALLOC_N(1, t->h->root_hashes); assert(t->h->root_hashes);
t->h->n_named_roots = -1;
t->h->names=0;
}
r = brt_init_header(t, txn);
if (r != 0) goto died7;
return r;
}
int toku_read_brt_header_and_store_in_cachefile (CACHEFILE cf, struct brt_header **header)
// If the cachefile already has the header, then just get it.
// If the cachefile has not been initialized, then don't modify anything.
......@@ -4174,3 +4218,25 @@ int toku_dump_brt (FILE *f, BRT brt) {
rootp = toku_calculate_root_offset_pointer(brt, &fullhash);
return toku_dump_brtnode(f, brt, *rootp, 0, 0, 0, 0, 0);
}
int toku_brt_truncate (BRT brt) {
int r;
// flush the cached tree blocks
r = toku_brt_flush(brt);
if (r != 0)
return r;
// truncate the underlying file
r = toku_cachefile_truncate0(brt->cf);
if (r != 0)
return r;
// TODO log the truncate?
// reinit the header
brtheader_partial_destroy(brt->h);
r = brt_init_header(brt, NULL_TXN);
return r;
}
......@@ -24,11 +24,6 @@ int toku_brt_set_dup_compare(BRT, int (*dup_compare)(DB *, const DBT*, const DBT
int brt_set_cachetable(BRT, CACHETABLE);
int toku_brt_open(BRT, const char *fname, const char *fname_in_env, const char *dbname, int is_create, int only_create, CACHETABLE ct, TOKUTXN txn, DB *db);
int toku_brt_reopen (BRT brt, const char *fname, const char *fname_in_env, TOKUTXN txn);
// reopen the tree
// effect: attach the tree to a new file
// returns: 0 if success
int toku_brt_remove_subdb(BRT brt, const char *dbname, u_int32_t flags);
int toku_brt_insert (BRT, DBT *, DBT *, TOKUTXN);
......@@ -51,10 +46,13 @@ int toku_brt_flush (BRT brt);
// effect: the tree's cachefile is flushed
// returns: 0 if success
/* create and initialize a cache table
cachesize is the upper limit on the size of the size of the values in the table
pass 0 if you want the default */
int toku_brt_truncate (BRT brt);
// effect: remove everything from the tree
// returns: 0 if success
// create and initialize a cache table
// cachesize is the upper limit on the size of the size of the values in the table
// pass 0 if you want the default
int toku_brt_create_cachetable(CACHETABLE *t, long cachesize, LSN initial_lsn, TOKULOGGER);
extern int toku_brt_debug_mode;
......
......@@ -272,6 +272,13 @@ int toku_cachefile_fd (CACHEFILE cf) {
return cf->fd;
}
int toku_cachefile_truncate0 (CACHEFILE cf) {
int r = ftruncate(cf->fd, 0);
if (r != 0)
r = errno;
return r;
}
static CACHEFILE remove_cf_from_list (CACHEFILE cf, CACHEFILE list) {
if (list==0) return 0;
else if (list==cf) {
......
......@@ -152,6 +152,10 @@ int toku_cachefile_set_fd (CACHEFILE cf, int fd, const char *fname);
// closing the user data.
int toku_cachefile_redirect_nullfd (CACHEFILE cf);
// Truncate a cachefile
// Effect: set the cachefile size to 0
int toku_cachefile_truncate0 (CACHEFILE cf);
// Return the logger associated with the cachefile
TOKULOGGER toku_cachefile_logger (CACHEFILE);
......
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