Skip to content

Commit

Permalink
Merge pull request #417 from ahrtr/surgery_clear_element_20230310
Browse files Browse the repository at this point in the history
Add cobra style `surgery clear-page-elements` command
  • Loading branch information
ahrtr committed Mar 28, 2023
2 parents 5a7a94e + 74e26be commit 64bac9b
Show file tree
Hide file tree
Showing 10 changed files with 694 additions and 8 deletions.
24 changes: 24 additions & 0 deletions cmd/bbolt/command_root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"github.com/spf13/cobra"
)

const (
cliName = "bbolt"
cliDescription = "A simple command line tool for inspecting bbolt databases"
)

func NewRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: cliName,
Short: cliDescription,
Version: "dev",
}

rootCmd.AddCommand(
newSurgeryCobraCommand(),
)

return rootCmd
}
80 changes: 80 additions & 0 deletions cmd/bbolt/command_surgery_cobra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"

"go.etcd.io/bbolt/internal/common"
"go.etcd.io/bbolt/internal/surgeon"
)

var (
surgeryTargetDBFilePath string
surgeryPageId uint64
surgeryStartElementIdx int
surgeryEndElementIdx int
)

func newSurgeryCobraCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "surgery <subcommand>",
Short: "surgery related commands",
}

cmd.AddCommand(newSurgeryClearPageElementsCommand())

return cmd
}

func newSurgeryClearPageElementsCommand() *cobra.Command {
clearElementCmd := &cobra.Command{
Use: "clear-page-elements <bbolt-file> [options]",
Short: "Clears elements from the given page, which can be a branch or leaf page",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("db file path not provided")
}
if len(args) > 1 {
return errors.New("too many arguments")
}
return nil
},

RunE: surgeryClearPageElementFunc,
}

clearElementCmd.Flags().StringVar(&surgeryTargetDBFilePath, "output", "", "path to the target db file")
clearElementCmd.Flags().Uint64VarP(&surgeryPageId, "pageId", "", 0, "page id")
clearElementCmd.Flags().IntVarP(&surgeryStartElementIdx, "from-index", "", 0, "start element index (included) to clear, starting from 0")
clearElementCmd.Flags().IntVarP(&surgeryEndElementIdx, "to-index", "", 0, "end element index (excluded) to clear, starting from 0, -1 means to the end of page")

return clearElementCmd
}

func surgeryClearPageElementFunc(cmd *cobra.Command, args []string) error {
srcDBPath := args[0]

if err := copyFile(srcDBPath, surgeryTargetDBFilePath); err != nil {
return fmt.Errorf("[clear-page-element] copy file failed: %w", err)
}

if surgeryPageId < 2 {
return fmt.Errorf("the pageId must be at least 2, but got %d", surgeryPageId)
}

needAbandonFreelist, err := surgeon.ClearPageElements(surgeryTargetDBFilePath, common.Pgid(surgeryPageId), surgeryStartElementIdx, surgeryEndElementIdx, false)
if err != nil {
return fmt.Errorf("clear-page-element command failed: %w", err)
}

if needAbandonFreelist {
fmt.Fprintf(os.Stdout, "WARNING: The clearing has abandoned some pages that are not yet referenced from free list.\n")
fmt.Fprintf(os.Stdout, "Please consider executing `./bbolt surgery abandon-freelist ...`\n")
}

fmt.Fprintf(os.Stdout, "All elements in [%d, %d) in page %d were cleared\n", surgeryStartElementIdx, surgeryEndElementIdx, surgeryPageId)
return nil
}
Loading

0 comments on commit 64bac9b

Please sign in to comment.