Skip to content

Commit 7f63749

Browse files
committed
[FAB-9817] Use Tx-simulator after obtaining results
In the current implementation, a transaction simulator instance releases itself (as an caution for optimization) when the caller has obtained the simulation results. The assumption was that this will be the last step in using the simulator. However, now there is a situation where gossip would need to obtain the simulation results and based on the private data present in the simulation results, it will use the simulator to fetch the collection configurations. This CR removes this self-release behavior. Also, a test is added to make sure that the previously obtained rwset are not affected by further data operations on the simulator. Change-Id: Ic5664cd8d4536b31c603154ede573bbf3c095e76 Signed-off-by: manish <manish.sethi@gmail.com>
1 parent 109db5b commit 7f63749

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/lockbased_tx_simulator.go

-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ func (s *lockBasedTxSimulator) ExecuteQueryOnPrivateData(namespace, collection,
125125
// GetTxSimulationResults implements method in interface `ledger.TxSimulator`
126126
func (s *lockBasedTxSimulator) GetTxSimulationResults() (*ledger.TxSimulationResults, error) {
127127
logger.Debugf("Simulation completed, getting simulation results")
128-
s.Done()
129128
if s.helper.err != nil {
130129
return nil, s.helper.err
131130
}

core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/txmgr_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ SPDX-License-Identifier: Apache-2.0
66
package lockbasedtxmgr
77

88
import (
9+
"bytes"
10+
"encoding/gob"
911
"encoding/json"
1012
"fmt"
1113
"testing"
@@ -72,6 +74,63 @@ func testTxSimulatorWithNoExistingData(t *testing.T, env testEnv) {
7274
assert.Nil(t, simulationResults.PvtSimulationResults)
7375
}
7476

77+
func TestTxSimulatorGetResults(t *testing.T) {
78+
testEnv := testEnvsMap[levelDBtestEnvName]
79+
testEnv.init(t, "testLedger", nil)
80+
defer testEnv.cleanup()
81+
var err error
82+
83+
// Create a simulator and get/set keys in one namespace "ns1"
84+
simulator, _ := testEnv.getTxMgr().NewTxSimulator("test_txid1")
85+
simulator.GetState("ns1", "key1")
86+
simulator.GetPrivateData("ns1", "coll1", "key1")
87+
simulator.SetState("ns1", "key1", []byte("value1"))
88+
// get simulation results and verify that this contains rwset only for one namespace
89+
simulationResults1, err := simulator.GetTxSimulationResults()
90+
assert.Equal(t, 1, len(simulationResults1.PubSimulationResults.NsRwset))
91+
// clone freeze simulationResults1
92+
buff1 := new(bytes.Buffer)
93+
assert.NoError(t, gob.NewEncoder(buff1).Encode(simulationResults1))
94+
frozenSimulationResults1 := &ledger.TxSimulationResults{}
95+
assert.NoError(t, gob.NewDecoder(buff1).Decode(&frozenSimulationResults1))
96+
97+
// use the same simulator after obtaining the simulaiton results by get/set keys in one more namespace "ns2"
98+
simulator.GetState("ns2", "key2")
99+
simulator.GetPrivateData("ns2", "coll2", "key2")
100+
simulator.SetState("ns2", "key2", []byte("value2"))
101+
// get simulation results and verify that this contains rwset for both the namespaces "ns1" and "ns2"
102+
simulationResults2, err := simulator.GetTxSimulationResults()
103+
assert.Equal(t, 2, len(simulationResults2.PubSimulationResults.NsRwset))
104+
// clone freeze simulationResults2
105+
buff2 := new(bytes.Buffer)
106+
assert.NoError(t, gob.NewEncoder(buff2).Encode(simulationResults2))
107+
frozenSimulationResults2 := &ledger.TxSimulationResults{}
108+
assert.NoError(t, gob.NewDecoder(buff2).Decode(&frozenSimulationResults2))
109+
110+
// use the same simulator further to operate on different keys in the namespcace "ns1"
111+
simulator.GetState("ns1", "key3")
112+
simulator.GetPrivateData("ns1", "coll3", "key3")
113+
simulator.SetState("ns1", "key3", []byte("value3"))
114+
// get simulation results and verify that this contains rwset for both the namespaces "ns1" and "ns2"
115+
simulationResults3, err := simulator.GetTxSimulationResults()
116+
assert.Equal(t, 2, len(simulationResults3.PubSimulationResults.NsRwset))
117+
118+
// Now, verify that the simulator operations did not have an effect on privously obtained results
119+
assert.Equal(t, frozenSimulationResults1, simulationResults1)
120+
assert.Equal(t, frozenSimulationResults2, simulationResults2)
121+
122+
// Call 'Done' and all the data get/set operations after calling 'Done' should fail.
123+
simulator.Done()
124+
_, err = simulator.GetState("ns3", "key3")
125+
assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()")
126+
err = simulator.SetState("ns3", "key3", []byte("value3"))
127+
assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()")
128+
_, err = simulator.GetPrivateData("ns3", "coll3", "key3")
129+
assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()")
130+
err = simulator.SetPrivateData("ns3", "coll3", "key3", []byte("value3"))
131+
assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()")
132+
}
133+
75134
func TestTxSimulatorWithExistingData(t *testing.T) {
76135
for _, testEnv := range testEnvs {
77136
t.Run(testEnv.getName(), func(t *testing.T) {

0 commit comments

Comments
 (0)