diff --git a/virtcontainers/store/manager.go b/virtcontainers/store/manager.go index 108603f8f7..d2238538a4 100644 --- a/virtcontainers/store/manager.go +++ b/virtcontainers/store/manager.go @@ -7,6 +7,7 @@ package store import ( "context" + "fmt" "net/url" "sync" @@ -87,6 +88,48 @@ type Store struct { host string } +type manager struct { + sync.RWMutex + stores map[string]*Store +} + +var stores = &manager{stores: make(map[string]*Store)} + +func (m *manager) addStore(s *Store) (err error) { + if s == nil { + return fmt.Errorf("Store can not be nil") + } + + if s.url == "" { + return fmt.Errorf("Store URL can not be nil") + } + + m.Lock() + defer m.Unlock() + + if m.stores[s.url] != nil { + return fmt.Errorf("Store %s already added", s.url) + } + + m.stores[s.url] = s + + return nil +} + +func (m *manager) removeStore(url string) { + m.Lock() + defer m.Unlock() + + delete(m.stores, url) +} + +func (m *manager) findStore(url string) *Store { + m.RLock() + defer m.RUnlock() + + return m.stores[url] +} + // New will return a new virtcontainers Store. // If there is already a Store for the URL, we will re-use it. // Otherwise a new Store is created. diff --git a/virtcontainers/store/manager_test.go b/virtcontainers/store/manager_test.go index 2e48783776..f2a3f52da8 100644 --- a/virtcontainers/store/manager_test.go +++ b/virtcontainers/store/manager_test.go @@ -12,10 +12,75 @@ import ( "github.com/stretchr/testify/assert" ) +var storeRoot = "file:///root1/" + func TestNewStore(t *testing.T) { - s, err := New(context.Background(), "file:///root/") + s, err := New(context.Background(), storeRoot) assert.Nil(t, err) assert.Equal(t, s.scheme, "file") assert.Equal(t, s.host, "") - assert.Equal(t, s.path, "/root/") + assert.Equal(t, s.path, "/root1/") +} + +func TestManagerAddStore(t *testing.T) { + s, err := New(context.Background(), storeRoot) + assert.Nil(t, err) + err = stores.addStore(s) + defer stores.removeStore(storeRoot) + assert.Nil(t, err, "addStore failed") + + // Duplicate, should fail + err = stores.addStore(s) + assert.NotNil(t, err, "addStore should have failed") + + // Try with an empty URL + sEmpty, err := New(context.Background(), storeRoot) + assert.Nil(t, err) + sEmpty.url = "" + err = stores.addStore(sEmpty) + assert.NotNil(t, err, "addStore should have failed on an empty store URL") + +} + +func TestManagerRemoveStore(t *testing.T) { + s, err := New(context.Background(), storeRoot) + assert.Nil(t, err) + + err = stores.addStore(s) + assert.Nil(t, err, "addStore failed") + + // Positive find + newStore := stores.findStore(storeRoot) + assert.NotNil(t, newStore, "findStore failed") + + // Negative removal + stores.removeStore(storeRoot + "foobar") + + // We should still find storeRoot + newStore = stores.findStore(storeRoot) + assert.NotNil(t, newStore, "findStore failed") + + // Positive removal + stores.removeStore(storeRoot) + + // We should no longer find storeRoot + newStore = stores.findStore(storeRoot) + assert.Nil(t, newStore, "findStore should not have found %s", storeRoot) +} + +func TestManagerFindStore(t *testing.T) { + s, err := New(context.Background(), storeRoot) + assert.Nil(t, err) + + err = stores.addStore(s) + defer stores.removeStore(storeRoot) + assert.Nil(t, err, "addStore failed") + + // Positive find + newStore := stores.findStore(storeRoot) + assert.NotNil(t, newStore, "findStore failed") + + // Negative find + newStore = stores.findStore(storeRoot + "foobar") + assert.Nil(t, newStore, "findStore should not have found a new store") }