| /* |
| * 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 plugin |
| |
| import ( |
| "github.com/apache/servicecomb-service-center/pkg/log" |
| "github.com/apache/servicecomb-service-center/pkg/plugin" |
| "github.com/apache/servicecomb-service-center/pkg/util" |
| "github.com/astaxie/beego" |
| "sync" |
| ) |
| |
| var pluginMgr = &PluginManager{} |
| |
| func init() { |
| pluginMgr.Initialize() |
| } |
| |
| type wrapInstance struct { |
| dynamic bool |
| instance PluginInstance |
| lock sync.RWMutex |
| } |
| |
| type PluginManager struct { |
| plugins map[PluginName]map[string]*Plugin |
| instances map[PluginName]*wrapInstance |
| } |
| |
| func (pm *PluginManager) Initialize() { |
| pm.plugins = make(map[PluginName]map[string]*Plugin, int(typeEnd)) |
| pm.instances = make(map[PluginName]*wrapInstance, int(typeEnd)) |
| |
| for t := PluginName(0); t != typeEnd; t++ { |
| pm.instances[t] = &wrapInstance{} |
| } |
| } |
| |
| func (pm *PluginManager) ReloadAll() { |
| for pn := range pm.instances { |
| pm.Reload(pn) |
| } |
| } |
| |
| // unsafe |
| func (pm *PluginManager) Register(p Plugin) { |
| m, ok := pm.plugins[p.PName] |
| if !ok { |
| m = make(map[string]*Plugin, 5) |
| } |
| m[p.Name] = &p |
| pm.plugins[p.PName] = m |
| log.Infof("load '%s' plugin named '%s'", p.PName, p.Name) |
| } |
| |
| func (pm *PluginManager) Get(pn PluginName, name string) *Plugin { |
| m, ok := pm.plugins[pn] |
| if !ok { |
| return nil |
| } |
| return m[name] |
| } |
| |
| func (pm *PluginManager) Instance(pn PluginName) PluginInstance { |
| wi := pm.instances[pn] |
| wi.lock.RLock() |
| if wi.instance != nil { |
| wi.lock.RUnlock() |
| return wi.instance |
| } |
| wi.lock.RUnlock() |
| |
| wi.lock.Lock() |
| if wi.instance != nil { |
| wi.lock.Unlock() |
| return wi.instance |
| } |
| pm.New(pn) |
| wi.lock.Unlock() |
| |
| return wi.instance |
| } |
| |
| func (pm *PluginManager) New(pn PluginName) { |
| var ( |
| title = STATIC |
| f func() PluginInstance |
| ) |
| |
| wi := pm.instances[pn] |
| p := pm.existDynamicPlugin(pn) |
| if p != nil { |
| wi.dynamic = true |
| title = DYNAMIC |
| f = p.New |
| } else { |
| wi.dynamic = false |
| m, ok := pm.plugins[pn] |
| if !ok { |
| return |
| } |
| |
| name := beego.AppConfig.DefaultString(pn.String()+"_plugin", BUILDIN) |
| p, ok = m[name] |
| if !ok { |
| return |
| } |
| |
| f = p.New |
| pn.ActiveConfigs().Set(keyPluginName, name) |
| } |
| log.Infof("call %s '%s' plugin %s(), new a '%s' instance", |
| title, p.PName, util.FuncName(f), p.Name) |
| |
| wi.instance = f() |
| } |
| |
| func (pm *PluginManager) Reload(pn PluginName) { |
| wi := pm.instances[pn] |
| wi.lock.Lock() |
| wi.instance = nil |
| pn.ClearConfigs() |
| wi.lock.Unlock() |
| } |
| |
| func (pm *PluginManager) existDynamicPlugin(pn PluginName) *Plugin { |
| m, ok := pm.plugins[pn] |
| if !ok { |
| return nil |
| } |
| // 'buildin' implement of all plugins should call DynamicPluginFunc() |
| if plugin.PluginLoader().Exist(pn.String()) { |
| return m[BUILDIN] |
| } |
| return nil |
| } |
| |
| func Plugins() *PluginManager { |
| return pluginMgr |
| } |
| |
| func RegisterPlugin(p Plugin) { |
| Plugins().Register(p) |
| } |
| |
| func LoadPlugins() { |
| for t := PluginName(0); t != typeEnd; t++ { |
| Plugins().Instance(t) |
| } |
| } |