-
Notifications
You must be signed in to change notification settings - Fork 0
/
scorebook.go
98 lines (80 loc) · 2.33 KB
/
scorebook.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
package store
import (
"context"
"sync/atomic"
"time"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/log"
ds "github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-base32"
)
const (
scoreCacheSize = 100
)
var scoresBase = ds.NewKey("/peers/scores")
// LastUpdate requires atomic update operations. Use the helper functions SetLastUpdated and LastUpdated to modify and access this field.
type scoreRecord struct {
LastUpdate int64 `json:"lastUpdate"` // unix timestamp in seconds
PeerScores PeerScores `json:"peerScores"`
}
func (s *scoreRecord) SetLastUpdated(t time.Time) {
atomic.StoreInt64(&s.LastUpdate, t.Unix())
}
func (s *scoreRecord) LastUpdated() time.Time {
return time.Unix(atomic.LoadInt64(&s.LastUpdate), 0)
}
func (s *scoreRecord) MarshalBinary() (data []byte, err error) {
return serializeScoresV0(*s)
}
func (s *scoreRecord) UnmarshalBinary(data []byte) error {
r, err := deserializeScoresV0(data)
if err != nil {
return err
}
*s = r
return nil
}
type scoreBook struct {
book *recordsBook[peer.ID, *scoreRecord]
}
func newScoreRecord() *scoreRecord {
return new(scoreRecord)
}
func peerIDKey(id peer.ID) ds.Key {
return ds.NewKey(base32.RawStdEncoding.EncodeToString([]byte(id)))
}
func newScoreBook(ctx context.Context, logger log.Logger, clock clock.Clock, store ds.Batching, retain time.Duration) (*scoreBook, error) {
book, err := newRecordsBook[peer.ID, *scoreRecord](ctx, logger, clock, store, scoreCacheSize, retain, scoresBase, newScoreRecord, peerIDKey)
if err != nil {
return nil, err
}
return &scoreBook{book: book}, nil
}
func (d *scoreBook) startGC() {
d.book.startGC()
}
func (d *scoreBook) GetPeerScores(id peer.ID) (PeerScores, error) {
record, err := d.book.getRecord(id)
if err == UnknownRecordErr {
return PeerScores{}, nil // return zeroed scores by default
}
if err != nil {
return PeerScores{}, err
}
return record.PeerScores, nil
}
func (d *scoreBook) GetPeerScore(id peer.ID) (float64, error) {
scores, err := d.GetPeerScores(id)
if err != nil {
return 0, err
}
return scores.Gossip.Total, nil
}
func (d *scoreBook) SetScore(id peer.ID, diff ScoreDiff) (PeerScores, error) {
v, err := d.book.SetRecord(id, diff)
return v.PeerScores, err
}
func (d *scoreBook) Close() {
d.book.Close()
}