Added the same functional options to the bitcask CLI and persist options to the db store (#40)

This commit is contained in:
James Mills 2019-08-07 10:23:10 +10:00 committed by GitHub
parent bce2721be4
commit 82e26449fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 2 deletions

@ -1,6 +1,7 @@
package bitcask
import (
"encoding/json"
"errors"
"hash/crc32"
"io"
@ -245,6 +246,28 @@ func (b *Bitcask) put(key string, value []byte) (int64, int64, error) {
return b.curr.Write(e)
}
func (b *Bitcask) readConfig() error {
if internal.Exists(filepath.Join(b.path, "config.json")) {
data, err := ioutil.ReadFile(filepath.Join(b.path, "config.json"))
if err != nil {
return err
}
if err := json.Unmarshal(data, &b.config); err != nil {
return err
}
}
return nil
}
func (b *Bitcask) writeConfig() error {
data, err := json.Marshal(b.config)
if err != nil {
return err
}
return ioutil.WriteFile(filepath.Join(b.path, "config.json"), data, 0600)
}
func (b *Bitcask) reopen() error {
b.mu.Lock()
defer b.mu.Unlock()
@ -411,9 +434,14 @@ func Open(path string, options ...Option) (*Bitcask, error) {
return nil, err
}
config, err := getConfig(path)
if err != nil {
return nil, err
}
bitcask := &Bitcask{
Flock: flock.New(filepath.Join(path, "lock")),
config: newDefaultConfig(),
config: config,
options: options,
path: path,
}
@ -435,6 +463,10 @@ func Open(path string, options ...Option) (*Bitcask, error) {
return nil, ErrDatabaseLocked
}
if err := bitcask.writeConfig(); err != nil {
return nil, err
}
if err := bitcask.reopen(); err != nil {
return nil, err
}

67
cmd/bitcask/initdb.go Normal file

@ -0,0 +1,67 @@
package main
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/prologic/bitcask"
)
var initdbCmd = &cobra.Command{
Use: "initdb",
Aliases: []string{"create", "init"},
Short: "Initialize a new database",
Long: `This initializes a new database with persisted options`,
Args: cobra.ExactArgs(0),
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("with-max-datafile-size", cmd.Flags().Lookup("with-max-datafile-size"))
viper.SetDefault("with-max-datafile-size", bitcask.DefaultMaxDatafileSize)
viper.BindPFlag("with-max-key-size", cmd.Flags().Lookup("with-max-key-size"))
viper.SetDefault("with-max-key-size", bitcask.DefaultMaxKeySize)
viper.BindPFlag("with-max-value-size", cmd.Flags().Lookup("with-max-value-size"))
viper.SetDefault("with-max-value-size", bitcask.DefaultMaxValueSize)
},
Run: func(cmd *cobra.Command, args []string) {
path := viper.GetString("path")
maxDatafileSize := viper.GetInt("with-max-datafile-size")
maxKeySize := viper.GetInt("with-max-key-size")
maxValueSize := viper.GetInt("with-max-value-size")
db, err := bitcask.Open(
path,
bitcask.WithMaxDatafileSize(maxDatafileSize),
bitcask.WithMaxKeySize(maxKeySize),
bitcask.WithMaxValueSize(maxValueSize),
)
if err != nil {
log.WithError(err).Error("error opening database")
os.Exit(1)
}
defer db.Close()
os.Exit(0)
},
}
func init() {
RootCmd.AddCommand(initdbCmd)
initdbCmd.PersistentFlags().IntP(
"with-max-datafile-size", "", bitcask.DefaultMaxDatafileSize,
"Maximum size of each datafile",
)
initdbCmd.PersistentFlags().IntP(
"with-max-key-size", "", bitcask.DefaultMaxKeySize,
"Maximum size of each key",
)
initdbCmd.PersistentFlags().IntP(
"with-max-value-size", "", bitcask.DefaultMaxValueSize,
"Maximum size of each value",
)
}

@ -1,6 +1,11 @@
package bitcask
import "errors"
import (
"encoding/json"
"errors"
"io/ioutil"
"path/filepath"
)
const (
// DefaultMaxDatafileSize is the default maximum datafile size in bytes
@ -29,6 +34,43 @@ type config struct {
maxConcurrency *int
}
func (c *config) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
MaxDatafileSize int `json:"max_datafile_size"`
MaxKeySize int `json:"max_key_size"`
MaxValueSize int `json:"max_value_size"`
}{
MaxDatafileSize: c.maxDatafileSize,
MaxKeySize: c.maxKeySize,
MaxValueSize: c.maxValueSize,
})
}
func getConfig(path string) (*config, error) {
type Config struct {
MaxDatafileSize int `json:"max_datafile_size"`
MaxKeySize int `json:"max_key_size"`
MaxValueSize int `json:"max_value_size"`
}
var cfg Config
data, err := ioutil.ReadFile(filepath.Join(path, "config.json"))
if err != nil {
return nil, err
}
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return &config{
maxDatafileSize: cfg.MaxDatafileSize,
maxKeySize: cfg.MaxKeySize,
maxValueSize: cfg.MaxValueSize,
}, nil
}
func newDefaultConfig() *config {
return &config{
maxDatafileSize: DefaultMaxDatafileSize,