Skip to content

Commit

Permalink
Fix: Address GH #2 by adding conditional short path on discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
yunginnanet committed Jul 4, 2024
1 parent 2209534 commit 4c46f0f
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 32 deletions.
11 changes: 8 additions & 3 deletions bitcask/bitcask.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,18 @@ func OpenDB(path string) *DB {

// discover is a helper function to discover and initialize all existing bitcask stores at the path.
// caller must hold write lock.
func (db *DB) discover() ([]string, error) {
if db.initialized.Load() {
func (db *DB) discover(force ...bool) ([]string, error) {
if db.initialized.Load() && (len(force) == 0 || !force[0]) {
stores := make([]string, 0, len(db.store))
for store := range db.store {
if store == "" {
continue
}
stores = append(stores, store)
}
return stores, nil
if len(stores) > 0 {
return stores, nil
}
}
stores := make([]string, 0, len(db.store))
errs := make([]error, 0, len(db.store))
Expand All @@ -170,6 +172,9 @@ func (db *DB) discover() ([]string, error) {
if err != nil {
return nil, err
}

_ = db._init()

for _, entry := range entries {
if !entry.IsDir() {
continue
Expand Down
2 changes: 1 addition & 1 deletion bitcask/bitcask_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (db *DB) RestoreAll(archivePath string) error {
return fmt.Errorf("failed to re-init db after restore%s: %w", preBackupPath, err)
}

_, err := db.discover()
_, err := db.discover(true)
if err != nil {
return fmt.Errorf("failed during discover call after restore%s: %w", preBackupPath, err)
}
Expand Down
22 changes: 16 additions & 6 deletions pogreb/pogreb.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ func (db *DB) allStores() map[string]database.Filer {

// AllStores returns a map of the names of all pogreb datastores and the corresponding Filers.
func (db *DB) AllStores() map[string]database.Filer {

db.mu.RLock()
ast := db.allStores()
db.mu.RUnlock()
Expand Down Expand Up @@ -262,8 +261,9 @@ func (db *DB) init() error {
return nil
}
db.mu.Lock()
defer db.mu.Unlock()
return db._init()
err := db._init()
db.mu.Unlock()
return err
}

// Destroy will remove a pogreb store and all data associated with it.
Expand Down Expand Up @@ -547,6 +547,10 @@ func (db *DB) allMetrics() map[string]*pogreb.Metrics {

func (db *DB) addAllStoresToMeta() {
storeMap := db.allStores()
if len(storeMap) == 0 {
println("no stores to add")
return
}
storeNames := make([]string, 0, len(storeMap))
for name := range storeMap {
if name == "" {
Expand All @@ -572,16 +576,18 @@ func (db *DB) SyncAll() error {
return compoundErrors(errs)
}

func (db *DB) discover() ([]string, error) {
if db.initialized.Load() {
func (db *DB) discover(force ...bool) ([]string, error) {
if db.initialized.Load() && (len(force) == 0 || !force[0]) {
stores := make([]string, 0, len(db.store))
for name := range db.store {
if name == "" {
continue
}
stores = append(stores, name)
}
return stores, nil
if len(stores) > 0 {
return stores, nil
}
}
stores := make([]string, 0)
errs := make([]error, 0)
Expand All @@ -592,6 +598,9 @@ func (db *DB) discover() ([]string, error) {
if err != nil {
return nil, err
}

_ = db._init()

for _, entry := range entries {
if !entry.IsDir() {
continue
Expand Down Expand Up @@ -624,6 +633,7 @@ func (db *DB) discover() ([]string, error) {
// Discover will discover and initialize all existing bitcask stores at the path opened by [OpenDB].
func (db *DB) Discover() ([]string, error) {
if err := db.init(); err != nil {
println("error initializing")
return nil, err
}
db.mu.Lock()
Expand Down
2 changes: 1 addition & 1 deletion pogreb/pogreb_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (db *DB) RestoreAll(archivePath string) error {
return fmt.Errorf("failed to re-init db after restore%s: %w", preBackupPath, err)
}

_, err := db.discover()
_, err := db.discover(true)
if err != nil {
return fmt.Errorf("failed during discover call after restore%s: %w", preBackupPath, err)
}
Expand Down
62 changes: 41 additions & 21 deletions pogreb/pogreb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ import (
func newTestDB(t *testing.T) (string, database.Keeper) {
t.Helper()
tpath := t.TempDir()
t.Cleanup(func() {
t.Logf("[CLEANUP] removing temp dir %s", tpath)
err := os.RemoveAll(tpath)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
panic(err.Error())
}
})
tdb := OpenDB(tpath)
if tdb == nil {
t.Fatalf("failed to open testdb at %s, got nil", tpath)
Expand All @@ -35,7 +42,7 @@ func seedRandStores(db database.Keeper, t *testing.T) []string {
randstore := c.RandStr(5)
err := db.Init(randstore)
if err != nil {
t.Errorf("failed to initialize store for test SyncAndCloseAll: %e", err)
t.Errorf("failed to initialize store for test SyncAndCloseAll: %s", err.Error())
}
err = seedRandKV(db, randstore)
if err != nil {
Expand Down Expand Up @@ -93,7 +100,7 @@ func TestDB_Init(t *testing.T) { //nolint:funlen,gocognit,cyclop
err := db.With("simple").Put(key, value)
t.Logf("Put Value %v at Key %v", string(value), key)
if err != nil {
t.Fatalf("[FAIL] %e", err)
t.Fatalf("[FAIL] %s", err.Error())
}
gvalue, gerr := db.With("simple").Get(key)
if gerr != nil {
Expand All @@ -107,16 +114,16 @@ func TestDB_Init(t *testing.T) { //nolint:funlen,gocognit,cyclop
t.Run("withNewStoreDoesExist", func(t *testing.T) {
nope := db.WithNew("bing")
if err := nope.Put([]byte("key"), []byte("value")); err != nil {
t.Fatalf("[FAIL] %e", err)
t.Fatalf("[FAIL] %s", err.Error())
}
err := nope.Put([]byte("bing"), []byte("bong"))
if err != nil {
t.Fatalf("[FAIL] %e", err)
t.Fatalf("[FAIL] %s", err.Error())
}
yup := db.WithNew("bing")
res, err := yup.Get([]byte("bing"))
if err != nil {
t.Errorf("[FAIL] %e", err)
t.Errorf("[FAIL] %s", err.Error())
}
if !bytes.Equal(res, []byte("bong")) {
t.Errorf("[FAIL] wanted %v, got %v", string("bong"), string(res))
Expand Down Expand Up @@ -147,28 +154,28 @@ func TestDB_Init(t *testing.T) { //nolint:funlen,gocognit,cyclop
if err == nil {
t.Fatalf("[FAIL] we should have gotten an error from bogus store map entry")
}
t.Logf("[SUCCESS] got compound error: %e", err)
t.Logf("[SUCCESS] got compound error: %s", err.Error())
})

// TODO: make sure sync is ACTUALLY sycing instead of only checking for nil err... ( ._. )

t.Run("syncAll", func(t *testing.T) {
err := db.SyncAll()
if err != nil {
t.Fatalf("[FAIL] got compound error: %e", err)
t.Fatalf("[FAIL] got compound error: %s", err.Error())
}
})
t.Run("closeAll", func(t *testing.T) {
t.Cleanup(func() {
err := os.RemoveAll("./testdata")
if err != nil {
t.Fatalf("[CLEANUP FAIL] %e", err)
t.Fatalf("[CLEANUP FAIL] %s", err.Error())
}
t.Logf("[CLEANUP] cleaned up ./testdata")
})
err := db.CloseAll()
if err != nil {
t.Fatalf("[FAIL] got compound error: %e", err)
t.Fatalf("[FAIL] got compound error: %s", err.Error())
}
db = nil
})
Expand All @@ -178,12 +185,15 @@ func TestDB_Init(t *testing.T) { //nolint:funlen,gocognit,cyclop
names := seedRandStores(db, t)
err := db.SyncAndCloseAll()
if err != nil {
t.Errorf("[FAIL] failed to SyncAndCloseAll: %e", err)
t.Fatalf("[FAIL] failed to SyncAndCloseAll: %s", err.Error())
}
db = OpenDB(tdbp)
found, err := db.Discover()
found, err := db.(*DB).Discover()
if err != nil {
t.Errorf("[FAIL] failed to discover stores: %e", err)
t.Fatalf("[FAIL] failed to discover stores: %s", err.Error())
}
if len(found) == 0 {
t.Fatalf("[FAIL] found no stores")
}
for _, n := range names {
matched := false
Expand Down Expand Up @@ -246,7 +256,7 @@ func Test_Close(t *testing.T) {
t.Run("CantCloseBogusStore", func(t *testing.T) {
err := db.Close(c.RandStr(55))
if !errors.Is(err, ErrBogusStore) {
t.Errorf("[FAIL] got err %e, wanted err %e", err, ErrBogusStore)
t.Errorf("[FAIL] got err %s, wanted err %s", err.Error(), ErrBogusStore)
}
})
}
Expand All @@ -264,7 +274,7 @@ func Test_withAll(t *testing.T) {
t.Run("withAllNoStores", func(t *testing.T) {
err := db.(*DB).withAll(121)
if !errors.Is(err, ErrNoStores) {
t.Errorf("[FAIL] got err %e, wanted err %e", err, ErrNoStores)
t.Errorf("[FAIL] got err %s, wanted err %s", err.Error(), ErrNoStores)
}
})
t.Run("withAllNilMap", func(t *testing.T) {
Expand All @@ -278,11 +288,11 @@ func Test_withAll(t *testing.T) {
t.Run("withAllBogusAction", func(t *testing.T) {
err := db.Init(asdf1)
if err != nil {
t.Errorf("[FAIL] unexpected error: %e", err)
t.Errorf("[FAIL] unexpected error: %s", err.Error())
}
wAllErr := db.(*DB).withAll(121)
if !errors.Is(wAllErr, ErrUnknownAction) {
t.Errorf("[FAIL] wanted error %e, got error %e", ErrUnknownAction, err)
t.Errorf("[FAIL] wanted error %s, got error %s", ErrUnknownAction.Error(), err)
}
})
t.Run("ListAll", func(t *testing.T) {
Expand All @@ -306,15 +316,15 @@ func Test_withAll(t *testing.T) {
t.Run("ListAllAndInteract", func(t *testing.T) {
err := db.Init(asdf2)
if err != nil {
t.Errorf("[FAIL] unexpected error: %e", err)
t.Errorf("[FAIL] unexpected error: %s", err.Error())
}
err = db.With(asdf1).Put([]byte("asdf"), []byte("asdf"))
if err != nil {
t.Errorf("[FAIL] unexpected error: %e", err)
t.Errorf("[FAIL] unexpected error: %s", err.Error())
}
err = db.With(asdf2).Put([]byte("asdf"), []byte("asdf"))
if err != nil {
t.Errorf("[FAIL] unexpected error: %e", err)
t.Errorf("[FAIL] unexpected error: %s", err.Error())
}
allStores := db.AllStores()
if len(allStores) == 0 {
Expand Down Expand Up @@ -357,13 +367,18 @@ func Test_withAll(t *testing.T) {

// initialize store for the defer closure call
if err := db.Init(asdf1); err != nil {
t.Fatalf("[FAIL] %e", err)
t.Fatalf("[FAIL] %s", err.Error())
}

}

func Test_WithOptions(t *testing.T) { //nolint:funlen,gocognit,cyclop
tpath := t.TempDir()
t.Cleanup(func() {
if err := os.RemoveAll(tpath); err != nil {
panic(err)
}
})
tdb := OpenDB(tpath)
if tdb == nil {
t.Fatalf("failed to open testdb at %s, got nil", tpath)
Expand All @@ -386,9 +401,14 @@ func Test_WithOptions(t *testing.T) { //nolint:funlen,gocognit,cyclop
}
func Test_PhonyInit(t *testing.T) {
newtmp := t.TempDir()
t.Cleanup(func() {
if err := os.RemoveAll(newtmp); err != nil {
panic(err)
}
})
err := os.MkdirAll(newtmp+"/"+t.Name(), 0755)
if err != nil {
t.Fatalf("[FAIL] failed to create test directory: %e", err)
t.Fatalf("[FAIL] failed to create test directory: %s", err.Error())
}
err = os.Symlink("/dev/null", filepath.Join(newtmp, t.Name(), "lock"))
if err != nil {
Expand Down

0 comments on commit 4c46f0f

Please sign in to comment.