-
Notifications
You must be signed in to change notification settings - Fork 107
/
utils.go
106 lines (84 loc) · 2.57 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package committee
import (
"fmt"
"strings"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/oasisprotocol/oasis-core/go/common"
cmnBackoff "github.com/oasisprotocol/oasis-core/go/common/backoff"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
storageApi "github.com/oasisprotocol/oasis-core/go/storage/api"
)
// outstandingMask records which storage roots still need to be synced or need to be retried.
// It is a bitwise set of storageApi.RootType values.
type outstandingMask uint
func bitForType(rootType storageApi.RootType) outstandingMask {
return outstandingMask(1 << (int(rootType) - 1))
}
var outstandingMaskFull = bitForType(storageApi.RootTypeMax+1) - 1
func (o outstandingMask) String() string {
represented := make([]string, 0, storageApi.RootTypeMax)
for i := storageApi.RootType(1); i <= storageApi.RootTypeMax; i++ {
if (1<<bitForType(i))&o != 0 {
represented = append(represented, i.String())
}
}
return fmt.Sprintf("outstanding_mask{%s}", strings.Join(represented, ", "))
}
func (o *outstandingMask) add(rootType storageApi.RootType) {
*o = (*o) | bitForType(rootType)
}
func (o *outstandingMask) remove(rootType storageApi.RootType) {
*o = (*o) & ^bitForType(rootType)
}
func (o outstandingMask) contains(rootType storageApi.RootType) bool {
return o&bitForType(rootType) > 0
}
func (o outstandingMask) isEmpty() bool {
return o == 0
}
func (o outstandingMask) hasAll() bool {
return o == outstandingMaskFull
}
type inFlight struct {
outstanding outstandingMask
awaitingRetry outstandingMask
}
func (i *inFlight) scheduleDiff(rootType storageApi.RootType) {
i.outstanding.add(rootType)
i.awaitingRetry.remove(rootType)
}
func (i *inFlight) retry(rootType storageApi.RootType) {
i.outstanding.remove(rootType)
i.awaitingRetry.add(rootType)
}
// blockSummary is a short summary of a single block.Block.
type blockSummary struct {
Namespace common.Namespace `json:"namespace"`
Round uint64 `json:"round"`
Roots []storageApi.Root `json:"roots"`
}
func (s *blockSummary) GetRound() uint64 {
return s.Round
}
func summaryFromBlock(blk *block.Block) *blockSummary {
return &blockSummary{
Namespace: blk.Header.Namespace,
Round: blk.Header.Round,
Roots: blk.Header.StorageRoots(),
}
}
type heartbeat struct {
*backoff.Ticker
}
func (h *heartbeat) reset() {
if h.Ticker != nil {
h.Stop()
}
boff := cmnBackoff.NewExponentialBackOff()
boff.InitialInterval = 5 * time.Second
boff.MaxInterval = 20 * time.Second
h.Ticker = backoff.NewTicker(boff)
// Gobble the first tick, which is immediate.
<-h.C
}