github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/params/types/upgrade_cache.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix" 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 11 ) 12 13 var ( 14 upgradeInfoPreifx = []byte("upgrade") 15 readyPrefix = []byte("readyUpgrade") 16 ) 17 18 type UpgradeCache struct { 19 storeKey *sdk.KVStoreKey 20 logger log.Logger 21 cdc *codec.Codec 22 23 readyLock sync.Mutex 24 upgradeReadyMap map[string][]func(UpgradeInfo) 25 infoLock sync.Mutex 26 upgradeInfoCache map[string]UpgradeInfo 27 } 28 29 func NewUpgreadeCache(storeKey *sdk.KVStoreKey, logger log.Logger, cdc *codec.Codec) *UpgradeCache { 30 return &UpgradeCache{ 31 storeKey: storeKey, 32 logger: logger, 33 cdc: cdc, 34 35 upgradeReadyMap: make(map[string][]func(UpgradeInfo)), 36 upgradeInfoCache: make(map[string]UpgradeInfo), 37 } 38 } 39 40 func (uc *UpgradeCache) ReadUpgradeInfo(ctx sdk.Context, name string) (UpgradeInfo, error) { 41 if ctx.UseParamCache() { 42 info, exist := uc.readUpgradeInfo(name) 43 if exist { 44 return info, nil 45 } 46 } 47 48 info, err := readUpgradeInfoFromStore(ctx, name, uc.storeKey, uc.cdc) 49 if err != nil { 50 return info, err 51 } 52 53 uc.writeUpgradeInfo(info) 54 return info, nil 55 } 56 57 func (uc *UpgradeCache) ClaimReadyForUpgrade(name string, cb func(UpgradeInfo)) { 58 uc.writeClaim(name, cb) 59 } 60 61 func (uc *UpgradeCache) QueryReadyForUpgrade(name string) ([]func(UpgradeInfo), bool) { 62 return uc.readClaim(name) 63 } 64 65 func (uc *UpgradeCache) WriteUpgradeInfo(ctx sdk.Context, info UpgradeInfo, forceCover bool) sdk.Error { 66 if err := writeUpgradeInfoToStore(ctx, info, forceCover, uc.storeKey, uc.cdc, uc.logger); err != nil { 67 return err 68 } 69 70 // store is updated, remove the info from cache so 71 // makeing ReadUpgradeInfo to re-read from store. 72 uc.removeUpgradeInfo(info.Name) 73 return nil 74 } 75 76 func (uc *UpgradeCache) IsUpgradeExist(ctx sdk.Context, name string) bool { 77 store := getUpgradeStore(ctx, uc.storeKey) 78 return store.Has([]byte(name)) 79 } 80 81 func (uc *UpgradeCache) IterateAllUpgradeInfo(ctx sdk.Context, cb func(info UpgradeInfo) (stop bool)) sdk.Error { 82 store := getUpgradeStore(ctx, uc.storeKey) 83 iterator := store.Iterator(nil, nil) 84 defer iterator.Close() 85 86 for ; iterator.Valid(); iterator.Next() { 87 data := iterator.Value() 88 89 var info UpgradeInfo 90 uc.cdc.MustUnmarshalJSON(data, &info) 91 92 if stop := cb(info); stop { 93 break 94 } 95 } 96 97 return nil 98 } 99 100 func (uc *UpgradeCache) readUpgradeInfo(name string) (UpgradeInfo, bool) { 101 uc.infoLock.Lock() 102 defer uc.infoLock.Unlock() 103 104 info, ok := uc.upgradeInfoCache[name] 105 return info, ok 106 } 107 108 func (uc *UpgradeCache) removeUpgradeInfo(name string) { 109 uc.infoLock.Lock() 110 defer uc.infoLock.Unlock() 111 112 delete(uc.upgradeInfoCache, name) 113 } 114 115 func (uc *UpgradeCache) writeUpgradeInfo(info UpgradeInfo) { 116 uc.infoLock.Lock() 117 defer uc.infoLock.Unlock() 118 119 uc.upgradeInfoCache[info.Name] = info 120 } 121 122 func (uc *UpgradeCache) readClaim(name string) ([]func(UpgradeInfo), bool) { 123 uc.readyLock.Lock() 124 defer uc.readyLock.Unlock() 125 126 cb, ok := uc.upgradeReadyMap[name] 127 return cb, ok 128 } 129 130 func (uc *UpgradeCache) writeClaim(name string, cb func(UpgradeInfo)) { 131 uc.readyLock.Lock() 132 defer uc.readyLock.Unlock() 133 134 readies, ok := uc.upgradeReadyMap[name] 135 if !ok { 136 uc.upgradeReadyMap[name] = []func(UpgradeInfo){cb} 137 } else { 138 uc.upgradeReadyMap[name] = append(readies, cb) 139 } 140 } 141 142 func readUpgradeInfoFromStore(ctx sdk.Context, name string, skey *sdk.KVStoreKey, cdc *codec.Codec) (UpgradeInfo, sdk.Error) { 143 store := getUpgradeStore(ctx, skey) 144 145 data := store.Get([]byte(name)) 146 if len(data) == 0 { 147 err := fmt.Errorf("upgrade '%s' is not exist", name) 148 return UpgradeInfo{}, err 149 } 150 151 var info UpgradeInfo 152 cdc.MustUnmarshalJSON(data, &info) 153 return info, nil 154 } 155 156 func writeUpgradeInfoToStore(ctx sdk.Context, info UpgradeInfo, forceCover bool, skey *sdk.KVStoreKey, cdc *codec.Codec, logger log.Logger) sdk.Error { 157 key := []byte(info.Name) 158 159 store := getUpgradeStore(ctx, skey) 160 if !forceCover && store.Has(key) { 161 logger.Error("upgrade proposal name has been exist", "proposal name", info.Name) 162 return sdk.ErrInternal(fmt.Sprintf("upgrade proposal name '%s' has been exist", info.Name)) 163 } 164 165 data := cdc.MustMarshalJSON(info) 166 store.Set(key, data) 167 168 return nil 169 } 170 171 func getUpgradeStore(ctx sdk.Context, skey *sdk.KVStoreKey) sdk.KVStore { 172 return prefix.NewStore(ctx.KVStore(skey), upgradeInfoPreifx) 173 } 174 175 func readReadyFromStore(ctx sdk.Context, name string, skey *sdk.KVStoreKey) ([]byte, bool) { 176 store := getReadyStore(ctx, skey) 177 data := store.Get([]byte(name)) 178 return data, len(data) != 0 179 } 180 181 func writeReadyToStore(ctx sdk.Context, name string, skey *sdk.KVStoreKey) { 182 store := getReadyStore(ctx, skey) 183 store.Set([]byte(name), []byte(name)) 184 } 185 186 func getReadyStore(ctx sdk.Context, skey *sdk.KVStoreKey) sdk.KVStore { 187 return prefix.NewStore(ctx.KVStore(skey), readyPrefix) 188 }