Skip to content

Commit

Permalink
cmd/load: show binay backup detail (#5404)
Browse files Browse the repository at this point in the history
Signed-off-by: jiefenghuang <[email protected]>
  • Loading branch information
jiefenghuang authored Dec 20, 2024
1 parent b748e97 commit 1549efb
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 31 deletions.
60 changes: 54 additions & 6 deletions cmd/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (

"github.com/DataDog/zstd"
"github.com/juicedata/juicefs/pkg/object"
"github.com/olekukonko/tablewriter"

"github.com/juicedata/juicefs/pkg/meta"
"github.com/juicedata/juicefs/pkg/utils"
Expand Down Expand Up @@ -60,6 +59,10 @@ func cmdLoad() *cli.Command {
Name: "stat",
Usage: "show statistics of the metadata binary file",
},
&cli.Int64Flag{
Name: "offset",
Usage: "offset of binary backup's segment (works with --stat and --binary). Use -1 to show all offsets, or specify one for details",
},
&cli.IntFlag{
Name: "threads",
Value: 10,
Expand Down Expand Up @@ -201,6 +204,21 @@ func statBak(ctx *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to open file %s: %w", path, err)
}
defer fp.Close()

if !ctx.IsSet("offset") {
return showBakSummary(ctx, fp, false)
}

offset := ctx.Int64("offset")
if offset == -1 {
return showBakSummary(ctx, fp, true)
}

return showBakDetail(ctx, fp, offset)
}

func showBakSummary(ctx *cli.Context, fp *os.File, withOffset bool) error {
bak := &meta.BakFormat{}
footer, err := bak.ReadFooter(fp)
if err != nil {
Expand All @@ -210,17 +228,47 @@ func statBak(ctx *cli.Context) error {
fmt.Printf("Backup Version: %d\n", footer.Msg.Version)
data := make([][]string, 0, len(footer.Msg.Infos))
for name, info := range footer.Msg.Infos {
data = append(data, []string{name, fmt.Sprintf("%d", info.Num)})
if withOffset {
data = append(data, []string{name, fmt.Sprintf("%d", info.Num), fmt.Sprintf("%d", info.Offset)})
} else {
data = append(data, []string{name, fmt.Sprintf("%d", info.Num)})
}
}
sort.Slice(data, func(i, j int) bool {
return data[i][0] < data[j][0]
})

table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Num"})
if withOffset {
fmt.Println(strings.Repeat("-", 34))
fmt.Printf("%-10s| %-10s| %-10s\n", "Name", "Num", "Offset")
fmt.Println(strings.Repeat("-", 34))
} else {
fmt.Println(strings.Repeat("-", 23))
fmt.Printf("%-10s| %-10s\n", "Name", "Num")
fmt.Println(strings.Repeat("-", 23))
}
for _, v := range data {
table.Append(v)
fmt.Printf("%-10s| %-10s|", v[0], v[1])
if withOffset {
fmt.Printf(" %-10s", v[2])
}
fmt.Println()
}
table.Render()
return nil
}

func showBakDetail(ctx *cli.Context, fp *os.File, offset int64) error {
bak := &meta.BakFormat{}
if _, err := fp.Seek(offset, io.SeekStart); err != nil {
return err
}

seg, err := bak.ReadSegment(fp)
if err != nil {
return fmt.Errorf("failed to read segment: %w", err)
}

fmt.Printf("Segment: %s\n", seg.Name())
fmt.Printf("Value: %s\n", seg)
return nil
}
33 changes: 22 additions & 11 deletions pkg/meta/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"unsafe"

"github.com/juicedata/juicefs/pkg/meta/pb"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
Expand Down Expand Up @@ -113,7 +114,7 @@ func newBakFormat() *BakFormat {
}
}

func (f *BakFormat) writeSegment(w io.Writer, seg *bakSegment) error {
func (f *BakFormat) writeSegment(w io.Writer, seg *BakSegment) error {
if seg == nil {
return nil
}
Expand All @@ -123,7 +124,7 @@ func (f *BakFormat) writeSegment(w io.Writer, seg *bakSegment) error {
return fmt.Errorf("failed to marshal segment %s: %v", seg, err)
}

name := seg.String()
name := seg.Name()
info, ok := f.Footer.Msg.Infos[name]
if !ok {
info = &pb.Footer_SegInfo{Offset: []uint64{}, Num: 0}
Expand All @@ -136,8 +137,8 @@ func (f *BakFormat) writeSegment(w io.Writer, seg *bakSegment) error {
return nil
}

func (f *BakFormat) readSegment(r io.Reader) (*bakSegment, error) {
seg := &bakSegment{}
func (f *BakFormat) ReadSegment(r io.Reader) (*BakSegment, error) {
seg := &BakSegment{}
if err := seg.Unmarshal(r); err != nil {
return nil, err
}
Expand Down Expand Up @@ -215,21 +216,31 @@ func (h *BakFooter) Unmarshal(r io.ReadSeeker) error {
return nil
}

type bakSegment struct {
type BakSegment struct {
typ uint32
len uint64
val proto.Message
}

func (s *bakSegment) String() string {
func (s *BakSegment) Name() string {
if name, ok := SegType2Name[int(s.typ)]; ok {
return name
}
return fmt.Sprintf("type-%d", s.typ)
}

func newBakSegment(val proto.Message) *bakSegment {
s := &bakSegment{val: val}
func (s *BakSegment) String() string {
switch s.val.(type) {
case *pb.Format:
return string(s.val.(*pb.Format).Data)
case *pb.Batch:
return protojson.Format(s.val)
}
return "unknown segment"
}

func newBakSegment(val proto.Message) *BakSegment {
s := &BakSegment{val: val}
switch v := s.val.(type) {
case *pb.Format:
s.typ = uint32(segTypeFormat)
Expand Down Expand Up @@ -267,7 +278,7 @@ func newBakSegment(val proto.Message) *bakSegment {
return s
}

func (s *bakSegment) num() uint64 {
func (s *BakSegment) num() uint64 {
switch s.typ {
case segTypeFormat:
return 1
Expand Down Expand Up @@ -305,7 +316,7 @@ func (s *bakSegment) num() uint64 {
}
}

func (s *bakSegment) Marshal(w io.Writer) (int, error) {
func (s *BakSegment) Marshal(w io.Writer) (int, error) {
if s == nil || s.val == nil {
return 0, fmt.Errorf("segment %s is nil", s)
}
Expand All @@ -329,7 +340,7 @@ func (s *bakSegment) Marshal(w io.Writer) (int, error) {
return binary.Size(s.typ) + binary.Size(s.len) + len(data), nil
}

func (s *bakSegment) Unmarshal(r io.Reader) error {
func (s *BakSegment) Unmarshal(r io.Reader) error {
if err := binary.Read(r, binary.BigEndian, &s.typ); err != nil {
return fmt.Errorf("failed to read segment type: %v", err)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/meta/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -3126,7 +3126,7 @@ func (m *baseMeta) DumpMetaV2(ctx Context, w io.Writer, opt *DumpOption) error {
return err
}
if opt.Progress != nil {
opt.Progress(seg.String(), int(seg.num()))
opt.Progress(seg.Name(), int(seg.num()))
}
if res.release != nil {
res.release(res.msg)
Expand Down Expand Up @@ -3181,7 +3181,7 @@ func (m *baseMeta) LoadMetaV2(ctx Context, r io.Reader, opt *LoadOption) error {

bak := &BakFormat{}
for {
seg, err := bak.readSegment(r)
seg, err := bak.ReadSegment(r)
if err != nil {
if errors.Is(err, errBakEOF) {
close(taskCh)
Expand All @@ -3198,7 +3198,7 @@ func (m *baseMeta) LoadMetaV2(ctx Context, r io.Reader, opt *LoadOption) error {
return ctx.Err()
case taskCh <- &task{int(seg.typ), seg.val}:
if opt.Progress != nil {
opt.Progress(seg.String(), int(seg.num()))
opt.Progress(seg.Name(), int(seg.num()))
}
}
}
Expand Down
19 changes: 10 additions & 9 deletions pkg/meta/pb/backup.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/meta/tkv_bak.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ func (m *kvMeta) LoadMetaV2(ctx Context, r io.Reader, opt *LoadOption) error {

bak := &BakFormat{}
for {
seg, err := bak.readSegment(r)
seg, err := bak.ReadSegment(r)
if err != nil {
if errors.Is(err, errBakEOF) {
close(taskCh)
Expand All @@ -703,7 +703,7 @@ func (m *kvMeta) LoadMetaV2(ctx Context, r io.Reader, opt *LoadOption) error {
return ctx.Err()
case taskCh <- &task{int(seg.typ), seg.val}:
if opt.Progress != nil {
opt.Progress(seg.String(), int(seg.num()))
opt.Progress(seg.Name(), int(seg.num()))
}
}
}
Expand Down

0 comments on commit 1549efb

Please sign in to comment.