-
Notifications
You must be signed in to change notification settings - Fork 107
/
cstore.go
116 lines (97 loc) · 2.66 KB
/
cstore.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
107
108
109
110
111
112
113
114
115
116
package backup
import (
"context"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/persistent"
)
var _ Backend = (*commonStoreBackend)(nil)
// commonStoreBackend uses the common store to backup and restore peers.
type commonStoreBackend struct {
logger *logging.Logger
bucket *persistent.ServiceStore // A handle to a bucket where peers are stored.
key string // A key under which peers are stored in the bucket.
}
// NewCommonStoreBackend creates a new common store backend.
//
// The name of the bucket and the key under which peers are stored should be unique to avoid
// backups to be overwritten.
func NewCommonStoreBackend(cs *persistent.CommonStore, bucket string, key string) Backend {
l := logging.GetLogger("p2p/backup/common-store-backend")
var b *persistent.ServiceStore
if cs != nil {
b = cs.GetServiceStore(bucket)
}
return &commonStoreBackend{
logger: l,
bucket: b,
key: key,
}
}
// Delete implements PeerBackup.
func (b *commonStoreBackend) Delete(context.Context) error {
if b.bucket == nil {
return nil
}
return b.bucket.Delete([]byte(b.key))
}
// Backup implements PeerBackup.
func (b *commonStoreBackend) Backup(_ context.Context, nsPeers map[string][]peer.AddrInfo) error {
if b.bucket == nil {
return nil
}
// Convert addresses to json, skipping empty ones.
data := make(map[string][][]byte)
for ns, infos := range nsPeers {
jsons := make([][]byte, 0, len(infos))
for _, info := range infos {
if len(info.Addrs) == 0 {
continue
}
json, err := info.MarshalJSON()
if err != nil {
return err
}
jsons = append(jsons, json)
}
if len(jsons) == 0 {
continue
}
data[ns] = jsons
}
// Don't override the last backup if not needed.
if len(data) == 0 {
return nil
}
// Store addresses.
return b.bucket.PutCBOR([]byte(b.key), data)
}
// Restore implements PeerBackup.
func (b *commonStoreBackend) Restore(_ context.Context) (map[string][]peer.AddrInfo, error) {
if b.bucket == nil {
return map[string][]peer.AddrInfo{}, nil
}
// Restore addresses.
data := make(map[string][][]byte)
if err := b.bucket.GetCBOR([]byte(b.key), &data); err != nil {
switch err {
case persistent.ErrNotFound:
return map[string][]peer.AddrInfo{}, nil
default:
return nil, err
}
}
// Convert them from json.
nsPeers := make(map[string][]peer.AddrInfo)
for ns, jsons := range data {
infos := make([]peer.AddrInfo, len(jsons))
for i := range jsons {
err := infos[i].UnmarshalJSON(jsons[i])
if err != nil {
return nil, err
}
}
nsPeers[ns] = infos
}
return nsPeers, nil
}