Way of fireAllrules in drools

1,340 views
Skip to first unread message

Nathalie Ravenel

unread,
Sep 26, 2014, 3:30:04 AM9/26/14
to drools...@googlegroups.com
Hi Everyone,
I upgraded an inference engine using drools. We have no problem at compiling but during execution we got some locked and the main program finally freezed. After debugging and profiling, the problem is the following : we used the function fireAllRules in a no correct way. Some rules modified some element so we implemented a function that modified the element and after the modification, in the function we added a fireAllRules. 
So in a process of fireAllRules, the command fireAllRules was called again. All this, create some locks.
In the previous inference engine, the fire of rules were done were the objets were modified in memory.
So, may be the good way is to implement an EventListener on objectupdated or other methods ?
Can you advice me ?
Thanks
Nathalie

Davide Sottara

unread,
Sep 26, 2014, 3:57:15 AM9/26/14
to drools...@googlegroups.com
Nathalie,
as per the previous discussion:
you should call fireAllRules after inserting/updating the WM from you JAVA code.
At this point, you should not need call fireAllRules again, even if some of your
consequences modify the objects.
If your rules do not then fire as expected, there may a problem with your logic,
or the function that does the modification.
We would need to see a full reproducer to understand what is going on exactly then
Best
Davide
--
You received this message because you are subscribed to the Google Groups "Drools Usage" group.
To unsubscribe from this group and stop receiving emails from it, send an email to drools-usage...@googlegroups.com.
To post to this group, send email to drools...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/drools-usage/8b632b73-3984-462f-b10f-6ed7e70c15c8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nathalie Ravenel

unread,
Sep 30, 2014, 10:24:38 AM9/30/14
to drools...@googlegroups.com
Hi Davide,
Following your advice, I create a RuleRuntimeEventListener to apply the fireAllRules when the Object is updated (and only at this stage). However, the main thread blocked again.
The Java mission control showed two calls to fireAllRules and I don't understand.
The objects can be modified in a rule (as a consequence) or updated in the Java code (after receiving TIPC message).
I don't understand how I can solve my problem.

Thanks

Nathalie Ravenel

unread,
Sep 30, 2014, 10:29:31 AM9/30/14
to drools...@googlegroups.com
The capture of the JMC


Le vendredi 26 septembre 2014 09:57:15 UTC+2, Davide Sottara a écrit :
droolsCore.JPG

Davide Sottara

unread,
Oct 1, 2014, 1:20:09 AM10/1/14
to drools...@googlegroups.com
Nathalie, I would suggest that you read the documentation at section 7.8.4 (right hand side)
The Drools "fireALLRules" method triggers the rule evaluation and chaining: if you insert, delete or modify a fact within the RHS of a rule, either direclty or with the mediation of a helper object,
the engine will automatically propagate the change and chain the rules. You MUST NOT call fireAllRules again in this case, or the engine will lock.
The only situation when you need an explicit call is when you insert or modify an object from outside the scope of a rule - usually from the main java code.
Davide

p.s. the rule listeners are supposed to be "read only" : calling back the engine from there will very likely put you in a deadlock

Nathalie Ravenel

unread,
Oct 2, 2014, 8:49:52 AM10/2/14
to drools...@googlegroups.com
Hello Davide,
Yes, but the rules are not fired if I supress the fireAllRules.  In my programs, if a rule modified an objet it is done through a java method not directly inside the rule.
After that, I update the facthandle and do a ksession.update(tmpFH, tmpO). This was done because the objects are modified in the rule but also by external events ...

Davide Sottara

unread,
Oct 2, 2014, 1:05:06 PM10/2/14
to drools...@googlegroups.com
You will have to differentiate the two scenarios. Ideally, you should have your helper just do the computation (invoking methods, setters, etc..), and return the updated object. If the caller is java, java will then invoke update+fireAllRules(). If the caller is a rule, it will just invoke update.
If this does not work in your case, I may have to look at your code to understand exactly what you are trying to do.
Davide

