Skip to content

Commit 41f5270

Browse files
author
Jun
committed
[TDB-20] With checkpoint disabled, closing FT file still rotates header.
[Updated the comments and formats from the last PR.] This is an attempt based on @BohuTANG's patch percona#331 in particular, the ctest mostly comes from his with minor updates. Summary: 1) The issue is real. 2) @bohu's patch works for mediating the issue but somewhat introduces a ft leak that the ft with ref=0 may be left until next open/close or checkpoint. 3) If ft_close should be held off upon a backup, then it simply means a backup should hold a ref to the ft and responsible for closing ft up if it is the last one to hold it, like any other possible referencer. including the checkpoint, the txn and ft handlers. 4) mtr test contributed by @BohuTANG still passes. (in a different PS PR).
1 parent af8783b commit 41f5270

12 files changed

+317
-85
lines changed

ft/cachetable/cachetable-internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ struct cachefile {
161161
void (*end_checkpoint_userdata)(CACHEFILE cf, int fd, void *userdata); // after checkpointing cachefiles call this function.
162162
void (*note_pin_by_checkpoint)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
163163
void (*note_unpin_by_checkpoint)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
164+
165+
void (*note_pin_by_backup)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
166+
void (*note_unpin_by_backup)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
164167
BACKGROUND_JOB_MANAGER bjm;
165168
};
166169

