Merge divergent versions of library
This commit is contained in:
parent
6f20fa59ee
commit
0d670b3fc5
@ -36,10 +36,35 @@ func (db *DB) Path() string {
|
|||||||
return db.path
|
return db.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DefaultBitcaskOptions []bitcask.Option
|
||||||
|
|
||||||
|
func SetDefaultBitcaskOptions(bitcaskopts ...bitcask.Option) {
|
||||||
|
for _, opt := range bitcaskopts {
|
||||||
|
DefaultBitcaskOptions = append(DefaultBitcaskOptions, opt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithMaxDatafileSize(size int) bitcask.Option {
|
||||||
|
return bitcask.WithMaxDatafileSize(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithMaxKeySize(size uint32) bitcask.Option {
|
||||||
|
return bitcask.WithMaxKeySize(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithMaxValueSize(size uint64) bitcask.Option {
|
||||||
|
return bitcask.WithMaxValueSize(size)
|
||||||
|
}
|
||||||
|
|
||||||
// Init opens a bitcask store at the given path to be referenced by storeName.
|
// Init opens a bitcask store at the given path to be referenced by storeName.
|
||||||
func (db *DB) Init(storeName string, bitcaskopts ...bitcask.Option) error {
|
func (db *DB) Init(storeName string, bitcaskopts ...bitcask.Option) error {
|
||||||
db.mu.Lock()
|
db.mu.Lock()
|
||||||
defer db.mu.Unlock()
|
defer db.mu.Unlock()
|
||||||
|
|
||||||
|
if len(DefaultBitcaskOptions) > 0 {
|
||||||
|
bitcaskopts = append(bitcaskopts, DefaultBitcaskOptions...)
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := db.store[storeName]; ok {
|
if _, ok := db.store[storeName]; ok {
|
||||||
return errStoreExists
|
return errStoreExists
|
||||||
}
|
}
|
||||||
@ -62,10 +87,27 @@ func (db *DB) With(storeName string) Store {
|
|||||||
db.mu.RLock()
|
db.mu.RLock()
|
||||||
defer db.mu.RUnlock()
|
defer db.mu.RUnlock()
|
||||||
d, ok := db.store[storeName]
|
d, ok := db.store[storeName]
|
||||||
if !ok {
|
if ok {
|
||||||
return Store{Bitcask: nil}
|
return d
|
||||||
}
|
}
|
||||||
return d
|
return Store{Bitcask: nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNew calls the given underlying bitcask instance, if it doesn't exist, it creates it.
|
||||||
|
func (db *DB) WithNew(storeName string) Store {
|
||||||
|
db.mu.RLock()
|
||||||
|
defer db.mu.RUnlock()
|
||||||
|
d, ok := db.store[storeName]
|
||||||
|
if ok {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
db.mu.RUnlock()
|
||||||
|
err := db.Init(storeName)
|
||||||
|
db.mu.RLock()
|
||||||
|
if err == nil {
|
||||||
|
return db.store[storeName]
|
||||||
|
}
|
||||||
|
return Store{Bitcask: nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close is a simple shim for bitcask's Close function.
|
// Close is a simple shim for bitcask's Close function.
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.tcp.direct/kayos/common/entropy"
|
c "git.tcp.direct/kayos/common/entropy"
|
||||||
)
|
)
|
||||||
|
|
||||||
var needle = "yeet"
|
var needle = "yeet"
|
||||||
@ -40,20 +40,20 @@ func setupTest(storename string, t *testing.T) *DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func genJunk(t *testing.T, correct bool) []byte {
|
func genJunk(t *testing.T, correct bool) []byte {
|
||||||
item := entropy.RandStr(5)
|
item := c.RandStr(5)
|
||||||
bar := entropy.RandStr(5)
|
bar := c.RandStr(5)
|
||||||
if correct {
|
if correct {
|
||||||
if entropy.RNG(100) > 50 {
|
if c.RNG(100) > 50 {
|
||||||
item = needle + entropy.RandStr(entropy.RNG(5))
|
item = needle + c.RandStr(c.RNG(5))
|
||||||
} else {
|
} else {
|
||||||
bar = entropy.RandStr(entropy.RNG(5)) + needle
|
bar = c.RandStr(c.RNG(5)) + needle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f := Foo{
|
f := Foo{
|
||||||
Bar: bar,
|
Bar: bar,
|
||||||
Yeet: entropy.RNG(50),
|
Yeet: c.RNG(50),
|
||||||
What: map[string]int{entropy.RandStr(5): 2, item: 7},
|
What: map[string]int{c.RandStr(5): 2, item: 7},
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, err := json.Marshal(f)
|
raw, err := json.Marshal(f)
|
||||||
@ -96,11 +96,11 @@ func Test_Search(t *testing.T) {
|
|||||||
var storename = "test_search"
|
var storename = "test_search"
|
||||||
var db = setupTest(storename, t)
|
var db = setupTest(storename, t)
|
||||||
|
|
||||||
one := entropy.RNG(100)
|
one := c.RNG(100)
|
||||||
two := entropy.RNG(100)
|
two := c.RNG(100)
|
||||||
three := entropy.RNG(100)
|
three := c.RNG(100)
|
||||||
four := entropy.RNG(100)
|
four := c.RNG(100)
|
||||||
five := entropy.RNG(100)
|
five := c.RNG(100)
|
||||||
|
|
||||||
addJunk(db, storename, one, two, three, four, five, t, true)
|
addJunk(db, storename, one, two, three, four, five, t, true)
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ func Test_Search(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("NoResultsSearch", func(t *testing.T) {
|
t.Run("NoResultsSearch", func(t *testing.T) {
|
||||||
bogus := entropy.RandStr(55)
|
bogus := c.RandStr(55)
|
||||||
t.Logf("executing search for %s", bogus)
|
t.Logf("executing search for %s", bogus)
|
||||||
|
|
||||||
results, err := db.With(storename).Search(bogus)
|
results, err := db.With(storename).Search(bogus)
|
||||||
@ -154,7 +154,7 @@ func Test_ValueExists(t *testing.T) {
|
|||||||
var db = setupTest(storename, t)
|
var db = setupTest(storename, t)
|
||||||
|
|
||||||
t.Run("ValueExists", func(t *testing.T) {
|
t.Run("ValueExists", func(t *testing.T) {
|
||||||
needles := addJunk(db, storename, entropy.RNG(100), entropy.RNG(100), entropy.RNG(100), entropy.RNG(100), entropy.RNG(100), t, true)
|
needles := addJunk(db, storename, c.RNG(100), c.RNG(100), c.RNG(100), c.RNG(100), c.RNG(100), t, true)
|
||||||
|
|
||||||
for _, needle := range needles {
|
for _, needle := range needles {
|
||||||
if k, exists := db.With(storename).ValueExists(needle); !exists {
|
if k, exists := db.With(storename).ValueExists(needle); !exists {
|
||||||
@ -167,7 +167,7 @@ func Test_ValueExists(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("ValueShouldNotExist", func(t *testing.T) {
|
t.Run("ValueShouldNotExist", func(t *testing.T) {
|
||||||
for n := 0; n != 5; n++ {
|
for n := 0; n != 5; n++ {
|
||||||
garbage := entropy.RandStr(55)
|
garbage := c.RandStr(55)
|
||||||
if _, exists := db.With(storename).ValueExists([]byte(garbage)); exists {
|
if _, exists := db.With(storename).ValueExists([]byte(garbage)); exists {
|
||||||
t.Errorf("[FAIL] store should have not contained value %v, but it did", []byte(garbage))
|
t.Errorf("[FAIL] store should have not contained value %v, but it did", []byte(garbage))
|
||||||
} else {
|
} else {
|
||||||
@ -192,28 +192,28 @@ func Test_PrefixScan(t *testing.T) {
|
|||||||
var storename = "test_prefix_scan"
|
var storename = "test_prefix_scan"
|
||||||
var db = setupTest(storename, t)
|
var db = setupTest(storename, t)
|
||||||
|
|
||||||
addJunk(db, storename, entropy.RNG(5), entropy.RNG(5), entropy.RNG(5), entropy.RNG(5), entropy.RNG(5), t, false)
|
addJunk(db, storename, c.RNG(5), c.RNG(5), c.RNG(5), c.RNG(5), c.RNG(5), t, false)
|
||||||
|
|
||||||
var needles = []KeyValue{
|
var needles = []KeyValue{
|
||||||
{
|
{
|
||||||
Key: Key{b: []byte("user:Fuckhole")},
|
Key: Key{b: []byte("user:Fuckhole")},
|
||||||
Value: Value{b: []byte(entropy.RandStr(55))},
|
Value: Value{b: []byte(c.RandStr(55))},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: Key{b: []byte("user:Johnson")},
|
Key: Key{b: []byte("user:Johnson")},
|
||||||
Value: Value{b: []byte(entropy.RandStr(55))},
|
Value: Value{b: []byte(c.RandStr(55))},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: Key{b: []byte("user:Jackson")},
|
Key: Key{b: []byte("user:Jackson")},
|
||||||
Value: Value{b: []byte(entropy.RandStr(55))},
|
Value: Value{b: []byte(c.RandStr(55))},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: Key{b: []byte("user:Frackhole")},
|
Key: Key{b: []byte("user:Frackhole")},
|
||||||
Value: Value{b: []byte(entropy.RandStr(55))},
|
Value: Value{b: []byte(c.RandStr(55))},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: Key{b: []byte("user:Baboshka")},
|
Key: Key{b: []byte("user:Baboshka")},
|
||||||
Value: Value{b: []byte(entropy.RandStr(55))},
|
Value: Value{b: []byte(c.RandStr(55))},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package bitcask
|
package bitcask
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.tcp.direct/kayos/common/entropy"
|
c "git.tcp.direct/kayos/common/entropy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestDB(t *testing.T) *DB {
|
func newTestDB(t *testing.T) *DB {
|
||||||
@ -17,12 +18,12 @@ func newTestDB(t *testing.T) *DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func seedRandKV(db *DB, store string) error {
|
func seedRandKV(db *DB, store string) error {
|
||||||
return db.With(store).Put([]byte(entropy.RandStr(55)), []byte(entropy.RandStr(55)))
|
return db.With(store).Put([]byte(c.RandStr(55)), []byte(c.RandStr(55)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func seedRandStores(db *DB, t *testing.T) {
|
func seedRandStores(db *DB, t *testing.T) {
|
||||||
for n := 0; n != 5; n++ {
|
for n := 0; n != 5; n++ {
|
||||||
randstore := entropy.RandStr(5)
|
randstore := c.RandStr(5)
|
||||||
err := db.Init(randstore)
|
err := db.Init(randstore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to initialize store for test SyncAndCloseAll: %e", err)
|
t.Errorf("failed to initialize store for test SyncAndCloseAll: %e", err)
|
||||||
@ -91,16 +92,24 @@ func TestDB_Init(t *testing.T) {
|
|||||||
if gerr != nil {
|
if gerr != nil {
|
||||||
t.Fatalf("[FAIL] %e", gerr)
|
t.Fatalf("[FAIL] %e", gerr)
|
||||||
}
|
}
|
||||||
if string(gvalue) != string(value) {
|
if !bytes.Equal(gvalue, value) {
|
||||||
t.Errorf("[FAIL] wanted %v, got %v", string(value), string(gvalue))
|
t.Errorf("[FAIL] wanted %v, got %v", string(value), string(gvalue))
|
||||||
}
|
}
|
||||||
t.Logf("Got Value %v at Key %v", string(gvalue), key)
|
t.Logf("Got Value %v at Key %v", string(gvalue), key)
|
||||||
})
|
})
|
||||||
t.Run("withStoreDoesntExist", func(t *testing.T) {
|
t.Run("withNewStoreDoesntExist", func(t *testing.T) {
|
||||||
if nope := db.With("asdfqwerty"); nope.Bitcask != nil {
|
if nope := db.WithNew("asdfqwerty"); nope.Bitcask == nil {
|
||||||
t.Errorf("[FAIL] got non nil result for nonexistent store: %T, %v", nope, nope)
|
t.Fatalf("[FAIL] got nil result for nonexistent store when it should have made itself: %T, %v", nope, nope)
|
||||||
|
} else {
|
||||||
|
t.Logf("[SUCCESS] got nil Value for store that doesn't exist")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.Run("withStoreDoesntExist", func(t *testing.T) {
|
||||||
|
if nope := db.With("afsafdassdfqwerty"); nope.Bitcask != nil {
|
||||||
|
t.Fatalf("[FAIL] got non nil result for nonexistent store: %T, %v", nope, nope)
|
||||||
|
} else {
|
||||||
|
t.Logf("[SUCCESS] got nil Value for store that doesn't exist")
|
||||||
}
|
}
|
||||||
t.Logf("[SUCCESS] got nil Value for store that doesn't exist")
|
|
||||||
})
|
})
|
||||||
t.Run("syncAllShouldFail", func(t *testing.T) {
|
t.Run("syncAllShouldFail", func(t *testing.T) {
|
||||||
db.store["wtf"] = Store{}
|
db.store["wtf"] = Store{}
|
||||||
@ -168,6 +177,9 @@ func Test_Sync(t *testing.T) {
|
|||||||
|
|
||||||
func Test_Close(t *testing.T) {
|
func Test_Close(t *testing.T) {
|
||||||
var db = newTestDB(t)
|
var db = newTestDB(t)
|
||||||
|
defer func() {
|
||||||
|
db = nil
|
||||||
|
}()
|
||||||
seedRandStores(db, t)
|
seedRandStores(db, t)
|
||||||
var oldstores []string
|
var oldstores []string
|
||||||
t.Run("Close", func(t *testing.T) {
|
t.Run("Close", func(t *testing.T) {
|
||||||
@ -175,7 +187,7 @@ func Test_Close(t *testing.T) {
|
|||||||
oldstores = append(oldstores, d)
|
oldstores = append(oldstores, d)
|
||||||
err := db.Close(d)
|
err := db.Close(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("[FAIL] failed to close %s: %e", d, err)
|
t.Fatalf("[FAIL] failed to close %s: %e", d, err)
|
||||||
} else {
|
} else {
|
||||||
t.Logf("[+] Close() successful for %s", d)
|
t.Logf("[+] Close() successful for %s", d)
|
||||||
}
|
}
|
||||||
@ -184,14 +196,14 @@ func Test_Close(t *testing.T) {
|
|||||||
t.Run("AssureClosed", func(t *testing.T) {
|
t.Run("AssureClosed", func(t *testing.T) {
|
||||||
for _, d := range oldstores {
|
for _, d := range oldstores {
|
||||||
if st := db.With(d); st.Bitcask != nil {
|
if st := db.With(d); st.Bitcask != nil {
|
||||||
t.Errorf("[FAIL] store %s should have been deleted", d)
|
t.Fatalf("[FAIL] store %s should have been deleted", d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Logf("[SUCCESS] Confirmed that all stores have been closed")
|
t.Logf("[SUCCESS] Confirmed that all stores have been closed")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("CantCloseBogusStore", func(t *testing.T) {
|
t.Run("CantCloseBogusStore", func(t *testing.T) {
|
||||||
err := db.Close(entropy.RandStr(55))
|
err := db.Close(c.RandStr(55))
|
||||||
if err != errBogusStore {
|
if err != errBogusStore {
|
||||||
t.Errorf("[FAIL] got err %e, wanted err %e", err, errBogusStore)
|
t.Errorf("[FAIL] got err %e, wanted err %e", err, errBogusStore)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package bitcask
|
package bitcask
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.tcp.direct/kayos/common/hash"
|
"bytes"
|
||||||
|
|
||||||
"git.tcp.direct/tcp.direct/database"
|
"git.tcp.direct/tcp.direct/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ func (k Key) String() string {
|
|||||||
|
|
||||||
// Equal determines if two keys are equal.
|
// Equal determines if two keys are equal.
|
||||||
func (k Key) Equal(k2 Key) bool {
|
func (k Key) Equal(k2 Key) bool {
|
||||||
return hash.BlakeEqual(k.Bytes(), k2.Bytes())
|
return bytes.Equal(k.Bytes(), k2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value represents a value in a key/value store.
|
// Value represents a value in a key/value store.
|
||||||
@ -51,5 +50,5 @@ func (v Value) String() string {
|
|||||||
|
|
||||||
// Equal determines if two values are equal.
|
// Equal determines if two values are equal.
|
||||||
func (v Value) Equal(v2 Value) bool {
|
func (v Value) Equal(v2 Value) bool {
|
||||||
return hash.BlakeEqual(v.Bytes(), v2.Bytes())
|
return bytes.Equal(v.Bytes(), v2.Bytes())
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ package bitcask
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.tcp.direct/kayos/common/entropy"
|
c "git.tcp.direct/kayos/common/entropy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Equal(t *testing.T) {
|
func Test_Equal(t *testing.T) {
|
||||||
t.Run("ShouldBeEqual", func(t *testing.T) {
|
t.Run("ShouldBeEqual", func(t *testing.T) {
|
||||||
v := entropy.RandStr(55)
|
v := c.RandStr(55)
|
||||||
kv1 := KeyValue{Key{b: []byte(v)}, Value{b: []byte(v)}}
|
kv1 := KeyValue{Key{b: []byte(v)}, Value{b: []byte(v)}}
|
||||||
kv2 := KeyValue{Key{b: []byte(v)}, Value{b: []byte(v)}}
|
kv2 := KeyValue{Key{b: []byte(v)}, Value{b: []byte(v)}}
|
||||||
if !kv1.Key.Equal(kv2.Key) {
|
if !kv1.Key.Equal(kv2.Key) {
|
||||||
@ -35,13 +35,11 @@ func Test_Equal(t *testing.T) {
|
|||||||
kv1.Value.String(), kv2.Value.String(),
|
kv1.Value.String(), kv2.Value.String(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("ShouldNotBeEqual", func(t *testing.T) {
|
t.Run("ShouldNotBeEqual", func(t *testing.T) {
|
||||||
v1 := entropy.RandStr(55)
|
v1 := c.RandStr(55)
|
||||||
v2 := entropy.RandStr(55)
|
v2 := c.RandStr(55)
|
||||||
kv1 := KeyValue{Key{b: []byte(v1)}, Value{b: []byte(v1)}}
|
kv1 := KeyValue{Key{b: []byte(v1)}, Value{b: []byte(v1)}}
|
||||||
kv2 := KeyValue{Key{b: []byte(v2)}, Value{b: []byte(v2)}}
|
kv2 := KeyValue{Key{b: []byte(v2)}, Value{b: []byte(v2)}}
|
||||||
if kv1.Key.Equal(kv2.Key) {
|
if kv1.Key.Equal(kv2.Key) {
|
||||||
@ -68,8 +66,6 @@ func Test_Equal(t *testing.T) {
|
|||||||
kv1.Value.String(), kv2.Value.String(),
|
kv1.Value.String(), kv2.Value.String(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user