-
Notifications
You must be signed in to change notification settings - Fork 51
/
utils.go
92 lines (70 loc) · 2.27 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
package basestore
import (
"context"
"encoding/binary"
"encoding/json"
"berty.tech/go-ipfs-log/entry"
"berty.tech/go-orbit-db/iface"
cid "github.com/ipfs/go-cid"
datastore "github.com/ipfs/go-datastore"
files "github.com/ipfs/go-ipfs-files"
"github.com/pkg/errors"
)
func SaveSnapshot(ctx context.Context, b iface.Store) (cid.Cid, error) {
// @glouvigny: I'd rather use protobuf here but I decided to keep the
// JS behavior for the sake of compatibility across implementations
// TODO: avoid using `*entry.Entry`?
unfinished := b.Replicator().GetQueue()
oplog := b.OpLog()
untypedEntries := oplog.Heads().Slice()
entries := make([]*entry.Entry, len(untypedEntries))
for i := range untypedEntries {
castedEntry, ok := untypedEntries[i].(*entry.Entry)
if !ok {
return cid.Cid{}, errors.New("unable to downcast entry")
}
entries[i] = castedEntry
}
header, err := json.Marshal(&storeSnapshot{
ID: oplog.GetID(),
Heads: entries,
Size: oplog.Len(),
Type: b.Type(),
})
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to serialize snapshot")
}
headerSize := len(header)
size := make([]byte, 2)
binary.BigEndian.PutUint16(size, uint16(headerSize))
rs := append(size, header...)
for _, e := range oplog.GetEntries().Slice() {
entryJSON, err := json.Marshal(e)
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to serialize entry as JSON")
}
size := make([]byte, 2)
binary.BigEndian.PutUint16(size, uint16(len(entryJSON)))
rs = append(rs, size...)
rs = append(rs, entryJSON...)
}
rs = append(rs, 0)
rsFileNode := files.NewBytesFile(rs)
snapshotPath, err := b.IPFS().Unixfs().Add(ctx, rsFileNode)
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to save log data on store")
}
err = b.Cache().Put(datastore.NewKey("snapshot"), []byte(snapshotPath.Cid().String()))
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to add snapshot data to cache")
}
unfinishedJSON, err := json.Marshal(unfinished)
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to marshal unfinished cids")
}
err = b.Cache().Put(datastore.NewKey("queue"), unfinishedJSON)
if err != nil {
return cid.Cid{}, errors.Wrap(err, "unable to add unfinished data to cache")
}
return snapshotPath.Cid(), nil
}