Merge divergent versions of library

This commit is contained in:
kayos@tcp.direct 2022-05-21 16:17:21 -07:00
parent 6f20fa59ee
commit 0d670b3fc5
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
5 changed files with 97 additions and 48 deletions

@ -36,10 +36,35 @@ func (db *DB) Path() string {
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.
func (db *DB) Init(storeName string, bitcaskopts ...bitcask.Option) error {
db.mu.Lock()
defer db.mu.Unlock()
if len(DefaultBitcaskOptions) > 0 {
bitcaskopts = append(bitcaskopts, DefaultBitcaskOptions...)
}
if _, ok := db.store[storeName]; ok {
return errStoreExists
}
@ -62,10 +87,27 @@ func (db *DB) With(storeName string) Store {
db.mu.RLock()
defer db.mu.RUnlock()
d, ok := db.store[storeName]
if !ok {
return Store{Bitcask: nil}
if ok {
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.

@ -7,7 +7,7 @@ import (
"strconv"
"testing"
"git.tcp.direct/kayos/common/entropy"
c "git.tcp.direct/kayos/common/entropy"
)
var needle = "yeet"
@ -40,20 +40,20 @@ func setupTest(storename string, t *testing.T) *DB {
}
func genJunk(t *testing.T, correct bool) []byte {
item := entropy.RandStr(5)
bar := entropy.RandStr(5)
item := c.RandStr(5)
bar := c.RandStr(5)
if correct {
if entropy.RNG(100) > 50 {
item = needle + entropy.RandStr(entropy.RNG(5))
if c.RNG(100) > 50 {
item = needle + c.RandStr(c.RNG(5))
} else {
bar = entropy.RandStr(entropy.RNG(5)) + needle
bar = c.RandStr(c.RNG(5)) + needle
}
}
f := Foo{
Bar: bar,
Yeet: entropy.RNG(50),
What: map[string]int{entropy.RandStr(5): 2, item: 7},
Yeet: c.RNG(50),
What: map[string]int{c.RandStr(5): 2, item: 7},
}
raw, err := json.Marshal(f)
@ -96,11 +96,11 @@ func Test_Search(t *testing.T) {
var storename = "test_search"
var db = setupTest(storename, t)
one := entropy.RNG(100)
two := entropy.RNG(100)
three := entropy.RNG(100)
four := entropy.RNG(100)
five := entropy.RNG(100)
one := c.RNG(100)
two := c.RNG(100)
three := c.RNG(100)
four := c.RNG(100)
five := c.RNG(100)
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) {
bogus := entropy.RandStr(55)
bogus := c.RandStr(55)
t.Logf("executing search for %s", bogus)
results, err := db.With(storename).Search(bogus)
@ -154,7 +154,7 @@ func Test_ValueExists(t *testing.T) {
var db = setupTest(storename, 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 {
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) {
for n := 0; n != 5; n++ {
garbage := entropy.RandStr(55)
garbage := c.RandStr(55)
if _, exists := db.With(storename).ValueExists([]byte(garbage)); exists {
t.Errorf("[FAIL] store should have not contained value %v, but it did", []byte(garbage))
} else {
@ -192,28 +192,28 @@ func Test_PrefixScan(t *testing.T) {
var storename = "test_prefix_scan"
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{
{
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")},
Value: Value{b: []byte(entropy.RandStr(55))},
Value: Value{b: []byte(c.RandStr(55))},
},
{
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")},
Value: Value{b: []byte(entropy.RandStr(55))},
Value: Value{b: []byte(c.RandStr(55))},
},
{
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
import (
"bytes"
"os"
"testing"
"git.tcp.direct/kayos/common/entropy"
c "git.tcp.direct/kayos/common/entropy"
)
func newTestDB(t *testing.T) *DB {
@ -17,12 +18,12 @@ func newTestDB(t *testing.T) *DB {
}
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) {
for n := 0; n != 5; n++ {
randstore := entropy.RandStr(5)
randstore := c.RandStr(5)
err := db.Init(randstore)
if err != nil {
t.Errorf("failed to initialize store for test SyncAndCloseAll: %e", err)
@ -91,16 +92,24 @@ func TestDB_Init(t *testing.T) {
if gerr != nil {
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.Logf("Got Value %v at Key %v", string(gvalue), key)
})
t.Run("withStoreDoesntExist", func(t *testing.T) {
if nope := db.With("asdfqwerty"); nope.Bitcask != nil {
t.Errorf("[FAIL] got non nil result for nonexistent store: %T, %v", nope, nope)
t.Run("withNewStoreDoesntExist", func(t *testing.T) {
if nope := db.WithNew("asdfqwerty"); nope.Bitcask == nil {
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) {
db.store["wtf"] = Store{}
@ -168,6 +177,9 @@ func Test_Sync(t *testing.T) {
func Test_Close(t *testing.T) {
var db = newTestDB(t)
defer func() {
db = nil
}()
seedRandStores(db, t)
var oldstores []string
t.Run("Close", func(t *testing.T) {
@ -175,7 +187,7 @@ func Test_Close(t *testing.T) {
oldstores = append(oldstores, d)
err := db.Close(d)
if err != nil {
t.Errorf("[FAIL] failed to close %s: %e", d, err)
t.Fatalf("[FAIL] failed to close %s: %e", d, err)
} else {
t.Logf("[+] Close() successful for %s", d)
}
@ -184,14 +196,14 @@ func Test_Close(t *testing.T) {
t.Run("AssureClosed", func(t *testing.T) {
for _, d := range oldstores {
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.Run("CantCloseBogusStore", func(t *testing.T) {
err := db.Close(entropy.RandStr(55))
err := db.Close(c.RandStr(55))
if err != errBogusStore {
t.Errorf("[FAIL] got err %e, wanted err %e", err, errBogusStore)
}

@ -1,8 +1,7 @@
package bitcask
import (
"git.tcp.direct/kayos/common/hash"
"bytes"
"git.tcp.direct/tcp.direct/database"
)
@ -30,7 +29,7 @@ func (k Key) String() string {
// Equal determines if two keys are equal.
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.
@ -51,5 +50,5 @@ func (v Value) String() string {
// Equal determines if two values are equal.
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 (
"testing"
"git.tcp.direct/kayos/common/entropy"
c "git.tcp.direct/kayos/common/entropy"
)
func Test_Equal(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)}}
kv2 := KeyValue{Key{b: []byte(v)}, Value{b: []byte(v)}}
if !kv1.Key.Equal(kv2.Key) {
@ -35,13 +35,11 @@ func Test_Equal(t *testing.T) {
kv1.Value.String(), kv2.Value.String(),
)
}
}
})
t.Run("ShouldNotBeEqual", func(t *testing.T) {
v1 := entropy.RandStr(55)
v2 := entropy.RandStr(55)
v1 := c.RandStr(55)
v2 := c.RandStr(55)
kv1 := KeyValue{Key{b: []byte(v1)}, Value{b: []byte(v1)}}
kv2 := KeyValue{Key{b: []byte(v2)}, Value{b: []byte(v2)}}
if kv1.Key.Equal(kv2.Key) {
@ -68,8 +66,6 @@ func Test_Equal(t *testing.T) {
kv1.Value.String(), kv2.Value.String(),
)
}
}
})
}