-
Notifications
You must be signed in to change notification settings - Fork 945
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: xuleiming <xuleiming@yf-networks.com>
- Loading branch information
xuleiming
committed
Dec 3, 2024
1 parent
9f0a6be
commit d1f3a8f
Showing
41 changed files
with
2,562 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
package mod_wasmplug | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path" | ||
"sync" | ||
|
||
"github.com/baidu/go-lib/log" | ||
"github.com/bfenetworks/bfe/bfe_basic/condition" | ||
"github.com/bfenetworks/bfe/bfe_util" | ||
"github.com/bfenetworks/bfe/bfe_util/json" | ||
"github.com/bfenetworks/bfe/bfe_wasmplug" | ||
gcfg "gopkg.in/gcfg.v1" | ||
) | ||
|
||
type ConfModWasm struct { | ||
Basic struct { | ||
WasmPluginPath string // path of Wasm plugins | ||
DataPath string // path of config data | ||
} | ||
|
||
Log struct { | ||
OpenDebug bool | ||
} | ||
} | ||
|
||
// ConfLoad loads config from config file | ||
func ConfLoad(filePath string, confRoot string) (*ConfModWasm, error) { | ||
var cfg ConfModWasm | ||
var err error | ||
|
||
// read config from file | ||
err = gcfg.ReadFileInto(&cfg, filePath) | ||
if err != nil { | ||
return &cfg, err | ||
} | ||
|
||
// check conf of mod_redirect | ||
err = cfg.Check(confRoot) | ||
if err != nil { | ||
return &cfg, err | ||
} | ||
|
||
return &cfg, nil | ||
} | ||
|
||
func (cfg *ConfModWasm) Check(confRoot string) error { | ||
if cfg.Basic.WasmPluginPath == "" { | ||
log.Logger.Warn("ModWasm.WasmPluginPath not set, use default value") | ||
cfg.Basic.WasmPluginPath = "mod_wasm" | ||
} | ||
cfg.Basic.WasmPluginPath = bfe_util.ConfPathProc(cfg.Basic.WasmPluginPath, confRoot) | ||
|
||
if cfg.Basic.DataPath == "" { | ||
log.Logger.Warn("ModWasm.DataPath not set, use default value") | ||
cfg.Basic.WasmPluginPath = "mod_wasm/wasm.data" | ||
} | ||
cfg.Basic.DataPath = bfe_util.ConfPathProc(cfg.Basic.DataPath, confRoot) | ||
|
||
return nil | ||
} | ||
|
||
type PluginConfFile struct { | ||
Version *string // version of the config | ||
BeforeLocationRules *[]FilterRuleFile // rule list for BeforeLocation | ||
ProductRules *map[string][]FilterRuleFile // product --> rule list | ||
PluginMap *map[string]PluginMeta | ||
} | ||
|
||
type FilterRuleFile struct { | ||
Cond *string // condition for plugin | ||
PluginList *[]string | ||
} | ||
|
||
type PluginMeta struct { | ||
Name string | ||
WasmVersion string | ||
ConfVersion string | ||
// Md5 string | ||
InstanceNum int | ||
Product string | ||
} | ||
|
||
type FilterRule struct { | ||
Cond condition.Condition // condition for plugin | ||
PluginList []*bfe_wasmplug.WasmPlugin | ||
} | ||
|
||
type RuleList []FilterRule | ||
type ProductRules map[string]*RuleList // product => list of filter rules | ||
|
||
func updatePluginConf(t *PluginTable, conf PluginConfFile, pluginPath string) error { | ||
if conf.Version != nil && *conf.Version != t.GetVersion() { | ||
pluginMapNew := make(map[string]*bfe_wasmplug.WasmPlugin) | ||
var beforeLocationRulesNew RuleList | ||
productRulesNew := make(ProductRules) | ||
|
||
// 1. check plugin map | ||
unchanged := make(map[string]bool) | ||
|
||
pm := t.GetPluginMap() | ||
if conf.PluginMap != nil { | ||
for pn, p := range *conf.PluginMap { | ||
plugOld := (*pm)[pn] | ||
// check whether plugin version changed. | ||
if plugOld != nil { | ||
configOld := (*plugOld).GetConfig() | ||
if configOld.WasmVersion == p.WasmVersion && configOld.ConfigVersion == p.ConfVersion { | ||
// not change, just copy to new map | ||
pluginMapNew[pn] = plugOld | ||
|
||
// ensure instance num | ||
actual := (*plugOld).EnsureInstanceNum(p.InstanceNum) | ||
if actual != p.InstanceNum { | ||
// log.DefaultLogger.Errorf("[wasm][plugin] NewWasmPlugin fail to ensure instance num, want: %v got 0", instanceNum) | ||
return fmt.Errorf("can not EnsureInstanceNum, plugin:%s, num:%d", pn, p.InstanceNum) | ||
} | ||
|
||
unchanged[pn] = true | ||
continue | ||
} | ||
} | ||
// if changed, construct a new plugin. | ||
wasmconf := bfe_wasmplug.WasmPluginConfig { | ||
PluginName: pn, | ||
WasmVersion: p.WasmVersion, | ||
ConfigVersion: p.ConfVersion, | ||
InstanceNum: p.InstanceNum, | ||
Path: path.Join(pluginPath, pn), | ||
// Md5: p.Md5, | ||
} | ||
plug, err := bfe_wasmplug.NewWasmPlugin(wasmconf) | ||
if err != nil { | ||
// build plugin error | ||
return err | ||
} | ||
|
||
plug.OnPluginStart() | ||
|
||
pluginMapNew[pn] = &plug | ||
} | ||
} | ||
|
||
// 2. construct product rules | ||
if conf.BeforeLocationRules != nil { | ||
for _, r := range *conf.BeforeLocationRules { | ||
rule := FilterRule{} | ||
cond, err := condition.Build(*r.Cond) | ||
if err != nil { | ||
return err | ||
} | ||
rule.Cond =cond | ||
for _, pn := range *r.PluginList { | ||
plug := pluginMapNew[pn] | ||
if plug == nil { | ||
return fmt.Errorf("unknown plugin: %s", pn) | ||
} | ||
rule.PluginList = append(rule.PluginList, plug) | ||
} | ||
beforeLocationRulesNew = append(beforeLocationRulesNew, rule) | ||
} | ||
} | ||
|
||
if conf.ProductRules != nil { | ||
for product, rules := range *conf.ProductRules { | ||
var rulelist RuleList | ||
for _, r := range rules { | ||
rule := FilterRule{} | ||
cond, err := condition.Build(*r.Cond) | ||
if err != nil { | ||
return err | ||
} | ||
rule.Cond =cond | ||
for _, pn := range *r.PluginList { | ||
plug := pluginMapNew[pn] | ||
if plug == nil { | ||
return fmt.Errorf("unknown plugin: %s", pn) | ||
} | ||
rule.PluginList = append(rule.PluginList, plug) | ||
} | ||
rulelist = append(rulelist, rule) | ||
} | ||
productRulesNew[product] = &rulelist | ||
} | ||
} | ||
|
||
// 3. update PluginTable | ||
t.Update(*conf.Version, &beforeLocationRulesNew, productRulesNew, &pluginMapNew) | ||
|
||
// 4. stop & clear old plugins | ||
for pn, plug := range *pm { | ||
if _, ok := unchanged[pn]; !ok { | ||
// stop plug | ||
(*plug).OnPluginDestroy() | ||
(*plug).Clear() | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
type PluginTable struct { | ||
lock sync.RWMutex | ||
version string | ||
beforeLocationRules *RuleList | ||
productRules ProductRules | ||
pluginMap *map[string]*bfe_wasmplug.WasmPlugin | ||
} | ||
|
||
func NewPluginTable() *PluginTable { | ||
t := new(PluginTable) | ||
t.productRules = make(ProductRules) | ||
t.pluginMap = new(map[string]*bfe_wasmplug.WasmPlugin) | ||
return t | ||
} | ||
|
||
func (t *PluginTable) Update(version string, beforeLocationRules *RuleList, productRules ProductRules, pluginMap *map[string]*bfe_wasmplug.WasmPlugin) { | ||
t.lock.Lock() | ||
|
||
t.version = version | ||
t.beforeLocationRules = beforeLocationRules | ||
t.productRules = productRules | ||
t.pluginMap = pluginMap | ||
|
||
t.lock.Unlock() | ||
} | ||
|
||
func (t *PluginTable) GetVersion() string { | ||
defer t.lock.RUnlock() | ||
t.lock.RLock() | ||
return t.version | ||
} | ||
|
||
func (t *PluginTable) GetPluginMap() *map[string]*bfe_wasmplug.WasmPlugin { | ||
defer t.lock.RUnlock() | ||
t.lock.RLock() | ||
return t.pluginMap | ||
} | ||
|
||
func (t *PluginTable) GetBeforeLocationRules() *RuleList { | ||
defer t.lock.RUnlock() | ||
t.lock.RLock() | ||
return t.beforeLocationRules | ||
} | ||
|
||
func (t *PluginTable) Search(product string) (*RuleList, bool) { | ||
t.lock.RLock() | ||
productRules := t.productRules | ||
t.lock.RUnlock() | ||
|
||
rules, ok := productRules[product] | ||
return rules, ok | ||
} | ||
|
||
|
||
func pluginConfLoad(filename string) (PluginConfFile, error) { | ||
var conf PluginConfFile | ||
|
||
/* open the file */ | ||
file, err := os.Open(filename) | ||
|
||
if err != nil { | ||
return conf, err | ||
} | ||
|
||
/* decode the file */ | ||
decoder := json.NewDecoder(file) | ||
|
||
err = decoder.Decode(&conf) | ||
file.Close() | ||
|
||
if err != nil { | ||
return conf, err | ||
} | ||
|
||
return conf, nil | ||
} |
Oops, something went wrong.