github.com/turingchain2020/turingchain@v1.1.21/system/store/mavl/mavl.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package mavl 默克尔平衡树接口 6 package mavl 7 8 import ( 9 "sync" 10 11 "github.com/turingchain2020/turingchain/common" 12 clog "github.com/turingchain2020/turingchain/common/log" 13 log "github.com/turingchain2020/turingchain/common/log/log15" 14 "github.com/turingchain2020/turingchain/queue" 15 drivers "github.com/turingchain2020/turingchain/system/store" 16 mavl "github.com/turingchain2020/turingchain/system/store/mavl/db" 17 "github.com/turingchain2020/turingchain/types" 18 ) 19 20 var mlog = log.New("module", "mavl") 21 22 // SetLogLevel set log level 23 func SetLogLevel(level string) { 24 clog.SetLogLevel(level) 25 } 26 27 // DisableLog disable log 28 func DisableLog() { 29 mlog.SetHandler(log.DiscardHandler()) 30 } 31 32 // Store mavl store struct 33 type Store struct { 34 *drivers.BaseStore 35 trees *sync.Map 36 treeCfg *mavl.TreeConfig 37 } 38 39 func init() { 40 drivers.Reg("mavl", New) 41 } 42 43 type subConfig struct { 44 // 是否使能mavl加前缀 45 EnableMavlPrefix bool `json:"enableMavlPrefix"` 46 EnableMVCC bool `json:"enableMVCC"` 47 // 是否使能mavl数据裁剪 48 EnableMavlPrune bool `json:"enableMavlPrune"` 49 // 裁剪高度间隔 50 PruneHeight int32 `json:"pruneHeight"` 51 // 是否使能内存树 52 EnableMemTree bool `json:"enableMemTree"` 53 // 是否使能内存树中叶子节点 54 EnableMemVal bool `json:"enableMemVal"` 55 // 缓存close ticket数目 56 TkCloseCacheLen int32 `json:"tkCloseCacheLen"` 57 } 58 59 // New new mavl store module 60 func New(cfg *types.Store, sub []byte, turingchaincfg *types.TuringchainConfig) queue.Module { 61 bs := drivers.NewBaseStore(cfg) 62 var subcfg subConfig 63 if sub != nil { 64 types.MustDecode(sub, &subcfg) 65 } 66 // 开启裁剪需要同时开启前缀树 67 if subcfg.EnableMavlPrune { 68 subcfg.EnableMavlPrefix = subcfg.EnableMavlPrune 69 } 70 treeCfg := &mavl.TreeConfig{ 71 EnableMavlPrefix: subcfg.EnableMavlPrefix, 72 EnableMVCC: subcfg.EnableMVCC, 73 EnableMavlPrune: subcfg.EnableMavlPrune, 74 PruneHeight: subcfg.PruneHeight, 75 EnableMemTree: subcfg.EnableMemTree, 76 EnableMemVal: subcfg.EnableMemVal, 77 TkCloseCacheLen: subcfg.TkCloseCacheLen, 78 } 79 mavls := &Store{bs, &sync.Map{}, treeCfg} 80 mavl.InitGlobalMem(treeCfg) 81 bs.SetChild(mavls) 82 return mavls 83 } 84 85 // Close close mavl store 86 func (mavls *Store) Close() { 87 mavl.ClosePrune() 88 mavls.BaseStore.Close() 89 mlog.Info("store mavl closed") 90 } 91 92 // Set set k v to mavl store db; sync is true represent write sync 93 func (mavls *Store) Set(datas *types.StoreSet, sync bool) ([]byte, error) { 94 return mavl.SetKVPair(mavls.GetDB(), datas, sync, mavls.treeCfg) 95 } 96 97 // Get get values by keys 98 func (mavls *Store) Get(datas *types.StoreGet) [][]byte { 99 var tree *mavl.Tree 100 var err error 101 values := make([][]byte, len(datas.Keys)) 102 search := string(datas.StateHash) 103 if data, ok := mavls.trees.Load(search); ok && data != nil { 104 tree = data.(*mavl.Tree) 105 } else { 106 tree = mavl.NewTree(mavls.GetDB(), true, mavls.treeCfg) 107 //get接口也应该传入高度 108 //tree.SetBlockHeight(datas.Height) 109 err = tree.Load(datas.StateHash) 110 mlog.Debug("store mavl get tree", "err", err, "StateHash", common.ToHex(datas.StateHash)) 111 } 112 if err == nil { 113 for i := 0; i < len(datas.Keys); i++ { 114 _, value, exit := tree.Get(datas.Keys[i]) 115 if exit { 116 values[i] = value 117 } 118 } 119 } 120 return values 121 } 122 123 // MemSet set keys values to memcory mavl, return root hash and error 124 func (mavls *Store) MemSet(datas *types.StoreSet, sync bool) ([]byte, error) { 125 beg := types.Now() 126 defer func() { 127 mlog.Debug("MemSet", "cost", types.Since(beg)) 128 }() 129 if len(datas.KV) == 0 { 130 mlog.Info("store mavl memset,use preStateHash as stateHash for kvset is null") 131 mavls.trees.Store(string(datas.StateHash), nil) 132 return datas.StateHash, nil 133 } 134 tree := mavl.NewTree(mavls.GetDB(), sync, mavls.treeCfg) 135 tree.SetBlockHeight(datas.Height) 136 err := tree.Load(datas.StateHash) 137 if err != nil { 138 return nil, err 139 } 140 for i := 0; i < len(datas.KV); i++ { 141 tree.Set(datas.KV[i].Key, datas.KV[i].Value) 142 } 143 hash := tree.Hash() 144 mavls.trees.Store(string(hash), tree) 145 return hash, nil 146 } 147 148 // Commit convert memcory mavl to storage db 149 func (mavls *Store) Commit(req *types.ReqHash) ([]byte, error) { 150 beg := types.Now() 151 defer func() { 152 mlog.Debug("Commit", "cost", types.Since(beg)) 153 }() 154 tree, ok := mavls.trees.Load(string(req.Hash)) 155 if !ok { 156 mlog.Error("store mavl commit", "err", types.ErrHashNotFound) 157 return nil, types.ErrHashNotFound 158 } 159 if tree == nil { 160 mlog.Info("store mavl commit,do nothing for kvset is null") 161 mavls.trees.Delete(string(req.Hash)) 162 return req.Hash, nil 163 } 164 hash := tree.(*mavl.Tree).Save() 165 if hash == nil { 166 mlog.Error("store mavl commit", "err", types.ErrHashNotFound) 167 return nil, types.ErrDataBaseDamage 168 } 169 mavls.trees.Delete(string(req.Hash)) 170 return req.Hash, nil 171 } 172 173 // MemSetUpgrade cacl mavl, but not store tree, return root hash and error 174 func (mavls *Store) MemSetUpgrade(datas *types.StoreSet, sync bool) ([]byte, error) { 175 beg := types.Now() 176 defer func() { 177 mlog.Debug("MemSet", "cost", types.Since(beg)) 178 }() 179 if len(datas.KV) == 0 { 180 mlog.Info("store mavl memset,use preStateHash as stateHash for kvset is null") 181 mavls.trees.Store(string(datas.StateHash), nil) 182 return datas.StateHash, nil 183 } 184 tree := mavl.NewTree(mavls.GetDB(), sync, mavls.treeCfg) 185 tree.SetBlockHeight(datas.Height) 186 err := tree.Load(datas.StateHash) 187 if err != nil { 188 return nil, err 189 } 190 for i := 0; i < len(datas.KV); i++ { 191 tree.Set(datas.KV[i].Key, datas.KV[i].Value) 192 } 193 hash := tree.Hash() 194 return hash, nil 195 } 196 197 // CommitUpgrade convert memcory mavl to storage db 198 func (mavls *Store) CommitUpgrade(req *types.ReqHash) ([]byte, error) { 199 return req.Hash, nil 200 } 201 202 // Rollback 回退将缓存的mavl树删除掉 203 func (mavls *Store) Rollback(req *types.ReqHash) ([]byte, error) { 204 beg := types.Now() 205 defer func() { 206 mlog.Debug("Rollback", "cost", types.Since(beg)) 207 }() 208 _, ok := mavls.trees.Load(string(req.Hash)) 209 if !ok { 210 mlog.Error("store mavl rollback", "err", types.ErrHashNotFound) 211 return nil, types.ErrHashNotFound 212 } 213 mavls.trees.Delete(string(req.Hash)) 214 return req.Hash, nil 215 } 216 217 // IterateRangeByStateHash 迭代实现功能; statehash:当前状态hash, start:开始查找的key, end: 结束的key, ascending:升序,降序, fn 迭代回调函数 218 func (mavls *Store) IterateRangeByStateHash(statehash []byte, start []byte, end []byte, ascending bool, fn func(key, value []byte) bool) { 219 mavl.IterateRangeByStateHash(mavls.GetDB(), statehash, start, end, ascending, mavls.treeCfg, fn) 220 } 221 222 // ProcEvent not support message 223 func (mavls *Store) ProcEvent(msg *queue.Message) { 224 if msg == nil { 225 return 226 } 227 msg.ReplyErr("Store", types.ErrActionNotSupport) 228 } 229 230 // Del ... 231 func (mavls *Store) Del(req *types.StoreDel) ([]byte, error) { 232 //not support 233 return nil, nil 234 }