@@ -413,6 +416,8 @@ class checkpointer {
413416
void add_background_job();
414417
void remove_background_job();
415418
void end_checkpoint(void (*testcallback_f)(void*), void* testextra);
419+
void begin_backup();
420+
void end_backup();
416421
TOKULOGGER get_logger();
417422
// used during begin_checkpoint
418423
void increment_num_txns();

ft/cachetable/cachetable.cc

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2793,6 +2793,37 @@ void toku_cachetable_end_checkpoint(CHECKPOINTER cp, TOKULOGGER UU(logger),
27932793
cp->end_checkpoint(testcallback_f, testextra);
27942794
}
27952795

2796+
// in_backup begin
2797+
2798+
struct iterate_note_pin_backup {
2799+
static int fn(const CACHEFILE &cf, uint32_t UU(idx), void **UU(extra)) {
2800+
assert(cf->note_pin_by_backup);
2801+
cf->note_pin_by_backup(cf, cf->userdata);
2802+
return 0;
2803+
}
2804+
};
2805+
2806+
struct iterate_note_unpin_backup {
2807+
static int fn(const CACHEFILE &cf, uint32_t UU(idx), void **UU(extra)) {
2808+
assert(cf->note_unpin_by_backup);
2809+
cf->note_unpin_by_backup(cf, cf->userdata);
2810+
return 0;
2811+
}
2812+
};
2813+
void toku_cachetable_begin_backup(CACHETABLE ct)
2814+
{
2815+
ct->cf_list.read_lock();
2816+
ct->cf_list.m_active_fileid.iterate<void *, iterate_note_pin_backup::fn>(nullptr);
2817+
ct->cf_list.read_unlock();
2818+
}
2819+
2820+
void toku_cachetable_end_backup(CACHETABLE ct)
2821+
{
2822+
ct->cf_list.m_active_fileid.iterate<void *, iterate_note_unpin_backup::fn>(nullptr);
2823+
}
2824+
2825+
// in_backup end
2826+
27962827
TOKULOGGER toku_cachefile_logger (CACHEFILE cf) {
27972828
return cf->cachetable->cp.get_logger();
27982829
}
@@ -2909,7 +2940,9 @@ toku_cachefile_set_userdata (CACHEFILE cf,
29092940
void (*begin_checkpoint_userdata)(LSN, void*),
29102941
void (*end_checkpoint_userdata)(CACHEFILE, int, void*),
29112942
void (*note_pin_by_checkpoint)(CACHEFILE, void*),
2912-
void (*note_unpin_by_checkpoint)(CACHEFILE, void*)) {
2943+
void (*note_unpin_by_checkpoint)(CACHEFILE, void*),
2944+
void (*note_pin_by_backup)(CACHEFILE, void*),
2945+
void (*note_unpin_by_backup)(CACHEFILE, void*)) {
29132946
cf->userdata = userdata;
29142947
cf->log_fassociate_during_checkpoint = log_fassociate_during_checkpoint;
29152948
cf->close_userdata = close_userdata;
@@ -2919,6 +2952,8 @@ toku_cachefile_set_userdata (CACHEFILE cf,
29192952
cf->end_checkpoint_userdata = end_checkpoint_userdata;
29202953
cf->note_pin_by_checkpoint = note_pin_by_checkpoint;
29212954
cf->note_unpin_by_checkpoint = note_unpin_by_checkpoint;
2955+
cf->note_pin_by_backup = note_pin_by_backup;
2956+
cf->note_unpin_by_backup = note_unpin_by_backup;
29222957
}
29232958

29242959
void *toku_cachefile_get_userdata(CACHEFILE cf) {

ft/cachetable/cachetable.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ void toku_cachetable_begin_checkpoint (CHECKPOINTER cp, struct tokulogger *logge
147147
void toku_cachetable_end_checkpoint(CHECKPOINTER cp, struct tokulogger *logger,
148148
void (*testcallback_f)(void*), void * testextra);
149149

150+
void toku_cachetable_begin_backup(CACHETABLE ct);
151+
void toku_cachetable_end_backup(CACHETABLE ct);
150152

151153
// Shuts down checkpoint thread
152154
// Requires no locks be held that are taken by the checkpoint function
@@ -285,7 +287,9 @@ void toku_cachefile_set_userdata(CACHEFILE cf, void *userdata,
285287
void (*begin_checkpoint_userdata)(LSN, void*),
286288
void (*end_checkpoint_userdata)(CACHEFILE, int, void*),
287289
void (*note_pin_by_checkpoint)(CACHEFILE, void*),
288-
void (*note_unpin_by_checkpoint)(CACHEFILE, void*));
290+
void (*note_unpin_by_checkpoint)(CACHEFILE, void*),
291+
void (*note_pin_by_backup)(CACHEFILE, void*),
292+
void (*note_unpin_by_backup)(CACHEFILE, void*));
289293
// Effect: Store some cachefile-specific user data. When the last reference to a cachefile is closed, we call close_userdata().
290294
// Before starting a checkpoint, we call checkpoint_prepare_userdata().
291295
// When the cachefile needs to be checkpointed, we call checkpoint_userdata().

ft/ft-internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ struct ft {
197197
uint32_t num_txns;
198198
// A checkpoint is running. If true, then keep this header around for checkpoint, like a transaction
199199
bool pinned_by_checkpoint;
200-
200+
// Number of backups that are using this FT. If it is nonzero, keep this header around until backup
201+
// is completd.
202+
uint32_t num_backups;
201203
// is this ft a blackhole? if so, all messages are dropped.
202204
bool blackhole;
203205

ft/ft.cc

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -306,13 +306,42 @@ static void unpin_by_checkpoint_callback(FT ft, void *extra) {
306306
}
307307

308308
// maps to cf->note_unpin_by_checkpoint
309-
//Must be protected by ydb lock.
310-
//Called by end_checkpoint, which grabs ydb lock around note_unpin
309+
// Must be protected by ydb lock.
310+
// Called by end_checkpoint, which grabs ydb lock around note_unpin
311311
static void ft_note_unpin_by_checkpoint (CACHEFILE UU(cachefile), void *header_v) {
312312
FT ft = (FT) header_v;
313313
toku_ft_remove_reference(ft, false, ZERO_LSN, unpin_by_checkpoint_callback, NULL);
314314
}
315315

316+
317+
// maps to cf->note_pin_by_backup
318+
// Must be protected by ydb lock.
319+
// Is only called by backup begin, which holds it
320+
static void ft_note_pin_by_backup (CACHEFILE UU(cachefile), void *header_v) {
321+
// Note: open_close lock is held by checkpoint begin
322+
FT ft = (FT) header_v;
323+
toku_ft_grab_reflock(ft);
324+
assert(toku_ft_needed_unlocked(ft));
325+
ft->num_backups++;
326+
toku_ft_release_reflock(ft);
327+
}
328+
329+
// Requires: the reflock is held.
330+
static void unpin_by_backup_callback(FT ft, void *extra) {
331+
invariant(extra == NULL);
332+
invariant(ft->num_backups > 0);
333+
ft->num_backups--;
334+
}
335+
336+
// maps to cf->note_unpin_by_backup
337+
// Must be protected by ydb lock.
338+
// Called by end_backup, which grabs ydb lock around note_unpin
339+
static void ft_note_unpin_by_backup (CACHEFILE UU(cachefile), void *header_v) {
340+
FT ft = (FT) header_v;
341+
toku_ft_remove_reference(ft, false, ZERO_LSN, unpin_by_backup_callback, NULL);
342+
}
343+
344+
316345
//
317346
// End of Functions that are callbacks to the cachefile
318347
/////////////////////////////////////////////////////////////////////////
@@ -332,38 +361,33 @@ static void setup_initial_ft_root_node(FT ft, BLOCKNUM blocknum) {
332361
}
333362

334363
static void ft_init(FT ft, FT_OPTIONS options, CACHEFILE cf) {
335-
// fake, prevent unnecessary upgrade logic
336-
ft->layout_version_read_from_disk = FT_LAYOUT_VERSION;
337-
ft->checkpoint_header = NULL;
364+
// fake, prevent unnecessary upgrade logic
365+
ft->layout_version_read_from_disk = FT_LAYOUT_VERSION;
366+
ft->checkpoint_header = NULL;
338367

339-
toku_list_init(&ft->live_ft_handles);
368+
toku_list_init(&ft->live_ft_handles);
340369

341-
// intuitively, the comparator points to the FT's cmp descriptor
342-
ft->cmp.create(options->compare_fun, &ft->cmp_descriptor, options->memcmp_magic);
343-
ft->update_fun = options->update_fun;
370+
// intuitively, the comparator points to the FT's cmp descriptor
371+
ft->cmp.create(options->compare_fun, &ft->cmp_descriptor,
372+
options->memcmp_magic);
373+
ft->update_fun = options->update_fun;
344374

345-
if (ft->cf != NULL) {
346-
assert(ft->cf == cf);
347-
}
348-
ft->cf = cf;
349-
ft->in_memory_stats = ZEROSTATS;
375+
if (ft->cf != NULL) {
376+
assert(ft->cf == cf);
377+
}
378+
ft->cf = cf;
379+
ft->in_memory_stats = ZEROSTATS;
350380

351-
setup_initial_ft_root_node(ft, ft->h->root_blocknum);
352-
toku_cachefile_set_userdata(ft->cf,
353-
ft,
354-
ft_log_fassociate_during_checkpoint,
355-
ft_close,
356-
ft_free,
357-
ft_checkpoint,
358-
ft_begin_checkpoint,
359-
ft_end_checkpoint,
360-
ft_note_pin_by_checkpoint,
361-
ft_note_unpin_by_checkpoint);
381+
setup_initial_ft_root_node(ft, ft->h->root_blocknum);
382+
toku_cachefile_set_userdata(
383+
ft->cf, ft, ft_log_fassociate_during_checkpoint, ft_close, ft_free,
384+
ft_checkpoint, ft_begin_checkpoint, ft_end_checkpoint,
385+
ft_note_pin_by_checkpoint, ft_note_unpin_by_checkpoint,
386+
ft_note_pin_by_backup, ft_note_unpin_by_backup);
362387

363-
ft->blocktable.verify_no_free_blocknums();
388+
ft->blocktable.verify_no_free_blocknums();
364389
}
365390

366-
367391
static FT_HEADER
368392
ft_header_create(FT_OPTIONS options, BLOCKNUM root_blocknum, TXNID root_xid_that_created)
369393
{
@@ -455,7 +479,9 @@ int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_handle, CACHEFILE cf, LSN
455479
ft_begin_checkpoint,
456480
ft_end_checkpoint,
457481
ft_note_pin_by_checkpoint,
458-
ft_note_unpin_by_checkpoint);
482+
ft_note_unpin_by_checkpoint,
483+
ft_note_pin_by_backup,
484+
ft_note_unpin_by_backup);
459485
*header = ft;
460486
return 0;
461487
}
@@ -475,7 +501,7 @@ static int
475501
ft_get_reference_count(FT ft) {
476502
uint32_t pinned_by_checkpoint = ft->pinned_by_checkpoint ? 1 : 0;
477503
int num_handles = toku_list_num_elements_est(&ft->live_ft_handles);
478-
return pinned_by_checkpoint + ft->num_txns + num_handles;
504+
return pinned_by_checkpoint + ft->num_txns + ft-> num_backups + num_handles;
479505
}
480506

481507
// a ft is needed in memory iff its reference count is non-zero

ft/tests/cachetable-pin-checkpoint.cc

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -358,21 +358,15 @@ cachetable_test (void) {
358358
toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
359359
const char *fname1 = TOKU_TEST_FILENAME;
360360
unlink(fname1);
361-
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
361+
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR | O_CREAT,
362+
S_IRWXU | S_IRWXG | S_IRWXO);
363+
assert(r == 0);
362364

363365
toku_cachefile_set_userdata(
364-
f1,
365-
NULL,
366-
&dummy_log_fassociate,
367-
&dummy_close_usr,
368-
&dummy_free_usr,
369-
&dummy_chckpnt_usr,
370-
&test_begin_checkpoint,
371-
&dummy_end,
372-
&dummy_note_pin,
373-
&dummy_note_unpin
374-
);
375-
366+
f1, NULL, &dummy_log_fassociate, &dummy_close_usr, &dummy_free_usr,
367+
&dummy_chckpnt_usr, &test_begin_checkpoint, &dummy_end, &dummy_note_pin,
368+
&dummy_note_unpin, &dummy_note_pin, &dummy_note_unpin);
369+
376370
toku_pthread_t time_tid;
377371
toku_pthread_t checkpoint_tid;
378372
toku_pthread_t move_tid[NUM_MOVER_THREADS];

ft/tests/cachetable-put-checkpoint.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -487,20 +487,16 @@ cachetable_test (void) {
487487
toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
488488
const char *fname1 = TOKU_TEST_FILENAME;
489489
unlink(fname1);
490-
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);
490+
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR | O_CREAT,
491+
S_IRWXU | S_IRWXG | S_IRWXO);
492+
assert(r == 0);
491493

