LCOV - code coverage report
Current view: top level - pebble/tool - remotecat.go (source / functions) Hit Total Coverage
Test: 2024-04-20 08:15Z 5b3f94f1 - tests + meta.lcov Lines: 82 92 89.1 %
Date: 2024-04-20 08:16:32 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : package tool
       6             : 
       7             : import (
       8             :         "fmt"
       9             :         "io"
      10             :         "slices"
      11             : 
      12             :         "github.com/cockroachdb/pebble"
      13             :         "github.com/cockroachdb/pebble/internal/base"
      14             :         "github.com/cockroachdb/pebble/objstorage"
      15             :         "github.com/cockroachdb/pebble/objstorage/objstorageprovider/remoteobjcat"
      16             :         "github.com/cockroachdb/pebble/record"
      17             :         "github.com/spf13/cobra"
      18             : )
      19             : 
      20             : // remoteCatalogT implements tools for the remote object catalog.
      21             : type remoteCatalogT struct {
      22             :         Root *cobra.Command
      23             :         Dump *cobra.Command
      24             : 
      25             :         verbose bool
      26             :         opts    *pebble.Options
      27             : }
      28             : 
      29           1 : func newRemoteCatalog(opts *pebble.Options) *remoteCatalogT {
      30           1 :         m := &remoteCatalogT{
      31           1 :                 opts: opts,
      32           1 :         }
      33           1 : 
      34           1 :         m.Root = &cobra.Command{
      35           1 :                 Use:   "remotecat",
      36           1 :                 Short: "remote object catalog introspection tools",
      37           1 :         }
      38           1 : 
      39           1 :         // Add dump command
      40           1 :         m.Dump = &cobra.Command{
      41           1 :                 Use:   "dump <remote-catalog-files>",
      42           1 :                 Short: "print remote object catalog contents",
      43           1 :                 Long: `
      44           1 : Print the contents of the REMOTE-OBJ-CATALOG files.
      45           1 : `,
      46           1 :                 Args: cobra.MinimumNArgs(1),
      47           1 :                 Run:  m.runDump,
      48           1 :         }
      49           1 :         m.Dump.Flags().BoolVarP(&m.verbose, "verbose", "v", false, "show each record in the catalog")
      50           1 :         m.Root.AddCommand(m.Dump)
      51           1 : 
      52           1 :         return m
      53           1 : }
      54             : 
      55           1 : func (m *remoteCatalogT) runDump(cmd *cobra.Command, args []string) {
      56           1 :         for _, arg := range args {
      57           1 :                 err := m.runDumpOne(cmd.OutOrStdout(), arg)
      58           1 :                 if err != nil {
      59           0 :                         fmt.Fprintf(cmd.OutOrStderr(), "%s\n", err)
      60           0 :                 }
      61             :         }
      62             : }
      63             : 
      64           1 : func (m *remoteCatalogT) runDumpOne(stdout io.Writer, filename string) error {
      65           1 :         f, err := m.opts.FS.Open(filename)
      66           1 :         if err != nil {
      67           0 :                 return err
      68           0 :         }
      69             : 
      70           1 :         var creatorID objstorage.CreatorID
      71           1 :         objects := make(map[base.DiskFileNum]remoteobjcat.RemoteObjectMetadata)
      72           1 : 
      73           1 :         fmt.Fprintf(stdout, "%s\n", filename)
      74           1 :         var editIdx int
      75           1 :         rr := record.NewReader(f, 0 /* logNum */)
      76           1 :         for {
      77           1 :                 offset := rr.Offset()
      78           1 :                 r, err := rr.Next()
      79           1 :                 if err == io.EOF {
      80           1 :                         break
      81           1 :                 } else if err != nil {
      82           0 :                         return err
      83           0 :                 }
      84             : 
      85           1 :                 var ve remoteobjcat.VersionEdit
      86           1 :                 err = ve.Decode(r)
      87           1 :                 if err != nil {
      88           0 :                         return err
      89           0 :                 }
      90             : 
      91           1 :                 if m.verbose {
      92           1 :                         fmt.Fprintf(stdout, "%d/%d\n", offset, editIdx)
      93           1 :                         if ve.CreatorID.IsSet() {
      94           1 :                                 fmt.Fprintf(stdout, "  CreatorID: %s\n", ve.CreatorID)
      95           1 :                         }
      96           1 :                         if len(ve.NewObjects) > 0 {
      97           1 :                                 fmt.Fprintf(stdout, "  NewObjects:\n")
      98           1 :                                 for _, m := range ve.NewObjects {
      99           1 :                                         fmt.Fprintf(
     100           1 :                                                 stdout, "    %s  CreatorID: %s  CreatorFileNum: %s  Locator: %q CustomObjectName: %q\n",
     101           1 :                                                 m.FileNum, m.CreatorID, m.CreatorFileNum, m.Locator, m.CustomObjectName,
     102           1 :                                         )
     103           1 :                                 }
     104             :                         }
     105           1 :                         if len(ve.DeletedObjects) > 0 {
     106           1 :                                 fmt.Fprintf(stdout, "  DeletedObjects:\n")
     107           1 :                                 for _, n := range ve.DeletedObjects {
     108           1 :                                         fmt.Fprintf(stdout, "    %s\n", n)
     109           1 :                                 }
     110             :                         }
     111             :                 }
     112           1 :                 editIdx++
     113           1 :                 if err := ve.Apply(&creatorID, objects); err != nil {
     114           0 :                         return err
     115           0 :                 }
     116             :         }
     117           1 :         fmt.Fprintf(stdout, "CreatorID: %v\n", creatorID)
     118           1 :         var filenums []base.DiskFileNum
     119           1 :         for n := range objects {
     120           1 :                 filenums = append(filenums, n)
     121           1 :         }
     122           1 :         slices.Sort(filenums)
     123           1 :         fmt.Fprintf(stdout, "Objects:\n")
     124           1 :         for _, n := range filenums {
     125           1 :                 m := objects[n]
     126           1 :                 fmt.Fprintf(
     127           1 :                         stdout, "    %s  CreatorID: %s  CreatorFileNum: %s  Locator: %q CustomObjectName: %q\n",
     128           1 :                         n, m.CreatorID, m.CreatorFileNum, m.Locator, m.CustomObjectName,
     129           1 :                 )
     130           1 :         }
     131           1 :         return nil
     132             : }

Generated by: LCOV version 1.14