pd/pkg/schedule/plugin_interface.go

67 lines
1.8 KiB
Go

// Copyright 2019 TiKV Project Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schedule
import (
"path/filepath"
"plugin"
"go.uber.org/zap"
"github.com/pingcap/log"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/utils/syncutil"
)
// PluginInterface is used to manage all plugin.
type PluginInterface struct {
pluginMap map[string]*plugin.Plugin
pluginMapLock syncutil.RWMutex
}
// NewPluginInterface create a plugin interface
func NewPluginInterface() *PluginInterface {
return &PluginInterface{
pluginMap: make(map[string]*plugin.Plugin),
pluginMapLock: syncutil.RWMutex{},
}
}
// GetFunction gets func by funcName from plugin(.so)
func (p *PluginInterface) GetFunction(path string, funcName string) (plugin.Symbol, error) {
p.pluginMapLock.Lock()
defer p.pluginMapLock.Unlock()
if _, ok := p.pluginMap[path]; !ok {
// open plugin
filePath, err := filepath.Abs(path)
if err != nil {
return nil, errs.ErrFilePathAbs.Wrap(err)
}
log.Info("open plugin file", zap.String("file-path", filePath))
plugin, err := plugin.Open(filePath)
if err != nil {
return nil, errs.ErrLoadPlugin.Wrap(err)
}
p.pluginMap[path] = plugin
}
// get func from plugin
f, err := p.pluginMap[path].Lookup(funcName)
if err != nil {
return nil, errs.ErrLookupPluginFunc.Wrap(err)
}
return f, nil
}