github.com/turingchain2020/turingchain@v1.1.21/system/dapp/util.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 dapp
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/turingchain2020/turingchain/common/db"
    11  	"github.com/turingchain2020/turingchain/types"
    12  )
    13  
    14  // HeightIndexStr height and index format string
    15  func HeightIndexStr(height, index int64) string {
    16  	v := height*types.MaxTxsPerBlock + index
    17  	return fmt.Sprintf("%018d", v)
    18  }
    19  
    20  //KVCreator 创建KV的辅助工具
    21  type KVCreator struct {
    22  	kvs          []*types.KeyValue
    23  	kvdb         db.KV
    24  	autorollback bool
    25  	prefix       []byte
    26  	rollbackkey  []byte
    27  	rollbackkvs  []*types.KeyValue
    28  }
    29  
    30  //NewKVCreator 创建创建者
    31  //注意: 自动回滚可能会严重影响系统性能
    32  func NewKVCreator(kv db.KV, prefix []byte, rollbackkey []byte) *KVCreator {
    33  	return &KVCreator{
    34  		kvdb:         kv,
    35  		prefix:       prefix,
    36  		rollbackkey:  rollbackkey,
    37  		autorollback: rollbackkey != nil,
    38  	}
    39  }
    40  
    41  func (c *KVCreator) addPrefix(key []byte) []byte {
    42  	newkey := append([]byte{}, c.prefix...)
    43  	return append(newkey, key...)
    44  }
    45  
    46  func (c *KVCreator) add(key, value []byte, set bool) *KVCreator {
    47  	if c.prefix != nil {
    48  		key = c.addPrefix(key)
    49  	}
    50  	return c.addnoprefix(key, value, set)
    51  }
    52  
    53  func (c *KVCreator) addnoprefix(key, value []byte, set bool) *KVCreator {
    54  	if c.autorollback {
    55  		prev, err := c.kvdb.Get(key)
    56  		//数据库发生错误,直接panic (再执行器中会recover)
    57  		if err != nil && err != types.ErrNotFound {
    58  			panic(err)
    59  		}
    60  		if value == nil { //del
    61  			//不需要做任何处理, 也不用加入 kvs
    62  			if err == types.ErrNotFound {
    63  				return c
    64  			}
    65  			rb := &types.KeyValue{Key: key, Value: prev}
    66  			c.rollbackkvs = append(c.rollbackkvs, rb)
    67  		} else {
    68  			if err == types.ErrNotFound { //add
    69  				rb := &types.KeyValue{Key: key}
    70  				c.rollbackkvs = append(c.rollbackkvs, rb)
    71  			} else { //update
    72  				rb := &types.KeyValue{Key: key, Value: prev}
    73  				c.rollbackkvs = append(c.rollbackkvs, rb)
    74  			}
    75  		}
    76  	}
    77  	c.kvs = append(c.kvs, &types.KeyValue{Key: key, Value: value})
    78  	if set {
    79  		err := c.kvdb.Set(key, value)
    80  		if err != nil {
    81  			panic(err)
    82  		}
    83  	}
    84  	return c
    85  }
    86  
    87  //Get 从KV中获取 value
    88  func (c *KVCreator) Get(key []byte) ([]byte, error) {
    89  	if c.prefix != nil {
    90  		newkey := c.addPrefix(key)
    91  		return c.kvdb.Get(newkey)
    92  	}
    93  	return c.kvdb.Get(key)
    94  }
    95  
    96  //GetNoPrefix 从KV中获取 value, 不自动添加前缀
    97  func (c *KVCreator) GetNoPrefix(key []byte) ([]byte, error) {
    98  	return c.kvdb.Get(key)
    99  }
   100  
   101  //Add add and set to kvdb
   102  func (c *KVCreator) Add(key, value []byte) *KVCreator {
   103  	return c.add(key, value, true)
   104  }
   105  
   106  //AddNoPrefix 不自动添加prefix
   107  func (c *KVCreator) AddNoPrefix(key, value []byte) *KVCreator {
   108  	return c.addnoprefix(key, value, true)
   109  }
   110  
   111  //AddListNoPrefix only add KVList
   112  func (c *KVCreator) AddListNoPrefix(list []*types.KeyValue) *KVCreator {
   113  	for _, kv := range list {
   114  		c.addnoprefix(kv.Key, kv.Value, true)
   115  	}
   116  	return c
   117  }
   118  
   119  //AddList only add KVList
   120  func (c *KVCreator) AddList(list []*types.KeyValue) *KVCreator {
   121  	for _, kv := range list {
   122  		c.add(kv.Key, kv.Value, true)
   123  	}
   124  	return c
   125  }
   126  
   127  //AddKVOnly only add KV(can't auto rollback)
   128  func (c *KVCreator) AddKVOnly(key, value []byte) *KVCreator {
   129  	if c.autorollback {
   130  		panic("autorollback open, AddKVOnly not allow")
   131  	}
   132  	return c.add(key, value, false)
   133  }
   134  
   135  //AddKVListOnly only add KVList (can't auto rollback)
   136  func (c *KVCreator) AddKVListOnly(list []*types.KeyValue) *KVCreator {
   137  	if c.autorollback {
   138  		panic("autorollback open, AddKVListOnly not allow")
   139  	}
   140  	for _, kv := range list {
   141  		c.add(kv.Key, kv.Value, false)
   142  	}
   143  	return c
   144  }
   145  
   146  //KVList 读取所有的kv列表
   147  func (c *KVCreator) KVList() []*types.KeyValue {
   148  	return c.kvs
   149  }
   150  
   151  //AddRollbackKV 添加回滚数据到 KV
   152  func (c *KVCreator) AddRollbackKV() {
   153  	rbLog := c.rollbackLog()
   154  	if rbLog != nil {
   155  		v := types.Encode(rbLog)
   156  		c.kvs = append(c.kvs, &types.KeyValue{Key: c.rollbackkey, Value: v})
   157  	}
   158  
   159  }
   160  
   161  //DelRollbackKV 删除rollback kv
   162  func (c *KVCreator) DelRollbackKV() {
   163  	if len(c.kvs) > 0 {
   164  		c.kvs = append(c.kvs, &types.KeyValue{Key: c.rollbackkey})
   165  	}
   166  }
   167  
   168  //GetRollbackKVList 获取 rollback 到 Key and Vaue
   169  func (c *KVCreator) GetRollbackKVList() ([]*types.KeyValue, error) {
   170  	data, err := c.kvdb.Get(c.rollbackkey)
   171  	if err == types.ErrNotFound {
   172  		return nil, nil
   173  	}
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	var rollbacklog types.ReceiptLog
   178  	err = types.Decode(data, &rollbacklog)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	kvs, err := c.parseRollback(&rollbacklog)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  	//reverse kvs
   187  	for left, right := 0, len(kvs)-1; left < right; left, right = left+1, right-1 {
   188  		kvs[left], kvs[right] = kvs[right], kvs[left]
   189  	}
   190  	return kvs, nil
   191  }
   192  
   193  //rollbackLog rollback log
   194  func (c *KVCreator) rollbackLog() *types.ReceiptLog {
   195  	if len(c.rollbackkvs) == 0 {
   196  		return nil
   197  	}
   198  	data := types.Encode(&types.LocalDBSet{KV: c.rollbackkvs})
   199  	return &types.ReceiptLog{Ty: types.TyLogRollback, Log: data}
   200  }
   201  
   202  //ParseRollback 解析rollback的数据
   203  func (c *KVCreator) parseRollback(log *types.ReceiptLog) ([]*types.KeyValue, error) {
   204  	var data types.LocalDBSet
   205  	if log.Ty != types.TyLogRollback {
   206  		return nil, types.ErrInvalidParam
   207  	}
   208  	err := types.Decode(log.Log, &data)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	return data.KV, nil
   213  }
   214  
   215  //AddToLogs add not empty log to logs
   216  func (c *KVCreator) AddToLogs(logs []*types.ReceiptLog) []*types.ReceiptLog {
   217  	if len(c.rollbackkvs) == 0 {
   218  		return logs
   219  	}
   220  	return append(logs, c.rollbackLog())
   221  }