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  }