Index: fedd/compose.py
===================================================================
--- fedd/compose.py	(revision 8a0c67fdbe39a1fab21c313e912ecc0138d2697e)
+++ fedd/compose.py	(revision 7ee16b3892e283b42897e007d392f33cb596da19)
@@ -231,6 +231,6 @@
 	if e.name in names:
 	    nn= make_new_name(names, "node")
-	    if e.name in marks:
-		marks[e.name].name = nn
+	    for c in marks.get(e.name, []):
+		c.name = nn
 	    e.name = nn
 	else:
@@ -254,4 +254,5 @@
     """
     got_all = True
+    node_match = { }
     for c in candidates:
 	if not c.match:
@@ -265,5 +266,10 @@
 		    if can.name != c.name and can.topology != c.topology and \
 			    not can.match:
-			# Now check that the candidate also accepts c
+			# Don't allow multiple matches between the same nodes
+			# (the "if" above is already pretty crowded).
+			if c.name in node_match and \
+				can.name in node_match[c.name]:
+			    continue
+			# Now check that can also accepts c
 			for ca in can.accepts:
 			    if ca in c.provides:
@@ -291,4 +297,8 @@
 		match.match = c
 		c.match = match
+		# Note the match of the nodes
+		for a, b in ((c.name, match.name), (match.name, c.name)):
+		    if a in node_match: node_match[a].append(b)
+		    else: node_match[a] = [ b]
 	    else:
 		got_all = False
@@ -378,5 +388,5 @@
     const_re = re.compile("\s*#\s*COMPOSITION:\s*([^:]+:[^:]+:.*)")
 
-    marks = { }
+    constraints = [ ]
     for l in contents:
 	m = const_re.search(l)
@@ -389,8 +399,7 @@
 	    p = p.split(",")
 	    a = a.split(",")
-	    c = constraint(name=nn, required=(r == 'required'),
-		    provides=p, accepts=a)
-	    marks[nn] = c
-    return marks
+	    constraints.append(constraint(name=nn, required=(r == 'required'),
+		    provides=p, accepts=a))
+    return constraints
 
 def import_ns2_component(fn):
@@ -416,20 +425,13 @@
 def import_topdl_component(fn):
     """
-    Pull a component in from a topdl description.  The topology generation is
-    straightforward and the constraints are pulled from the attributes of
-    Computer nodes in the experiment.  The compisition_point attribute being
-    true marks a node as a composition point.  The required, provides and
-    accepts attributes map directly into those constraint fields.  The dict of
-    constraints and the topology are returned.
-    """
-    top = topdl.topology_from_xml(filename=fn, top='experiment')
-    cons = constraints_from_xml(filename=fn, top='constraints')
-    marks= dict([(c.name, c ) for c in cons])
-    return (top, marks)
-
-def index_constraints(constraints, provides, accepts):
+    Pull a component in from a topdl description.
+    """
+    return (topdl.topology_from_xml(filename=fn, top='experiment'), 
+	    constraints_from_xml(filename=fn, top='constraints'))
+
+def index_constraints(constraints, provides, accepts, names):
     """
     Add constraints to the provides and accepts indices based on the attributes
-    of the contstraints.
+    of the contstraints.  Also index by name.
     """
     for c in constraints:
@@ -438,4 +440,6 @@
 		if a not in dict: dict[a] = [c]
 		else: dict[a].append(c)
+	if c.name in names: names[c.name].append(c)
+	else: names[c.name]= [ c ]
 
 def get_suffix(fn):
@@ -548,9 +552,8 @@
 
     for fn, cnt in files:
-	top = None
 	try:
 	    s = get_suffix(fn)
 	    if s and s in importers:
-		top, marks = importers[s](fn)
+		top, cons = importers[s](fn)
 	    else:
 		warn("Unknown suffix on file %s.  Ignored" % fn)
@@ -569,11 +572,12 @@
 	    components += 1
 	    t = top.clone()
-	    m = copy.deepcopy(marks)
+	    c = copy.deepcopy(cons)
+	    marks = { }
 	    # Bind the constraints in m (the marks copy) to this topology
-	    for c in m.values():
-		c.topology = t
-	    index_constraints(m.values(), provides, accepts)
-	    localize_names(t, names, m)
-	    constraints.extend(m.values())
+	    for cc in c:
+		cc.topology = t
+	    index_constraints(c, provides, accepts, marks)
+	    localize_names(t, names, marks)
+	    constraints.extend(c)
 	    topos.append(t)
 
