Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2012-12-17 09:44:33 +0000
committerHenrik Rentz-Reichert2012-12-17 09:44:33 +0000
commitf94a099d308b39ccc96a6a09202bb88ef0ab8ba7 (patch)
tree69fa7d04c6188faa8096324c3bf8ad9256f728db
parent92eb1e2afe598eeb11d74987885f8030c4699c54 (diff)
downloadorg.eclipse.etrice-f94a099d308b39ccc96a6a09202bb88ef0ab8ba7.tar.gz
org.eclipse.etrice-f94a099d308b39ccc96a6a09202bb88ef0ab8ba7.tar.xz
org.eclipse.etrice-f94a099d308b39ccc96a6a09202bb88ef0ab8ba7.zip
[core.genmodel] 396251: Port Replications not correct after preparations for dynamic actors
https://bugs.eclipse.org/bugs/show_bug.cgi?id=396251
-rw-r--r--plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/BindingUtil.java241
-rw-r--r--plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/GeneratorModelBuilder.java179
2 files changed, 269 insertions, 151 deletions
diff --git a/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/BindingUtil.java b/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/BindingUtil.java
new file mode 100644
index 000000000..aa17ab837
--- /dev/null
+++ b/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/BindingUtil.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2012 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.core.genmodel.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.BindingInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.ETriceGenFactory;
+import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician;
+import org.eclipse.etrice.core.genmodel.etricegen.PortInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.PortKind;
+import org.eclipse.etrice.core.genmodel.etricegen.StructureInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance;
+import org.eclipse.etrice.core.room.ActorClass;
+import org.eclipse.etrice.core.room.ActorContainerRef;
+import org.eclipse.etrice.core.room.ActorRef;
+import org.eclipse.etrice.core.room.Binding;
+import org.eclipse.etrice.core.room.BindingEndPoint;
+import org.eclipse.etrice.core.room.Port;
+import org.eclipse.etrice.core.room.RoomPackage;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ */
+public class BindingUtil {
+
+ private static class BindingInfo {
+ private Binding binding;
+ private int multiplicity;
+
+ public BindingInfo(Binding binding) {
+ this.binding = binding;
+
+ int m1 = getMultiplicity(binding.getEndpoint1());
+ int m2 = getMultiplicity(binding.getEndpoint2());
+
+ multiplicity = Math.max(m1, m2);
+ }
+
+ public int getMultiplicity() {
+ return multiplicity;
+ }
+
+ public Port getPeer(Port p) {
+ if (binding.getEndpoint1().getPort()==p)
+ return binding.getEndpoint2().getPort();
+ else
+ return binding.getEndpoint1().getPort();
+ }
+
+ private int getMultiplicity(BindingEndPoint ep) {
+ if (ep.getActorRef() instanceof ActorRef)
+ return ((ActorRef) ep.getActorRef()).getSize();
+
+ return 1;
+ }
+ }
+ private static final String SEP = "#";
+
+ private StructureInstance si;
+ private IDiagnostician diagnostician;
+ private ArrayList<Binding> bindings = new ArrayList<Binding>();
+
+ private HashMap<String, ArrayList<PortInstance>> ep2portInstances = new HashMap<String, ArrayList<PortInstance>>();
+ private HashMap<String, ArrayList<BindingInfo>> ep2bindings = new HashMap<String, ArrayList<BindingInfo>>();
+ private HashMap<Binding, BindingInfo> binding2info = new HashMap<Binding, BindingInfo>();
+
+ /**
+ * @param diagnostician
+ */
+ public BindingUtil(StructureInstance si, IDiagnostician diagnostician) {
+ this.si = si;
+ this.diagnostician = diagnostician;
+
+ // collect bindings
+ if (si instanceof ActorInstance) {
+ ActorClass ac = ((ActorInstance) si).getActorClass();
+ while (ac!=null) {
+ bindings.addAll(ac.getBindings());
+ ac = ac.getBase();
+ }
+ }
+ else if (si instanceof SubSystemInstance)
+ bindings.addAll(((SubSystemInstance) si).getSubSystemClass().getBindings());
+ }
+
+ /**
+ * create binding instances. Since bindings connect port instances the ports can point back to their bindings
+ * using EOpposite
+ * @param si - create bindings for this actor instance
+ * @param bindings - a list of bindings
+ */
+ public void createBindingInstances() {
+ initPortInstanceMap();
+
+ for (Binding bind : bindings) {
+ if (bind.getEndpoint1().getActorRef()==null && bind.getEndpoint2().getActorRef()==null) {
+ int idx = bindings.indexOf(bind);
+ diagnostician.error("binding connects two ports of the same actor", bind, RoomPackage.eINSTANCE.getStructureClass_Bindings(), idx);
+ }
+ else {
+ ArrayList<PortInstance> ep1Ports = ep2portInstances.get(getEndPointKey(bind.getEndpoint1()));
+ ArrayList<PortInstance> ep2Ports = ep2portInstances.get(getEndPointKey(bind.getEndpoint2()));
+ BindingInfo bi = binding2info.get(bind);
+ int nBind = Math.min(bi.getMultiplicity(), ep1Ports.size());
+ nBind = Math.min(nBind, ep2Ports.size());
+ for (int i=0; i<nBind; ++i) {
+ createBindingInstance(ep1Ports.get(0), ep2Ports.get(0), bind);
+ ep1Ports.remove(0);
+ ep2Ports.remove(0);
+ }
+ }
+ }
+ }
+
+ private void createBindingInstance(PortInstance pi1, PortInstance pi2, Binding bind) {
+ BindingInstance bi = ETriceGenFactory.eINSTANCE.createBindingInstance();
+
+ bi.getPorts().add(pi1);
+ bi.getPorts().add(pi2);
+ bi.setBinding(bind);
+
+ si.getBindings().add(bi);
+ }
+
+ private void initPortInstanceMap() {
+ // 1. register existing port instances
+
+ // local end ports
+ for (PortInstance pi : si.getPorts()) {
+ if (pi.getKind()!=PortKind.EXTERNAL) {
+ addPortInstance(pi, getEndPointKey(null, pi));
+ }
+ }
+
+ // ports of actor refs
+ for (ActorInstance sub : si.getInstances()) {
+ boolean forceMultFixed = sub.getReplIdx()>1;
+ for (PortInstance pi : sub.getPorts()) {
+ if (pi.getKind()!=PortKind.INTERNAL) {
+ if (forceMultFixed && pi.getPort().getMultiplicity()<0)
+ diagnostician.error("port multiplicity of replicated actor has to be fixed", pi.getPort(), RoomPackage.eINSTANCE.getPort_Multiplicity());
+ addPortInstance(pi, getEndPointKey(sub, pi));
+ }
+ }
+ }
+
+ // 2. compute binding info
+ for (Binding bind : bindings) {
+ BindingInfo bi = new BindingInfo(bind);
+ binding2info.put(bind, bi);
+ addBindingInfoToEndPoint(bi, bind.getEndpoint1());
+ addBindingInfoToEndPoint(bi, bind.getEndpoint2());
+ }
+
+ // 3. determine * multiplicities
+ outer: for (Entry<String, ArrayList<BindingInfo>> entry : ep2bindings.entrySet()) {
+ ArrayList<PortInstance> ports = ep2portInstances.get(entry.getKey());
+ PortInstance pi = ports.get(0);
+ Port p = pi.getPort();
+ if (p.getMultiplicity()<0) {
+ int m = 0;
+ for (BindingInfo bi : entry.getValue()) {
+ Port peer = bi.getPeer(p);
+ if (peer.getMultiplicity()>0)
+ m += bi.getMultiplicity();
+ else {
+ diagnostician.error("could not compute multiplicity", p, RoomPackage.Literals.PORT__MULTIPLICITY);
+ break outer;
+ }
+ }
+
+ // fill in port instances such that ports.size()==p.getMultiplicity()
+ m -= ports.size();
+ for (; m>0; --m)
+ ports.add(pi);
+ }
+ }
+ }
+
+ /**
+ * @param bi
+ * @param ep
+ */
+ private void addBindingInfoToEndPoint(BindingInfo bi, BindingEndPoint ep) {
+ String key = getEndPointKey(ep.getActorRef(), ep.getPort());
+ ArrayList<BindingInfo> list = ep2bindings.get(key);
+ if (list==null) {
+ list = new ArrayList<BindingInfo>();
+ ep2bindings.put(key, list);
+ }
+
+ list.add(bi);
+ }
+
+ private static String getEndPointKey(ActorInstance ai, PortInstance pi) {
+ return (ai!=null? ai.getUnindexedName():"")+SEP+pi.getPort().getName();
+ }
+
+ private static String getEndPointKey(BindingEndPoint ep) {
+ return getEndPointKey(ep.getActorRef(), ep.getPort());
+ }
+
+ private static String getEndPointKey(ActorContainerRef ref, Port port) {
+ return ref==null? SEP+port.getName() : ref.getName()+SEP+port.getName();
+ }
+
+ /**
+ * add the port instance to the map. Replicated ports are added 'multiplicity' times. If the multiplicity is * then the port is added once.
+ *
+ * @param pi
+ * @param ep2portInstances
+ */
+ private void addPortInstance(PortInstance pi, String key) {
+ ArrayList<PortInstance> ports = ep2portInstances.get(key);
+ if (ports==null) {
+ ports = new ArrayList<PortInstance>();
+ ep2portInstances.put(key, ports);
+ }
+ int repl = pi.getPort().getMultiplicity();
+ if (repl<=0)
+ repl = 1;
+ for (int i=0; i<repl; ++i)
+ ports.add(pi);
+ }
+
+}
diff --git a/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/GeneratorModelBuilder.java b/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/GeneratorModelBuilder.java
index ca828f358..7acaf9207 100644
--- a/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/GeneratorModelBuilder.java
+++ b/plugins/org.eclipse.etrice.core.genmodel/src/org/eclipse/etrice/core/genmodel/builder/GeneratorModelBuilder.java
@@ -15,7 +15,6 @@ package org.eclipse.etrice.core.genmodel.builder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
@@ -25,12 +24,30 @@ import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.etrice.core.genmodel.base.ILogger;
+import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.BindingInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.ConnectionInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.ETriceGenFactory;
+import org.eclipse.etrice.core.genmodel.etricegen.ExpandedActorClass;
+import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician;
+import org.eclipse.etrice.core.genmodel.etricegen.InstanceBase;
+import org.eclipse.etrice.core.genmodel.etricegen.InterfaceItemInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.PortInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.PortKind;
+import org.eclipse.etrice.core.genmodel.etricegen.Root;
+import org.eclipse.etrice.core.genmodel.etricegen.SAPInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.SPPInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.ServiceImplInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.StructureInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.SystemInstance;
+import org.eclipse.etrice.core.genmodel.etricegen.impl.StructureInstanceImpl;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerClass;
import org.eclipse.etrice.core.room.ActorContainerRef;
import org.eclipse.etrice.core.room.ActorRef;
import org.eclipse.etrice.core.room.Binding;
-import org.eclipse.etrice.core.room.BindingEndPoint;
import org.eclipse.etrice.core.room.CommunicationType;
import org.eclipse.etrice.core.room.ExternalPort;
import org.eclipse.etrice.core.room.LayerConnection;
@@ -49,25 +66,6 @@ import org.eclipse.etrice.core.room.ServiceImplementation;
import org.eclipse.etrice.core.room.SubProtocol;
import org.eclipse.etrice.core.room.SubSystemClass;
import org.eclipse.etrice.core.room.SubSystemRef;
-import org.eclipse.etrice.core.genmodel.base.ILogger;
-import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.BindingInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.ConnectionInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.ETriceGenFactory;
-import org.eclipse.etrice.core.genmodel.etricegen.ExpandedActorClass;
-import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician;
-import org.eclipse.etrice.core.genmodel.etricegen.InstanceBase;
-import org.eclipse.etrice.core.genmodel.etricegen.InterfaceItemInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.PortInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.PortKind;
-import org.eclipse.etrice.core.genmodel.etricegen.Root;
-import org.eclipse.etrice.core.genmodel.etricegen.SAPInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.SPPInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.ServiceImplInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.StructureInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.SystemInstance;
-import org.eclipse.etrice.core.genmodel.etricegen.impl.StructureInstanceImpl;
/**
* A class for the creation of an intermediate model combining all information needed by
@@ -471,7 +469,7 @@ public class GeneratorModelBuilder {
}
// bindings are handled now since port instances of sub-actor instances are available
- createBindingInstances(instance, ssc.getBindings());
+ new BindingUtil(instance, diagnostician).createBindingInstances();
createConnectionInstances(instance, ssc.getConnections());
return instance;
@@ -498,7 +496,7 @@ public class GeneratorModelBuilder {
}
// bindings are handled now since port instances of sub-actor instances are available
- createBindingInstances(instance, ssc.getBindings());
+ new BindingUtil(instance, diagnostician).createBindingInstances();
createConnectionInstances(instance, ssc.getConnections());
return instance;
@@ -569,7 +567,7 @@ public class GeneratorModelBuilder {
bindings.addAll(acl.getBindings());
connections.addAll(acl.getConnections());
}
- createBindingInstances(ai, bindings);
+ new BindingUtil(ai, diagnostician).createBindingInstances();
createConnectionInstances(ai, connections);
return ai;
@@ -665,131 +663,6 @@ public class GeneratorModelBuilder {
ai.getServices().add(sii);
}
}
-
- private static final String SEP = "#";
-
- /**
- * create binding instances. Since bindings connect port instances the ports can point back to their bindings
- * using EOpposite
- * @param si - create bindings for this actor instance
- * @param bindings - a list of bindings
- */
- private void createBindingInstances(StructureInstance si, List<Binding> bindings) {
- HashMap<String, ArrayList<PortInstance>> ep2portInstances = initPortInstanceMap(si, bindings);
-
- for (Binding bind : bindings) {
- if (bind.getEndpoint1().getActorRef()==null && bind.getEndpoint2().getActorRef()==null) {
- int idx = bindings.indexOf(bind);
- diagnostician.error("binding connects two ports of the same actor", bind, RoomPackage.eINSTANCE.getStructureClass_Bindings(), idx);
- }
- else {
- ArrayList<PortInstance> ep1Ports = ep2portInstances.get(getEndPointKey(bind.getEndpoint1()));
- ArrayList<PortInstance> ep2Ports = ep2portInstances.get(getEndPointKey(bind.getEndpoint2()));
- int nBind = ep1Ports.size()>ep2Ports.size()? ep2Ports.size():ep1Ports.size();
- for (int i=0; i<nBind; ++i) {
- createBindingInstance(si, ep1Ports.get(0), ep2Ports.get(0), bind);
- ep1Ports.remove(0);
- ep2Ports.remove(0);
- }
- }
- }
- }
-
- private void createBindingInstance(StructureInstance si, PortInstance pi1, PortInstance pi2, Binding bind) {
- BindingInstance bi = ETriceGenFactory.eINSTANCE.createBindingInstance();
-
- bi.getPorts().add(pi1);
- bi.getPorts().add(pi2);
- bi.setBinding(bind);
-
- si.getBindings().add(bi);
- }
-
- private HashMap<String, ArrayList<PortInstance>> initPortInstanceMap(StructureInstance si, List<Binding> bindings) {
- HashMap<String, ArrayList<PortInstance>> ep2portInstances = new HashMap<String, ArrayList<PortInstance>>();
- for (PortInstance pi : si.getPorts()) {
- if (pi.getKind()!=PortKind.EXTERNAL) {
- addPortInstance(pi, getEndPointKey(null, pi), ep2portInstances);
- }
- }
- for (ActorInstance sub : si.getInstances()) {
- boolean forceMultFixed = sub.getReplIdx()>1;
- for (PortInstance pi : sub.getPorts()) {
- if (pi.getKind()!=PortKind.INTERNAL) {
- if (forceMultFixed && pi.getPort().getMultiplicity()<0)
- diagnostician.error("port multiplicity of replicated actor has to be fixed", pi.getPort(), RoomPackage.eINSTANCE.getPort_Multiplicity());
- addPortInstance(pi, getEndPointKey(sub, pi), ep2portInstances);
- }
- }
- }
-
- // in a second step the actually needed number of instances for multiplicity * is filled into the list
- HashSet<String> multAny = new HashSet<String>();
- for (Binding bind : bindings) {
- addNeededInstance(bind.getEndpoint1(), bind.getEndpoint2(), ep2portInstances, multAny);
- addNeededInstance(bind.getEndpoint2(), bind.getEndpoint1(), ep2portInstances, multAny);
- }
-
- return ep2portInstances;
- }
-
- private void addNeededInstance(BindingEndPoint ep, BindingEndPoint peer_ep, HashMap<String, ArrayList<PortInstance>> ep2portInstances, HashSet<String> multAny) {
- String endPointKey = getEndPointKey(ep);
- ArrayList<PortInstance> ports = ep2portInstances.get(endPointKey);
- PortInstance pi = ports.get(0);
- boolean implicitMany = pi.getProtocol()==null || pi.getProtocol().getCommType() == CommunicationType.DATA_DRIVEN;
- if (implicitMany || pi.getPort().getMultiplicity() < 0) {
- int size = 1;
- if (peer_ep.getActorRef() instanceof ActorRef) {
- int peerMult = peer_ep.getPort().getMultiplicity();
- if (peerMult<=0)
- peerMult = 1;
- size = ((ActorRef)peer_ep.getActorRef()).getSize()*peerMult;
- }
-
- for (int i=0; i<size; ++i) {
- if (!multAny.contains(endPointKey)) {
- // we just register
- multAny.add(endPointKey);
- }
- else {
- // we add another copy of this instance
- ports.add(pi);
- }
- }
- }
- }
-
- private String getEndPointKey(ActorInstance ai, PortInstance pi) {
- return (ai!=null? ai.getUnindexedName():"")+SEP+pi.getPort().getName();
- }
-
- private String getEndPointKey(BindingEndPoint ep) {
- return getEndPointKey(ep.getActorRef(), ep.getPort());
- }
-
- private String getEndPointKey(ActorContainerRef ref, Port port) {
- return ref==null? SEP+port.getName() : ref.getName()+SEP+port.getName();
- }
-
- /**
- * add the port instance to the map. Replicated ports are added 'multiplicity' times. If the multiplicity is * then the port is added once.
- *
- * @param pi
- * @param ep2portInstances
- */
- private void addPortInstance(PortInstance pi, String key, HashMap<String, ArrayList<PortInstance>> ep2portInstances) {
- ArrayList<PortInstance> ports = ep2portInstances.get(key);
- if (ports==null) {
- ports = new ArrayList<PortInstance>();
- ep2portInstances.put(key, ports);
- }
- int repl = pi.getPort().getMultiplicity();
- if (repl<=0)
- repl = 1;
- for (int i=0; i<repl; ++i)
- ports.add(pi);
- }
/**
* Create layer connection instances.
@@ -911,8 +784,12 @@ public class GeneratorModelBuilder {
if (obj instanceof ActorInstance) {
for (PortInstance pi : ((ActorInstance) obj).getPorts()) {
if (pi.getKind()!=PortKind.RELAY && pi.getPeers().size()>1)
- if (pi.getPeers().get(0).getPeers().size()>1)
- connectPeersOneToOne(pi);
+ if (pi.getPeers().get(0).getPeers().size()>1) {
+ BindingInstance bi = pi.getBindings().get(0);
+ if (bi.getPorts().get(0).getKind()==PortKind.RELAY
+ || bi.getPorts().get(1).getKind()==PortKind.RELAY)
+ connectPeersOneToOne(pi);
+ }
}
}
}

Back to the top