Files
velero/pkg/plugin/client_store.go
2018-08-27 11:29:25 -07:00

129 lines
3.3 KiB
Go

package plugin
import (
"sync"
"github.com/pkg/errors"
)
// clientKey is a unique ID for a plugin client.
type clientKey struct {
kind PluginKind
// scope is an additional identifier that allows multiple clients
// for the same kind/name to be differentiated. It will typically
// be the name of the applicable backup/restore for ItemAction
// clients, and blank for Object/BlockStore clients.
scope string
}
func newClientStore() *clientStore {
return &clientStore{
clients: make(map[clientKey]map[string]pluginClient),
lock: &sync.RWMutex{},
}
}
// clientStore is a repository of active plugin clients.
type clientStore struct {
// clients is a nested map, keyed first by clientKey (a
// combo of kind and "scope"), and second by plugin name.
// This enables easy listing of all clients for a given
// kind and scope (e.g. all BackupItemActions for a given
// backup), and efficient lookup by kind+name+scope (e.g.
// the AWS ObjectStore.)
clients map[clientKey]map[string]pluginClient
lock *sync.RWMutex
}
// get returns a plugin client for the given kind/name/scope, or an error if none
// is found.
func (s *clientStore) get(kind PluginKind, name, scope string) (pluginClient, error) {
s.lock.RLock()
defer s.lock.RUnlock()
if forScope, found := s.clients[clientKey{kind, scope}]; found {
if client, found := forScope[name]; found {
return client, nil
}
}
return nil, errors.New("client not found")
}
// list returns all plugin clients for the given kind/scope, or an
// error if none are found.
func (s *clientStore) list(kind PluginKind, scope string) ([]pluginClient, error) {
s.lock.RLock()
defer s.lock.RUnlock()
if forScope, found := s.clients[clientKey{kind, scope}]; found {
var clients []pluginClient
for _, client := range forScope {
clients = append(clients, client)
}
return clients, nil
}
return nil, errors.New("clients not found")
}
// listAll returns all plugin clients for all kinds/scopes, or a
// zero-valued slice if there are none.
func (s *clientStore) listAll() []pluginClient {
s.lock.RLock()
defer s.lock.RUnlock()
var clients []pluginClient
for _, pluginsByName := range s.clients {
for name := range pluginsByName {
clients = append(clients, pluginsByName[name])
}
}
return clients
}
// add stores a plugin client for the given kind/name/scope.
func (s *clientStore) add(client pluginClient, kind PluginKind, name, scope string) {
s.lock.Lock()
defer s.lock.Unlock()
key := clientKey{kind, scope}
if _, found := s.clients[key]; !found {
s.clients[key] = make(map[string]pluginClient)
}
s.clients[key][name] = client
}
// delete removes the client with the given kind/name/scope from the store.
func (s *clientStore) delete(kind PluginKind, name, scope string) {
s.lock.Lock()
defer s.lock.Unlock()
if forScope, found := s.clients[clientKey{kind, scope}]; found {
delete(forScope, name)
}
}
// deleteAll removes all clients with the given kind/scope from
// the store.
func (s *clientStore) deleteAll(kind PluginKind, scope string) {
s.lock.Lock()
defer s.lock.Unlock()
delete(s.clients, clientKey{kind, scope})
}
// clear removes all clients for all kinds/scopes from the store.
func (s *clientStore) clear() {
s.lock.Lock()
defer s.lock.Unlock()
s.clients = make(map[clientKey]map[string]pluginClient)
}