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  }