github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/ledger/kvledger/txmgmt/rwsetutil/rwset_builder.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package rwsetutil 18 19 import ( 20 "github.com/hyperledger/fabric/common/flogging" 21 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 22 "github.com/hyperledger/fabric/core/ledger/util" 23 "github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset" 24 ) 25 26 var logger = flogging.MustGetLogger("rwsetutil") 27 28 type nsRWs struct { 29 readMap map[string]*kvrwset.KVRead //for mvcc validation 30 writeMap map[string]*kvrwset.KVWrite 31 rangeQueriesMap map[rangeQueryKey]*kvrwset.RangeQueryInfo //for phantom read validation 32 rangeQueriesKeys []rangeQueryKey 33 } 34 35 func newNsRWs() *nsRWs { 36 return &nsRWs{make(map[string]*kvrwset.KVRead), 37 make(map[string]*kvrwset.KVWrite), 38 make(map[rangeQueryKey]*kvrwset.RangeQueryInfo), nil} 39 } 40 41 type rangeQueryKey struct { 42 startKey string 43 endKey string 44 itrExhausted bool 45 } 46 47 // RWSetBuilder helps building the read-write set 48 type RWSetBuilder struct { 49 rwMap map[string]*nsRWs 50 } 51 52 // NewRWSetBuilder constructs a new instance of RWSetBuilder 53 func NewRWSetBuilder() *RWSetBuilder { 54 return &RWSetBuilder{make(map[string]*nsRWs)} 55 } 56 57 // AddToReadSet adds a key and corresponding version to the read-set 58 func (rws *RWSetBuilder) AddToReadSet(ns string, key string, version *version.Height) { 59 nsRWs := rws.getOrCreateNsRW(ns) 60 nsRWs.readMap[key] = NewKVRead(key, version) 61 } 62 63 // AddToWriteSet adds a key and value to the write-set 64 func (rws *RWSetBuilder) AddToWriteSet(ns string, key string, value []byte) { 65 nsRWs := rws.getOrCreateNsRW(ns) 66 nsRWs.writeMap[key] = newKVWrite(key, value) 67 } 68 69 // AddToRangeQuerySet adds a range query info for performing phantom read validation 70 func (rws *RWSetBuilder) AddToRangeQuerySet(ns string, rqi *kvrwset.RangeQueryInfo) { 71 nsRWs := rws.getOrCreateNsRW(ns) 72 key := rangeQueryKey{rqi.StartKey, rqi.EndKey, rqi.ItrExhausted} 73 _, ok := nsRWs.rangeQueriesMap[key] 74 if !ok { 75 nsRWs.rangeQueriesMap[key] = rqi 76 nsRWs.rangeQueriesKeys = append(nsRWs.rangeQueriesKeys, key) 77 } 78 } 79 80 // GetTxReadWriteSet returns the read-write set in the form that can be serialized 81 func (rws *RWSetBuilder) GetTxReadWriteSet() *TxRwSet { 82 txRWSet := &TxRwSet{} 83 sortedNamespaces := util.GetSortedKeys(rws.rwMap) 84 for _, ns := range sortedNamespaces { 85 //Get namespace specific read-writes 86 nsReadWriteMap := rws.rwMap[ns] 87 88 //add read set 89 var reads []*kvrwset.KVRead 90 sortedReadKeys := util.GetSortedKeys(nsReadWriteMap.readMap) 91 for _, key := range sortedReadKeys { 92 reads = append(reads, nsReadWriteMap.readMap[key]) 93 } 94 95 //add write set 96 var writes []*kvrwset.KVWrite 97 sortedWriteKeys := util.GetSortedKeys(nsReadWriteMap.writeMap) 98 for _, key := range sortedWriteKeys { 99 writes = append(writes, nsReadWriteMap.writeMap[key]) 100 } 101 102 //add range query info 103 var rangeQueriesInfo []*kvrwset.RangeQueryInfo 104 rangeQueriesMap := nsReadWriteMap.rangeQueriesMap 105 for _, key := range nsReadWriteMap.rangeQueriesKeys { 106 rangeQueriesInfo = append(rangeQueriesInfo, rangeQueriesMap[key]) 107 } 108 kvRWs := &kvrwset.KVRWSet{Reads: reads, Writes: writes, RangeQueriesInfo: rangeQueriesInfo} 109 nsRWs := &NsRwSet{ns, kvRWs} 110 txRWSet.NsRwSets = append(txRWSet.NsRwSets, nsRWs) 111 } 112 return txRWSet 113 } 114 115 func (rws *RWSetBuilder) getOrCreateNsRW(ns string) *nsRWs { 116 var nsRWs *nsRWs 117 var ok bool 118 if nsRWs, ok = rws.rwMap[ns]; !ok { 119 nsRWs = newNsRWs() 120 rws.rwMap[ns] = nsRWs 121 } 122 return nsRWs 123 }