Closed JeremyBryans closed 10 years ago
Adding the file here:
-- add chan to output state of MessageStore?
-- add chan to output "I am leader"
types
NODE = nat1
ALLNODES = set of nat1
CLAIM = <leader>|<follower>|<undecided>|<off>
DATA = token
CS :: c : CLAIM
s : STRENGTH
-- The only messages transmitted are CS messages, so MSG can be specialised to them
MSG :: src : NODE
dest : NODE
cs : [CS]
STRENGTH = nat
values
allNodes : set of nat1 = {1,...,3}
ulp : nat = 10
n_timeout : nat = 4 -- the timeout value employed by the Nodes
channels
inn : MSG
out : MSG
n_req : NODE
test : set of MSG
process MessageStore =
begin
state
store : set of MSG := {}
functions
selectMSG(sm : set of MSG) r:MSG
pre sm <> {}
post r in set sm
operations
add:(MSG) ==> ()
add(m) ==
store := store union {m}
-- fetchFor fetchs all messages in the store that are for the node n
fetchFor:(NODE) ==> MSG
fetchFor(n) ==
(
dcl m : MSG @
(
dcl s : set of MSG @ s := {msg|msg in set store @ msg.dest = n};
(
if s <> {}
then (m := selectMSG(s); store := store \ {m})
else m := mk_MSG(n,n,nil)
); return m
)
)
-- don't think this will work: too difficult to select a single element from a set
fetchOne:(NODE) ==> MSG
fetchOne(n) ==
let msgs = {msg|msg in set store @msg.dest=n} in
(if msgs <> {} then
let m = select(msgs) in
( store := store\{m};
return m
)
else
return mk_MSG(n,n,nil)
)
-- helper function; selects an "arbitrary" element from a non-empty set
select(sn : set of MSG) r: MSG
pre sn <> {}
post r in set sn
actions
In = inn?m -> add(m); Skip
Listen = [] i in set allNodes @ n_req.i -> (dcl m : MSG @ m := fetchOne(i);out!m->Skip)
Test = test!store -> Skip
Loop = (In [] Listen [] Test);Loop
@
Loop
end
channels
on, off : nat1
init : nat1
-- test channels
leading : nat1
following : nat1
process Node = i : nat1 @
begin
state
-- mem is volatile memory
mem: map NODE to [CS] := { cid |-> nil | cid in set allNodes \ {i} } -- the map of node ids to their CSs, using mk_CS(<off>, 0) instead of nil
inv dom mem = allNodes \ {i} and -- the domain of mem must not include id (the ID of the node)
dom mem <> {} -- must be more than one node in the network (although this model
-- should work if there is only one node)
-- below are summary variables
highest_strength : [STRENGTH] := nil -- the highest strength of leadership claim node is aware of
highest_strength_id : [NODE] := nil -- id of node making the leadership claim with the highest strength
-- this is allowed to be any node id, including id itself
inv highest_strength_id <> nil => highest_strength_id in set (dom mem union {i})
leaders : nat := 0 -- the leader count among my neighbours; nat, so can't be -1 in CML
inv leaders <= card dom mem
myCS : CS := mk_CS(<off>, 0) -- my claim/strength pair
myNeighbours : seq of NODE := [j| j in set dom mem @ j <>i]
isleader : bool := false
operations
Init: () ==> ()
Init() ==
(
flushState() -- flush volatile and summary memory
)
flushState: () ==> ()
flushState() ==
(
flushMemory();
flushSummary()
)
flushMemory: () ==> ()
flushMemory() ==
(
mem := { cid |-> nil | cid in set allNodes \ {i} } -- reset
)
flushSummary: () ==> ()
flushSummary() ==
(
highest_strength := 0;
highest_strength_id := nil;
leaders := 0; -- can't be -1 if nat :: could be nil
myCS := mk_CS(<off>, 0);
isleader := false
)
-- used by controller to write a CS to a memory cell
write: MSG ==> ()
write(m) ==
(
mem(m.src) := m.cs
)
pre m.src in set dom mem
post mem(m.src) = m.cs
update:()==>()
update() ==
(
leaders := card{n|n in set dom mem @ mem(n)<>nil => mem(n).c = <leader>};
highest_strength := maxStrength();
highest_strength_id := maxStrengthID();
isleader := amILeader()
)
post isleader or
(leaders > 0 and /* highest_strength_id <> nil => */ mem(highest_strength_id).s = highest_strength)
-- maxStrengh returns the maximum strength of leadership claim
maxStrength:() ==> [nat]
maxStrength() ==
(
let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
(
let strs = {mem(l).s|l in set leaderNodes} in
if strs <> {}
then return maxSet(strs)
else return nil
)
)
/*
maxStrength:() ==> [nat]
maxStrength() ==
(
dcl leaderNodes : set of nat1 @ leaderNodes := {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>};
(
dcl strs : set of nat @ strs := {mem(l).s|l in set leaderNodes};
if strs <> {} then return maxSet(strs) -- maxSet(strs)
else return nil
)
)
*/
-- return the ID of the leader with the max strength
-- or nil if no leader claims
maxStrengthID : () ==> [NODE]
maxStrengthID() ==
(
let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
(
dcl maxStrIds : set of NODE @
(
if leaderNodes = {}
then return nil
else maxStrIds := {n | n in set leaderNodes @ mem(n).s = highest_strength};
return select(maxStrIds)
)
)
)
/*
maxStrengthID : () ==> [NODE]
maxStrengthID() ==
(
dcl leaderNodes : set of nat1 @ leaderNodes := {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>};
(
dcl maxStrIds : set of NODE @
(
if leaderNodes = {}
then return nil
else maxStrIds := {n | n in set leaderNodes @ mem(n).s = highest_strength};
return select(maxStrIds)
)
)
)
*/
-- update my claim
-- note that we can enforce state transitions through the changeClaim operation
-- since Claim corresponds directly to the states in the ST diagram
changeClaim: CLAIM ==> ()
changeClaim(newc) ==
(
dcl currStr : STRENGTH := myCS.s @
myCS := mk_CS(newc, currStr)
)
pre myCS.c = <off> => newc = <undecided> and
myCS.c = <undecided> => newc = <leader> or newc = <follower> and
myCS.c = <leader> => newc = <undecided> and
myCS.c = <follower> => newc = <undecided>
-- increase the strength of my claim up to the maximum (upper limit of petitions: ulp)
incStrength:()==>()
incStrength() ==
(
if myCS.s < ulp
then myCS := mk_CS(myCS.c, myCS.s+1)
)
pre myCS.s < ulp
post myCS.s = myCS~.s + 1
amILeader: () ==> bool
amILeader() ==
(
return (leaders = 0) or
(highest_strength = nil) or
(highest_strength <> nil and highest_strength < myCS.s) or
(highest_strength <> nil and highest_strength = myCS.s and highest_strength_id < i)
)
maxSet: set of nat ==> nat
maxSet(sn) ==
(dcl s: set of nat @ s:= sn;
(dcl c:nat @ c := select(s);
s := s \ {c};
while (s <> {}) do
(dcl n:nat @ n := select(s);
if (n>c) then c:=n else c:=c;
s := s\{n}
);
return c
)
)
pre sn <> {}
-- post c in set sn and forall s in set sn @ c >=s
functions
-- implicit helper function; selects an element of a non-empty set
select(sn : set of nat) r: nat
pre sn <> {}
post r in set sn
actions
Listener = ReceiveData;update(); Skip
-- Asks for data via n_rec, then receives it, then repeats
ReceiveData =
n_req!i ->
out?msg ->
(
[msg.cs = nil] & Skip
[]
[msg.cs <> nil] & write(msg);ReceiveData
)
-- [_ n_timeout _> Skip
SendCS = (||| t in set dom mem @ [{}] inn!mk_MSG(i,t,myCS) -> Skip) -- insists on sending all messages before it progresses.
Off = on!i -> (Undecided /_\ off!i -> flushState();Off)
Undecided = changeClaim(<undecided>);Listener;
(
[isleader] & Leader
[]
[not isleader] & Follower
)
Leader = changeClaim(<leader>);SendCS; leading.i -> Listener;
(
[not isleader] & Undecided
[]
[isleader] & incStrength();Leader
)
Follower = changeClaim(<follower>);flushMemory(); following.i -> SendCS; Listener; -- flushing primary memory; self-declare as a follower
(
[leaders <> 1] & Undecided
[]
[leaders = 1] & Follower
)
@ init.i -> Init();Off
end
process AllNodes = ||| i in set allNodes @ (Node(i))
process Election = AllNodes [|{|inn,out,n_req|}|] MessageStore
The problem is the deepCopy
-clone that's made for one of the parallel constructs. The stack runs down ProcessObjectValues
and eventually hits a base Context
which includes a non-serilizable field ThreadState
A fix for this in Overture is in overturetool/overture@5d6025b4badf4e51dcbb12e766b3cba0e121e23f
Hi Kennet,
Thank you. The link you posted 404'd; could you resend?
J
That's a commit link — we'll have a build of it later today most likely
There is a new development build that should incorporate the fix for this.
Reopening: Jeremy found another case where it happens. Use trace: <tock, tock>
.
The code is a bit long; exception trace follows.
-- add chan to output state of MessageStore?
-- add chan to output "I am leader"
-- uses of dcl are replaced by let...in where possible.
-- otherwise, temporary variable are used
values
debugS = false --debug Store
debugMem = false -- true
debugCS = false -- true
debugR = false -- true --debug Rest
allNodes : set of nat = {1,...,3}
uls : nat = 10
n_timeout : nat = 1 -- the timeout value employed by the Nodes
types
NODE = nat
inv n == n in set allNodes
CLAIM = <leader>|<follower>|<undecided>|<off>|<TEST>
STRENGTH = nat
CS :: c : CLAIM
s : STRENGTH
-- The only messages transmitted are CS messages, so MSG can be specialised to them
MSG :: src : NODE
dest : NODE
cs : CS
channels
inn : NODE * NODE * MSG -- SRC * DEST * MSG
out : NODE * NODE * MSG -- DEST * SRC * MSG
debugStore : map NODE to seq of MSG
debugKey : NODE
debugTail, debugStoreI : seq of MSG
process MessageStore =
begin
state
store : map NODE to seq of MSG := {i|->[]|i in set allNodes}
operations
RmvHdFrmStore:NODE ==> ()
RmvHdFrmStore(i) ==
store := store ++ {i |-> tl(store(i))}
pre store(i) <> []
-- temp back in functions
/* -- implicit helper function; selects an element of a non-empty set
select(sn : set of nat) r: nat
pre sn <> {}
post r in set sn
*/
actions
DebugState = i : nat @
if debugS then
debugStore!store ->
debugStoreI!(store(i)) ->
debugKey!i ->
debugTail!(tl(store(i))) -> Skip
else
Skip
Loop =
inn?src?des?m -> store(m.dest) := store(m.dest)^[m]; Skip
[]
([] i in set allNodes @
[store(i) <> []] & -- there are messages for node i
let m = hd(store(i)) in
out!(m.dest)!(m.src)!m ->
RmvHdFrmStore(i);
Skip)
@ while true do Loop
end
channels
on, off,init : nat1
-- test channels
leading : nat1
following : nat1
undecided : nat1
DebugLeaders : NODE * nat * nat
DebugHighestStrength : NODE * nat * [STRENGTH]
DebugHighestStrengthID : NODE * nat * [NODE]
DebugIsLeader : NODE * nat *bool
DebugMem : NODE * nat * map NODE to [CS]
DebugClaim : NODE * nat * CS
DebugClaimBeforeL : NODE * CS
DebugClaimAfterL : NODE * CS
DebugStrength : NODE * STRENGTH
process Node = i : nat1 @
begin
state
mem: map NODE to [CS] := { cid |-> nil | cid in set allNodes \ {i} }
inv dom mem = allNodes \ {i} and -- the domain of mem must not include id (the ID of the node)
dom mem <> {} -- must be more than one node in the network (although this model
-- should work if there is only one node)
-- below are summary variables
highest_strength : [STRENGTH] := nil -- the highest strength of leadership claim node is aware of
highest_strength_id : [NODE] := nil -- id of node making the leadership claim with the highest strength
-- this is allowed to be any node id, including id itself
inv highest_strength_id <> nil => highest_strength_id in set (dom mem union {i})
leaders : nat := 0 -- the leader count among my neighbours
inv leaders <= card dom mem
myCS : CS := mk_CS(<off>, 0) -- my claim/strength pair
isleader : bool := false
-- temp variables s,c created here while maxSet cannot use dcl to create them.
s : set of nat
c : nat
operations
flushState: () ==> ()
flushState() ==
(
flushMemory();flushSummary()
)
flushMemory: () ==> ()
flushMemory() ==
(
mem := { cid |-> nil | cid in set allNodes \ {i} }
)
flushSummary: () ==> ()
flushSummary() ==
(
highest_strength := nil; --0;
highest_strength_id := nil;
leaders := 0;
myCS := mk_CS(<off>, 0);
isleader := false
)
write: NODE * MSG ==> ()
write(j,m) ==
(
mem := mem ++ {j |-> m.cs}
)
pre j in set dom mem
post mem(j) = m.cs
update:()==>()
update() ==
( --the leaders count should not increase if mem(c)=nil
leaders := card{n|n in set dom mem @ mem(n)<>nil and mem(n).c = <leader>};
highest_strength := maxStrength();
highest_strength_id := maxStrengthID()
)
-- post isleader or
-- (leaders > 0 and mem(highest_strength_id).s = highest_strength)
-- maxStrengh returns the maximum strength of leadership claim
maxStrength:() ==> [nat]
maxStrength() ==
(
let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
(
if leaderNodes <> {} then
let strs = {mem(l).s|l in set leaderNodes} in
if strs <> {}
then return maxSet(strs)
else return nil
else return nil
)
)
-- return the ID of the leader with the max strength
-- or nil if no leader claims
maxStrengthID : () ==> [NODE]
maxStrengthID() ==
(
let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
(
if leaderNodes = {}
then return nil
else
let maxStrIds = {n | n in set leaderNodes @ mem(n).s = highest_strength} in
-- return select(maxStrIds) -- select is wrong here; has to pixk the maximum one!!
return maxSet(maxStrIds)
)
)
-- update my claim
-- note that we can enforce state transitions through the changeClaim operation
-- since Claim corresponds directly to the states in the ST diagram
changeClaim: CLAIM ==> ()
changeClaim(newc) ==
(
-- if myCS.c = newc then
-- myCS := mk_CS(newc, myCS.s)
-- else --reset strength -- could differentiate between leader and follower
-- myCS := mk_CS(newc,0)
myCS.c := newc
)
/* pre myCS.c = <off> => newc = <undecided> and
myCS.c = <undecided> => newc = <leader> or newc = <follower> and
myCS.c = <leader> => newc = <undecided> and
myCS.c = <follower> => newc = <undecided>
*/
changeStrength: nat ==> ()
changeStrength(n) ==
myCS := mk_CS(myCS.c,n)
-- increase the strength of my claim up to the maximum (upper limit of petitions: uls)
incStrength:()==>()
incStrength() ==
(
if myCS.s < uls
then myCS := mk_CS(myCS.c, myCS.s+1)
else Skip
)
amILeader: () ==> bool
amILeader() ==
(
return (leaders = 0) or
(highest_strength = nil) or
(highest_strength <> nil and highest_strength < myCS.s) or
(highest_strength <> nil and highest_strength = myCS.s and highest_strength_id < i)
)
maxSet: set of nat ==> nat
maxSet(sn) ==
(
-- dcl s:nat @
s:= sn;
-- (
-- dcl c:nat @
c := select(s);
s := s \ {c};
while (s <> {}) do
(let n = select(s) in
(if (n>c) then c:=n else c:=c;
s := s\{n})
);
return c
-- )
)
pre sn <> {}
functions
-- implicit helper function; selects an element of a non-empty set
select(sn : set of nat) r: nat
pre sn <> {}
post r in set sn
actions
Listener = ReceiveData;update();Skip
Debug = pos : nat @ DebugM(pos);DebugRest(pos);DebugMyCS(pos)
DebugM = pos : nat @
if debugMem then
DebugMem!i!pos!mem -> Skip
else
Skip
DebugRest = pos : nat @
if debugR then
DebugLeaders!i!pos!leaders ->
DebugHighestStrength!i!pos!highest_strength ->
DebugHighestStrengthID!i!pos!highest_strength_id ->
DebugIsLeader!i!pos!isleader ->
Skip
else
Skip
DebugMyCS = pos : nat @
if debugCS then
DebugClaim!i!pos!myCS ->
Skip
else
Skip
ReceiveData =
(
out!i?j?msg -> (mem := mem ++ {j |-> msg.cs}); ReceiveData
) [_ n_timeout _> Skip
-- The first version of SendCS produces an exception: it is reported as Bug#268; should now be fixed, but doesn't apear to be.
SendCS = (||| t in set dom mem @ [{}] inn!i!t!(mk_MSG(i,t,myCS)) -> Skip) -- insists on sending all messages before it progresses.
-- The second version is temporary.
/*
SendCS =
let mycs = myCS in
(
for all d in set dom mem do
(
inn!i!d!(mk_MSG(i,d,mycs)) -> Skip
)
)
*/
Off = on!i -> (Undecided /_\ off!i -> flushState();Off)
-- isleader must to be updated separately and directly; otherwise the guards don't work correctly.
Undecided = Debug(1);
(myCS.c := <undecided>);
-- changeClaim(<undecided>); -- the operation fails; I don't know why.
Debug(2);
undecided!i -> Debug(3);Listener;
(isleader := amILeader());
Debug(4);
(
[isleader] & Leader
[]
[not isleader] & Follower
)
Leader = (myCS.c := <leader>);
--changeClaim(<leader>);
leading.i -> SendCS; Debug(1);
Listener; Debug(2);
(isleader := amILeader());
Debug(3);
(
[not isleader] & Undecided
[]
[isleader] & incStrength();Leader
)
Follower =
-- changeClaim(<follower>);changeStrength(0);
(myCS.c := <follower>); (myCS.s := 0);
following!i ->
-- Debug(2);
SendCS; flushMemory();Listener; -- flushing primary memory; then listen
(isleader := amILeader());
-- Debug(2);
(
[leaders <> 1] & Undecided
[]
[leaders = 1] & Follower
)
@ init.i -> flushState();Off
end
process AllNodesSet = ||| i in set allNodes @ (Node(i))
process OneNode = Node(1)
process TwoUnconnectedNodes = Node(1) ||| Node(2)
process ThreeNodes = Node(1) ||| Node(2) ||| Node(3)
process TwoProcesses = (TwoUnconnectedNodes [|{|inn,out|}|] MessageStore) \\ {|inn,out|}
process Election = (AllNodesSet [|{|inn,out|}|] MessageStore) \\ {|inn,out|}
process Election2 = (ThreeNodes [|{|inn,out|}|] MessageStore) \\ {|inn,out|}
--===testing area===--
channels
success, cp1,cp2,cp3,offthree,alloff
chansets
allEventsExcOff = {|init,on,undecided,leading,following|}
allEvents = {|init,on,undecided,leading,following|} union {|off|}
process Tests = i : nat @
begin
actions
RunTest =
[i=1] & Init;AllOn;Trace1;Success -- success after three tocks
[]
[i=2] & Init;AllOn;Trace2;Success -- success after two tocks [off.3, offthree, tock, tock, success]
[]
[i=3] & Skip;Success -- immediate success
[]
[i=4] & Init;AllOn;Trace1;AllOff;AllOn;Trace4;Success -- success should have [tock, tock, tock, tock, tock, tock, success]
[]
[i=5] & Init;AllOn;Trace1;Trace5;Success -- fails
[]
[i=6] & Trace6;Success
Init = init.1 -> init.2 -> init.3 -> Skip
AllOn = on.1 -> on.2 -> on.3 -> Skip
AllOff = off.1 -> off.2 -> off.3 -> Skip
Success = success -> Skip
Trace1 = undecided.1 -> undecided.2 -> undecided.3 ->
leading.1 -> leading.2 -> leading.3 ->
leading.3 -> undecided.1 ->
undecided.2 ->
following.1 -> following.2 -> leading.3 -> Skip
Trace2 = undecided.1 -> undecided.2 -> undecided.3 -> offthree ->
leading.1 -> leading.2 -> leading.2 -> undecided.1 -> Skip
Trace4 = undecided.1 -> undecided.2 -> undecided.3 -> off.3 ->
leading.1 -> leading.2 -> leading.2 -> undecided.1 ->
leading.2 -> following.1 -> Skip
Trace6 = Trace1;AllOff;AllOn
Trace5 = off.3 -> undecided.1 -> undecided.2 ->
leading.2 -> following.1 -> leading.2 -> following.1 ->
on.3 -> undecided.3 -> leading.2 -> following.1 ->
leading.2 -> following.1 -> following.3 -> Skip
@RunTest
end
process TestOne = Election2 [|allEventsExcOff|] Tests(1) \\ allEventsExcOff
process TestTwo = Election2 [|allEventsExcOff|] Tests(2) \\ allEventsExcOff
process TestThree = Election2 [|allEventsExcOff|] Tests(3) \\ allEventsExcOff
process TestFour = Election2 [|allEvents|] Tests(4) \\ allEvents
process TestFive = Election2 [|allEvents|] Tests(5) \\ allEvents
Exception trace:
Exception in thread "main" Internal 0005: Illegal clone: java.io.NotSerializableException: eu.compassresearch.core.interpreter.api.values.NoConstraint
at org.overture.interpreter.values.ObjectValue.deepCopy(ObjectValue.java:469)
at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:77)
at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:74)
at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:74)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
at eu.compassresearch.core.interpreter.runtime.DelayedWriteContext.deepCopy(DelayedWriteContext.java:184)
at eu.compassresearch.core.interpreter.ActionInspectionVisitor.caseParallelBegin(ActionInspectionVisitor.java:573)
at eu.compassresearch.core.interpreter.ActionInspectionVisitor.access$000(ActionInspectionVisitor.java:87)
at eu.compassresearch.core.interpreter.ActionInspectionVisitor$5.execute(ActionInspectionVisitor.java:450)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$30.execute(CommonInspectionVisitor.java:1113)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:411)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$29.execute(CommonInspectionVisitor.java:1064)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:414)
at eu.compassresearch.core.interpreter.ProcessInspectionVisitor$8.execute(ProcessInspectionVisitor.java:346)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:414)
at eu.compassresearch.core.interpreter.ProcessInspectionVisitor$8.execute(ProcessInspectionVisitor.java:346)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$9.execute(CommonInspectionVisitor.java:491)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$12.execute(CommonInspectionVisitor.java:627)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$9.execute(CommonInspectionVisitor.java:491)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.CommonInspectionVisitor$12.execute(CommonInspectionVisitor.java:627)
at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.executeBehaviour(VanillaCmlInterpreter.java:344)
at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.executeTopProcess(VanillaCmlInterpreter.java:301)
at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.execute(VanillaCmlInterpreter.java:228)
at eu.compassresearch.core.interpreter.debug.SocketServerCmlDebugger.start(SocketServerCmlDebugger.java:436)
at eu.compassresearch.core.interpreter.debug.DebugMain.main(DebugMain.java:208)
The two tocks occur after debugging on TestFive
Also in TestOne
, which is what I had tried.
In the model Jeremy.cml, following the trace [init.1, init.2, init.3, on.1, on.2, on.3, n_req.1, out.mk_MSG(1, 1, nil)] an "exception in thread main" is reported (in red, so it must be important ;
I've emailed the file to Joey and Kennet.