Skip to content

Commit aba0358

Browse files
author
Srinivasan Muralidharan
committed
FAB-1497 sundry changes in prep for moving ccchecker
https://jira.hyperledger.org/browse/FAB-1497 Some name changes and provide more info to the shadow. Change-Id: Ie058ded0339956aa871e4da90301777242110691 Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent 151e6ac commit aba0358

File tree

5 files changed

+94
-45
lines changed

5 files changed

+94
-45
lines changed

examples/ccchecker/ccchecker.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var ccchecker *CCChecker
3636
//CCChecker encapsulates ccchecker properties and runtime
3737
type CCChecker struct {
3838
//Chaincodes to do ccchecker over (see ccchecker.json for defaults)
39-
Chaincodes []*chaincodes.CC
39+
Chaincodes []*chaincodes.CCClient
4040
//TimeoutToAbortSecs abort deadline
4141
TimeoutToAbortSecs int
4242
//ChainName name of the chain
@@ -62,7 +62,7 @@ func LoadCCCheckerParams(file string) error {
6262
//concurrency <=0 will be dropped
6363
if scc.Concurrency > 0 {
6464
for i := 0; i < scc.Concurrency; i++ {
65-
tmp := &chaincodes.CC{}
65+
tmp := &chaincodes.CCClient{}
6666
*tmp = *scc
6767
tmp.ID = id
6868
id = id + 1
@@ -77,14 +77,14 @@ func LoadCCCheckerParams(file string) error {
7777
return nil
7878
}
7979

80-
//CCCheckerInit assigns shadow chaincode to each of the CC from registered shadow chaincodes
80+
//CCCheckerInit assigns shadow chaincode to each of the CCClient from registered shadow chaincodes
8181
func CCCheckerInit() {
8282
if ccchecker == nil {
8383
fmt.Printf("LoadCCCheckerParams needs to be called before init\n")
8484
os.Exit(1)
8585
}
8686

87-
if err := chaincodes.RegisterCCs(ccchecker.Chaincodes); err != nil {
87+
if err := chaincodes.RegisterCCClients(ccchecker.Chaincodes); err != nil {
8888
panic(fmt.Sprintf("%s", err))
8989
}
9090
}
@@ -119,16 +119,16 @@ func CCCheckerRun(report bool, verbose bool) error {
119119
//an anonymous struct to hold failures
120120
var failures struct {
121121
sync.Mutex
122-
failedCCs int
122+
failedCCClients int
123123
}
124124

125125
//run the invokes
126126
ccerrs := make([]error, len(ccchecker.Chaincodes))
127127
for _, cc := range ccchecker.Chaincodes {
128-
go func(cc2 *chaincodes.CC) {
128+
go func(cc2 *chaincodes.CCClient) {
129129
if ccerrs[cc2.ID] = cc2.Run(ctxt, ccchecker.ChainName, bc, ec, signer, &ccsWG); ccerrs[cc2.ID] != nil {
130130
failures.Lock()
131-
failures.failedCCs = failures.failedCCs + 1
131+
failures.failedCCClients = failures.failedCCClients + 1
132132
failures.Unlock()
133133
}
134134
}(cc)
@@ -138,11 +138,11 @@ func CCCheckerRun(report bool, verbose bool) error {
138138
err = ccchecker.wait(&ccsWG)
139139

140140
//verify results
141-
if err == nil && failures.failedCCs < len(ccchecker.Chaincodes) {
141+
if err == nil && failures.failedCCClients < len(ccchecker.Chaincodes) {
142142
ccsWG = sync.WaitGroup{}
143-
ccsWG.Add(len(ccchecker.Chaincodes) - failures.failedCCs)
143+
ccsWG.Add(len(ccchecker.Chaincodes) - failures.failedCCClients)
144144
for _, cc := range ccchecker.Chaincodes {
145-
go func(cc2 *chaincodes.CC) {
145+
go func(cc2 *chaincodes.CCClient) {
146146
if ccerrs[cc2.ID] == nil {
147147
ccerrs[cc2.ID] = cc2.Validate(ctxt, ccchecker.ChainName, bc, ec, signer, &ccsWG)
148148
} else {

examples/ccchecker/ccchecker.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
{"Chaincodes":
22
[
33
{"Name": "mycc",
4+
"InitArgs":[""],
45
"Path": "github.com/hyperledger/fabric/examples/ccchecker/chaincodes/newkeyperinvoke",
56
"NumFinalQueryAttempts": 10,
6-
"NumberOfIterations": 10,
7+
"NumberOfInvokes": 10,
78
"DelayBetweenInvokeMs": 1,
89
"DelayBetweenQueryMs": 10,
910
"TimeoutToAbortSecs": 60,

examples/ccchecker/chaincodes/chaincodes.go

+43-21
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import (
3232
//ShadowCCIntf interfaces to be implemented by shadow chaincodes
3333
type ShadowCCIntf interface {
3434
//InitShadowCC initializes the shadow chaincode (will be called once for each chaincode)
35-
InitShadowCC()
35+
InitShadowCC(initArgs []string)
3636

3737
//GetInvokeArgs gets invoke arguments from shadow
3838
GetInvokeArgs(ccnum int, iter int) [][]byte
@@ -45,22 +45,31 @@ type ShadowCCIntf interface {
4545

4646
//Validate the results against the query arguments
4747
Validate(args [][]byte, value []byte) error
48+
49+
//GetNumQueries returns number of queries to perform
50+
GetNumQueries(numSuccessfulInvokes int) int
51+
52+
//OverrideNumInvokes overrides the users number of invoke request
53+
OverrideNumInvokes(numInvokesPlanned int) int
4854
}
4955

50-
//CC chaincode properties, config and runtime
51-
type CC struct {
56+
//CCClient chaincode properties, config and runtime
57+
type CCClient struct {
5258
//-------------config properties ------------
5359
//Name of the chaincode
5460
Name string
5561

62+
//InitArgs used for deploying the chaincode
63+
InitArgs []string
64+
5665
//Path to the chaincode
5766
Path string
5867

5968
//NumFinalQueryAttempts number of times to try final query before giving up
6069
NumFinalQueryAttempts int
6170

62-
//NumberOfInvokeIterations number of iterations to do invoke on
63-
NumberOfIterations int
71+
//NumberOfInvokes number of iterations to do invoke on
72+
NumberOfInvokes int
6473

6574
//DelayBetweenInvokeMs delay between each invoke
6675
DelayBetweenInvokeMs int
@@ -87,14 +96,22 @@ type CC struct {
8796
//shadow CC where the chaincode stats is maintained
8897
shadowCC ShadowCCIntf
8998

99+
//number of iterations a shadow cc actually wants
100+
//this could be different from NumberOfInvokes
101+
overriddenNumInvokes int
102+
103+
//numer of queries to perform
104+
//retrieved from the shadow CC
105+
numQueries int
106+
90107
//current iteration of invoke
91108
currentInvokeIter int
92109

93110
//start of invokes in epoch seconds
94-
invokeStartTime int
111+
invokeStartTime int64
95112

96113
//end of invokes in epoch seconds
97-
invokeEndTime int
114+
invokeEndTime int64
98115

99116
//error that stopped invoke iterations
100117
invokeErr error
@@ -109,7 +126,7 @@ type CC struct {
109126
queryErrs []error
110127
}
111128

112-
func (cc *CC) getChaincodeSpec(args [][]byte) *pb.ChaincodeSpec {
129+
func (cc *CCClient) getChaincodeSpec(args [][]byte) *pb.ChaincodeSpec {
113130
return &pb.ChaincodeSpec{
114131
Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[cc.Lang]),
115132
ChaincodeID: &pb.ChaincodeID{Path: cc.Path, Name: cc.Name},
@@ -120,12 +137,15 @@ func (cc *CC) getChaincodeSpec(args [][]byte) *pb.ChaincodeSpec {
120137
//doInvokes calls invoke for each iteration for the chaincode
121138
//Stops at the first invoke with error
122139
//currentInvokeIter contains the number of successful iterations
123-
func (cc *CC) doInvokes(ctxt context.Context, chainID string,
140+
func (cc *CCClient) doInvokes(ctxt context.Context, chainID string,
124141
bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity,
125142
wg *sync.WaitGroup, quit func() bool) error {
126143

144+
//perhaps the shadow CC wants to override the number of iterations
145+
cc.overriddenNumInvokes = cc.shadowCC.OverrideNumInvokes(cc.NumberOfInvokes)
146+
127147
var err error
128-
for cc.currentInvokeIter = 0; cc.currentInvokeIter < cc.NumberOfIterations; cc.currentInvokeIter++ {
148+
for cc.currentInvokeIter = 0; cc.currentInvokeIter < cc.overriddenNumInvokes; cc.currentInvokeIter++ {
129149
if quit() {
130150
break
131151
}
@@ -154,7 +174,7 @@ func (cc *CC) doInvokes(ctxt context.Context, chainID string,
154174
}
155175

156176
//don't sleep for the last iter
157-
if cc.DelayBetweenInvokeMs > 0 && cc.currentInvokeIter < (cc.NumberOfIterations-1) {
177+
if cc.DelayBetweenInvokeMs > 0 && cc.currentInvokeIter < (cc.overriddenNumInvokes-1) {
158178
time.Sleep(time.Duration(cc.DelayBetweenInvokeMs) * time.Millisecond)
159179
}
160180
}
@@ -165,7 +185,7 @@ func (cc *CC) doInvokes(ctxt context.Context, chainID string,
165185
//Run test over given number of iterations
166186
// i will be unique across chaincodes and can be used as a key
167187
// this is useful if chaincode occurs multiple times in the array of chaincodes
168-
func (cc *CC) Run(ctxt context.Context, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup) error {
188+
func (cc *CCClient) Run(ctxt context.Context, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup) error {
169189
defer wg.Done()
170190

171191
var (
@@ -181,12 +201,12 @@ func (cc *CC) Run(ctxt context.Context, chainID string, bc common.BroadcastClien
181201
quitF := func() bool { return quit }
182202

183203
//start of invokes
184-
cc.invokeStartTime = time.Now().Second()
204+
cc.invokeStartTime = time.Now().UnixNano() / 1000000
185205

186206
err = cc.doInvokes(ctxt, chainID, bc, ec, signer, wg, quitF)
187207

188208
//end of invokes
189-
cc.invokeEndTime = time.Now().Second()
209+
cc.invokeEndTime = time.Now().UnixNano() / 1000000
190210
}()
191211

192212
//we could be done or cancelled or timedout
@@ -203,7 +223,7 @@ func (cc *CC) Run(ctxt context.Context, chainID string, bc common.BroadcastClien
203223
}
204224

205225
//validates the invoke iteration for this chaincode
206-
func (cc *CC) validateIter(ctxt context.Context, iter int, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup, quit func() bool) {
226+
func (cc *CCClient) validateIter(ctxt context.Context, iter int, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup, quit func() bool) {
207227
defer wg.Done()
208228
args := cc.shadowCC.GetQueryArgs(cc.ID, iter)
209229

@@ -253,7 +273,7 @@ func (cc *CC) validateIter(ctxt context.Context, iter int, chainID string, bc co
253273
}
254274

255275
//Validate test that was Run. Each successful iteration in the run is validated against
256-
func (cc *CC) Validate(ctxt context.Context, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup) error {
276+
func (cc *CCClient) Validate(ctxt context.Context, chainID string, bc common.BroadcastClient, ec pb.EndorserClient, signer msp.SigningIdentity, wg *sync.WaitGroup) error {
257277
defer wg.Done()
258278

259279
//this will signal inner validators to get out via
@@ -280,8 +300,10 @@ func (cc *CC) Validate(ctxt context.Context, chainID string, bc common.Broadcast
280300
//return the quit closure for validation within validateIter
281301
quitF := func() bool { return quit }
282302

303+
cc.numQueries = cc.shadowCC.GetNumQueries(cc.currentInvokeIter)
304+
283305
//try only till successful invoke iterations
284-
for i := 0; i < cc.currentInvokeIter; i++ {
306+
for i := 0; i < cc.numQueries; i++ {
285307
go func(iter int) {
286308
cc.validateIter(ctxt, iter, chainID, bc, ec, signer, &innerwg, quitF)
287309
}(i)
@@ -317,22 +339,22 @@ func (cc *CC) Validate(ctxt context.Context, chainID string, bc common.Broadcast
317339
}
318340

319341
//Report reports chaincode test execution, iter by iter
320-
func (cc *CC) Report(verbose bool, chainID string) {
342+
func (cc *CCClient) Report(verbose bool, chainID string) {
321343
fmt.Printf("%s/%s(%d)\n", cc.Name, chainID, cc.ID)
322-
fmt.Printf("\tNum successful invokes: %d(%d)\n", cc.currentInvokeIter, cc.NumberOfIterations)
344+
fmt.Printf("\tNum successful invokes: %d(%d,%d)\n", cc.currentInvokeIter, cc.NumberOfInvokes, cc.overriddenNumInvokes)
323345
if cc.invokeErr != nil {
324346
fmt.Printf("\tError on invoke: %s\n", cc.invokeErr)
325347
}
326348
//test to see if validate was called (validate alloc the arrays, one of which is queryWorked)
327349
if cc.queryWorked != nil {
328-
for i := 0; i < cc.currentInvokeIter; i++ {
350+
for i := 0; i < cc.numQueries; i++ {
329351
fmt.Printf("\tQuery(%d) : succeeded-%t, num trials-%d(%d), error if any(%s)\n", i, cc.queryWorked[i], cc.currQueryIter[i], cc.NumFinalQueryAttempts, cc.queryErrs[i])
330352
}
331353
} else {
332354
fmt.Printf("\tQuery validation appears not have been performed(#invokes-%d). timed out ?\n", cc.currentInvokeIter)
333355
}
334356
//total actual time for cc.currentInvokeIter
335-
invokeTime := (cc.invokeEndTime-cc.invokeStartTime)*1000 - (cc.DelayBetweenInvokeMs * (cc.currentInvokeIter - 1))
357+
invokeTime := cc.invokeEndTime - cc.invokeStartTime - int64(cc.DelayBetweenInvokeMs*(cc.currentInvokeIter-1))
336358
fmt.Printf("\tTime for invokes(ms): %d\n", invokeTime)
337359

338360
fmt.Printf("\tFinal query worked ? %t\n", cc.queryWorked)

examples/ccchecker/chaincodes/newkeyperinvoke/shadow/newkeyperinvoke.go

+17-5
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ type NewKeyPerInvoke struct {
3333
//---------- implements ShadowCCIntf functions -------
3434

3535
//InitShadowCC initializes CC
36-
func (t *NewKeyPerInvoke) InitShadowCC() {
36+
func (t *NewKeyPerInvoke) InitShadowCC(initArgs []string) {
3737
t.state = make(map[string][]byte)
3838
}
3939

40-
//setState sets the state
41-
func (t *NewKeyPerInvoke) setState(key []byte, val []byte) {
40+
//invokeSuccessful sets the state and increments succefull invokes counter
41+
func (t *NewKeyPerInvoke) invokeSuccessful(key []byte, val []byte) {
4242
t.Lock()
43+
defer t.Unlock()
4344
t.state[string(key)] = val
44-
t.Unlock()
4545
}
4646

4747
//getState gets the state
@@ -52,6 +52,18 @@ func (t *NewKeyPerInvoke) getState(key []byte) ([]byte, bool) {
5252
return v, ok
5353
}
5454

55+
//OverrideNumInvokes returns the number of invokes shadow wants
56+
//accept users request, no override
57+
func (t *NewKeyPerInvoke) OverrideNumInvokes(numInvokesPlanned int) int {
58+
return numInvokesPlanned
59+
}
60+
61+
//GetNumQueries returns the number of queries shadow wants ccchecked to do.
62+
//For our purpose, just do as many queries as there were invokes for.
63+
func (t *NewKeyPerInvoke) GetNumQueries(numInvokesCompletedSuccessfully int) int {
64+
return numInvokesCompletedSuccessfully
65+
}
66+
5567
//GetInvokeArgs get args for invoke based on chaincode ID and iteration num
5668
func (t *NewKeyPerInvoke) GetInvokeArgs(ccnum int, iter int) [][]byte {
5769
args := make([][]byte, 3)
@@ -77,7 +89,7 @@ func (t *NewKeyPerInvoke) PostInvoke(args [][]byte, resp []byte) error {
7789
return fmt.Errorf("invalid response %s", string(resp))
7890
}
7991

80-
t.setState(args[1], args[2])
92+
t.invokeSuccessful(args[1], args[2])
8193

8294
return nil
8395
}

examples/ccchecker/chaincodes/registershadow.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,39 @@ var shadowCCs = map[string]ShadowCCIntf{
2828
"github.com/hyperledger/fabric/examples/ccchecker/chaincodes/newkeyperinvoke": &nkpi.NewKeyPerInvoke{},
2929
}
3030

31-
//RegisterCCs registers all possible chaincodes that can be used in test
32-
func RegisterCCs(ccs []*CC) error {
33-
inUse := make(map[string]ShadowCCIntf)
31+
type shadowCCArgs struct {
32+
initArgs []string
33+
}
34+
35+
//For each chaincode that's deployed corresdponds a shadowCC. Not all
36+
//shadows in shadowCCs maybe used in a run using the input JSON. And each
37+
//chaincode maybe used multiple times (either because Concurrency is > 1 or
38+
//the chaincode is used multiple times in the JSON with different CCChecker
39+
//parameters). inUseShadowCCs keeps a set of all shadow CCs in use
40+
var inUseShadowCCs map[ShadowCCIntf]*shadowCCArgs
41+
42+
//RegisterCCClients registers and maps chaincode clients to their shadows
43+
func RegisterCCClients(ccs []*CCClient) error {
44+
inUseShadowCCs = make(map[ShadowCCIntf]*shadowCCArgs)
3445
for _, cc := range ccs {
3546
scc, ok := shadowCCs[cc.Path]
3647
if !ok || scc == nil {
3748
return fmt.Errorf("%s not a registered chaincode", cc.Path)
3849
}
39-
if _, ok := inUse[cc.Path]; !ok {
40-
inUse[cc.Path] = scc
41-
}
50+
4251
//setup the shadow chaincode to plug into the ccchecker framework
4352
cc.shadowCC = scc
53+
54+
//add cc to the list in shadow cc
55+
if _, ok := inUseShadowCCs[scc]; !ok {
56+
inUseShadowCCs[scc] = &shadowCCArgs{cc.InitArgs}
57+
}
4458
}
4559

4660
//initialize a shadow chaincode just once. A chaincode may be used
4761
//multiple times in test run
48-
for _, cc := range inUse {
49-
cc.InitShadowCC()
62+
for scc, sccArgs := range inUseShadowCCs {
63+
scc.InitShadowCC(sccArgs.initArgs)
5064
}
5165

5266
return nil

0 commit comments

Comments
 (0)