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 }