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  }