p.s. We are working on a more structured and typed way of creating "modification tasks" to submit to the engine, but that won't be immediately available. You might want to keep an eye on the blog or the drools-dev group for news over the next weeks.

Nathalie Ravenel

unread,
Oct 7, 2014, 4:01:23 AM10/7/14
to drools...@googlegroups.com
Hi Davide, I only saw your answer today. I did it. I modify the rule file introducing the drool function modify (see below) and for the tcp message incoming, I kept the java code with the session.update and fireAllRules. 
However I still have some blocking. May be I managed two many messages and did two many session.update and fireAllRules ?

rule "command for acquisition unit ready"

when 
$courant : Choc(nom == "courant")
and eval($courant.myCompare("courant_commande","force_acquisition"))
then 
$core.print("OPERATEUR ==> ready for acquidition\n");
;
modify($courant) { modifierAttributString("courant_commande","")}
end



Davide Sottara

unread,
Oct 7, 2014, 10:12:46 AM10/7/14
to drools...@googlegroups.com
Could you show the actual implementation of the modifierAttributeString function?, as well as the code where you call update/fire?
Are you also sure it's a block and not an infinite loop?
Davide

Nathalie Ravenel

unread,
Oct 23, 2014, 9:50:57 AM10/23/14
to drools...@googlegroups.com

public void modifier_element(String nom_slot, String valeur) {
                String tmp;
nom_slot = nom_slot.toLowerCase();
try {
// on parcourt la liste de noms
for (String nom : listeDesNoms) {
if (nom_slot.contains(nom)) {
                                        // be carefull element serveur_choc ... not dealed by this command
                                        // find the element and the string attribute
tmpO = listeElements.get(nom);
                                        tmp=tmpO.getString(nom_slot);
                                     
if ( tmp == null || !tmp.equals(valeur)){
                              
try{
tmpFH = listeFactHandle.get(tmpO.getNom());

}
catch(NullPointerException e){
System.err.println("erreur de recuperation dans le fact handle...");
}
                                                tmpO.modifierAttributString(nom_slot, valeur);
// update memory
                                                //this.session.update(listeFactHandle.get("myBool"), myBool );
this.session.update(tmpFH, tmpO);
                                        
}
break;
}
}
// 
} catch (NullPointerException e) {
//if(!nom_slot.contains("_phase") & !nom_slot.contains("_seuil") & !nom_slot.contains("_color") & !nom_slot.contains("_left") & !nom_slot.contains("_right") & !nom_slot.contains("_middle")) {
if(debug) System.out.println("Objet not in slots (str): " + nom_slot+ " valeur "+valeur);
                        //}
}
// RAZ de elements temporaires
tmpO = null;
tmpFH = null;

Davide Sottara

unread,
Oct 23, 2014, 11:09:10 AM10/23/14
to drools...@googlegroups.com
Nathalie, I see
In your method, at some point you call "this.session.update(tmpFH,tmpO)
If you invoke "modifier_element", there is no need to use "modify" in the RHS of a rule.
In your example rule, though, you had "modifierAttributString", which I'm not sure
how it relates to "modifier_element".
Baseline is, make sure you don't get nested or circular updates
Hope it helps
Davide

Nathalie Ravenel

unread,
Oct 24, 2014, 5:30:13 AM10/24/14
to drools...@googlegroups.com
Hi Davide, 
This method is not used in a rule. It is used by a callback to update some elements in the working memory. We have two ways of updating the working memory. In this method, before after update the session (this.session.update), I used fireAllRules that triggered the blocking problem. 
In a rule the syntax used , is the following : we used the function modify to update the values in the working memory

rule "command : prepare a pulse"
        no-loop true

when 
$courant : Choc(nom == "courant")
and eval($courant.myCompare("courant_commande","preparation_choc"))
and eval(!$courant.myCompare("courant_tirs",0))

then 
$core.print("OPERATEUR ==> command to prepare the pulse  rule 4\n");

                modify($courant) { modifierAttributNumeric("courant_etat",(double)0)}
$core.enleve_du_choc();
$core.liste_choc();
modify($courant) { modifierAttributString("courant_preparation_choc","true"),modifierAttributString("courant_fin_du_choc","false"),modifierAttributString("courant_commande"," ")}
end

Davide Sottara

unread,
Oct 24, 2014, 12:53:40 PM10/24/14
to drools...@googlegroups.com
Apologies, but I'm trying to understand exactly what is going on here.
The baseline is:

1) It is safe to call modifier_element BEFORE or AFTER fireAllRules.
That is:
session.fireAllRules();
... modifier_element(...) ...
session.fireAllRules();

