##############################################################################
# JBoss, Home of Professional Open Source
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
# by the @authors tag. See the copyright.txt in the distribution for a
# full listing of individual contributors.
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this software; if not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
#
# @authors Andrew Dinn
#
# BA Subordinate Transaction Crash During Prepare
#
# This script automates testing of a specific recovery scenario for the
# JBossTS XTS implementation of the WS-AT 1.1 protocol using orchestration
# rules. The basic scenario employs a coordinator, a subordinate coordinator
# and 2 web services running in a single JVM, the second one employing local
# (subordinate) coordination. It checks that the transaction rolls back
# all prepared participants afetr crashing in the middle of prepare.
# The crash happens after the subordinate transaction has been prepared and
# logged to disk but before its proxy participant is able to write a log record.
# The scenario is as follows
# (** indicates intercession by a Byteman rule):
#
# AS boots
# Cient starts a WS-AT transaction T1
# Client invokes web service S1 with enlist durable request
# S1 registers Participant P1 in T1
# Client invokes subordinate web service S2 with enlist durable request
# S2 creates a subordinate BA transaction T2
# S2 registers pseudo-participant PP in T1
# S2 registers Participant P2 in T2
# Client invokes subordinate web service S2 with enlist durable request
# S2 resumes T2
# S2 registers Participant P3 in T2
#
# Client initiates transaction close for T1
#
# Coordinator initiates prepare of participant P1
# ** Rule system logs dispatch of prepare to P1
# ** Rule system logs receipt of prepared from P1
#
# Coordinator initiates prepare of subordinate participant PP
# ** Rule system logs dispatch of prepare to PP
# PP calls subordinate coordinator prepare
# ** Rule system logs call to prepare
#
# Subordinate coordinator initiates prepare of participant P2
# ** Rule system logs dispatch of prepare to P1
# ** Rule system logs receipt of prepared from P1
# Subordinate coordinator initiates prepare of participant P3
# ** Rule system logs dispatch of prepare to P1
# ** Rule system logs receipt of prepared from P1
# Subordinate coordinator writes T2 to log
# Subordinate coordinator complete returns
# ** Rule system intercepts return and crashes JVM
#
# AS reboots
# Recovery system starts after 2 minutes
# Recovery system recreates transaction T2
# ** Rule system traces create
# ** Rule system traces create
# Recovery system recreates participant engine for P1
# ** Rule system traces create
# Recovery system recreates participant engine for P2
# ** Rule system traces create
# Recovery system recreates participant engine for P3
# ** Rule system traces create
# Recovery system recreates coordinator engine for P2
# ** Rule system traces create
# Recovery system recreates coordinator engine for P3
# ** Rule system traces create
#
# (parallel optional)
# prepared sent for P2/P3 and ignored during recovery
# ** Rule system traces dispatch of prepared
# (parallel)
# Recovery system detects missing proxy P2 for transaction T2
# Recovery system calls rollback for subordinate coordinator
# ** Rule system traces call to rollback
#
# Coordinator sends rollback to P2
# ** Rule system traces dispatch of rollback
# P2 replies with aborted
# ** Rule system traces dispatch of aborted
# ** Rule system detects removal of P2
#
# Coordinator sends rollback to P3
# ** Rule system traces dispatch of rollback
# P3 replies with aborted
# ** Rule system traces dispatch of aborted
# ** Rule system detects removal of P3
# Subordinate coordinator rol;back call returns
# ** Rule system traces return from rollback
#
# Recovery system removes transaction T2
# ** Rule system traces removal of transaction
# (parallel)
# completed sent for P1
# ** Rule system traces dispatch of completed
# rollback sent to P1
# ** Rule system traces dispatch of rollback
# ** Rule system detects removal of P1
# (end parallel)
#
# ** Rule system detects 3 participant deletes and 1 tx delete and kills JVM
#
# Use of this script
#
# The default way of exercising this test is to deploy the xtstest war
# to a single AS and configure it to run the relevant XTS Service Test.
# The web services and coordinator will be located with the client.
# The number of participants and subordinate participants must be
# exactly 3. The  web service(s), client (i.e. the XTS Service Test which
# drives the test) and coordinator and subordinate coordinator service must
# be colocated for this script to work (it is possible to distribute all of
# these agents if desired but that woud lrequire more complex script rules).
# The AS should crash when the client closes. At reboot the rest of the test
# should run automatically and the server should be killed after the recovered
# transaction is successfuly replayed.
#
# This script needs to be passed to a Byteman agent in the JVM running
# the coordinator service both at first boot and at reboot. Output will be
# written to file testlog in the working directory of the AS.
#
# XTS Service tests which can operate with this scenario can be selected for
# execution at AS boot by the XTSServiceTestRunnerBean by setting system
# property
#    org.jboss.jbossts.xts.servicetests.XTSServiceTestName
# to the name of a class which will execute the test. This property must
# be defined in the JVM running the AS to which the xtstest war is deployed
# i.e. the client AS. n.b. if the client is colocated with the coordinator then
# this property must be left undefined at AS reboot otherwise the client
# will run again, starting a new TX which may interfere with recovery of the
# crashed TX. It is also possible to run the service test using the form
# interface provided on the xtstest war's main index page.
#
# Available tests include:
#
# org.jboss.jbossts.xts.servicetests.test.at.subordinate.MultiParticipantPrepareAndCommitTest
# this test starts an activity then registers a durable participant with the service whose location is defined by
# system property:
#    org.jboss.jbossts.xts.servicetests.ServiceURL1
# if this is not set the value used defaults to
#    http://localhost:8080/xtstest/xtsservicetest1
# the test then registers two durable participants with a second web service (which must install a
# subordinate transaction) whose location is defined system property:
#    org.jboss.jbossts.xts.servicetests.serviceURL1
# if this is not set the value used defaults to
#    http://localhost:8080/xtstest/xtssubservicetest1
# The test then closes the transaction
#
# Expected output
#
# After the first boot the JVM should exit leaving the following in file testlog
# (the number and order of entries depends upon how many and which type of participants
# are enlisted)
#
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepared sent for participant XXXXXX
#   prepared received for participant XXXXXX
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepare called for pseudo participant XXXXXX
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepared sent for participant XXXXXX
#   prepared received for participant XXXXXX
#   prepare returned for subordinate transaction XXXXXX
#   saved to disk transaction XXXXXX
#   prepare returned for pseudo participant XXXXXX
#   JVM exit
#
# n.b. there should be at least one prepare/prepared sent/received message received for each participant
#      there should be at least one prepare called/prepare returned message for the pseudo participant
#
# and in some cases there may be repeat messages
#
# After reboot the JVM should exit leaving output in the following format in file
# testlog.
#
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepared sent for participant XXXXXX
#   prepared received for participant XXXXXX
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepare called for pseudo participant XXXXXX
#   prepare sent for participant XXXXXX
#   prepare received for participant XXXXXX
#   prepared sent for participant XXXXXX
#   prepared received for participant XXXXXX
#   prepare returned for subordinate transaction XXXXXX
#   saved to disk transaction XXXXXX
#   prepare returned for pseudo participant XXXXXX
#   JVM exit
#   created recovered participant engine XXXXXX
#   created recovered participant engine XXXXXX
#   created recovered participant engine XXXXXX
#   created recovered coordinator engine XXXXXX
#   created recovered coordinator engine XXXXXX
#   reinstated prepared subordinate transaction XXXXXX
#
#   (parallel -- optional and may be repeated depending upon timing)
#   completed sent for participant P2/P3
#   completed received for participant P2/P3
#   (parallel)
#   completed sent for participant P1
#   completed received for participant P1
#   rollback sent for participant P1
#   rollback received for participant P1
#   (parallel)
#   rollback called for pseudo participant XXXXXX
#   rollback called for subordinate transaction XXX
#   rollback sent for Participant XXXXXX
#   rollback received for Participant XXXXXX
#   aborted sent for Participant XXXXXX
#   aborted received for Participant XXXXXX
#   rollback sent for Participant XXXXXX
#   rollback received for Participant XXXXXX
#   aborted sent for Participant XXXXXX
#   aborted received for Participant XXXXXX
#   rollback returned for subordinate transaction XXX
#   rollback completed for pseudo participant XXXXXX
#   removed transaction XXXXXX
#   (end parallel)
#
#   JVM exit
#
#######################################################################
# This rule opens a file for the trace output during XTS startup
# It will be opened for append at reboot so messages from both runs
# will go to this file
#
RULE open trace file
CLASS org.jboss.jbossts.XTSService
METHOD start()
BIND NOTHING
IF TRUE
DO openTrace("log", "testlog")
ENDRULE

