Skip to content

Commit

Permalink
[DROOLS-6432] fix concurrency issue when calling simultaneously the s… (
Browse files Browse the repository at this point in the history
#3695)

* [DROOLS-6432] fix concurrency issue when calling simultaneously the same mvel consequence from 2 different KieSessions

* - Adding eval concurrency test (#13)

* [DROOLS-6432] make all mvel expression evaluation thread safe

* Adding accumulate concurrency tests (#14)

* - Adding eval concurrency test

* - Adding accumulate concurrency test

* wip

* MVELObjectClassFieldReaderConcurrencyTest (#15)

* - Adding eval concurrency test

* - Adding accumulate concurrency test

* MVELObjectClassFieldReader concurrency test

* wip

* wip

Co-authored-by: Toshiya Kobayashi <toshiyakobayashi@gmail.com>
  • Loading branch information
mariofusco and tkobayas authored Jun 29, 2021
1 parent 43ad37a commit 5926097
Show file tree
Hide file tree
Showing 18 changed files with 893 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
Expand All @@ -31,20 +30,22 @@
import org.drools.core.spi.PropagationContext;
import org.drools.core.spi.Tuple;
import org.drools.core.util.ArrayIterator;
import org.drools.mvel.MVELSafeHelper;
import org.drools.mvel.MVELDialectRuntimeData;
import org.drools.mvel.expr.MVELCompilationUnit;
import org.drools.mvel.expr.MVELCompileable;
import org.drools.mvel.expr.MvelEvaluator;
import org.mvel2.integration.VariableResolverFactory;

import static org.drools.mvel.expr.MvelEvaluator.createMvelEvaluator;

public class MVELDataProvider implements DataProvider, MVELCompileable, Externalizable {

private static final long serialVersionUID = 510l;

private MVELCompilationUnit unit;
private String id;

private Serializable expr;
private MvelEvaluator<Object> evaluator;

private List<MVELDataProvider> clones;

Expand Down Expand Up @@ -91,19 +92,16 @@ public void writeExternal(ObjectOutput out) throws IOException {

@SuppressWarnings("unchecked")
public void compile( MVELDialectRuntimeData runtimeData) {
expr = unit.getCompiledExpression( runtimeData );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData ) );
if (clones != null) {
for (MVELDataProvider clone : clones) {
clone.expr = clone.unit.getCompiledExpression(runtimeData);
clone.evaluator = createMvelEvaluator( clone.unit.getCompiledExpression(runtimeData) );
}
}
// @TODO URGENT DO NOT FORGET!!!!
// Map previousDeclarations = this.unit.getFactory().getPreviousDeclarations();
// this.requiredDeclarations = (Declaration[]) previousDeclarations.values().toArray( new Declaration[previousDeclarations.size()] );
}

public void compile( MVELDialectRuntimeData runtimeData, RuleImpl rule) {
expr = unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() ) );
}

public Declaration[] getRequiredDeclarations() {
Expand All @@ -129,7 +127,7 @@ public Iterator getResults(final Tuple tuple,

protected Object evaluate( Tuple tuple, InternalWorkingMemory wm ) {
VariableResolverFactory factory = unit.getFactory( null, null, null, null, tuple, null, wm, wm.getGlobalResolver() );
return MVELSafeHelper.getEvaluator().executeExpression( this.expr, factory );
return evaluator.evaluate( factory );
}

protected Iterator asIterator( Object result ) {
Expand All @@ -148,7 +146,7 @@ protected Iterator asIterator( Object result ) {

public DataProvider clone() {
MVELDataProvider clone = new MVELDataProvider(unit.clone(), id);
clone.expr = expr;
clone.evaluator = evaluator;
if (clones == null) {
clones = new ArrayList<MVELDataProvider>();
}
Expand Down
39 changes: 17 additions & 22 deletions drools-mvel/src/main/java/org/drools/mvel/expr/MVELAccumulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
import org.drools.core.spi.MvelAccumulator;
import org.drools.core.spi.Tuple;
import org.drools.mvel.MVELDialectRuntimeData;
import org.drools.mvel.MVELSafeHelper;
import org.drools.mvel.expr.MVELCompilationUnit.DroolsVarFactory;
import org.mvel2.integration.VariableResolverFactory;

import static org.drools.mvel.expr.MvelEvaluator.createMvelEvaluator;

/**
* An MVEL accumulator implementation
*/
Expand All @@ -49,10 +50,10 @@ public class MVELAccumulator
MVELCompilationUnit reverseUnit;
MVELCompilationUnit resultUnit;

private Serializable init;
private Serializable action;
private Serializable reverse;
private Serializable result;
private MvelEvaluator<Void> init;
private MvelEvaluator<Void> action;
private MvelEvaluator<Void> reverse;
private MvelEvaluator<Void> result;

public MVELAccumulator() {
}
Expand Down Expand Up @@ -88,12 +89,12 @@ public void compile( MVELDialectRuntimeData runtimeData) {
}

public void compile( MVELDialectRuntimeData runtimeData, RuleImpl rule) {
init = initUnit.getCompiledExpression( runtimeData );
action = actionUnit.getCompiledExpression( runtimeData );
result = resultUnit.getCompiledExpression( runtimeData );
init = createMvelEvaluator( initUnit.getCompiledExpression( runtimeData ) );
action = createMvelEvaluator( actionUnit.getCompiledExpression( runtimeData ) );
result = createMvelEvaluator( resultUnit.getCompiledExpression( runtimeData ) );

if ( reverseUnit != null ) {
reverse = reverseUnit.getCompiledExpression( runtimeData, rule != null ? rule.toRuleNameAndPathString() : null );
reverse = createMvelEvaluator( reverseUnit.getCompiledExpression( runtimeData, rule != null ? rule.toRuleNameAndPathString() : null ) );
}
}

Expand Down Expand Up @@ -124,9 +125,7 @@ public Object init(Object workingMemoryContext,
factory.setNextFactory( data.getFunctionFactory() );
}

MVELSafeHelper.getEvaluator().executeExpression( this.init,
null,
factory );
this.init.evaluate( factory );


DroolsVarFactory df = ( DroolsVarFactory ) factory.getNextFactory();
Expand Down Expand Up @@ -164,11 +163,9 @@ public Object accumulate(Object workingMemoryContext,
shadow[i] = factory.getIndexedVariableResolver( i ).getValue();
}
}
MVELSafeHelper.getEvaluator().executeExpression( this.action,
null,
factory );



this.action.evaluate( factory );

if ( localVars.length > 0 ) {
for ( int i = 0; i < df.getOtherVarsLength(); i++ ) {
localVars[i] = factory.getIndexedVariableResolver( df.getOtherVarsPos() + i ).getValue();
Expand Down Expand Up @@ -210,10 +207,8 @@ public boolean tryReverse(Object workingMemoryContext,
}
}

MVELSafeHelper.getEvaluator().executeExpression( this.reverse,
null,
factory );

this.reverse.evaluate( factory );

if ( localVars.length > 0 ) {
for ( int i = 0; i < df.getOtherVarsLength(); i++ ) {
localVars[i] = factory.getIndexedVariableResolver( df.getOtherVarsPos() + i ).getValue();
Expand All @@ -239,7 +234,7 @@ public Object getResult(Object workingMemoryContext,
VariableResolverFactory factory = factoryContext.getResultFactory();
resultUnit.updateFactory( null, tuple, localVars, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver(), factory );

return MVELSafeHelper.getEvaluator().executeExpression( this.result, null, factory );
return this.result.evaluate( factory );
}

public boolean supportsReverse() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
import org.drools.core.spi.MvelAccumulator;
import org.drools.core.spi.Tuple;
import org.drools.mvel.MVELDialectRuntimeData;
import org.mvel2.MVEL;
import org.mvel2.integration.VariableResolverFactory;

import static org.drools.mvel.expr.MvelEvaluator.createMvelEvaluator;

/**
* An MVEL accumulator function executor implementation
*/
Expand All @@ -45,7 +46,7 @@ public class MVELAccumulatorFunctionExecutor
private MVELCompilationUnit unit;
private org.kie.api.runtime.rule.AccumulateFunction function;

private Serializable expression;
private MvelEvaluator<Object> evaluator;

public MVELAccumulatorFunctionExecutor() {

Expand All @@ -70,11 +71,11 @@ public void writeExternal(ObjectOutput out) throws IOException {
}

public void compile( MVELDialectRuntimeData runtimeData) {
expression = unit.getCompiledExpression( runtimeData );
evaluator = createMvelEvaluator(unit.getCompiledExpression( runtimeData ));
}

public void compile( MVELDialectRuntimeData runtimeData, RuleImpl rule) {
expression = unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() );
evaluator = createMvelEvaluator(unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() ));
}

/* (non-Javadoc)
Expand Down Expand Up @@ -108,7 +109,7 @@ public Object accumulate(Object workingMemoryContext,

VariableResolverFactory factory = unit.getFactory( null, null, null, handle, tuple, null, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver() );

final Object value = MVEL.executeExpression( this.expression, handle.getObject(), factory );
final Object value = evaluator.evaluate( handle.getObject(), factory );
return this.function.accumulateValue( (Serializable) context, value );
}

Expand Down
49 changes: 16 additions & 33 deletions drools-mvel/src/main/java/org/drools/mvel/expr/MVELConsequence.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,24 @@
import org.drools.core.spi.Consequence;
import org.drools.core.spi.KnowledgeHelper;
import org.drools.mvel.MVELDialectRuntimeData;
import org.mvel2.MVEL;
import org.mvel2.compiler.CompiledExpression;
import org.mvel2.debug.DebugTools;
import org.mvel2.integration.VariableResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.drools.mvel.expr.MvelEvaluator.createMvelEvaluator;

public class MVELConsequence
implements
Consequence,
MVELCompileable,
Externalizable {
private static final long serialVersionUID = 510l;
protected static transient Logger logger = LoggerFactory.getLogger(MVELConsequence.class);

private MVELCompilationUnit unit;
private String id;

private Serializable expr;

private String consequenceName;

private MvelEvaluator<Void> evaluator;

public MVELConsequence() {
}

Expand All @@ -75,44 +71,31 @@ public void writeExternal(ObjectOutput out) throws IOException {
}

public void compile( MVELDialectRuntimeData runtimeData) {
expr = unit.getCompiledExpression( runtimeData );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData ) );
}

public void compile( MVELDialectRuntimeData runtimeData, RuleImpl rule) {
expr = unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() ) );
}

public void evaluate(final KnowledgeHelper knowledgeHelper,
final WorkingMemory workingMemory) throws Exception {
VariableResolverFactory factory = unit.getFactory( knowledgeHelper, ((AgendaItem)knowledgeHelper.getMatch()).getTerminalNode().getRequiredDeclarations(),
knowledgeHelper.getRule(), knowledgeHelper.getTuple(), null, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver() );

VariableResolverFactory factory = unit.getFactory(knowledgeHelper, ((AgendaItem) knowledgeHelper.getMatch()).getTerminalNode().getRequiredDeclarations(),
knowledgeHelper.getRule(), knowledgeHelper.getTuple(), null, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver());

// do we have any functions for this namespace?
InternalKnowledgePackage pkg = workingMemory.getKnowledgeBase().getPackage( "MAIN" );
if ( pkg != null ) {
MVELDialectRuntimeData data = ( MVELDialectRuntimeData ) pkg.getDialectRuntimeRegistry().getDialectData( this.id );
factory.setNextFactory( data.getFunctionFactory() );
InternalKnowledgePackage pkg = workingMemory.getKnowledgeBase().getPackage("MAIN");
if (pkg != null) {
MVELDialectRuntimeData data = (MVELDialectRuntimeData) pkg.getDialectRuntimeRegistry().getDialectData(this.id);
factory.setNextFactory(data.getFunctionFactory());
}

CompiledExpression compexpr = (CompiledExpression) this.expr;

if ( MVELDebugHandler.isDebugMode() ) {
if ( MVELDebugHandler.verbose ) {
logger.info(DebugTools.decompile(compexpr));
}
MVEL.executeDebugger( compexpr,
knowledgeHelper,
factory );
} else {
MVEL.executeExpression( compexpr,
knowledgeHelper,
factory );
}
evaluator.evaluate(knowledgeHelper, factory);
}

public Serializable getCompExpr() {
return expr;
return evaluator != null ? evaluator.getExpr() : null;
}

public String getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;

Expand All @@ -32,9 +31,10 @@
import org.drools.core.spi.Enabled;
import org.drools.core.spi.Tuple;
import org.drools.mvel.MVELDialectRuntimeData;
import org.mvel2.MVEL;
import org.mvel2.integration.VariableResolverFactory;

import static org.drools.mvel.expr.MvelEvaluator.createMvelEvaluator;

public class MVELEnabledExpression
implements
Enabled,
Expand All @@ -46,7 +46,7 @@ public class MVELEnabledExpression
private MVELCompilationUnit unit;
private String id;

private Serializable expr;
private MvelEvaluator<Boolean> evaluator;

public MVELEnabledExpression() {
}
Expand All @@ -73,11 +73,11 @@ public MVELCompilationUnit getMVELCompilationUnit() {
}

public void compile( MVELDialectRuntimeData runtimeData) {
expr = unit.getCompiledExpression( runtimeData );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData ) );
}

public void compile( MVELDialectRuntimeData runtimeData, RuleImpl rule ) {
expr = unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() );
evaluator = createMvelEvaluator( unit.getCompiledExpression( runtimeData, rule.toRuleNameAndPathString() ) );
}

public boolean getValue(final Tuple tuple,
Expand All @@ -94,9 +94,7 @@ public boolean getValue(final Tuple tuple,
factory.setNextFactory( data.getFunctionFactory() );
}

return ((Boolean) MVEL.executeExpression( this.expr,
null,
factory )).booleanValue();
return evaluator.evaluate( factory );
}

public String toString() {
Expand Down
Loading

0 comments on commit 5926097

Please sign in to comment.