Skip to content

Commit 6f2b12f

Browse files
committed
cmd: add blockstore tar-blocks command
1 parent 33eb66f commit 6f2b12f

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

cmd/radiance/blockstore/blockstore.go

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"go.firedancer.io/radiance/cmd/radiance/blockstore/dumpshreds"
1010
"go.firedancer.io/radiance/cmd/radiance/blockstore/statdatarate"
1111
"go.firedancer.io/radiance/cmd/radiance/blockstore/statentries"
12+
"go.firedancer.io/radiance/cmd/radiance/blockstore/tarblocks"
1213
"go.firedancer.io/radiance/cmd/radiance/blockstore/verifydata"
1314
"go.firedancer.io/radiance/cmd/radiance/blockstore/yaml"
1415
)
@@ -25,6 +26,7 @@ func init() {
2526
&dumpbatches.Cmd,
2627
&statdatarate.Cmd,
2728
&statentries.Cmd,
29+
&tarblocks.Cmd,
2830
&verifydata.Cmd,
2931
&yaml.Cmd,
3032
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//go:build !lite
2+
3+
package tarblocks
4+
5+
import (
6+
"archive/tar"
7+
"bufio"
8+
"fmt"
9+
"io"
10+
"os"
11+
"time"
12+
13+
"github.com/mattn/go-isatty"
14+
"github.com/spf13/cobra"
15+
"go.firedancer.io/radiance/pkg/blockstore"
16+
"go.firedancer.io/radiance/pkg/shred"
17+
"k8s.io/klog/v2"
18+
)
19+
20+
var Cmd = cobra.Command{
21+
Use: "tar-blocks <rocksdb> <out>",
22+
Short: "Export rooted blocks from RocksDB to TAR stream",
23+
Long: `Creates a TAR stream of rooted blocks in serialized-batches binary format.
24+
25+
Each block/<slot>.bin file is a bincode Vec<Vec<Entry>> serialization of the block data.
26+
Currently outputs only rooted slots in replayable order.
27+
This may change in the future.
28+
29+
Use "-" as <out> to write the TAR stream to stdout.`,
30+
Args: cobra.ExactArgs(2),
31+
}
32+
33+
func init() {
34+
Cmd.Run = run
35+
}
36+
37+
func run(_ *cobra.Command, args []string) {
38+
rocksDB := args[0]
39+
outPath := args[1]
40+
41+
db, err := blockstore.OpenReadOnly(rocksDB)
42+
if err != nil {
43+
klog.Exitf("Failed to open blockstore: %s", err)
44+
}
45+
defer db.Close()
46+
47+
walker, err := blockstore.NewBlockWalk([]blockstore.WalkHandle{{DB: db}}, 2)
48+
if err != nil {
49+
klog.Fatal(err)
50+
}
51+
defer walker.Close()
52+
53+
var rawOutStream io.Writer
54+
if outPath == "-" {
55+
if isatty.IsTerminal(os.Stdout.Fd()) {
56+
klog.Exit("Refusing to write binary data to terminal")
57+
}
58+
rawOutStream = os.Stdout
59+
} else {
60+
f, err := os.Create(outPath)
61+
if err != nil {
62+
klog.Exitf("Failed to create output file: %s", err)
63+
}
64+
defer f.Close()
65+
rawOutStream = f
66+
}
67+
68+
outStream := bufio.NewWriter(rawOutStream)
69+
defer outStream.Flush()
70+
71+
outTar := tar.NewWriter(outStream)
72+
defer outTar.Close()
73+
74+
outTar.WriteHeader(&tar.Header{
75+
Typeflag: tar.TypeDir,
76+
Name: "block/",
77+
Mode: 0755,
78+
ModTime: time.Now(),
79+
})
80+
81+
for {
82+
meta, ok := walker.Next()
83+
if !ok {
84+
break
85+
}
86+
87+
shreds, err := walker.Current().GetAllDataShreds(meta.Slot, 2)
88+
if err != nil {
89+
klog.Warningf("Failed to get shreds for slot %d: %s", meta.Slot, err)
90+
break
91+
}
92+
93+
block := shred.Concat(shreds)
94+
hdr := tar.Header{
95+
Typeflag: tar.TypeReg,
96+
Name: fmt.Sprintf("block/%d.bin", meta.Slot),
97+
Size: int64(len(block)),
98+
Mode: 0644,
99+
ModTime: time.Now(),
100+
}
101+
if err := outTar.WriteHeader(&hdr); err != nil {
102+
klog.Warningf("Failed to write header for slot %d: %s", meta.Slot, err)
103+
break
104+
}
105+
if _, err := outTar.Write(block); err != nil {
106+
klog.Warningf("Failed to write block %d: %s", meta.Slot, err)
107+
break
108+
}
109+
110+
klog.V(7).Infof("Dmuped %s", hdr.Name)
111+
}
112+
113+
klog.Info("Done")
114+
}

pkg/blockstore/blockwalk_rocks.go

+7
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ func (m *BlockWalk) Next() (meta *SlotMeta, ok bool) {
109109
return meta, true
110110
}
111111

112+
func (m *BlockWalk) Current() *DB {
113+
if len(m.handles) == 0 {
114+
return nil
115+
}
116+
return m.handles[0].DB
117+
}
118+
112119
// Entries returns the entries at the current cursor.
113120
// Caller must have made an ok call to BlockWalk.Next before calling this.
114121
func (m *BlockWalk) Entries(meta *SlotMeta) ([][]shred.Entry, error) {

0 commit comments

Comments
 (0)