refactor: split plugin files

This commit is contained in:
debugtalk
2022-02-23 16:24:59 +08:00
parent c827222d34
commit 00df455931
3 changed files with 130 additions and 119 deletions

View File

@@ -0,0 +1,70 @@
package common
import (
"fmt"
"plugin"
"reflect"
"runtime"
"github.com/rs/zerolog/log"
)
// GoPlugin implements golang official plugin
type GoPlugin struct {
*plugin.Plugin
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
}
func (p *GoPlugin) Init(path string) error {
if runtime.GOOS == "windows" {
log.Warn().Msg("go plugin does not support windows")
return fmt.Errorf("go plugin does not support windows")
}
var err error
p.Plugin, err = plugin.Open(path)
if err != nil {
log.Error().Err(err).Str("path", path).Msg("load go plugin failed")
return err
}
p.cachedFunctions = make(map[string]reflect.Value)
log.Info().Str("path", path).Msg("load go plugin success")
return nil
}
func (p *GoPlugin) Has(funcName string) bool {
fn, ok := p.cachedFunctions[funcName]
if ok {
return fn.IsValid()
}
sym, err := p.Plugin.Lookup(funcName)
if err != nil {
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
return false
}
fn = reflect.ValueOf(sym)
// check function type
if fn.Kind() != reflect.Func {
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
return false
}
p.cachedFunctions[funcName] = fn
return true
}
func (p *GoPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
if !p.Has(funcName) {
return nil, fmt.Errorf("function %s not found", funcName)
}
fn := p.cachedFunctions[funcName]
return CallFunc(fn, args...)
}
func (p *GoPlugin) Quit() error {
// no need to quit for go plugin
return nil
}

View File

@@ -0,0 +1,60 @@
package common
import (
pluginHost "github.com/httprunner/hrp/plugin/host"
pluginShared "github.com/httprunner/hrp/plugin/shared"
"github.com/rs/zerolog/log"
)
// HashicorpPlugin implements hashicorp/go-plugin
type HashicorpPlugin struct {
pluginShared.FuncCaller
cachedFunctions map[string]bool // cache loaded functions to improve performance
}
func (p *HashicorpPlugin) Init(path string) error {
f, err := pluginHost.Init(path)
if err != nil {
log.Error().Err(err).Str("path", path).Msg("load go hashicorp plugin failed")
return err
}
p.FuncCaller = f
p.cachedFunctions = make(map[string]bool)
log.Info().Str("path", path).Msg("load hashicorp go plugin success")
return nil
}
func (p *HashicorpPlugin) Has(funcName string) bool {
flag, ok := p.cachedFunctions[funcName]
if ok {
return flag
}
funcNames, err := p.GetNames()
if err != nil {
return false
}
for _, name := range funcNames {
if name == funcName {
p.cachedFunctions[funcName] = true // cache as exists
return true
}
}
p.cachedFunctions[funcName] = false // cache as not exists
return false
}
func (p *HashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
return p.FuncCaller.Call(funcName, args...)
}
func (p *HashicorpPlugin) Quit() error {
// kill hashicorp plugin process
log.Info().Msg("quit hashicorp plugin process")
pluginHost.Quit()
return nil
}

View File

@@ -4,13 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"plugin"
"reflect"
"runtime"
"github.com/rs/zerolog/log"
pluginHost "github.com/httprunner/hrp/plugin/host"
pluginShared "github.com/httprunner/hrp/plugin/shared"
)
@@ -29,119 +23,6 @@ type Plugin interface {
Quit() error // quit plugin
}
// GoPlugin implements golang official plugin
type GoPlugin struct {
*plugin.Plugin
cachedFunctions map[string]reflect.Value // cache loaded functions to improve performance
}
func (p *GoPlugin) Init(path string) error {
if runtime.GOOS == "windows" {
log.Warn().Msg("go plugin does not support windows")
return fmt.Errorf("go plugin does not support windows")
}
var err error
p.Plugin, err = plugin.Open(path)
if err != nil {
log.Error().Err(err).Str("path", path).Msg("load go plugin failed")
return err
}
p.cachedFunctions = make(map[string]reflect.Value)
log.Info().Str("path", path).Msg("load go plugin success")
return nil
}
func (p *GoPlugin) Has(funcName string) bool {
fn, ok := p.cachedFunctions[funcName]
if ok {
return fn.IsValid()
}
sym, err := p.Plugin.Lookup(funcName)
if err != nil {
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
return false
}
fn = reflect.ValueOf(sym)
// check function type
if fn.Kind() != reflect.Func {
p.cachedFunctions[funcName] = reflect.Value{} // mark as invalid
return false
}
p.cachedFunctions[funcName] = fn
return true
}
func (p *GoPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
if !p.Has(funcName) {
return nil, fmt.Errorf("function %s not found", funcName)
}
fn := p.cachedFunctions[funcName]
return CallFunc(fn, args...)
}
func (p *GoPlugin) Quit() error {
// no need to quit for go plugin
return nil
}
// HashicorpPlugin implements hashicorp/go-plugin
type HashicorpPlugin struct {
pluginShared.FuncCaller
cachedFunctions map[string]bool // cache loaded functions to improve performance
}
func (p *HashicorpPlugin) Init(path string) error {
f, err := pluginHost.Init(path)
if err != nil {
log.Error().Err(err).Str("path", path).Msg("load go hashicorp plugin failed")
return err
}
p.FuncCaller = f
p.cachedFunctions = make(map[string]bool)
log.Info().Str("path", path).Msg("load hashicorp go plugin success")
return nil
}
func (p *HashicorpPlugin) Has(funcName string) bool {
flag, ok := p.cachedFunctions[funcName]
if ok {
return flag
}
funcNames, err := p.GetNames()
if err != nil {
return false
}
for _, name := range funcNames {
if name == funcName {
p.cachedFunctions[funcName] = true // cache as exists
return true
}
}
p.cachedFunctions[funcName] = false // cache as not exists
return false
}
func (p *HashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
return p.FuncCaller.Call(funcName, args...)
}
func (p *HashicorpPlugin) Quit() error {
// kill hashicorp plugin process
log.Info().Msg("quit hashicorp plugin process")
pluginHost.Quit()
return nil
}
func Init(path string) (Plugin, error) {
if path == "" {
return nil, nil