github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/flatkv/store.go (about) 1 package flatkv 2 3 import ( 4 "sync/atomic" 5 "time" 6 7 dbm "github.com/fibonacci-chain/fbc/libs/tm-db" 8 "github.com/spf13/viper" 9 ) 10 11 const ( 12 latestVersionKey = "s/latest" 13 14 FlagEnable = "enable-flat-kv" 15 ) 16 17 // Store wraps app_flat_kv.db for read performance. 18 type Store struct { 19 db dbm.DB 20 cache *Cache 21 readTime int64 22 writeTime int64 23 readCount int64 24 writeCount int64 25 enable bool 26 } 27 28 func NewStore(db dbm.DB) *Store { 29 return &Store{ 30 db: db, 31 cache: newCache(), 32 readTime: 0, 33 writeTime: 0, 34 readCount: 0, 35 writeCount: 0, 36 enable: viper.GetBool(FlagEnable), 37 } 38 } 39 40 func (st *Store) Enable() bool { 41 return st.enable 42 } 43 func (st *Store) Get(key []byte) []byte { 44 if !st.enable { 45 return nil 46 } 47 if cacheVal, ok := st.cache.get(key); ok { 48 return cacheVal 49 } 50 ts := time.Now() 51 value, err := st.db.Get(key) 52 st.addDBReadTime(time.Now().Sub(ts).Nanoseconds()) 53 st.addDBReadCount() 54 if err == nil && len(value) != 0 { 55 return value 56 } 57 return nil 58 } 59 60 func (st *Store) Set(key, value []byte) { 61 if !st.enable { 62 return 63 } 64 st.cache.add(key, value) 65 } 66 67 func (st *Store) Has(key []byte) bool { 68 if !st.enable { 69 return false 70 } 71 if _, ok := st.cache.get(key); ok { 72 return true 73 } 74 st.addDBReadCount() 75 if ok, err := st.db.Has(key); err == nil && ok { 76 return true 77 } 78 return false 79 } 80 81 func (st *Store) Delete(key []byte) { 82 if !st.enable { 83 return 84 } 85 ts := time.Now() 86 st.db.Delete(key) 87 st.addDBWriteTime(time.Now().Sub(ts).Nanoseconds()) 88 st.addDBWriteCount() 89 st.cache.delete(key) 90 } 91 92 func (st *Store) Commit(version int64) { 93 if !st.enable { 94 return 95 } 96 ts := time.Now() 97 // commit to flat kv db 98 batch := st.db.NewBatch() 99 defer batch.Close() 100 cache := st.cache.copy() 101 for key, value := range cache { 102 batch.Set([]byte(key), value) 103 } 104 st.setLatestVersion(batch, version) 105 batch.Write() 106 st.addDBWriteTime(time.Now().Sub(ts).Nanoseconds()) 107 st.addDBWriteCount() 108 // clear cache 109 st.cache.reset() 110 } 111 112 func (st *Store) ResetCount() { 113 if !st.enable { 114 return 115 } 116 st.resetDBReadTime() 117 st.resetDBWriteTime() 118 st.resetDBReadCount() 119 st.resetDBWriteCount() 120 } 121 122 func (st *Store) GetDBReadTime() int { 123 if !st.enable { 124 return 0 125 } 126 return int(atomic.LoadInt64(&st.readTime)) 127 } 128 129 func (st *Store) addDBReadTime(ts int64) { 130 atomic.AddInt64(&st.readTime, ts) 131 } 132 133 func (st *Store) resetDBReadTime() { 134 atomic.StoreInt64(&st.readTime, 0) 135 } 136 137 func (st *Store) GetDBWriteTime() int { 138 if !st.enable { 139 return 0 140 } 141 return int(atomic.LoadInt64(&st.writeTime)) 142 } 143 144 func (st *Store) addDBWriteTime(ts int64) { 145 atomic.AddInt64(&st.writeTime, ts) 146 } 147 148 func (st *Store) resetDBWriteTime() { 149 atomic.StoreInt64(&st.writeTime, 0) 150 } 151 152 func (st *Store) GetDBReadCount() int { 153 if !st.enable { 154 return 0 155 } 156 return int(atomic.LoadInt64(&st.readCount)) 157 } 158 159 func (st *Store) addDBReadCount() { 160 atomic.AddInt64(&st.readCount, 1) 161 } 162 163 func (st *Store) resetDBReadCount() { 164 atomic.StoreInt64(&st.readCount, 0) 165 } 166 167 func (st *Store) GetDBWriteCount() int { 168 if !st.enable { 169 return 0 170 } 171 return int(atomic.LoadInt64(&st.writeCount)) 172 } 173 174 func (st *Store) addDBWriteCount() { 175 atomic.AddInt64(&st.writeCount, 1) 176 } 177 178 func (st *Store) resetDBWriteCount() { 179 atomic.StoreInt64(&st.writeCount, 0) 180 } 181 182 func (st *Store) GetLatestVersion() int64 { 183 if !st.enable { 184 return 0 185 } 186 return getLatestVersion(st.db) 187 } 188 189 func getLatestVersion(db dbm.DB) int64 { 190 var latest int64 191 latestBytes, err := db.Get([]byte(latestVersionKey)) 192 if err != nil { 193 panic(err) 194 } else if latestBytes == nil { 195 return 0 196 } 197 198 err = cdc.UnmarshalBinaryLengthPrefixed(latestBytes, &latest) 199 if err != nil { 200 panic(err) 201 } 202 203 return latest 204 } 205 206 func (st *Store) setLatestVersion(batch dbm.Batch, version int64) { 207 latestBytes := cdc.MustMarshalBinaryLengthPrefixed(version) 208 batch.Set([]byte(latestVersionKey), latestBytes) 209 }