github.com/turingchain2020/turingchain@v1.1.21/system/store/base.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 store 6 7 import ( 8 "sync" 9 10 dbm "github.com/turingchain2020/turingchain/common/db" 11 clog "github.com/turingchain2020/turingchain/common/log" 12 log "github.com/turingchain2020/turingchain/common/log/log15" 13 "github.com/turingchain2020/turingchain/queue" 14 "github.com/turingchain2020/turingchain/types" 15 "github.com/turingchain2020/turingchain/util" 16 ) 17 18 /* 19 模块主要的功能: 20 21 //批量写 22 1. EventStoreSet(stateHash, (k1,v1),(k2,v2),(k3,v3)) -> 返回 stateHash 23 24 //批量读 25 2. EventStoreGet(stateHash, k1,k2,k3) 26 27 */ 28 29 var slog = log.New("module", "store") 30 31 // EmptyRoot mavl树空的根hash 32 var EmptyRoot [32]byte 33 34 // SetLogLevel set log level 35 func SetLogLevel(level string) { 36 clog.SetLogLevel(level) 37 } 38 39 // DisableLog disable log 40 func DisableLog() { 41 slog.SetHandler(log.DiscardHandler()) 42 } 43 44 // SubStore store db的操作接口 45 type SubStore interface { 46 Set(datas *types.StoreSet, sync bool) ([]byte, error) 47 Get(datas *types.StoreGet) [][]byte 48 MemSet(datas *types.StoreSet, sync bool) ([]byte, error) 49 Commit(hash *types.ReqHash) ([]byte, error) 50 Rollback(req *types.ReqHash) ([]byte, error) 51 Del(req *types.StoreDel) ([]byte, error) 52 IterateRangeByStateHash(statehash []byte, start []byte, end []byte, ascending bool, fn func(key, value []byte) bool) 53 ProcEvent(msg *queue.Message) 54 55 //用升级本地交易构建store 56 MemSetUpgrade(datas *types.StoreSet, sync bool) ([]byte, error) 57 CommitUpgrade(hash *types.ReqHash) ([]byte, error) 58 } 59 60 // BaseStore 基础的store结构体 61 type BaseStore struct { 62 db dbm.DB 63 qclient queue.Client 64 done chan struct{} 65 child SubStore 66 wg sync.WaitGroup 67 } 68 69 // NewBaseStore new base store struct 70 func NewBaseStore(cfg *types.Store) *BaseStore { 71 db := dbm.NewDB("store", cfg.Driver, cfg.DbPath, cfg.DbCache) 72 db.SetCacheSize(102400) 73 store := &BaseStore{db: db} 74 store.done = make(chan struct{}, 1) 75 slog.Info("Enter store " + cfg.Name) 76 return store 77 } 78 79 // SetQueueClient set client queue for recv msg 80 func (store *BaseStore) SetQueueClient(c queue.Client) { 81 store.qclient = c 82 store.qclient.Sub("store") 83 //recv 消息的处理 84 go func() { 85 for msg := range store.qclient.Recv() { 86 //slog.Debug("store recv", "msg", msg) 87 store.processMessage(msg) 88 //slog.Debug("store process end", "msg.id", msg.Id) 89 } 90 store.done <- struct{}{} 91 }() 92 } 93 94 //Wait wait for basestore ready 95 func (store *BaseStore) Wait() {} 96 97 func (store *BaseStore) processMessage(msg *queue.Message) { 98 client := store.qclient 99 if msg.Ty == types.EventStoreSet { 100 store.wg.Add(1) 101 go func() { 102 defer store.wg.Done() 103 datas := msg.GetData().(*types.StoreSetWithSync) 104 hash, err := store.child.Set(datas.Storeset, datas.Sync) 105 if err != nil { 106 msg.Reply(client.NewMessage("", types.EventStoreSetReply, err)) 107 return 108 } 109 msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash})) 110 }() 111 } else if msg.Ty == types.EventStoreGet { 112 store.wg.Add(1) 113 go func() { 114 defer store.wg.Done() 115 datas := msg.GetData().(*types.StoreGet) 116 values := store.child.Get(datas) 117 msg.Reply(client.NewMessage("", types.EventStoreGetReply, &types.StoreReplyValue{Values: values})) 118 }() 119 } else if msg.Ty == types.EventStoreMemSet { //只是在内存中set 一下,并不改变状态 120 store.wg.Add(1) 121 go func() { 122 defer store.wg.Done() 123 datas := msg.GetData().(*types.StoreSetWithSync) 124 var hash []byte 125 var err error 126 if datas.Upgrade { 127 hash, err = store.child.MemSetUpgrade(datas.Storeset, datas.Sync) 128 } else { 129 hash, err = store.child.MemSet(datas.Storeset, datas.Sync) 130 } 131 if err != nil { 132 msg.Reply(client.NewMessage("", types.EventStoreSetReply, err)) 133 return 134 } 135 msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash})) 136 }() 137 } else if msg.Ty == types.EventStoreCommit { //把内存中set 的交易 commit 138 store.wg.Add(1) 139 go func() { 140 defer store.wg.Done() 141 req := msg.GetData().(*types.ReqHash) 142 var hash []byte 143 var err error 144 if req.Upgrade { 145 hash, err = store.child.CommitUpgrade(req) 146 } else { 147 hash, err = store.child.Commit(req) 148 } 149 if hash == nil { 150 msg.Reply(client.NewMessage("", types.EventStoreCommit, types.ErrHashNotFound)) 151 if err == types.ErrDataBaseDamage { //如果是数据库写失败,需要上报给用户 152 go util.ReportErrEventToFront(slog, client, "store", "wallet", err) 153 } 154 } else { 155 msg.Reply(client.NewMessage("", types.EventStoreCommit, &types.ReplyHash{Hash: hash})) 156 } 157 }() 158 } else if msg.Ty == types.EventStoreRollback { 159 store.wg.Add(1) 160 go func() { 161 defer store.wg.Done() 162 req := msg.GetData().(*types.ReqHash) 163 hash, err := store.child.Rollback(req) 164 if err != nil { 165 msg.Reply(client.NewMessage("", types.EventStoreRollback, types.ErrHashNotFound)) 166 } else { 167 msg.Reply(client.NewMessage("", types.EventStoreRollback, &types.ReplyHash{Hash: hash})) 168 } 169 }() 170 } else if msg.Ty == types.EventStoreGetTotalCoins { 171 store.wg.Add(1) 172 go func() { 173 defer store.wg.Done() 174 req := msg.GetData().(*types.IterateRangeByStateHash) 175 resp := &types.ReplyGetTotalCoins{} 176 resp.Count = req.Count 177 store.child.IterateRangeByStateHash(req.StateHash, req.Start, req.End, true, resp.IterateRangeByStateHash) 178 msg.Reply(client.NewMessage("", types.EventGetTotalCoinsReply, resp)) 179 }() 180 } else if msg.Ty == types.EventStoreDel { 181 store.wg.Add(1) 182 go func() { 183 defer store.wg.Done() 184 req := msg.GetData().(*types.StoreDel) 185 hash, err := store.child.Del(req) 186 if err != nil { 187 msg.Reply(client.NewMessage("", types.EventStoreDel, types.ErrHashNotFound)) 188 } else { 189 msg.Reply(client.NewMessage("", types.EventStoreDel, &types.ReplyHash{Hash: hash})) 190 } 191 }() 192 } else if msg.Ty == types.EventStoreList { 193 store.wg.Add(1) 194 go func() { 195 defer store.wg.Done() 196 req := msg.GetData().(*types.StoreList) 197 query := NewStoreListQuery(store.child, req) 198 msg.Reply(client.NewMessage("", types.EventStoreListReply, query.Run())) 199 }() 200 } else { 201 store.wg.Add(1) 202 go func() { 203 defer store.wg.Done() 204 store.child.ProcEvent(msg) 205 }() 206 } 207 } 208 209 // SetChild 设置BaseStore中的子存储参数 210 func (store *BaseStore) SetChild(sub SubStore) { 211 store.child = sub 212 } 213 214 // Close 关闭BaseStore 相关资源包括数据库、client等 215 func (store *BaseStore) Close() { 216 if store.qclient != nil { 217 store.qclient.Close() 218 <-store.done 219 store.wg.Wait() 220 } 221 store.db.Close() 222 } 223 224 // GetDB 返回 store db 225 func (store *BaseStore) GetDB() dbm.DB { 226 return store.db 227 } 228 229 // GetQueueClient 返回store模块的client 230 func (store *BaseStore) GetQueueClient() queue.Client { 231 return store.qclient 232 } 233 234 // NewStoreListQuery new store list query object 235 func NewStoreListQuery(store SubStore, req *types.StoreList) *StorelistQuery { 236 reply := &types.StoreListReply{Start: req.Start, End: req.End, Suffix: req.Suffix, Count: req.Count, Mode: req.Mode} 237 return &StorelistQuery{StoreListReply: reply, req: req, store: store} 238 } 239 240 // StorelistQuery defines a type store list query 241 type StorelistQuery struct { 242 store SubStore 243 req *types.StoreList 244 *types.StoreListReply 245 } 246 247 // Run store list query 248 func (t *StorelistQuery) Run() *types.StoreListReply { 249 t.store.IterateRangeByStateHash(t.req.StateHash, t.req.Start, t.req.End, true, t.IterateCallBack) 250 return t.StoreListReply 251 } 252 253 // IterateCallBack store list query iterate callback 254 func (t *StorelistQuery) IterateCallBack(key, value []byte) bool { 255 if t.Mode == 1 { //[start, end)模式 256 if t.Num >= t.Count { 257 t.NextKey = key 258 return true 259 } 260 t.Num++ 261 t.Keys = append(t.Keys, cloneByte(key)) 262 t.Values = append(t.Values, cloneByte(value)) 263 return false 264 } 265 if t.Mode == 2 { //prefix + suffix模式,要对按prefix得到的数据key进行suffix的判断,符合条件的数据才是最终要的数据 266 if len(key) > len(t.Suffix) { 267 if string(key[len(key)-len(t.Suffix):]) == string(t.Suffix) { 268 t.Num++ 269 t.Keys = append(t.Keys, cloneByte(key)) 270 t.Values = append(t.Values, cloneByte(value)) 271 if t.Num >= t.Count { 272 t.NextKey = key 273 return true 274 } 275 return false 276 } 277 return false 278 } 279 return false 280 } 281 slog.Error("StoreListReply.IterateCallBack unsupported mode", "mode", t.Mode) 282 return true 283 } 284 285 func cloneByte(v []byte) []byte { 286 value := make([]byte, len(v)) 287 copy(value, v) 288 return value 289 }