Skip to content

Commit

Permalink
feature: add Close func for Store backend
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Wan <[email protected]>
  • Loading branch information
HusterWan committed Nov 1, 2018
1 parent 4f6e625 commit 788156a
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 55 deletions.
4 changes: 4 additions & 0 deletions pkg/meta/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type Backend interface {

// Path returns the path with the specified key.
Path(key string) string

// Close releases all resources used by the store
// It does not make any changes to store.
Close() error
}

// Register registers a backend to be daemon's store.
Expand Down
6 changes: 6 additions & 0 deletions pkg/meta/boltdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,9 @@ func (b *bolt) List(bucket string) ([][]byte, error) {

return values, err
}

// Close releases all database resources.
// All transactions must be closed before closing the database.
func (b *bolt) Close() error {
return b.db.Close()
}
5 changes: 5 additions & 0 deletions pkg/meta/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ func (s *localStore) Keys(fileName string) ([]string, error) {
return keys, nil
}

// Close do nothing in local store
func (s *localStore) Close() error {
return nil
}

func mkdirIfNotExist(dir string) error {
if _, err := os.Stat(dir); err != nil {
if os.IsNotExist(err) {
Expand Down
5 changes: 5 additions & 0 deletions pkg/meta/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,8 @@ func (s *Store) KeysWithPrefix(prefix string) ([]string, error) {
func (s *Store) Path(key string) string {
return s.backend.Path(key)
}

// Shutdown releases all resources used by the backend
func (s *Store) Shutdown() error {
return s.backend.Close()
}
239 changes: 184 additions & 55 deletions pkg/meta/store_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package meta

import (
"fmt"
"os"
"path"
"reflect"
"testing"

"github.com/alibaba/pouch/pkg/utils"
)

type Demo struct {
Expand All @@ -23,25 +28,58 @@ func (d *Demo2) Key() string {
return d.B
}

var s *Store

var cfg = Config{
Driver: "local",
BaseDir: "/tmp/containers",
Buckets: []Bucket{
var (
localBuckets = []Bucket{
{MetaJSONFile, reflect.TypeOf(Demo{})},
{"test.json", reflect.TypeOf(Demo2{})},
},
}

boltdbBuckets = []Bucket{
{"boltdb", reflect.TypeOf(Demo3{})},
}
)

func initStore(dbFile, driver string, buckets []Bucket) (*Store, error) {
localCfg := Config{
Driver: driver,
BaseDir: dbFile,
Buckets: buckets,
}

return NewStore(localCfg)
}

func TestPut(t *testing.T) {
func testStoreWrapper(t *testing.T, name, driver string, buckets []Bucket, test func(t *testing.T, s *Store)) {
// initialize
var err error
s, err = NewStore(cfg)
dbFile := path.Join("/tmp", utils.RandString(8, name, ""))
if err := ensureFileNotExist(dbFile); err != nil {
t.Fatal(err)
}
defer ensureFileNotExist(dbFile)

s, err := initStore(dbFile, driver, buckets)
if err != nil {
t.Fatal(err)
}

test(t, s)
}

func ensureFileNotExist(file string) error {
_, err := os.Stat(file)
if err == nil {
os.RemoveAll(file)
return nil
}

if !os.IsNotExist(err) {
return err
}

return nil
}

func testPut(t *testing.T, s *Store) {
// put 1
if err := s.Put(&Demo{
A: 1,
Expand All @@ -65,7 +103,19 @@ func TestPut(t *testing.T) {
}
}

func TestGet(t *testing.T) {
func TestPut(t *testing.T) {
testStoreWrapper(t, "TestPut", "local", localBuckets, testPut)
}

func testGet(t *testing.T, s *Store) {
// put 1
if err := s.Put(&Demo{
A: 1,
B: "key",
}); err != nil {
t.Fatal(err)
}

obj, err := s.Get("key")
if err != nil {
t.Fatal(err)
Expand All @@ -79,7 +129,19 @@ func TestGet(t *testing.T) {
}
}

func TestFetch(t *testing.T) {
func TestGet(t *testing.T) {
testStoreWrapper(t, "TestGet", "local", localBuckets, testGet)
}

func testFetch(t *testing.T, s *Store) {
// put 2
if err := s.Put(&Demo{
A: 2,
B: "key2",
}); err != nil {
t.Fatal(err)
}

d := &Demo{}
d.B = "key2"

Expand All @@ -92,22 +154,50 @@ func TestFetch(t *testing.T) {
}
}

func TestList(t *testing.T) {
func TestFetch(t *testing.T) {
testStoreWrapper(t, "TestFetch", "local", localBuckets, testFetch)
}

func testList(t *testing.T, s *Store) {
// put 2
if err := s.Put(&Demo{
A: 2,
B: "key2",
}); err != nil {
t.Fatal(err)
}

objs, err := s.List()
if err != nil {
t.Fatal(err)
}
if len(objs) != 2 {
if len(objs) != 1 {
t.Fatalf("failed to list")
}

}

func TestRemove(t *testing.T) {
func TestList(t *testing.T) {
testStoreWrapper(t, "TestList", "local", localBuckets, testList)
}

func testRemove(t *testing.T, s *Store) {
// put 1
if err := s.Put(&Demo{
A: 1,
B: "key",
}); err != nil {
t.Fatal(err)
}
if err := s.Remove("key"); err != nil {
t.Fatal(err)
}
}

func TestRemove(t *testing.T) {
testStoreWrapper(t, "TestRemove", "local", localBuckets, testList)
}

type Demo3 struct {
A int
B string
Expand All @@ -117,24 +207,7 @@ func (d *Demo3) Key() string {
return d.B
}

var boltdbStore *Store

var boltdbCfg = Config{
Driver: "boltdb",
BaseDir: "/tmp/bolt.db",
Buckets: []Bucket{
{"boltdb", reflect.TypeOf(Demo3{})},
},
}

func TestBoltdbPut(t *testing.T) {
// initialize
var err error
boltdbStore, err = NewStore(boltdbCfg)
if err != nil {
t.Fatal(err)
}

func testBoltdbPut(t *testing.T, boltdbStore *Store) {
// put 1
if err := boltdbStore.Put(&Demo3{
A: 1,
Expand All @@ -158,7 +231,19 @@ func TestBoltdbPut(t *testing.T) {
}
}

func TestBoltdbGet(t *testing.T) {
func TestBoltdbPut(t *testing.T) {
testStoreWrapper(t, "TestBoltdbPut", "boltdb", boltdbBuckets, testBoltdbPut)
}

func testBoltdbGet(t *testing.T, boltdbStore *Store) {
// first put 1
if err := boltdbStore.Put(&Demo3{
A: 1,
B: "key",
}); err != nil {
t.Fatal(err)
}

obj, err := boltdbStore.Get("key")
if err != nil {
t.Fatal(err)
Expand All @@ -172,7 +257,19 @@ func TestBoltdbGet(t *testing.T) {
}
}

func TestBoltdbFetch(t *testing.T) {
func TestBoltdbGet(t *testing.T) {
testStoreWrapper(t, "TestBoltdbGet", "boltdb", boltdbBuckets, testBoltdbGet)
}

func testBoltdbFetch(t *testing.T, boltdbStore *Store) {
// first put 2
if err := boltdbStore.Put(&Demo3{
A: 2,
B: "key2",
}); err != nil {
t.Fatal(err)
}

d := &Demo3{}
d.B = "key2"

Expand All @@ -185,22 +282,66 @@ func TestBoltdbFetch(t *testing.T) {
}
}

func TestBoltdbList(t *testing.T) {
func TestBoltdbFetch(t *testing.T) {
testStoreWrapper(t, "TestBoltdbFetch", "boltdb", boltdbBuckets, testBoltdbFetch)
}

func testBoltdbList(t *testing.T, boltdbStore *Store) {
// first put 2
if err := boltdbStore.Put(&Demo3{
A: 2,
B: "key2",
}); err != nil {
t.Fatal(err)
}

objs, err := boltdbStore.List()
if err != nil {
t.Fatal(err)
}
if len(objs) != 2 {
if len(objs) != 1 {
t.Fatalf("failed to list")
}
}

func TestBoltdbRemove(t *testing.T) {
func TestBoltdbList(t *testing.T) {
testStoreWrapper(t, "TestBoltdbList", "boltdb", boltdbBuckets, testBoltdbList)
}

func testBoltdbRemove(t *testing.T, boltdbStore *Store) {
// first put 1
if err := boltdbStore.Put(&Demo3{
A: 1,
B: "key",
}); err != nil {
t.Fatal(err)
}

if err := boltdbStore.Remove("key"); err != nil {
t.Fatal(err)
}
}

func TestBoltdbRemove(t *testing.T) {
testStoreWrapper(t, "TestBoltdbRemove", "boltdb", boltdbBuckets, testBoltdbRemove)
}

func testBoltdbClose(t *testing.T, boltdbStore *Store) {
if err := boltdbStore.Shutdown(); err != nil {
t.Fatal(err)
}

// test List again, should occur error here
_, err := boltdbStore.List()
if err == nil {
t.Fatal(fmt.Errorf("still can visit the boltdb after execute close db action"))
}
}

func TestBoltdbClose(t *testing.T) {
testStoreWrapper(t, "TestBoltdbClose", "boltdb", boltdbBuckets, testBoltdbClose)
}

type Demo4 struct {
A int
B string
Expand All @@ -210,23 +351,7 @@ func (d *Demo4) Key() string {
return d.B
}

var boltdb4 *Store

var boltdbCfg4 = Config{
Driver: "boltdb",
BaseDir: "/tmp/bolt4.db",
Buckets: []Bucket{
{"boltdb", reflect.TypeOf(Demo4{})},
},
}

func TestKeysWithPrefix(t *testing.T) {
var err error
boltdb4, err = NewStore(boltdbCfg4)
if err != nil {
t.Fatal(err)
}

func testKeysWithPrefix(t *testing.T, boltdb4 *Store) {
// put 1
if err := boltdb4.Put(&Demo4{
A: 1,
Expand Down Expand Up @@ -260,3 +385,7 @@ func TestKeysWithPrefix(t *testing.T) {
t.Fatal("should get empty item")
}
}

func TestKeysWithPrefix(t *testing.T) {
testStoreWrapper(t, "TestKeysWithPrefix", "boltdb", boltdbBuckets, testKeysWithPrefix)
}

0 comments on commit 788156a

Please sign in to comment.