Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » ATL » EMFTVM: Transformation not terminating in Standalone Mode
EMFTVM: Transformation not terminating in Standalone Mode [message #1738342] Tue, 19 July 2016 07:59 Go to next message
Sven L. is currently offline Sven L.Friend
Messages: 16
Registered: May 2012
Junior Member
Hello,

I wrote a refining transformation that would create a custom trace model as second output.

For this purpose I created a simple Trace metamodel which just contains a trace root container and a trace class, that stores a source and a target value, both Strings.

During the transformations I would create trace elements, which I add to the container through an endpoint rule, to make sure all the elements are created.
When the transformation is run in my eclipse it terminates in 0.5 seconds. When it's run in a standalone application it does not terminate at all (been running > 5 min now)

I suspect it's the endpoint rule that causes the trouble, but I don't know why. Here's the code:

-- @atlcompiler emftvm
-- @nsURI EMFTVM=http://www.eclipse.org/m2m/atl/2011/EMFTVM

-- @path NodeSet=/metamodel/NodeSet.ecore
-- @path Trace=/metamodel/MyTrace.ecore

module ChangeNodeId;

create OUT: NodeSet, TRACE: MyTrace refining IN: NodeSet;

helper def : traceList : Sequence(MyTrace!Trace) = Sequence{};

helper def : traceModel : MyTrace!Traces = OclUndefined;

-- root rule: create trace container
rule Traces {
	from
		s : NodeSet!NodeSetType
	to
		t : NodeSet!NodeSetType,
		traceModel : MyTrace!Traces
	do {
		thisModule.traceModel <- traceModel;	
	}
}

-- change something, create trace of change
rule ChangeNodeId {
	from
		s : NodeSet!Variable
	to
		t : NodeSet!Variable (
			nodeId <- thisModule.generateNodeId(source.nodeId)
		),
		trace : MyTrace!Trace (
			source <- source.nodeId	
		)
	do {
		trace.target <- target.nodeId;
		thisModule.traceList <- thisModule.traceList -> append(trace);
	}
}

-- add traces to container
endpoint rule addTraces() {
	do {
		thisModule.traceModel.traces <- thisModule.traceList;
	}
}


When I remove the endpoint rule the transformation also terminates in standalone mode, but now I don't know, how I can add the created traces to the container. I also tried something like this: I would like to iterate over all source elements, get the trace (if one was created), and add it to the container.

-- root rule: create trace container
rule Traces {
	from
		s : NodeSet!NodeSetType
	to
		t : NodeSet!NodeSetType,
		traceModel : MyTrace!Traces (
			traces <- NodeSet!Node.allInstances() -> select(i | not thisModule.resolveTemp(i, 'trace').oclIsUndefined()) -> collect(e | thisModule.resolveTemp(e, 'trace'))
		)
}


but here I can't figure out how to find the created traces. This throws an VMException: Cannot resolve default trace target, when not every element has a trace.

I could obviously make it mandatory to create a trace for every source element, but I would rather look for another solution first.

[Updated on: Tue, 19 July 2016 08:01]

Report message to a moderator

Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1738498 is a reply to message #1738342] Wed, 20 July 2016 11:09 Go to previous messageGo to next message
Dennis Wagelaar is currently offline Dennis WagelaarFriend
Messages: 351
Registered: September 2012
Location: Belgium
Senior Member

First of all, let's look into the reason why your standalone setup behaves different from the Eclipse setup. Can you post a thread dump of the Java thread that executes the transformation?

Second: do you really need your own custom trace model? If the EMFTVM trace model suffices, you can simply save it by adding a "trace" in/out model to your launch config.

Third: your programming style is a rewriting style, where you update the model/execution state incrementally. ATL is a mapping style language, that works best by assigning values only once. Updating global helper attributes multiple times makes your transformation more complex. Your second attempt with thisModule.resolveTemp() follows the recommended ATL programming style, but is complicated by having to repeat the ChangeNodeId rule's filter expression. The simplest way to deal with this is to extract the ChangeNodeId rule's filter expression into a helper attribute defined on the rule's source element, so that you can reuse the same helper attribute in the Traces rule. Alternatively, you can use trace model reflection to iterate over all rule applications.


Cheers,
Dennis
Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1738505 is a reply to message #1738498] Wed, 20 July 2016 12:29 Go to previous messageGo to next message
Sven L. is currently offline Sven L.Friend
Messages: 16
Registered: May 2012
Junior Member
Hi Dennis,

thank you for your reply.

1) Since I was running the transformation in an OSGi environment I didn't notice that it's actually indeed terminating. If I run it as a java application I can see that it throws a StackOverflowException.