2) is IS safe to call modify from a RHS, assuming that the "modify"
method just changes the value of the field. The engine will pick up the change
without the need to call "update", directly or indirectly. In fact "modify"
is internally rewritten as an update.

3) it is NOT safe to make callbacks to the session from within a listener
The problem is that, when the callback listener is executed, the working
memory will be locked. Any attempt to fire rules or insert new facts or update
a fact back to the working memory will hit the lock.

I assume that modifierString does not make any update internally, so that
should be fine.
I'd need to see where you call modifier_element AND fireAllRules, relatively
to each other, to be able to tell for sure.
Best
Davide

Nathalie Ravenel

unread,
Oct 27, 2014, 8:04:11 AM10/27/14
to drools...@googlegroups.com
Hi Davide, 
I call modifier_element from a java callback. These callback are triggered when receiving Tipc messages. Before, I put fireAllrules inside the modifier-element java code --> lock.
I suppressed the fireAllRules but my program didn't do anymore what it was supposed to. What is my problem ?

It is necessary to find a way to update the working memory from the java callback and also to call a modify from a RHS.
 I don't know anymore to achieve the requirements.

Davide Sottara

unread,
Oct 27, 2014, 9:45:55 AM10/27/14
to drools...@googlegroups.com
Nathalie, no problems with calling modify from the RHS, but using the callbacks to do further modifications is a dangerous practice. Can you give an example of why do you need a modification in a callback? What are you trying to achieve there? I'm sure there is another way to do what you are trying to do without using the callbacks, but "the program doesn't do what it is supposed to do" without an example OR the overall requirements is a bit difficult to understand :)
Thanks
Davide

Nathalie Ravenel

unread,
Oct 28, 2014, 4:34:58 AM10/28/14
to drools...@googlegroups.com
Hi Davide,

We used a TIPC message to collect the states of the different units involved in a fusion plasma. So each systems received some commands and send asynchronously their states. The callbacks are used to collect the information of the different systems (diagnostics; serveurs, process). So I need to update the internal objetcs (so the working memory) considering the states, what's why I used the callback in the java code. After updating the working memory, some rules may triggered and eventually modifying some others objects. For instance, if a diagnostic object is a specified state and if a process is in an other specified states, the value of the experiment can change.
So I have different sources for the update of the working memory (RHS and the callbacks from the java code).

Do you need some examples ?
Nathalie

Nathalie Ravenel

unread,
Nov 7, 2014, 3:55:31 AM11/7/14
to drools...@googlegroups.com
Hi, 
I am a little confused. because if I look at the different systems using drools. The process seems to be the same as mine. For instance, for bank systems, some informations are provided by external systems (HMI, program ) and the rules are executed affecting values to some variables. So my process seems to be classical. How can I implement to avoid lock. The variables modified by rules or other processes are not the same of course.
Thank you for your comments
Nathalie

Davide Sottara

unread,
Nov 7, 2014, 2:39:56 PM11/7/14
to drools...@googlegroups.com
Nathalie, we may need to see your code or - even better - if you could extract a small reproducer for the issue.
So far I have only seen bits and pieces, it is difficult to tell whether there is a problem in the way you invoke the engine
or there is indeed a synchronization problem somewhere inside Drools.
Do you think you could share the code, even in private?
Thanks
Davide

Reply all
Reply to author
Forward
0 new messages