Skip to content

Commit 1dc036f

Browse files
committed
Add dbtool
1 parent 153b95d commit 1dc036f

File tree

7 files changed

+192
-0
lines changed

7 files changed

+192
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ require (
4545
github.com/rivo/uniseg v0.2.0 // indirect
4646
github.com/shirou/gopsutil v3.21.4+incompatible
4747
github.com/sirupsen/logrus v1.7.0
48+
github.com/spf13/cobra v0.0.5
4849
github.com/tklauser/go-sysconf v0.3.6 // indirect
4950
github.com/twmb/murmur3 v1.1.5
5051
github.com/valyala/bytebufferpool v1.0.0

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200715173712-053cf528c12f/go.mod h1:
205205
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
206206
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
207207
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
208+
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
208209
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
209210
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
210211
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
@@ -341,8 +342,10 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b
341342
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
342343
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
343344
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
345+
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
344346
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
345347
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
348+
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
346349
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
347350
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
348351
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

scripts/dbtool/cmd/get.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"os"
7+
8+
"github.com/dgraph-io/badger/v2"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func (d *dbTool) newGetCommand() *cobra.Command {
13+
return &cobra.Command{
14+
Use: "get <key>",
15+
Short: "Retrieves key value and dumps it to stdout",
16+
RunE: d.runGet,
17+
Args: cobra.MinimumNArgs(1),
18+
PreRunE: d.openDB(true),
19+
}
20+
}
21+
22+
func (d *dbTool) runGet(_ *cobra.Command, args []string) error {
23+
return d.db.View(func(txn *badger.Txn) error {
24+
item, err := txn.Get([]byte(args[0]))
25+
if err != nil {
26+
return err
27+
}
28+
v, err := item.ValueCopy(nil)
29+
if err != nil {
30+
return err
31+
}
32+
_, _ = io.Copy(os.Stdout, bytes.NewBuffer(v))
33+
return nil
34+
})
35+
}

scripts/dbtool/cmd/list.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/dgraph-io/badger/v2"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
func (d *dbTool) newListCommand() *cobra.Command {
12+
cmd := cobra.Command{
13+
Use: "list",
14+
Short: "Lists db keys",
15+
RunE: d.runList,
16+
PreRunE: d.openDB(true),
17+
}
18+
cmd.Flags().StringVarP(&d.prefix, "prefix", "p", "", "key prefix")
19+
return &cmd
20+
}
21+
22+
func (d *dbTool) runList(_ *cobra.Command, _ []string) error {
23+
return d.db.View(func(txn *badger.Txn) error {
24+
opts := badger.DefaultIteratorOptions
25+
opts.PrefetchValues = false
26+
opts.Prefix = []byte(d.prefix)
27+
it := txn.NewIterator(opts)
28+
defer it.Close()
29+
for it.Rewind(); it.Valid(); it.Next() {
30+
_, _ = fmt.Fprintf(os.Stdout, "%s\n", it.Item().Key())
31+
}
32+
return nil
33+
})
34+
}

scripts/dbtool/cmd/remove.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package cmd
2+
3+
import (
4+
"github.com/dgraph-io/badger/v2"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
func (d *dbTool) newRemoveCommand() *cobra.Command {
9+
return &cobra.Command{
10+
Use: "remove <key>",
11+
Short: "Removes key value from the database",
12+
RunE: d.runRemove,
13+
Args: cobra.MinimumNArgs(1),
14+
PreRunE: d.openDB(false),
15+
}
16+
}
17+
18+
func (d *dbTool) runRemove(_ *cobra.Command, args []string) error {
19+
return d.db.Update(func(txn *badger.Txn) error {
20+
return txn.Delete([]byte(args[0]))
21+
})
22+
}

scripts/dbtool/cmd/root.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/dgraph-io/badger/v2"
9+
"github.com/dgraph-io/badger/v2/options"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
type dbTool struct {
14+
dir string
15+
prefix string
16+
17+
db *badger.DB
18+
}
19+
20+
func Execute() error {
21+
return newRootCommand().Execute()
22+
}
23+
24+
func newRootCommand() *cobra.Command {
25+
d := new(dbTool)
26+
root := cobra.Command{
27+
Use: "dbtool [command]",
28+
Short: "DB helper tool",
29+
SilenceUsage: true,
30+
SilenceErrors: true,
31+
PersistentPostRunE: d.closeDB(),
32+
}
33+
34+
root.PersistentFlags().StringVarP(&d.dir, "dir", "d", ".", "database directory path")
35+
root.AddCommand(
36+
d.newListCommand(),
37+
d.newRemoveCommand(),
38+
d.newGetCommand())
39+
40+
return &root
41+
}
42+
43+
func (d *dbTool) openDB(ro bool) func(cmd *cobra.Command, args []string) error {
44+
return func(c *cobra.Command, _ []string) error {
45+
db, err := openDB(d.dir, ro)
46+
if err != nil {
47+
return fmt.Errorf("failed to open %s: %v", d.dir, err)
48+
}
49+
d.db = db
50+
return nil
51+
}
52+
}
53+
54+
func (d *dbTool) closeDB() func(cmd *cobra.Command, args []string) error {
55+
return func(c *cobra.Command, _ []string) error {
56+
if d.db == nil {
57+
return nil
58+
}
59+
if err := d.db.Close(); err != nil {
60+
return fmt.Errorf("closing database: %w", err)
61+
}
62+
return nil
63+
}
64+
}
65+
66+
func openDB(dir string, ro bool) (*badger.DB, error) {
67+
if !ro {
68+
// When DB is opened for RW, badger.Open does not fail
69+
// if the directory is not a badger database, instead it
70+
// creates one.
71+
f, err := os.Open(filepath.Join(dir, badger.ManifestFilename))
72+
if err != nil {
73+
return nil, err
74+
}
75+
_ = f.Close()
76+
}
77+
return badger.Open(badger.DefaultOptions(dir).
78+
WithCompression(options.ZSTD).
79+
WithReadOnly(ro))
80+
}

scripts/dbtool/main.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/fatih/color"
8+
9+
"github.com/pyroscope-io/pyroscope/scripts/dbtool/cmd"
10+
)
11+
12+
func main() {
13+
if err := cmd.Execute(); err != nil {
14+
_, _ = fmt.Fprintln(os.Stderr, color.RedString("Error:"), err)
15+
os.Exit(1)
16+
}
17+
}

0 commit comments

Comments
 (0)