From 410f7df98661a581c12815759183b8b6ac7c707c Mon Sep 17 00:00:00 2001 From: "yanfei.zyf" Date: Tue, 15 Sep 2015 15:12:40 +0800 Subject: [PATCH] FT-701 keep all FT files consistency before next checkpoint [summary] When we do hot backup like below: 1) take checkpoint lock 2) lock table for read 3) wirte binary log postion 4) copy redo log to backup dir 5) unlock tables 6) start to copy datas files 6.1) write data by another client 6.2) copy file1 to backup dir 7) release checkpoint lock Between 6.1) and 6.2) the FT may does ft_close and update FT header to new, the new writes are visible in the backup instance, this broke the consistency. It would be better for TokuDB to update FT header only in checkpoint, keep all FT files consistency. Copyright (c) 2015, BohuTANG All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- ft/cachetable/cachetable.cc | 5 +++++ ft/cachetable/cachetable.h | 3 +++ ft/ft.cc | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ft/cachetable/cachetable.cc b/ft/cachetable/cachetable.cc index 5bba977de..a8578d29e 100644 --- a/ft/cachetable/cachetable.cc +++ b/ft/cachetable/cachetable.cc @@ -336,6 +336,11 @@ int toku_cachefile_of_filenum (CACHETABLE ct, FILENUM filenum, CACHEFILE *cf) { return ct->cf_list.cachefile_of_filenum(filenum, cf); } +// Check a cachefile is in checkpoint or NOT +bool toku_cachefile_forcheckpoint(CACHEFILE cf) { + return cf->for_checkpoint; +} + // TEST-ONLY function // If something goes wrong, close the fd. After this, the caller shouldn't close the fd, but instead should close the cachefile. int toku_cachetable_openfd (CACHEFILE *cfptr, CACHETABLE ct, int fd, const char *fname_in_env) { diff --git a/ft/cachetable/cachetable.h b/ft/cachetable/cachetable.h index 148326562..9842459b7 100644 --- a/ft/cachetable/cachetable.h +++ b/ft/cachetable/cachetable.h @@ -138,6 +138,9 @@ int toku_cachefile_of_filenum (CACHETABLE t, FILENUM filenum, CACHEFILE *cf); // During a transaction, we cannot reuse an iname. int toku_cachefile_of_iname_in_env (CACHETABLE ct, const char *iname_in_env, CACHEFILE *cf); +// Check a cachefile is in checkpoint or NOT +bool toku_cachefile_forcheckpoint(CACHEFILE cf); + // Get the iname (within the cwd) associated with the cachefile // Return the filename char *toku_cachefile_fname_in_cwd (CACHEFILE cf); diff --git a/ft/ft.cc b/ft/ft.cc index 2a0fb6f68..b2a44f4f3 100644 --- a/ft/ft.cc +++ b/ft/ft.cc @@ -256,7 +256,9 @@ static void ft_close(CACHEFILE cachefile, int fd, void *header_v, bool oplsn_val } if (ft->h->dirty) { // this is the only place this bit is tested (in currentheader) bool do_checkpoint = true; - if (logger && logger->rollback_cachefile == cachefile) { + bool for_checkpoint = toku_cachefile_forcheckpoint(cachefile); + // It would be better for FT to update header only in checkpoint, so all FT files keep consistency before next checkpoint. + if ((!for_checkpoint) || (logger && logger->rollback_cachefile == cachefile)) { do_checkpoint = false; } if (do_checkpoint) {