106 lines
2.8 KiB
Go
106 lines
2.8 KiB
Go
package plugin
|
|
|
|
import (
|
|
"sync"
|
|
|
|
plugin "github.com/hashicorp/go-plugin"
|
|
"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]*plugin.Client),
|
|
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]*plugin.Client
|
|
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) (*plugin.Client, 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) ([]*plugin.Client, error) {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
if forScope, found := s.clients[clientKey{kind, scope}]; found {
|
|
var clients []*plugin.Client
|
|
|
|
for _, client := range forScope {
|
|
clients = append(clients, client)
|
|
}
|
|
|
|
return clients, nil
|
|
}
|
|
|
|
return nil, errors.New("clients not found")
|
|
}
|
|
|
|
// add stores a plugin client for the given kind/name/scope.
|
|
func (s *clientStore) add(client *plugin.Client, 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]*plugin.Client)
|
|
}
|
|
|
|
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})
|
|
}
|