github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/kv/store_op.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package kv 15 16 import ( 17 "fmt" 18 "sync" 19 "time" 20 21 "github.com/pingcap/errors" 22 "github.com/pingcap/log" 23 "github.com/pingcap/ticdc/cdc/model" 24 cerror "github.com/pingcap/ticdc/pkg/errors" 25 "github.com/pingcap/ticdc/pkg/flags" 26 "github.com/pingcap/ticdc/pkg/security" 27 tidbconfig "github.com/pingcap/tidb/config" 28 "github.com/pingcap/tidb/kv" 29 tidbkv "github.com/pingcap/tidb/kv" 30 "github.com/pingcap/tidb/meta" 31 "github.com/pingcap/tidb/store" 32 "github.com/pingcap/tidb/store/driver" 33 "github.com/pingcap/tidb/store/tikv" 34 "github.com/pingcap/tidb/store/tikv/oracle" 35 "go.uber.org/zap" 36 ) 37 38 // TiKVStorage is the tikv storage interface used by CDC. 39 type TiKVStorage interface { 40 tikv.Storage 41 GetCachedCurrentVersion() (version tidbkv.Version, err error) 42 } 43 44 const ( 45 storageVersionCacheUpdateInterval = time.Second * 2 46 ) 47 48 // StorageWithCurVersionCache adds GetCachedCurrentVersion() to tikv.Storage 49 type StorageWithCurVersionCache struct { 50 tikv.Storage 51 cacheKey string 52 } 53 54 type curVersionCacheEntry struct { 55 ts model.Ts 56 lastUpdated time.Time 57 mu sync.Mutex 58 } 59 60 var ( 61 curVersionCache = make(map[string]*curVersionCacheEntry, 1) 62 curVersionCacheMu sync.Mutex 63 ) 64 65 func newStorageWithCurVersionCache(storage tikv.Storage, cacheKey string) TiKVStorage { 66 curVersionCacheMu.Lock() 67 defer curVersionCacheMu.Unlock() 68 69 if _, exists := curVersionCache[cacheKey]; !exists { 70 curVersionCache[cacheKey] = &curVersionCacheEntry{ 71 ts: 0, 72 lastUpdated: time.Unix(0, 0), 73 } 74 } 75 76 return &StorageWithCurVersionCache{ 77 Storage: storage, 78 cacheKey: cacheKey, 79 } 80 } 81 82 // GetCachedCurrentVersion gets the cached version of currentVersion, and update the cache if necessary 83 func (s *StorageWithCurVersionCache) GetCachedCurrentVersion() (version tidbkv.Version, err error) { 84 curVersionCacheMu.Lock() 85 entry, exists := curVersionCache[s.cacheKey] 86 curVersionCacheMu.Unlock() 87 88 if !exists { 89 err = cerror.ErrCachedTSONotExists.GenWithStackByArgs() 90 log.Warn("GetCachedCurrentVersion: cache entry does not exist", zap.String("cacheKey", s.cacheKey)) 91 return 92 } 93 entry.mu.Lock() 94 defer entry.mu.Unlock() 95 96 if time.Now().After(entry.lastUpdated.Add(storageVersionCacheUpdateInterval)) { 97 var ts uint64 98 ts, err = s.CurrentTimestamp(oracle.GlobalTxnScope) 99 if err != nil { 100 return 101 } 102 ver := kv.NewVersion(ts) 103 entry.ts = ver.Ver 104 entry.lastUpdated = time.Now() 105 } 106 107 version.Ver = entry.ts 108 return 109 } 110 111 // GetSnapshotMeta returns tidb meta information 112 // TODO: Simplify the signature of this function 113 func GetSnapshotMeta(tiStore tidbkv.Storage, ts uint64) (*meta.Meta, error) { 114 snapshot := tiStore.GetSnapshot(tidbkv.NewVersion(ts)) 115 return meta.NewSnapshotMeta(snapshot), nil 116 } 117 118 // CreateTiStore creates a new tikv storage client 119 func CreateTiStore(urls string, credential *security.Credential) (kv.Storage, error) { 120 urlv, err := flags.NewURLsValue(urls) 121 if err != nil { 122 return nil, errors.Trace(err) 123 } 124 125 // Ignore error if it is already registered. 126 _ = store.Register("tikv", driver.TiKVDriver{}) 127 128 if credential.CAPath != "" { 129 conf := tidbconfig.GetGlobalConfig() 130 conf.Security.ClusterSSLCA = credential.CAPath 131 conf.Security.ClusterSSLCert = credential.CertPath 132 conf.Security.ClusterSSLKey = credential.KeyPath 133 tidbconfig.StoreGlobalConfig(conf) 134 } 135 136 tiPath := fmt.Sprintf("tikv://%s?disableGC=true", urlv.HostString()) 137 tiStore, err := store.New(tiPath) 138 if err != nil { 139 return nil, cerror.WrapError(cerror.ErrNewStore, err) 140 } 141 return tiStore, nil 142 }