Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2010-07-12 21:15:27 +0000
committereutarass2010-07-12 21:15:27 +0000
commit3f0dda210a02e7f905561566a7c774a83408d762 (patch)
tree63f3da39494db8d1ff861b2c5f99bb712c72337e
parentd72141d6ce4d9b4b53a1238f10d7143b6c721e40 (diff)
downloadorg.eclipse.tcf-3f0dda210a02e7f905561566a7c774a83408d762.tar.gz
org.eclipse.tcf-3f0dda210a02e7f905561566a7c774a83408d762.tar.xz
org.eclipse.tcf-3f0dda210a02e7f905561566a7c774a83408d762.zip
Locator.redirect command changed to allow command argument to be either peer ID or complete set of peer attributes.
This allow a client to redirect a channel to a peer that is not known by remote Locator.
-rw-r--r--docs/TCF Specification.html16
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java4
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/LocatorProxy.java13
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/AbstractChannel.java94
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/protocol/IChannel.java7
-rw-r--r--plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ILocator.java6
-rw-r--r--plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/Main.java67
7 files changed, 146 insertions, 61 deletions
diff --git a/docs/TCF Specification.html b/docs/TCF Specification.html
index 7e42cb695..fc7c8dd33 100644
--- a/docs/TCF Specification.html
+++ b/docs/TCF Specification.html
@@ -1263,7 +1263,7 @@ targets require no further configuration. Additional targets can be configured m
<p>All TCF peers must implement Locator service. The implementation is part of the framework itself.
It is the only required service, all other services are optional and, formally, not part of the framework.</p>
-<h2><a name='LocatorPeer'>Peer Atributes</a></h2>
+<h2><a name='LocatorPeer'>Peer Attributes</a></h2>
<p><i>&lt;object: peer data&gt;</i> is collection of peer attributes. It should, at least, contain member
<b><font face="Courier New" size=2 color=#333399>"ID" : <i>&lt;string&gt;</i></font></b>.
@@ -1272,7 +1272,13 @@ Predefined attributes are:</p>
<ul>
<li><code><b><font face="Courier New" size=2 color=#333399>"ID" : <i>&lt;string&gt;</i></font></b></code>
- - ID of the peer.
+ - unique ID of the peer.
+
+ <li><code><b><font face="Courier New" size=2 color=#333399>"ServiceManagerID" : <i>&lt;string&gt;</i></font></b></code>
+ - unique ID of service manager that is represented by this peer.
+
+ <li><code><b><font face="Courier New" size=2 color=#333399>"AgentID" : <i>&lt;string&gt;</i></font></b></code>
+ - agent unique ID.
<li><code><b><font face="Courier New" size=2 color=#333399>"Name" : <i>&lt;string&gt;</i></font></b></code>
- human readable peer name.
@@ -1306,7 +1312,11 @@ at services it implements (use IChannel.getRemoteServices() method to get a map
<h3><a name='LocatorCommandRedirect'>redirect</a></h3>
<pre><b><font face="Courier New" size=2 color=#333399>
-C &bull; <i>&lt;token&gt;</i> &bull; Locator &bull; redirect &bull; <i>&lt;string: peer ID&gt;</i> &bull;
+C &bull; <i>&lt;token&gt;</i> &bull; Locator &bull; redirect &bull; <i>&lt;peer&gt;</i> &bull;
+
+<i>&lt;peer&gt;</i>
+ &rArr; <i>&lt;string: peer ID&gt;</i>
+ &rArr; <i>&lt;object: peer data&gt;</i>
</font></b></pre>
<p>The command redirects the channel to become connected to given peer.
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
index 249589571..21ec0fb62 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
@@ -1070,6 +1070,10 @@ public class LocatorService implements ILocator {
throw new Error("Channel redirect cannot be done on local peer");
}
+ public IToken redirect(Map<String,String> peer, DoneRedirect done) {
+ throw new Error("Channel redirect cannot be done on local peer");
+ }
+
public IToken sync(DoneSync done) {
throw new Error("Channel sync cannot be done on local peer");
}
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/LocatorProxy.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/LocatorProxy.java
index 3415fa321..94ec1ff91 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/LocatorProxy.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/LocatorProxy.java
@@ -190,6 +190,19 @@ public class LocatorProxy implements ILocator {
}.token;
}
+ public IToken redirect(Map<String,String> peer, final DoneRedirect done) {
+ return new Command(channel, this, "redirect", new Object[]{ peer }) {
+ @Override
+ public void done(Exception error, Object[] args) {
+ if (error == null) {
+ assert args.length == 1;
+ error = toError(args[0]);
+ }
+ done.doneRedirect(token, error);
+ }
+ }.token;
+ }
+
public IToken sync(final DoneSync done) {
return new Command(channel, this, "sync", null) {
@Override
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/AbstractChannel.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/AbstractChannel.java
index dc6ac4eac..14cb5af62 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/AbstractChannel.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/AbstractChannel.java
@@ -118,7 +118,7 @@ public abstract class AbstractChannel implements IChannel {
private static IChannelListener[] listeners_array = new IChannelListener[4];
- private final LinkedList<String> redirect_queue = new LinkedList<String>();
+ private final LinkedList<Map<String,String>> redirect_queue = new LinkedList<Map<String,String>>();
private final Map<Class<?>,IService> local_service_by_class = new HashMap<Class<?>,IService>();
private final Map<Class<?>,IService> remote_service_by_class = new HashMap<Class<?>,IService>();
private final Map<String,IService> local_service_by_name = new HashMap<String,IService>();
@@ -398,10 +398,20 @@ public abstract class AbstractChannel implements IChannel {
* Redirect this channel to given peer using this channel remote peer locator service as a proxy.
* @param peer_id - peer that will become new remote communication endpoint of this channel
*/
- public void redirect(final String peer_id) {
+ public void redirect(String peer_id) {
+ Map<String,String> map = new HashMap<String,String>();
+ map.put(IPeer.ATTR_ID, peer_id);
+ redirect(map);
+ }
+
+ /**
+ * Redirect this channel to given peer using this channel remote peer locator service as a proxy.
+ * @param peer_attrs - peer that will become new remote communication endpoint of this channel
+ */
+ public void redirect(final Map<String,String> peer_attrs) {
assert Protocol.isDispatchThread();
if (state == STATE_OPENNING) {
- redirect_queue.add(peer_id);
+ redirect_queue.add(peer_attrs);
}
else {
assert state == STATE_OPEN;
@@ -410,43 +420,67 @@ public abstract class AbstractChannel implements IChannel {
final ILocator l = (ILocator)remote_service_by_class.get(ILocator.class);
if (l == null) throw new IOException("Cannot redirect channel: peer " +
remote_peer.getID() + " has no locator service");
- final IPeer peer = l.getPeers().get(peer_id);
- if (peer == null) {
- // Peer not found, must wait for a while until peer is discovered or time out
- final boolean[] found = new boolean[1];
- Protocol.invokeLater(ILocator.DATA_RETENTION_PERIOD / 3, new Runnable() {
- public void run() {
- if (found[0]) return;
- terminate(new Exception("Peer " + peer_id + " not found"));
- }
- });
- l.addListener(new ILocator.LocatorListener() {
- public void peerAdded(IPeer peer) {
- if (peer.getID().equals(peer_id)) {
- found[0] = true;
- state = STATE_OPEN;
- l.removeListener(this);
- redirect(peer_id);
+ final String peer_id = peer_attrs.get(IPeer.ATTR_ID);
+ if (peer_id != null && peer_attrs.size() == 1) {
+ final IPeer peer = l.getPeers().get(peer_id);
+ if (peer == null) {
+ // Peer not found, must wait for a while until peer is discovered or time out
+ final boolean[] found = new boolean[1];
+ Protocol.invokeLater(ILocator.DATA_RETENTION_PERIOD / 3, new Runnable() {
+ public void run() {
+ if (found[0]) return;
+ terminate(new Exception("Peer " + peer_id + " not found"));
+ }
+ });
+ l.addListener(new ILocator.LocatorListener() {
+ public void peerAdded(IPeer peer) {
+ if (peer.getID().equals(peer_id)) {
+ found[0] = true;
+ state = STATE_OPEN;
+ l.removeListener(this);
+ redirect(peer_id);
+ }
+ }
+ public void peerChanged(IPeer peer) {
}
- }
- public void peerChanged(IPeer peer) {
- }
- public void peerHeartBeat(String id) {
- }
+ public void peerHeartBeat(String id) {
+ }
- public void peerRemoved(String id) {
- }
- });
+ public void peerRemoved(String id) {
+ }
+ });
+ }
+ else {
+ redirect_command = l.redirect(peer_id, new ILocator.DoneRedirect() {
+ public void doneRedirect(IToken token, Exception x) {
+ assert redirect_command == token;
+ redirect_command = null;
+ if (state != STATE_OPENNING) return;
+ if (x != null) terminate(x);
+ remote_peer = peer;
+ remote_service_by_class.clear();
+ remote_service_by_name.clear();
+ event_listeners.clear();
+ }
+ });
+ }
}
else {
- redirect_command = l.redirect(peer_id, new ILocator.DoneRedirect() {
+ redirect_command = l.redirect(peer_attrs, new ILocator.DoneRedirect() {
public void doneRedirect(IToken token, Exception x) {
assert redirect_command == token;
redirect_command = null;
if (state != STATE_OPENNING) return;
if (x != null) terminate(x);
- remote_peer = peer;
+ final IPeer parent = remote_peer;
+ remote_peer = new AbstractPeer(peer_attrs) {
+ public IChannel openChannel() {
+ IChannel c = parent.openChannel();
+ c.redirect(peer_attrs);
+ return c;
+ }
+ };
remote_service_by_class.clear();
remote_service_by_name.clear();
event_listeners.clear();
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/protocol/IChannel.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/protocol/IChannel.java
index aabca468e..21ff2fa22 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/protocol/IChannel.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/protocol/IChannel.java
@@ -11,6 +11,7 @@
package org.eclipse.tm.tcf.protocol;
import java.util.Collection;
+import java.util.Map;
/**
* IChannel represents communication link connecting two end points (peers).
@@ -296,4 +297,10 @@ public interface IChannel {
* @param peer_id - peer that will become new remote communication endpoint of this channel
*/
void redirect(String peer_id);
+
+ /**
+ * Redirect this channel to given peer using this channel remote peer locator service as a proxy.
+ * @param peer_attrs - peer that will become new remote communication endpoint of this channel
+ */
+ void redirect(Map<String,String> peer_attrs);
}
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ILocator.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ILocator.java
index 8940a6f18..ddb88190e 100644
--- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ILocator.java
+++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ILocator.java
@@ -69,6 +69,12 @@ public interface ILocator extends IService {
*/
IToken redirect(String peer_id, DoneRedirect done);
+ /**
+ * Redirect this service channel to given peer using this service as a proxy.
+ * @param peer - Peer attributes.
+ */
+ IToken redirect(Map<String,String> peer, DoneRedirect done);
+
interface DoneRedirect {
void doneRedirect(IToken token, Exception error);
}
diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/Main.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/Main.java
index ffad60f31..46dc10f04 100644
--- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/Main.java
+++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/Main.java
@@ -10,12 +10,14 @@
*******************************************************************************/
package org.eclipse.tm.internal.tcf.debug.tests;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.eclipse.tm.tcf.core.AbstractPeer;
+import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.tcf.protocol.IEventQueue;
import org.eclipse.tm.tcf.protocol.IPeer;
import org.eclipse.tm.tcf.protocol.Protocol;
@@ -75,38 +77,47 @@ public class Main {
private static class RemotePeer extends AbstractPeer {
- public RemotePeer(Map<String,String> attrs) {
- super(attrs);
+ private final ArrayList<Map<String,String>> attrs;
+
+ public RemotePeer(ArrayList<Map<String,String>> attrs) {
+ super(attrs.get(0));
+ this.attrs = attrs;
+ }
+
+ public IChannel openChannel() {
+ assert Protocol.isDispatchThread();
+ IChannel c = super.openChannel();
+ for (int i = 1; i < attrs.size(); i++) c.redirect(attrs.get(i));
+ return c;
}
}
- private static IPeer getPeer(String s) {
- Map<String,String> map = new HashMap<String,String>();
- int len = s.length();
- int i = 0;
- while (i < len) {
- int i0 = i;
- while (i < len && s.charAt(i) != '=' && s.charAt(i) != 0) i++;
- int i1 = i;
- if (i < len && s.charAt(i) == '=') i++;
- int i2 = i;
- while (i < len && s.charAt(i) != ':') i++;
- int i3 = i;
- if (i < len && s.charAt(i) == ':') i++;
- String key = s.substring(i0, i1);
- String val = s.substring(i2, i3);
- map.put(key, val);
+ private static IPeer getPeer(String[] arr) {
+ ArrayList<Map<String,String>> l = new ArrayList<Map<String,String>>();
+ for (String s : arr) {
+ Map<String,String> map = new HashMap<String,String>();
+ int len = s.length();
+ int i = 0;
+ while (i < len) {
+ int i0 = i;
+ while (i < len && s.charAt(i) != '=' && s.charAt(i) != 0) i++;
+ int i1 = i;
+ if (i < len && s.charAt(i) == '=') i++;
+ int i2 = i;
+ while (i < len && s.charAt(i) != ':') i++;
+ int i3 = i;
+ if (i < len && s.charAt(i) == ':') i++;
+ String key = s.substring(i0, i1);
+ String val = s.substring(i2, i3);
+ map.put(key, val);
+ }
+ l.add(map);
}
- String id = map.get(IPeer.ATTR_ID);
+ String id = l.get(0).get(IPeer.ATTR_ID);
if (id == null) throw new Error("Invalid peer info: no ID");
IPeer peer = Protocol.getLocator().getPeers().get(id);
- if (peer instanceof RemotePeer) {
- ((RemotePeer)peer).updateAttributes(map);
- }
- else {
- peer = new RemotePeer(map);
- }
- return peer;
+ if (peer != null) throw new Error("Invalid peer info: ID is not unique");
+ return new RemotePeer(l);
}
private static void runTestSuite(IPeer peer) {
@@ -143,14 +154,14 @@ public class Main {
* "ID=Test:TransportName=TCP:Host=127.0.0.1:Port=1534"
*/
public static void main(final String[] args) {
- if (args.length != 1) {
+ if (args.length < 1) {
System.err.println("Missing command line argument - peer identification string");
System.exit(4);
}
Protocol.setEventQueue(new EventQueue());
Protocol.invokeLater(new Runnable() {
public void run() {
- runTestSuite(getPeer(args[0]));
+ runTestSuite(getPeer(args));
}
});
}

Back to the top