492494
toku_cachefile_set_userdata(
493-
f1,
494-
NULL,
495-
&dummy_log_fassociate,
496-
&dummy_close_usr,
497-
&dummy_free_usr,
495+
f1, NULL, &dummy_log_fassociate, &dummy_close_usr, &dummy_free_usr,
498496
&dummy_chckpnt_usr,
499497
test_begin_checkpoint, // called in begin_checkpoint
500-
&dummy_end,
501-
&dummy_note_pin,
502-
&dummy_note_unpin
503-
);
498+
&dummy_end, &dummy_note_pin, &dummy_note_unpin, &dummy_note_pin,
499+
&dummy_note_unpin);
504500

505501
toku_pthread_t time_tid;
506502
toku_pthread_t checkpoint_tid;

ft/tests/cachetable-simple-close.cc

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,10 @@ static void free_usr(CACHEFILE UU(cf), void* UU(p)) {
5050
}
5151

5252
static void set_cf_userdata(CACHEFILE f1) {
53-
toku_cachefile_set_userdata(
54-
f1,
55-
NULL,
56-
&dummy_log_fassociate,
57-
&close_usr,
58-
&free_usr,
59-
&dummy_chckpnt_usr,
60-
&dummy_begin,
61-
&dummy_end,
62-
&dummy_note_pin,
63-
&dummy_note_unpin
64-
);
53+
toku_cachefile_set_userdata(f1, NULL, &dummy_log_fassociate, &close_usr,
54+
&free_usr, &dummy_chckpnt_usr, &dummy_begin,
55+
&dummy_end, &dummy_note_pin, &dummy_note_unpin,
56+
&dummy_note_pin, &dummy_note_unpin);
6557
}
6658

