diff --git a/engine/gengine.go b/engine/gengine.go index 6315623..31049db 100644 --- a/engine/gengine.go +++ b/engine/gengine.go @@ -3,11 +3,12 @@ package engine import ( "errors" "fmt" - "github.com/bilibili/gengine/builder" - "github.com/bilibili/gengine/internal/base" "sort" "sync" + "github.com/bilibili/gengine/builder" + "github.com/bilibili/gengine/internal/base" + "github.com/google/martian/log" ) @@ -17,7 +18,9 @@ type Gengine struct { } func NewGengine() *Gengine { - return &Gengine{} + return &Gengine{ + returnResult: make(map[string]interface{}), + } } type Stag struct { @@ -34,7 +37,8 @@ func (g *Gengine) GetRulesResultMap() (map[string]interface{}, error) { return g.returnResult, nil } -/** +/* +* sort execute model when b is true it means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule @@ -74,7 +78,8 @@ func (g *Gengine) Execute(rb *builder.RuleBuilder, b bool) error { return nil } -/** +/* +* sort execute model when b is true it means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule; @@ -125,8 +130,8 @@ func (g *Gengine) ExecuteWithStopTagDirect(rb *builder.RuleBuilder, b bool, sTag } /* - concurrent execute model - in this mode, it will not consider the priority and not consider err control +concurrent execute model +in this mode, it will not consider the priority and not consider err control */ func (g *Gengine) ExecuteConcurrent(rb *builder.RuleBuilder) error { @@ -170,10 +175,10 @@ func (g *Gengine) ExecuteConcurrent(rb *builder.RuleBuilder) error { } /* - mix model to execute rules +mix model to execute rules - in this mode, it will not consider the priority,and it also concurrently to execute rules - first to execute the most high priority rule,then concurrently to execute last rules without consider the priority +in this mode, it will not consider the priority,and it also concurrently to execute rules +first to execute the most high priority rule,then concurrently to execute last rules without consider the priority */ func (g *Gengine) ExecuteMixModel(rb *builder.RuleBuilder) error { @@ -228,8 +233,10 @@ func (g *Gengine) ExecuteMixModel(rb *builder.RuleBuilder) error { return nil } -/** - mix execute model +/* +* + + mix execute model base type :golang translate value not base type: golang translate pointer @@ -239,7 +246,6 @@ stopTag is a name given by user, and user can use it to control rules execute b it used in this scene: where the first rule execute finished, you don't want to execute to the last rules, you can use sTag to control it out of gengine - */ func (g *Gengine) ExecuteMixModelWithStopTagDirect(rb *builder.RuleBuilder, sTag *Stag) error { @@ -295,7 +301,8 @@ func (g *Gengine) ExecuteMixModelWithStopTagDirect(rb *builder.RuleBuilder, sTag return nil } -/** +/* +* user can choose specified name rules to run with sort, and it will continue to execute the last rules,even if there rule execute error */ func (g *Gengine) ExecuteSelectedRules(rb *builder.RuleBuilder, names []string) error { @@ -349,7 +356,8 @@ func (g *Gengine) ExecuteSelectedRules(rb *builder.RuleBuilder, names []string) return nil } -/** +/* +* user can choose specified name rules to run with sort b bool:control whether continue to execute last rules ,when a rule execute error; if b == true ,the func is same to ExecuteSelectedRules */ @@ -408,7 +416,8 @@ func (g *Gengine) ExecuteSelectedRulesWithControl(rb *builder.RuleBuilder, b boo return nil } -/** +/* +* user can choose specified name rules to run with given sorted name b bool:control whether continue to execute last rules ,when a rule execute error; if b == true ,the func is same to ExecuteSelectedRules @@ -463,7 +472,8 @@ func (g *Gengine) ExecuteSelectedRulesWithControlAsGivenSortedName(rb *builder.R return nil } -/** +/* +* user can choose specified name rules to run with sort b bool:control whether continue to execute last rules ,when a rule execute error; if b == true ,the func is same to ExecuteSelectedRules */ @@ -526,7 +536,8 @@ func (g *Gengine) ExecuteSelectedRulesWithControlAndStopTag(rb *builder.RuleBuil return nil } -/** +/* +* user can choose specified name rules to run with given sorted name b bool:control whether continue to execute last rules ,when a rule execute error; if b == true ,the func is same to ExecuteSelectedRules @@ -585,7 +596,8 @@ func (g *Gengine) ExecuteSelectedRulesWithControlAndStopTagAsGivenSortedName(rb return nil } -/** +/* +* user can choose specified name rules to concurrent run */ func (g *Gengine) ExecuteSelectedRulesConcurrent(rb *builder.RuleBuilder, names []string) error { @@ -655,7 +667,8 @@ func (g *Gengine) ExecuteSelectedRulesConcurrent(rb *builder.RuleBuilder, names return nil } -/** +/* +* user can choose specified name rules to run with mix model */ func (g *Gengine) ExecuteSelectedRulesMixModel(rb *builder.RuleBuilder, names []string) error { @@ -750,7 +763,7 @@ func (g *Gengine) ExecuteSelectedRulesMixModel(rb *builder.RuleBuilder, names [] return nil } -//inverse mix model +// inverse mix model func (g *Gengine) ExecuteInverseMixModel(rb *builder.RuleBuilder) error { //check rb if rb == nil { @@ -811,7 +824,7 @@ func (g *Gengine) ExecuteInverseMixModel(rb *builder.RuleBuilder) error { return e } -//inverse mix model with user selected +// inverse mix model with user selected func (g *Gengine) ExecuteSelectedRulesInverseMixModel(rb *builder.RuleBuilder, names []string) error { //check rb if rb == nil { @@ -888,7 +901,9 @@ func (g *Gengine) ExecuteSelectedRulesInverseMixModel(rb *builder.RuleBuilder, n // 1.first n piece rules to sort execute based on priority // 2.bool b means: when in sort execute stage,if a rule execute error whether continue to execute the last all rules, -// if b == true, means continue, if false, means stop and return +// +// if b == true, means continue, if false, means stop and return +// // 3.then m piece rules to concurrent execute based without priority func (g *Gengine) ExecuteNSortMConcurrent(nSort, mConcurrent int, rb *builder.RuleBuilder, b bool) error { @@ -959,10 +974,10 @@ func (g *Gengine) ExecuteNSortMConcurrent(nSort, mConcurrent int, rb *builder.Ru return nil } -// 1. first n piece rules to concurrent execute based without priority -// 2. bool b means: after concurrent execute stage,if a rule execute error whether continue to execute the last all rules, -// if b == true, means continue, if false, means stop and return -// 3. then m piece rules to sort execute based on priority +// 1. first n piece rules to concurrent execute based without priority +// 2. bool b means: after concurrent execute stage,if a rule execute error whether continue to execute the last all rules, +// if b == true, means continue, if false, means stop and return +// 3. then m piece rules to sort execute based on priority func (g *Gengine) ExecuteNConcurrentMSort(nConcurrent, mSort int, rb *builder.RuleBuilder, b bool) error { //check rb if rb == nil { @@ -1037,10 +1052,10 @@ func (g *Gengine) ExecuteNConcurrentMSort(nConcurrent, mSort int, rb *builder.Ru return nil } -// 1. first n piece rules to concurrent execute based without priority -// 2. bool b means: if the first stage executed error, whether continue to execute the next concurrent stage -// if b == true, means continue, if false, means stop and return -// 3. then m piece rules to concurrent execute based without priority +// 1. first n piece rules to concurrent execute based without priority +// 2. bool b means: if the first stage executed error, whether continue to execute the next concurrent stage +// if b == true, means continue, if false, means stop and return +// 3. then m piece rules to concurrent execute based without priority func (g *Gengine) ExecuteNConcurrentMConcurrent(nConcurrent, mConcurrent int, rb *builder.RuleBuilder, b bool) error { //check rb @@ -1124,7 +1139,9 @@ func (g *Gengine) ExecuteNConcurrentMConcurrent(nConcurrent, mConcurrent int, rb // 0.based on selected rules // 1.first n piece rules to sort execute based on priority // 2.bool b means: when in sort execute stage,if a rule execute error whether continue to execute the last all rules, -// if b == true, means continue, if false, means stop and return +// +// if b == true, means continue, if false, means stop and return +// // 3.then m piece rules to concurrent execute based without priority func (g *Gengine) ExecuteSelectedNSortMConcurrent(nSort, mConcurrent int, rb *builder.RuleBuilder, b bool, names []string) error { @@ -1214,11 +1231,11 @@ func (g *Gengine) ExecuteSelectedNSortMConcurrent(nSort, mConcurrent int, rb *bu return nil } -// 0. based on selected rules -// 1. first n piece rules to concurrent execute based without priority -// 2. bool b means: after concurrent execute stage,if a rule execute error whether continue to execute the last all rules, -// if b == true, means continue, if false, means stop and return -// 3. then m piece rules to sort execute based on priority +// 0. based on selected rules +// 1. first n piece rules to concurrent execute based without priority +// 2. bool b means: after concurrent execute stage,if a rule execute error whether continue to execute the last all rules, +// if b == true, means continue, if false, means stop and return +// 3. then m piece rules to sort execute based on priority func (g *Gengine) ExecuteSelectedNConcurrentMSort(nConcurrent, mSort int, rb *builder.RuleBuilder, b bool, names []string) error { //check rb @@ -1314,10 +1331,10 @@ func (g *Gengine) ExecuteSelectedNConcurrentMSort(nConcurrent, mSort int, rb *bu } // based on selected rules -// 1. first n piece rules to concurrent execute based without priority -// 2. bool b means: if the first stage executed error, whether continue to execute the next concurrent stage -// if b == true, means continue, if false, means stop and return -// 3. then m piece rules to concurrent execute based without priority +// 1. first n piece rules to concurrent execute based without priority +// 2. bool b means: if the first stage executed error, whether continue to execute the next concurrent stage +// if b == true, means continue, if false, means stop and return +// 3. then m piece rules to concurrent execute based without priority func (g *Gengine) ExecuteSelectedNConcurrentMConcurrent(nConcurrent, mConcurrent int, rb *builder.RuleBuilder, b bool, names []string) error { //check rb @@ -1417,7 +1434,7 @@ func (g *Gengine) ExecuteSelectedNConcurrentMConcurrent(nConcurrent, mConcurrent return nil } -//DAG model +// DAG model func (g *Gengine) ExecuteDAGModel(rb *builder.RuleBuilder, dag [][]string) error { //check rb diff --git a/engine/gengine_pool.go b/engine/gengine_pool.go index d96434c..6d74ab5 100644 --- a/engine/gengine_pool.go +++ b/engine/gengine_pool.go @@ -3,14 +3,15 @@ package engine import ( "errors" "fmt" - "github.com/antlr/antlr4/runtime/Go/antlr" + "sync" + + "github.com/antlr/antlr4/runtime/Go/antlr/v4" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/internal/base" parser "github.com/bilibili/gengine/internal/iantlr/alr" "github.com/bilibili/gengine/internal/iparser" "github.com/bilibili/gengine/internal/tool" - "sync" "github.com/google/martian/log" ) @@ -131,7 +132,7 @@ func NewGenginePool(poolMinLen, poolMaxLen int64, em int, rulesStr string, apiOu return p, nil } -//this could ensure make thread safety! +// this could ensure make thread safety! func makeRuleBuilder(ruleStr string, apiOuter map[string]interface{}) (*builder.RuleBuilder, error) { dataContext := context.NewDataContext() if apiOuter != nil { @@ -157,27 +158,30 @@ func (gp *GenginePool) getGengine() (*gengineWrapper, error) { for { gp.getEngineLock.Lock() //check if there has enough resource in pool + gp.runningLock.Lock() numFree := len(gp.freeGengines) if numFree > 0 { - gp.runningLock.Lock() gw := gp.freeGengines[0] + gp.freeGengines[0] = nil gp.freeGengines = gp.freeGengines[1:] gp.runningLock.Unlock() gp.getEngineLock.Unlock() return gw, nil } + gp.runningLock.Unlock() //check if there has addition resource + gp.additionLock.Lock() numAddition := len(gp.additionGengines) if numAddition > 0 { - gp.additionLock.Lock() gw := gp.additionGengines[0] + gp.additionGengines[0] = nil gp.additionGengines = gp.additionGengines[1:] gp.additionLock.Unlock() gp.getEngineLock.Unlock() return gw, nil } - + gp.additionLock.Unlock() gp.getEngineLock.Unlock() } } @@ -198,13 +202,13 @@ func (gp *GenginePool) putGengineLocked(gw *gengineWrapper) { }() } -//sync method -//update the all rules in all engine in the pool -//update success: return nil -//update failed: return error +// sync method +// update the all rules in all engine in the pool +// update success: return nil +// update failed: return error // this is very different from connection pool, -//connection pool just need to init once -//while gengine pool need to update the rules whenever the user want to init +// connection pool just need to init once +// while gengine pool need to update the rules whenever the user want to init func (gp *GenginePool) UpdatePooledRules(ruleStr string) error { //check the rules gp.updateLock.Lock() @@ -332,13 +336,13 @@ func updateIncremental(kc *base.KnowledgeContext, rb *builder.RuleBuilder) { rb.Kc.SortRules = newSortRules } -//sync method -//incremental update the rules in all engine in the pool -//incremental update success: return nil -//incremental update failed: return error +// sync method +// incremental update the rules in all engine in the pool +// incremental update success: return nil +// incremental update failed: return error // if a rule already exists, this method will use the new rule to replace the old one // if a rule doesn't exist, this method will add the new rule to the existed rules list -//see: func (builder *RuleBuilder)BuildRuleWithIncremental(ruleString string) in rule_builder.go +// see: func (builder *RuleBuilder)BuildRuleWithIncremental(ruleString string) in rule_builder.go func (gp *GenginePool) UpdatePooledRulesIncremental(ruleStr string) error { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -361,7 +365,7 @@ func (gp *GenginePool) UpdatePooledRulesIncremental(ruleStr string) error { return nil } -//clear all rules in engine in pool +// clear all rules in engine in pool func (gp *GenginePool) ClearPoolRules() { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -372,7 +376,7 @@ func (gp *GenginePool) ClearPoolRules() { } } -//remove rules +// remove rules func (gp *GenginePool) RemoveRules(ruleNames []string) error { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -388,11 +392,11 @@ func (gp *GenginePool) RemoveRules(ruleNames []string) error { return nil } -//plugin_exportName_apiName.so +// plugin_exportName_apiName.so // _ is a separator -//plugin is prefix -//exportName is user export in plugin file -//apiName is plugin used in gengine +// plugin is prefix +// exportName is user export in plugin file +// apiName is plugin used in gengine func (gp *GenginePool) PluginLoader(absolutePathOfSO string) error { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -425,12 +429,12 @@ func (gp *GenginePool) SetExecModel(execModel int) error { return nil } -//get the execute model the user set +// get the execute model the user set func (gp *GenginePool) GetExecModel() int { return gp.execModel } -//check the rule whether exist +// check the rule whether exist func (gp *GenginePool) IsExist(ruleNames []string) []bool { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -455,7 +459,7 @@ func (gp *GenginePool) IsExist(ruleNames []string) []bool { return exist } -//get the rule's salience +// get the rule's salience func (gp *GenginePool) GetRuleSalience(ruleName string) (int64, error) { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -471,7 +475,7 @@ func (gp *GenginePool) GetRuleSalience(ruleName string) (int64, error) { } } -//get the rule's description +// get the rule's description func (gp *GenginePool) GetRuleDesc(ruleName string) (string, error) { gp.updateLock.Lock() defer gp.updateLock.Unlock() @@ -538,9 +542,9 @@ func (gp *GenginePool) prepareWithMultiInput(data map[string]interface{}) (*geng return gw, nil } -//execute rules as the user set execute model when init or update -//req, it is better to be ptr, or you will not get changed data -//resp, it is better to be ptr, or you will not get changed data +// execute rules as the user set execute model when init or update +// req, it is better to be ptr, or you will not get changed data +// resp, it is better to be ptr, or you will not get changed data // the return map[string]interface{} collection each rule returned result func (gp *GenginePool) ExecuteRulesWithSpecifiedEM(reqName string, req interface{}, respName string, resp interface{}) (error, map[string]interface{}) { @@ -589,7 +593,8 @@ func (gp *GenginePool) ExecuteRulesWithSpecifiedEM(reqName string, req interface return nil, returnResultMap } -/** +/* +* user can input more data to use in engine it is no difference with ExecuteRules, you just can inject more data use this api @@ -643,7 +648,8 @@ func (gp *GenginePool) ExecuteRulesWithMultiInputWithSpecifiedEM(data map[string } -/*** +/* +** this make user could use exemodel to control the select-exemodel the return map[string]interface{} collection each rule returned result @@ -743,7 +749,7 @@ func (gp *GenginePool) ExecuteWithStopTagDirect(data map[string]interface{}, b b return e, returnResultMap } -//see gengine.go ExecuteConcurrent +// see gengine.go ExecuteConcurrent func (gp *GenginePool) ExecuteConcurrent(data map[string]interface{}) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -791,7 +797,7 @@ func (gp *GenginePool) ExecuteMixModel(data map[string]interface{}) (error, map[ return e, returnResultMap } -//see gengine.go ExecuteMixModelWithStopTagDirect +// see gengine.go ExecuteMixModelWithStopTagDirect func (gp *GenginePool) ExecuteMixModelWithStopTagDirect(data map[string]interface{}, sTag *Stag) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -840,7 +846,7 @@ func (gp *GenginePool) ExecuteSelectedRules(data map[string]interface{}, names [ return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesWithControl +// see gengine.go ExecuteSelectedRulesWithControl func (gp *GenginePool) ExecuteSelectedRulesWithControl(data map[string]interface{}, b bool, names []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -864,7 +870,7 @@ func (gp *GenginePool) ExecuteSelectedRulesWithControl(data map[string]interface return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesWithControlAsGivenSortedName +// see gengine.go ExecuteSelectedRulesWithControlAsGivenSortedName func (gp *GenginePool) ExecuteSelectedRulesWithControlAsGivenSortedName(data map[string]interface{}, b bool, sortedNames []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -888,7 +894,7 @@ func (gp *GenginePool) ExecuteSelectedRulesWithControlAsGivenSortedName(data map return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesWithControlAndStopTag +// see gengine.go ExecuteSelectedRulesWithControlAndStopTag func (gp *GenginePool) ExecuteSelectedRulesWithControlAndStopTag(data map[string]interface{}, b bool, sTag *Stag, names []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -912,7 +918,7 @@ func (gp *GenginePool) ExecuteSelectedRulesWithControlAndStopTag(data map[string return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesWithControlAndStopTagAsGivenSortedName +// see gengine.go ExecuteSelectedRulesWithControlAndStopTagAsGivenSortedName func (gp *GenginePool) ExecuteSelectedRulesWithControlAndStopTagAsGivenSortedName(data map[string]interface{}, b bool, sTag *Stag, sortedNames []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared @@ -936,7 +942,7 @@ func (gp *GenginePool) ExecuteSelectedRulesWithControlAndStopTagAsGivenSortedNam return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesConcurrent +// see gengine.go ExecuteSelectedRulesConcurrent func (gp *GenginePool) ExecuteSelectedRulesConcurrent(data map[string]interface{}, names []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) @@ -961,7 +967,7 @@ func (gp *GenginePool) ExecuteSelectedRulesConcurrent(data map[string]interface{ return e, returnResultMap } -//see gengine.go ExecuteSelectedRulesMixModel +// see gengine.go ExecuteSelectedRulesMixModel func (gp *GenginePool) ExecuteSelectedRulesMixModel(data map[string]interface{}, names []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) @@ -1012,7 +1018,7 @@ func (gp *GenginePool) ExecuteInverseMixModel(data map[string]interface{}) (erro } -//see gengine.go ExecuteSelectedRulesInverseMixModel +// see gengine.go ExecuteSelectedRulesInverseMixModel func (gp *GenginePool) ExecuteSelectedRulesInverseMixModel(data map[string]interface{}, names []string) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) @@ -1086,7 +1092,7 @@ func (gp *GenginePool) ExecuteNConcurrentMSort(nSort, mConcurrent int, b bool, d return e, returnResultMap } -//see gengine.go ExecuteNConcurrentMConcurrent +// see gengine.go ExecuteNConcurrentMConcurrent func (gp *GenginePool) ExecuteNConcurrentMConcurrent(nSort, mConcurrent int, b bool, data map[string]interface{}) (error, map[string]interface{}) { returnResultMap := make(map[string]interface{}) //rules has bean cleared