1
0
mirror of https://github.com/taigrr/bitcask synced 2025-01-18 04:03:17 -08:00

Initial Commit

This commit is contained in:
James Mills
2019-03-09 22:41:59 +10:00
commit a42cd20ddf
26 changed files with 1706 additions and 0 deletions

46
cmd/bitcask/del.go Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var delCmd = &cobra.Command{
Use: "del <key>",
Aliases: []string{"delete", "remove", "rm"},
Short: "Delete a key and its value",
Long: `This deletes a key and its value`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
key := args[0]
os.Exit(del(path, key))
},
}
func init() {
RootCmd.AddCommand(delCmd)
}
func del(path, key string) int {
db, err := bitcask.Open(path)
if err != nil {
log.WithError(err).Error("error opening database")
return 1
}
err = db.Delete(key)
if err != nil {
log.WithError(err).Error("error deleting key")
return 1
}
return 0
}

50
cmd/bitcask/get.go Normal file
View File

@@ -0,0 +1,50 @@
package main
import (
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var getCmd = &cobra.Command{
Use: "get <key>",
Aliases: []string{"view"},
Short: "Get a new Key and display its Value",
Long: `This retrieves a key and display its value`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
key := args[0]
os.Exit(get(path, key))
},
}
func init() {
RootCmd.AddCommand(getCmd)
}
func get(path, key string) int {
db, err := bitcask.Open(path)
if err != nil {
log.WithError(err).Error("error opening database")
return 1
}
value, err := db.Get(key)
if err != nil {
log.WithError(err).Error("error reading key")
return 1
}
fmt.Printf("%s\n", string(value))
log.WithField("key", key).WithField("value", value).Debug("key/value")
return 0
}

48
cmd/bitcask/keys.go Normal file
View File

@@ -0,0 +1,48 @@
package main
import (
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var keysCmd = &cobra.Command{
Use: "keys",
Aliases: []string{"list", "ls"},
Short: "Display all keys in Database",
Long: `This displays all known keys in the Database"`,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
os.Exit(keys(path))
},
}
func init() {
RootCmd.AddCommand(keysCmd)
}
func keys(path string) int {
db, err := bitcask.Open(path)
if err != nil {
log.WithError(err).Error("error opening database")
return 1
}
err = db.Fold(func(key string) error {
fmt.Printf("%s\n", key)
return nil
})
if err != nil {
log.WithError(err).Error("error listing keys")
return 1
}
return 0
}

5
cmd/bitcask/main.go Normal file
View File

@@ -0,0 +1,5 @@
package main
func main() {
Execute()
}

50
cmd/bitcask/merge.go Normal file
View File

@@ -0,0 +1,50 @@
package main
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var mergeCmd = &cobra.Command{
Use: "merge",
Aliases: []string{"clean", "compact", "defrag"},
Short: "Merges the Datafiles in the Database",
Long: `This merges all non-active Datafiles in the Database and
compacts the data stored on disk. Old values are removed as well as deleted
keys.`,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
force, err := cmd.Flags().GetBool("force")
if err != nil {
log.WithError(err).Error("error parsing force flag")
os.Exit(1)
}
os.Exit(merge(path, force))
},
}
func init() {
RootCmd.AddCommand(mergeCmd)
mergeCmd.Flags().BoolP(
"force", "f", false,
"Force a re-merge even if .hint files exist",
)
}
func merge(path string, force bool) int {
err := bitcask.Merge(path, force)
if err != nil {
log.WithError(err).Error("error merging database")
return 1
}
return 0
}

60
cmd/bitcask/root.go Normal file
View File

@@ -0,0 +1,60 @@
package main
import (
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "bitcask",
Version: bitcask.FullVersion(),
Short: "Command-line tools for bitcask",
Long: `This is the command-line tool to interact with a bitcask database.
This lets you get, set and delete key/value pairs as well as perform merge
(or compaction) operations. This tool serves as an example implementation
however is also intended to be useful in shell scripts.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// set logging level
if viper.GetBool("debug") {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.InfoLevel)
}
},
}
// Execute adds all child commands to the root command
// and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
RootCmd.PersistentFlags().BoolP(
"debug", "d", false,
"Enable debug logging",
)
RootCmd.PersistentFlags().StringP(
"path", "p", "/tmp/bitcask",
"Path to Bitcask database",
)
viper.BindPFlag("path", RootCmd.PersistentFlags().Lookup("path"))
viper.SetDefault("path", "/tmp/bitcask")
viper.BindPFlag("debug", RootCmd.PersistentFlags().Lookup("debug"))
viper.SetDefault("debug", false)
}

64
cmd/bitcask/set.go Normal file
View File

@@ -0,0 +1,64 @@
package main
import (
"bytes"
"io"
"io/ioutil"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var setCmd = &cobra.Command{
Use: "set <key> [<value>]",
Aliases: []string{"add"},
Short: "Add/Set a new Key/Value pair",
Long: `This adds or sets a new key/value pair.
If the value is not specified as an argument it is read from standard input.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
key := args[0]
var value io.Reader
if len(args) > 1 {
value = bytes.NewBufferString(args[1])
} else {
value = os.Stdin
}
os.Exit(set(path, key, value))
},
}
func init() {
RootCmd.AddCommand(setCmd)
}
func set(path, key string, value io.Reader) int {
db, err := bitcask.Open(path)
if err != nil {
log.WithError(err).Error("error opening database")
return 1
}
data, err := ioutil.ReadAll(value)
if err != nil {
log.WithError(err).Error("error writing key")
return 1
}
err = db.Put(key, data)
if err != nil {
log.WithError(err).Error("error writing key")
return 1
}
return 0
}