Compare commits

..

5 Commits

Author SHA1 Message Date
James Mills
962e53af17 Add Has() to exported API (extended API) 2019-03-21 10:24:48 +10:00
James Mills
7a427a237a Update README.md 2019-03-21 08:36:17 +10:00
James Mills
8bf169c96f Add MergeOpen test case 2019-03-20 17:10:24 +10:00
James Mills
c1488fed2a Added Fold() test case 2019-03-20 16:55:59 +10:00
James Mills
d6e806e655 Update README.md 2019-03-20 15:30:08 +10:00
3 changed files with 109 additions and 12 deletions

View File

@@ -6,13 +6,13 @@
[![GoDoc](https://godoc.org/github.com/prologic/bitcask?status.svg)](https://godoc.org/github.com/prologic/bitcask)
[![Sourcegraph](https://sourcegraph.com/github.com/prologic/bitcask/-/badge.svg)](https://sourcegraph.com/github.com/prologic/bitcask?badge)
A Bitcask (LSM+WAL) Key/Value Store written in Go.
A high performance Key/Value store written in [Go](https://golang.org) with a predictable read/write performance and high throughput. Uses a [Bitcask](https://en.wikipedia.org/wiki/Bitcask) on-disk layout (LSM+WAL) similar to [Riak](https://riak.com/).
## Features
* Embeddable
* Builtin CLI
* Builtin Redis-compatible server
* Embeddable (`import "github.com/prologic/bitcask"`)
* Builtin CLI (`bitcask`)
* Builtin Redis-compatible server (`bitcaskd`)
* Predictable read/write performance
* Low latecny
* High throughput (See: [Performance](README.md#Performance)
@@ -34,16 +34,13 @@ $ go get github.com/prologic/bitcask
```#!go
package main
import (
"log"
"github.com/prologic/bitcask"
)
import "github.com/prologic/bitcask"
func main() {
db, _ := bitcask.Open("/tmp/db")
defer db.Close()
db.Set("Hello", []byte("World"))
db.Close()
val, _ := db.Get("hello")
}
```

View File

@@ -79,6 +79,11 @@ func (b *Bitcask) Get(key string) ([]byte, error) {
return e.Value, nil
}
func (b *Bitcask) Has(key string) bool {
_, ok := b.keydir.Get(key)
return ok
}
func (b *Bitcask) Put(key string, value []byte) error {
if len(key) > b.config.MaxKeySize {
return ErrKeyTooLarge

View File

@@ -40,6 +40,30 @@ func TestAll(t *testing.T) {
assert.Equal([]byte("bar"), val)
})
t.Run("Has", func(t *testing.T) {
assert.True(db.Has("foo"))
})
t.Run("Fold", func(t *testing.T) {
var (
keys []string
values [][]byte
)
err := db.Fold(func(key string) error {
value, err := db.Get(key)
if err != nil {
return err
}
keys = append(keys, key)
values = append(values, value)
return nil
})
assert.NoError(err)
assert.Equal([]string{"foo"}, keys)
assert.Equal([][]byte{[]byte("bar")}, values)
})
t.Run("Delete", func(t *testing.T) {
err := db.Delete("foo")
assert.NoError(err)
@@ -174,7 +198,7 @@ func TestMaxValueSize(t *testing.T) {
})
}
func TestMerge(t *testing.T) {
func TestOpenMerge(t *testing.T) {
assert := assert.New(t)
testdir, err := ioutil.TempDir("", "bitcask")
@@ -187,7 +211,7 @@ func TestMerge(t *testing.T) {
)
t.Run("Open", func(t *testing.T) {
db, err = Open(testdir, WithMaxDatafileSize(1024))
db, err = Open(testdir, WithMaxDatafileSize(32))
assert.NoError(err)
})
@@ -245,6 +269,77 @@ func TestMerge(t *testing.T) {
})
}
func TestMergeOpen(t *testing.T) {
var (
db *Bitcask
err error
)
assert := assert.New(t)
testdir, err := ioutil.TempDir("", "bitcask")
assert.NoError(err)
t.Run("Setup", func(t *testing.T) {
t.Run("Open", func(t *testing.T) {
db, err = Open(testdir, WithMaxDatafileSize(32))
assert.NoError(err)
})
t.Run("Put", func(t *testing.T) {
for i := 0; i < 1024; i++ {
err = db.Put(string(i), []byte(strings.Repeat(" ", 1024)))
assert.NoError(err)
}
})
t.Run("Get", func(t *testing.T) {
for i := 0; i < 32; i++ {
err = db.Put(string(i), []byte(strings.Repeat(" ", 1024)))
assert.NoError(err)
val, err := db.Get(string(i))
assert.NoError(err)
assert.Equal([]byte(strings.Repeat(" ", 1024)), val)
}
})
t.Run("Sync", func(t *testing.T) {
err = db.Sync()
assert.NoError(err)
})
t.Run("Close", func(t *testing.T) {
err = db.Close()
assert.NoError(err)
})
})
t.Run("Merge", func(t *testing.T) {
t.Run("Merge", func(t *testing.T) {
err = Merge(testdir, true)
assert.NoError(err)
})
t.Run("Open", func(t *testing.T) {
db, err = Open(testdir)
assert.NoError(err)
})
t.Run("Get", func(t *testing.T) {
for i := 0; i < 32; i++ {
val, err := db.Get(string(i))
assert.NoError(err)
assert.Equal([]byte(strings.Repeat(" ", 1024)), val)
}
})
t.Run("Close", func(t *testing.T) {
err = db.Close()
assert.NoError(err)
})
})
}
func TestConcurrent(t *testing.T) {
var (
db *Bitcask