Exception in thread "main" java.lang.StackOverflowError
	at org.eclipse.m2m.atl.emftvm.util.LazyCollection$AppendIterator.<init>(LazyCollection.java:406)
	at org.eclipse.m2m.atl.emftvm.util.LazyList$AppendList.iterator(LazyList.java:383)
	at org.eclipse.m2m.atl.emftvm.util.OCLOperations$ResolveList$ResolveIterator.<init>(OCLOperations.java:69)
	at org.eclipse.m2m.atl.emftvm.util.OCLOperations$ResolveList.iterator(OCLOperations.java:119)
	at org.eclipse.m2m.atl.emftvm.util.LazyCollection$WrappedIterator.<init>(LazyCollection.java:90)
	at org.eclipse.m2m.atl.emftvm.util.LazyCollection$AppendIterator.<init>(LazyCollection.java:407)
	at org.eclipse.m2m.atl.emftvm.util.LazyList$AppendList.iterator(LazyList.java:383)
	at org.eclipse.m2m.atl.emftvm.util.OCLOperations$ResolveList$ResolveIterator.<init>(OCLOperations.java:69)
	at org.eclipse.m2m.atl.emftvm.util.OCLOperations$ResolveList.iterator(OCLOperations.java:119)
	at org.eclipse.m2m.atl.emftvm.util.LazyCollection$WrappedIterator.<init>(LazyCollection.java:90)
	at org.eclipse.m2m.atl.emftvm.util.LazyCollection$AppendIterator.<init>(LazyCollection.java:407)
	at org.eclipse.m2m.atl.emftvm.util.LazyList$AppendList.iterator(LazyList.java:383)


Again, if I remove the endpoint rule, everything works just fine.

2) Yes, I think I do. I want to keep track of attributes that changed. With the EMFTVM trace model I can only find out which object changed, but not which value the attribute of the element had before it was changed. (In this simple case above, I want to keep track of the change on the NodeId Attribute)

Of course, if you are aware of a better way to achieve this, please let me know.

3) Yes, I'm aware of that. While looking into custom traces I found this solution: https://wiki.eclipse.org/ATL/Design_Patterns#Custom_Tracing. I tried to follow this idea and just use it as second output model (encapsulated in my simple trace model).

Quote:
The simplest way to deal with this is to extract the ChangeNodeId rule's filter expression into a helper attribute defined on the rule's source element, so that you can reuse the same helper attribute in the Traces rule


This is a good idea. Will this also work if other rules would create traces as well? I fear this might get very confusing and I feel like using the trace model reflection might be the cleanest way. I will look into both options.
Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1738644 is a reply to message #1738505] Thu, 21 July 2016 15:52 Go to previous messageGo to next message
Dennis Wagelaar is currently offline Dennis WagelaarFriend
Messages: 351
Registered: September 2012
Location: Belgium
Senior Member

1) The StackOverflowException is not an infinite loop in this case, but caused by too deep recursion into the lazy list structure built in the ChangeNodeId rule. On every binding, each element in the list is resolved to its target element, and this list only contains target elements already(!). You can use the <:= assignment operator instead of the binding operator to skip the source-to-target resolution step:
-- change something, create trace of change
rule ChangeNodeId {
	from
		s : NodeSet!Variable
	to
		t : NodeSet!Variable (
			nodeId <- thisModule.generateNodeId(source.nodeId)
		),
		trace : MyTrace!Trace (
			source <- source.nodeId	
		)
	do {
		trace.target <- target.nodeId;
		thisModule.traceList <:= thisModule.traceList -> append(trace);
	}
}

-- add traces to container
endpoint rule addTraces() {
	do {
		thisModule.traceModel.traces <:= thisModule.traceList;
	}
}


That said, EMFTVM's lazy collection implementation isn't very efficient in applying many operations to a single collection; all (simple) operations are kept in a chain of wrappers around the initial collection, and an attempt to iterate the collection will instantiate a similar chain of wrapped iterators.


Cheers,
Dennis
Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1738653 is a reply to message #1738644] Thu, 21 July 2016 17:09 Go to previous messageGo to next message
Dennis Wagelaar is currently offline Dennis WagelaarFriend
Messages: 351
Registered: September 2012
Location: Belgium
Senior Member

2) Ok, when you use refining mode, you can indeed not keep a trace reference to the original source element, and therefore you no longer have the original attribute values. You need custom tracing.

3) You could use trace model reflection in the Traces rule as follows:
-- root rule: create trace container
rule Traces {
	from
		s : NodeSet!NodeSetType
	to
		t : NodeSet!NodeSetType,
		traceModel : MyTrace!Traces (
			traces <- thisModule.traces.rules
				->collect(r | r.links
					->collect(l | l.targetElements
						->select(te | te.name = 'trace')
						->collect(te | te.object)
					)
				)->flatten()
		)
}


Cheers,
Dennis
Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1738815 is a reply to message #1738653] Mon, 25 July 2016 07:59 Go to previous messageGo to next message
Sven L. is currently offline Sven L.Friend
Messages: 16
Registered: May 2012
Junior Member
Hi Dennis,

thank you for clearing this up. This solved my problem.
I assume the differences in execution in Eclipse and standalone application are then caused by different stack sizes?
Re: EMFTVM: Transformation not terminating in Standalone Mode [message #1744424 is a reply to message #1738815] Mon, 26 September 2016 19:40 Go to previous message
Dennis Wagelaar is currently offline Dennis WagelaarFriend
Messages: 351
Registered: September 2012
Location: Belgium
Senior Member

Sven L. wrote on Mon, 25 July 2016 09:59
I assume the differences in execution in Eclipse and standalone application are then caused by different stack sizes?


Unless you explicitly set a JVM stack size, or run the JVMs on a different platform, it probably depends on how much was on the JVM call stack already at the point where you started the EMFTVM transformation.


Cheers,
Dennis
Previous Topic:Ruining QVT to ATL Virtual Machine Compiler Project
Next Topic:Computing Metrics on ATL Transformations
Goto Forum:
  


Current Time: Sat Nov 18 04:47:51 GMT 2017

Powered by FUDForum. Page generated in 0.01755 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software