@@ -41,6 +41,7 @@ type deliverTxTask struct {
41
41
Ctx sdk.Context
42
42
AbortCh chan occ.Abort
43
43
44
+ mx sync.RWMutex
44
45
Status status
45
46
Dependencies []int
46
47
Abort * occ.Abort
@@ -52,8 +53,20 @@ type deliverTxTask struct {
52
53
ValidateCh chan status
53
54
}
54
55
56
+ func (dt * deliverTxTask ) IsStatus (s status ) bool {
57
+ dt .mx .RLock ()
58
+ defer dt .mx .RUnlock ()
59
+ return dt .Status == s
60
+ }
61
+
62
+ func (dt * deliverTxTask ) SetStatus (s status ) {
63
+ dt .mx .Lock ()
64
+ defer dt .mx .Unlock ()
65
+ dt .Status = s
66
+ }
67
+
55
68
func (dt * deliverTxTask ) Reset () {
56
- dt .Status = statusPending
69
+ dt .SetStatus ( statusPending )
57
70
dt .Response = nil
58
71
dt .Abort = nil
59
72
dt .AbortCh = nil
@@ -182,7 +195,7 @@ func (s *scheduler) tryInitMultiVersionStore(ctx sdk.Context) {
182
195
183
196
func indexesValidated (tasks []* deliverTxTask , idx []int ) bool {
184
197
for _ , i := range idx {
185
- if tasks [i ].Status != statusValidated {
198
+ if ! tasks [i ].IsStatus ( statusValidated ) {
186
199
return false
187
200
}
188
201
}
@@ -191,7 +204,7 @@ func indexesValidated(tasks []*deliverTxTask, idx []int) bool {
191
204
192
205
func allValidated (tasks []* deliverTxTask ) bool {
193
206
for _ , t := range tasks {
194
- if t . Status != statusValidated {
207
+ if ! t . IsStatus ( statusValidated ) {
195
208
return false
196
209
}
197
210
}
@@ -220,7 +233,7 @@ type schedulerMetrics struct {
220
233
221
234
func (s * scheduler ) emitMetrics () {
222
235
telemetry .IncrCounter (float32 (s .metrics .retries ), "scheduler" , "retries" )
223
- telemetry .SetGauge (float32 (s .metrics .maxIncarnation ), "scheduler" , "max_incarnation " )
236
+ telemetry .IncrCounter (float32 (s .metrics .maxIncarnation ), "scheduler" , "incarnations " )
224
237
}
225
238
226
239
func (s * scheduler ) ProcessAll (ctx sdk.Context , reqs []* sdk.DeliverTxEntry ) ([]types.ResponseDeliverTx , error ) {
@@ -296,12 +309,12 @@ func (s *scheduler) shouldRerun(task *deliverTxTask) bool {
296
309
} else {
297
310
// otherwise, wait for completion
298
311
task .Dependencies = conflicts
299
- task .Status = statusWaiting
312
+ task .SetStatus ( statusWaiting )
300
313
return false
301
314
}
302
315
} else if len (conflicts ) == 0 {
303
316
// mark as validated, which will avoid re-validating unless a lower-index re-validates
304
- task .Status = statusValidated
317
+ task .SetStatus ( statusValidated )
305
318
return false
306
319
}
307
320
// conflicts and valid, so it'll validate next time
@@ -346,18 +359,18 @@ func (s *scheduler) validateAll(ctx sdk.Context, tasks []*deliverTxTask) ([]*del
346
359
return nil , nil
347
360
}
348
361
349
- wg := sync.WaitGroup {}
362
+ wg := & sync.WaitGroup {}
350
363
for i := startIdx ; i < len (tasks ); i ++ {
351
- t := tasks [i ]
352
364
wg .Add (1 )
365
+ t := tasks [i ]
353
366
s .DoValidate (func () {
354
367
defer wg .Done ()
355
368
if ! s .validateTask (ctx , t ) {
369
+ mx .Lock ()
370
+ defer mx .Unlock ()
356
371
t .Reset ()
357
372
t .Increment ()
358
- mx .Lock ()
359
373
res = append (res , t )
360
- mx .Unlock ()
361
374
}
362
375
})
363
376
}
@@ -373,53 +386,28 @@ func (s *scheduler) executeAll(ctx sdk.Context, tasks []*deliverTxTask) error {
373
386
374
387
// validationWg waits for all validations to complete
375
388
// validations happen in separate goroutines in order to wait on previous index
376
- validationWg := & sync.WaitGroup {}
377
- validationWg .Add (len (tasks ))
389
+ wg := & sync.WaitGroup {}
390
+ wg .Add (len (tasks ))
378
391
379
392
for _ , task := range tasks {
380
393
t := task
381
394
s .DoExecute (func () {
382
- s .prepareAndRunTask (validationWg , ctx , t )
395
+ s .prepareAndRunTask (wg , ctx , t )
383
396
})
384
397
}
385
398
386
- validationWg .Wait ()
399
+ wg .Wait ()
387
400
388
401
return nil
389
402
}
390
403
391
- func (s * scheduler ) waitOnPreviousAndValidate (wg * sync.WaitGroup , task * deliverTxTask ) {
392
- defer wg .Done ()
393
- defer close (task .ValidateCh )
394
- // wait on previous task to finish validation
395
- // if a previous task fails validation, then subsequent should fail too (cascade)
396
- if task .Index > 0 {
397
- res , ok := <- s .allTasks [task .Index - 1 ].ValidateCh
398
- if ok && res != statusValidated {
399
- task .Reset ()
400
- task .ValidateCh <- task .Status
401
- return
402
- }
403
- }
404
- // if not validated, reset the task
405
- if ! s .validateTask (task .Ctx , task ) {
406
- task .Reset ()
407
- }
408
-
409
- // notify next task of this one's status
410
- task .ValidateCh <- task .Status
411
- }
412
-
413
404
func (s * scheduler ) prepareAndRunTask (wg * sync.WaitGroup , ctx sdk.Context , task * deliverTxTask ) {
414
405
eCtx , eSpan := s .traceSpan (ctx , "SchedulerExecute" , task )
415
406
defer eSpan .End ()
416
- task .Ctx = eCtx
417
407
408
+ task .Ctx = eCtx
418
409
s .executeTask (task )
419
-
420
- s .DoValidate (func () {
421
- s .waitOnPreviousAndValidate (wg , task )
422
- })
410
+ wg .Done ()
423
411
}
424
412
425
413
func (s * scheduler ) traceSpan (ctx sdk.Context , name string , task * deliverTxTask ) (sdk.Context , trace.Span ) {
@@ -509,12 +497,12 @@ func (s *scheduler) executeTask(task *deliverTxTask) {
509
497
510
498
// If abort has occurred, return, else set the response and status
511
499
if abortOccurred {
512
- task .Status = statusAborted
500
+ task .SetStatus ( statusAborted )
513
501
task .Abort = abort
514
502
return
515
503
}
516
504
517
- task .Status = statusExecuted
505
+ task .SetStatus ( statusExecuted )
518
506
task .Response = & resp
519
507
520
508
// write from version store to multiversion stores
0 commit comments