blob: 564059c07c68fd6955f2600345b3dbd8ba0ec625 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 plugins
import (
pg "plugin"
"sync"
"github.com/apache/servicecomb-service-center/pkg/plugin"
)
var (
pluginMgr Manager
pluginConfig map[string]string
)
type Manager map[PluginType]*pluginMap
type PluginInstance interface{}
type pluginMap struct {
plugins map[string]*Plugin
dynamic bool
instance PluginInstance
lock sync.RWMutex
}
type Plugin struct {
Kind PluginType
Name string
New func() PluginInstance
}
func init() {
pluginMgr = make(Manager, pluginTotal)
for t := PluginType(0); t != pluginTotal; t++ {
pluginMgr[t] = &pluginMap{plugins: map[string]*Plugin{}}
}
pluginConfig = make(map[string]string, pluginTotal)
}
func (m Manager) Register(p *Plugin) {
pm, ok := m[p.Kind]
if !ok {
pm = &pluginMap{plugins: map[string]*Plugin{}}
}
pm.plugins[p.Name] = p
m[p.Kind] = pm
}
func (m Manager) Get(pn PluginType, name string) *Plugin {
pm, ok := m[pn]
if !ok {
return nil
}
return pm.plugins[name]
}
func (m Manager) Instance(pn PluginType) PluginInstance {
pm := m[pn]
pm.lock.RLock()
if pm.instance != nil {
pm.lock.RUnlock()
return pm.instance
}
pm.lock.RUnlock()
pm.lock.Lock()
if pm.instance != nil {
pm.lock.Unlock()
return pm.instance
}
m.New(pn)
pm.lock.Unlock()
return pm.instance
}
func (m Manager) New(pn PluginType) {
var (
//title = STATIC
f func() PluginInstance
)
wi := m[pn]
p := m.existDynamicPlugin(pn)
if p != nil {
wi.dynamic = true
//title = DYNAMIC
f = p.New
} else {
wi.dynamic = false
pm, ok := m[pn]
if !ok {
return
}
name, ok := pluginConfig[pn.String()]
if !ok {
name = BUILDIN
}
p, ok = pm.plugins[name]
if !ok {
return
}
f = p.New
}
wi.instance = f()
}
func (m Manager) existDynamicPlugin(pn PluginType) *Plugin {
pm, ok := m[pn]
if !ok {
return nil
}
// 'buildin' implement of all plugins should call DynamicPluginFunc()
if plugin.PluginLoader().Exist(pn.String()) {
return pm.plugins[BUILDIN]
}
return nil
}
func DynamicPluginFunc(pn PluginType, funcName string) pg.Symbol {
if wi, ok := pluginMgr[pn]; ok && !wi.dynamic {
return nil
}
f, err := plugin.FindFunc(pn.String(), funcName)
if err != nil {
return nil
}
return f
}
func Plugins() Manager {
return pluginMgr
}
func RegisterPlugin(p *Plugin) {
pluginMgr.Register(p)
}
func LoadPlugins() {
for t := PluginType(0); t != pluginTotal; t++ {
pluginMgr.Instance(t)
}
}
func SetPluginConfig(key, val string) {
pluginConfig[key] = val
}