6759
bool keep_me;

ft/tests/cachetable-test.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,9 @@ static void dummy_note_unpin(CACHEFILE UU(cf), void* UU(p)) { }
5858
static UU() void
5959
create_dummy_functions(CACHEFILE cf)
6060
{
61-
void *ud = NULL;
62-
toku_cachefile_set_userdata(cf,
63-
ud,
64-
&dummy_log_fassociate,
65-
&dummy_close_usr,
66-
&dummy_free_usr,
67-
&dummy_chckpnt_usr,
68-
&dummy_begin,
69-
&dummy_end,
70-
&dummy_note_pin,
71-
&dummy_note_unpin);
61+
void *ud = NULL;
62+
toku_cachefile_set_userdata(cf, ud, &dummy_log_fassociate, &dummy_close_usr,
63+
&dummy_free_usr, &dummy_chckpnt_usr, &dummy_begin,
64+
&dummy_end, &dummy_note_pin, &dummy_note_unpin,
65+
&dummy_note_pin, &dummy_note_unpin);
7266
};

ft/tests/fifo-test.cc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,17 @@ test_enqueue(int n) {
7373
if (i == 0) {
7474
xids = toku_xids_get_root_xids();
7575
} else {
76-
int r = toku_xids_create_child(toku_xids_get_root_xids(), &xids, (TXNID)i);
77-
assert_zero(r);
76+
int r = toku_xids_create_child(toku_xids_get_root_xids(), &xids,
77+
(TXNID)i);
78+
assert_zero(r);
7879
}
7980
MSN msn = next_dummymsn();
8081
if (startmsn.msn == ZERO_MSN.msn)
81-
startmsn = msn;
82-
enum ft_msg_type type = (enum ft_msg_type) i;
82+
startmsn = msn;
83+
enum ft_msg_type type = (enum ft_msg_type)i;
8384
DBT k, v;
84-
ft_msg msg(toku_fill_dbt(&k, thekey, thekeylen), toku_fill_dbt(&v, theval, thevallen), type, msn, xids);
85+
ft_msg msg(toku_fill_dbt(&k, thekey, thekeylen),
86+
toku_fill_dbt(&v, theval, thevallen), type, msn, xids);
8587
msg_buffer.enqueue(msg, true, nullptr);
8688
toku_xids_destroy(&xids);
8789
toku_free(thekey);

0 commit comments

Comments
 (0)