#######################################################################
# This rule creates a counter used to track the number of participant
# records which have been deleted
RULE create participant deletes counter
CLASS org.jboss.jbossts.XTSService
METHOD start()
BIND NOTHING
IF TRUE
DO createCounter("participant deletes")
ENDRULE

#######################################################################
# This rule resets the periodic recovery wait period to 10 seconds
# in order to speed up the test
#
RULE reset periodic recovery wait time
CLASS com.arjuna.ats.arjuna.common.RecoveryEnvironmentBean
METHOD getPeriodicRecoveryPeriod()
AT ENTRY
IF TRUE
DO return 10
ENDRULE

#######################################################################
## rules for first run of AS

#######################################################################
# This rule is triggered when a Coordinator engine
# (CoordinatorEngine) is requested to send a prepare message. It
# traces the call.

RULE trace send participant prepare
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD prepare
AFTER SYNCHRONIZE
BIND engine:CoordinatorEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("prepare sent for Coordinator engine " + identifier),
   traceln("log", "prepare sent for Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Coordinator engine
# (CoordinatorEngine) receives a prepared message. It traces the call.

RULE trace receive participant prepared
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD prepared(Notification, MAP, ArjunaContext)
AT ENTRY
BIND engine:CoordinatorEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("prepared received for Coordinator engine " + identifier),
   traceln("log", "prepared received for Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a participant
# (ParticipantEngine) receives a prepare message. It
# traces the call.

RULE trace receive participant prepare
CLASS com.arjuna.wst11.messaging.engines.ParticipantEngine
METHOD prepare
AFTER SYNCHRONIZE
BIND engine:ParticipantEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("prepare received for participant " + identifier),
   traceln("log", "prepare received for participant " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Participant
# (ParticipantEngine) is requested to send a prepared message. It
# traces the call.

RULE trace send Participant prepared
CLASS com.arjuna.wst11.messaging.engines.ParticipantEngine
METHOD sendPrepared(boolean)
AT INVOKE sendPrepared
BIND engine:ParticipantEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("prepared sent for Participant " + identifier),
   traceln("log", "prepared sent for Participant " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Coordinator engine
# (CoordinatorEngine) is requested to send a rollback message. It
# traces the call.

RULE trace send Participant rollback
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD rollback
AFTER SYNCHRONIZE
BIND engine:CoordinatorEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("rollback sent for Coordinator engine " + identifier),
   traceln("log", "rollback sent for Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Coordinator engine
# (CoordinatorEngine) receives an aborted message. It traces the call.

RULE trace receive Participant aborted
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD aborted(Notification, MAP, ArjunaContext)
AT ENTRY
BIND engine:CoordinatorEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("aborted received for Coordinator engine " + identifier),
   traceln("log", "aborted received for Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Participant
# (ParticipantEngine) receives a rollback message. It
# traces the call.

RULE trace receive Participant rollback
CLASS com.arjuna.wst11.messaging.engines.ParticipantEngine
METHOD rollback
AFTER SYNCHRONIZE
BIND engine:ParticipantEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("rollback received for Participant " + identifier),
   traceln("log", "rollback received for Participant " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Participant
# (ParticipantEngine) is requested to send an aborted message. It
# traces the call.

RULE trace send Participant aborted
CLASS com.arjuna.wst11.messaging.engines.ParticipantEngine
METHOD sendAborted(boolean)
AT INVOKE sendAborted
BIND engine:ParticipantEngine = $0,
     identifier:String = engine.getId()
IF TRUE
DO debug("aborted sent for Participant " + identifier),
   traceln("log", "aborted sent for Participant " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) is requested to send a prepared message. It
# traces the call.

RULE trace subordinate participant stub prepare
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD prepare
AT ENTRY
BIND NOTHING
IF TRUE
DO debug("prepare called for pseudo-participant " + $0),
   traceln("log", "prepare called for pseudo-participant " + $0)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) has forwarded a prepare message. It
# kills the JVM.

RULE trace subordinate participant stub prepare 2
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD prepare
AFTER INVOKE prepare
BIND NOTHING
IF TRUE
DO traceln("log", "JVM exit"),
   debug("JVM exit"),
   killJVM()
ENDRULE

#######################################################################
## rules for reboot run of AS

#######################################################################
# This rule is triggered when a Coordinator engine (CoordinatorEngine)
# is created from details located in the log record. It traces the
# create operation. The trigger location is at entry but the rule
# should only be triggered after calling the super constructor

RULE trace Coordinator engine create
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD <init>(String, boolean, W3CEndpointReference, boolean, State)
AT ENTRY
BIND identifier = $1,
     recovered=$4
IF recovered
DO debug("created recovered Coordinator engine " + identifier),
   traceln("log", "created recovered Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Participant (ParticipantEngine)
# is created from details located in the log record. It traces the
# create operation. The trigger location is at entry but the rule
# should only be triggered after calling the super constructor

RULE trace Participant create
CLASS com.arjuna.wst11.messaging.engines.ParticipantEngine
METHOD <init>(Participant, String, State, W3CEndpointReference, boolean)
AT ENTRY
BIND identifier = $2,
     recovered=$5
IF recovered
DO debug("created recovered Participant engine " + identifier),
   traceln("log", "created recovered Participant engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a Coordinator processor
# (CoordinatorProcessorImpl) sends a rollback.
# This happens during replay of a prepared TX from
# the log. It traces the call.

RULE trace Participant send rollback
CLASS com.arjuna.wst11.messaging.CoordinatorProcessorImpl
METHOD prepared(Notification, MAP, ArjunaContext)
AT CALL sendRollback
BIND identifier:String = $3.getInstanceIdentifier().getInstanceIdentifier()
IF TRUE
DO debug("sent rollback for unknown Coordinator engine " + identifier),
   traceln("log", "sent rollback for unknown Coordinator engine " + identifier)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) is requested to forward a rollback message. It
# traces the call.

RULE trace subordinate participant stub rollback
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD rollback
AT ENTRY
BIND NOTHING
IF TRUE
DO debug("rollback called for pseudo-participant " + $0),
   traceln("log", "rollback called for pseudo-participant " + $0)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) forwards a rollback message to its subordinate
# coordinator during recovery. It traces the call.

RULE trace subordinate participant stub rollback forward
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD rollback
AT INVOKE rollback 2
BIND NOTHING
IF TRUE
DO debug("forwarding rollback or pseudo-participant " + $0 + " as rollback to subordinate coordinator"),
   traceln("log", "forwarding rollback for pseudo-participant " + $0 + " as rollback to subordinate coordinator")
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) throws an error from its rollback method
# because the subordinate coordinator has not yet been recovered. It
# traces the throw.

RULE trace subordinate participant stub rollback with no coordinator
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD rollback
AT THROW
BIND NOTHING
IF TRUE
DO debug("throw during rollback for pseudo-participant " + $0 + " with no subordinate coordinator"),
   traceln("log", "throw during rollback for pseudo-participant " + $0 + " with no subordinate coordinator")
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) throws an error from its rollback method
# because the subordinate coordinator has not yet been activated. It
# traces the throw.


RULE trace subordinate participant stub rollback with unactivated coordinator
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD rollback
AT THROW 2
BIND NOTHING
IF TRUE
DO debug("throw during rollback for pseudo-participant " + $0 + " with unactivated subordinate coordinator"),
   traceln("log", "throw during rollback for pseudo-participant " + $0 + " with unactivated subordinate coordinator")
ENDRULE

#######################################################################
# This rule is triggered when a subordinate pseudo participant
# (SubordinateDurable2PCStub) returns from frowarding a rollback message. It
# traces the call.

RULE trace subordinate participant stub rollback return
CLASS com.arjuna.wst11.stub.SubordinateDurable2PCStub
METHOD rollback
AT EXIT
BIND NOTHING
IF TRUE
DO debug("rollback completed for pseudo-participant " + $0),
   traceln("log", "rollback completed for pseudo-participant " + $0)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate coordinator
# (SubordinateATCoordinator) calls prepare during completion. It
# traces the call.

RULE trace subordinate coordinator prepare
CLASS com.arjuna.mwlabs.wscf.model.twophase.arjunacore.subordinate.SubordinateATCoordinator
METHOD prepare
AT INVOKE prepare
BIND uid = $0.get_uid()
IF TRUE
DO debug("prepare for subordinate transaction " + uid),
   traceln("log", "prepare for subordinate transaction " + uid)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate coordinator
# (SubordinateCoordinator) is requested to perform a rollback. It
# traces the call.

RULE trace subordinate coordinator close
CLASS com.arjuna.mwlabs.wscf.model.twophase.arjunacore.subordinate.SubordinateATCoordinator
METHOD rollback
AT ENTRY
BIND NOTHING
IF TRUE
DO debug("rollback called for subordinate coordinator " + $0),
   traceln("log", "rollback called for subordinate coordinator " + $0)
ENDRULE

#######################################################################
# This rule is triggered when a subordinate coordinator
# (SubordinateCoordinator) is requested to perform a close. It
# traces the call.

RULE trace subordinate coordinator rollback 2
CLASS com.arjuna.mwlabs.wscf.model.twophase.arjunacore.subordinate.SubordinateATCoordinator
METHOD rollback
AT EXIT
BIND NOTHING
IF TRUE
DO debug("rollback returned for subordinate coordinator " + $0),
   traceln("log", "rollback returned for subordinate coordinator " + $0)
ENDRULE

#######################################################################
# This rule is triggered when the recovery system finds a PREPARED
# parent activity in the log and reruns the phase 2 commit operation.
# It prints a message which can be used to verify that the test has
# progressed as expected and creates a countdown used to detect exit of
# both transactions

RULE trace prepared replay
CLASS org.jboss.jbossts.xts.recovery.coordinator.at.RecoveryATCoordinator
METHOD replayPhase2
AT INVOKE phase2Commit
BIND coordinator = $0,
     uid : Uid = coordinator.identifier(),
     status : int = coordinator.status()
IF (status == com.arjuna.ats.arjuna.coordinator.ActionStatus.PREPARED)
     OR
     (status == com.arjuna.ats.arjuna.coordinator.ActionStatus.COMMITTING)
DO debug("replaying commit for prepared transaction " + uid),
   traceln("log", "replaying commit for prepared transaction " + uid),
   createCountDown("exit countdown", 1)
ENDRULE

#######################################################################
# This rule is triggered when the recovery system finds a PREPARED
# subordinate activity in the log. It prints a message which can be
# used to verify that the test has progressed as expected

RULE trace subordinate prepared replay
CLASS org.jboss.jbossts.xts.recovery.coordinator.at.RecoverySubordinateATCoordinator
METHOD replayPhase2
AT ENTRY
BIND coordinator = $0,
     uid : Uid = coordinator.identifier(),
     status : int = coordinator.status()
IF (status == com.arjuna.ats.arjuna.coordinator.ActionStatus.PREPARED)
     OR
     (status == com.arjuna.ats.arjuna.coordinator.ActionStatus.COMMITTING)
DO debug("reinstated prepared subordinate transaction " + uid),
   traceln("log", "reinstated prepared subordinate transaction " + uid)
ENDRULE

#######################################################################
# This rule is triggered when a TX is saved to disk during prepare.

RULE trace TX save at prepare
CLASS com.arjuna.ats.arjuna.coordinator.BasicAction
METHOD prepare(boolean)
AFTER CALL save_state
BIND action : BasicAction = $0,
     uid  = action.get_uid()
IF TRUE
DO traceln("log", "saved to disk transaction " + uid),
   debug("saved to disk transaction " + uid)
ENDRULE

#######################################################################
# This rule is called when removing a transaction from the log. It
# ensures that the JVM exits but only after we have seen all the
# necessary aborted messages

RULE trace remove committed state and exit JVM
CLASS com.arjuna.ats.arjuna.coordinator.BasicAction
METHOD updateState
AFTER CALL remove_committed
BIND action : BasicAction = $0,
     uid  = action.get_uid(),
     dummy = flag("tx removed")
IF readCounter("participant deletes") == 3
DO traceln("log", "JVM exit"),
   debug("JVM exit"),
   killJVM()
ENDRULE

#######################################################################
# This rule is called when deleting a participant record from the log.
# It ensures that the JVM exits but only after we have seen 3 deletes
# and also seen the tx removed

RULE trace delete participant and exit JVM
CLASS org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManagerImple
METHOD deleteParticipantRecoveryRecord
AFTER CALL remove_committed
BIND dummy = flag("tx removed")
IF incrementCounter("participant deletes") == 3 &&
   flagged("tx removed")
DO traceln("log", "JVM exit"),
   debug("JVM exit"),
   killJVM()
ENDRULE

#######################################################################
# This rule is triggered when the recovery system deletes an
# activity from the log. It prints a message which can be used to
# verify that the test has completed.

RULE trace remove committed state
CLASS com.arjuna.ats.arjuna.coordinator.BasicAction
METHOD updateState
AFTER CALL remove_committed
BIND action : BasicAction = $0,
     uid  = action.get_uid()
IF TRUE
DO traceln("log", "removed transaction " + uid),
   debug("removed transaction " + uid)
ENDRULE
