From 63748a27584e1ff97994427852b6e8fe60a2432e Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Thu, 3 Aug 2017 21:19:04 -0700 Subject: [PATCH] Add option to defrag a data directory directly, for cases where etcd is not running. --- etcdctl/ctlv3/command/defrag_command.go | 40 ++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/etcdctl/ctlv3/command/defrag_command.go b/etcdctl/ctlv3/command/defrag_command.go index b00ca2054d62..a7e6f76f3cad 100644 --- a/etcdctl/ctlv3/command/defrag_command.go +++ b/etcdctl/ctlv3/command/defrag_command.go @@ -17,20 +17,38 @@ package command import ( "fmt" "os" + "path/filepath" + "time" + "github.com/coreos/etcd/mvcc/backend" "github.com/spf13/cobra" ) +var ( + defragDataDir string +) + // NewDefragCommand returns the cobra command for "Defrag". func NewDefragCommand() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "defrag", Short: "Defragments the storage of the etcd members with given endpoints", Run: defragCommandFunc, } + cmd.Flags().StringVar(&defragDataDir, "data-dir", "", "Optional. If present, defragments a data directory not in use by etcd.") + return cmd } func defragCommandFunc(cmd *cobra.Command, args []string) { + if len(defragDataDir) > 0 { + err := defragData(defragDataDir) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to defragment etcd data[%s] (%v)\n", defragDataDir, err) + os.Exit(ExitError) + } + return + } + failures := 0 c := mustClientFromCmd(cmd) for _, ep := range c.Endpoints() { @@ -49,3 +67,23 @@ func defragCommandFunc(cmd *cobra.Command, args []string) { os.Exit(ExitError) } } + +func defragData(dataDir string) error { + var be backend.Backend + + bch := make(chan struct{}) + dbDir := filepath.Join(dataDir, "member", "snap", "db") + go func() { + defer close(bch) + be = backend.NewDefaultBackend(dbDir) + + }() + select { + case <-bch: + case <-time.After(time.Second): + fmt.Fprintf(os.Stderr, "waiting for etcd to close and release its lock on %q. "+ + "To defrag a running etcd instance, omit --data-dir.\n", dbDir) + <-bch + } + return be.Defrag() +}