From ed5c67c6fab3ae9f47090aefc2fb66915ab4a8c1 Mon Sep 17 00:00:00 2001
From: David Chen <chendahui007@gmail.com>
Date: Fri, 30 Mar 2018 14:59:30 +0800
Subject: [PATCH] update tikv_gc_life_time if needed (#24)

---
 lightning/restore/restore.go | 57 +++++++++++++++++++++++++++++-------
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/lightning/restore/restore.go b/lightning/restore/restore.go
index fb874be0d6d10..1493e721bd926 100644
--- a/lightning/restore/restore.go
+++ b/lightning/restore/restore.go
@@ -1,6 +1,7 @@
 package restore
 
 import (
+	"database/sql"
 	"fmt"
 	"io"
 	"runtime"
@@ -28,6 +29,10 @@ var (
 	concurrency   = 1
 )
 
+const (
+	defaultGCLifeTime = 100 * time.Hour
+)
+
 func init() {
 	concurrency = runtime.NumCPU() // TODO ... config
 
@@ -725,19 +730,20 @@ func DoChecksum(dsn config.DBStore, tables []string) ([]*RemoteChecksum, error)
 	db := common.ConnectDB(dsn.Host, dsn.Port, dsn.User, dsn.Psw)
 	defer db.Close()
 
-	// ps : checksum command usually take long time to execute,
-	//		so here need to expand the gcLifeTime for single transaction.
-	oriGCLifeTime, gcErr := ObtainGCLifeTime(db)
-	if gcErr == nil {
-		gcErr = UpdateGCLifeTime(db, "100h")
-	}
-	if gcErr != nil {
-		return nil, errors.Trace(gcErr)
+	ori, err := increaseGCLifeTime(db)
+	if err != nil {
+		return nil, errors.Trace(err)
 	}
-	defer UpdateGCLifeTime(db, oriGCLifeTime)
+	// set it back finally
+	defer func() {
+		err = UpdateGCLifeTime(db, ori)
+		if err != nil {
+			log.Errorf("update tikv_gc_life_time error %s", errors.ErrorStack(err))
+		}
+	}()
 
 	// ps : speed up executing checksum temporarily
-	_, err := db.Exec("set session tidb_checksum_table_concurrency = 32")
+	_, err = db.Exec("set session tidb_checksum_table_concurrency = 32")
 	if err != nil {
 		log.Warnf("failed to set variable @tidb_checksum_table_concurrency: %s", err.Error())
 	}
@@ -775,6 +781,37 @@ func DoChecksum(dsn config.DBStore, tables []string) ([]*RemoteChecksum, error)
 	return checksums, nil
 }
 
+func increaseGCLifeTime(db *sql.DB) (oriGCLifeTime string, err error) {
+	// checksum command usually takes a long time to execute,
+	// so here need to increase the gcLifeTime for single transaction.
+	oriGCLifeTime, err = ObtainGCLifeTime(db)
+	if err != nil {
+		return "", errors.Trace(err)
+	}
+
+	var increaseGCLifeTime bool
+	if oriGCLifeTime != "" {
+		ori, err := time.ParseDuration(oriGCLifeTime)
+		if err != nil {
+			return "", errors.Trace(err)
+		}
+		if ori < defaultGCLifeTime {
+			increaseGCLifeTime = true
+		}
+	} else {
+		increaseGCLifeTime = true
+	}
+
+	if increaseGCLifeTime {
+		err = UpdateGCLifeTime(db, defaultGCLifeTime.String())
+		if err != nil {
+			return "", errors.Trace(err)
+		}
+	}
+
+	return oriGCLifeTime, nil
+}
+
 func (tr *TableRestore) excCheckTable() error {
 	log.Infof("Verify by execute `admin check table` : %s", tr.tableMeta.Name)