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  }