Skip to content

Commit

Permalink
Add option to defrag a data directory directly, for cases where etcd …
Browse files Browse the repository at this point in the history
…is not running.
  • Loading branch information
jpbetz committed Aug 7, 2017
1 parent faa4a62 commit 63748a2
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion etcdctl/ctlv3/command/defrag_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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()
}

0 comments on commit 63748a2

Please sign in to comment.