Skip to content

Commit 024f795

Browse files
committed
Refactor and Debug
Fixed multiple publisher/subscriber bug
1 parent c3092bc commit 024f795

20 files changed

+111
-204
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
*.class
3+
*.jar

src/main/java/org/ros/internal/node/DefaultNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public <T> Publisher<T> newPublisher(GraphName topicName, String messageType) {
258258
TopicDeclaration.newFromTopicName(resolvedTopicName, topicDescription);
259259
Publisher<T> publisher = null;
260260
try {
261-
publisher = publisherFactory.newOrExisting(topicDeclaration, slaveServer.getSubscribers());
261+
publisher = publisherFactory.newOrExisting(topicDeclaration);
262262
} catch(IOException e) { throw new RosRuntimeException(e); }
263263
return publisher;
264264
}

src/main/java/org/ros/internal/node/server/SlaveServer.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,7 @@ public SlaveServer(GraphName nodeName, BindAddress tcpRosBindAddress,
7979
public AdvertiseAddress getTcpRosAdvertiseAddress() {
8080
return tcpRosServer.getAdvertiseAddress();
8181
}
82-
/**
83-
* Return the ChannelHandlerContext array of subscribers
84-
* @return
85-
*/
86-
public ArrayBlockingQueue<ChannelHandlerContext> getSubscribers() {
87-
return tcpRosServer.getSubscribers();
88-
}
82+
8983
/**
9084
* Start the RPC server. This start() routine requires that the
9185
* {@link TcpRosServer} is initialized first so that the slave server returns

src/main/java/org/ros/internal/node/topic/DefaultPublisher.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ public class DefaultPublisher<T> extends DefaultTopicParticipant implements Publ
5959
private final ArrayBlockingQueue<ChannelHandlerContext> subscribers;
6060

6161
public DefaultPublisher(NodeIdentifier nodeIdentifier, TopicDeclaration topicDeclaration,
62-
MessageFactory messageFactory, ScheduledExecutorService executorService, ArrayBlockingQueue<ChannelHandlerContext> arrayBlockingQueue) throws IOException {
62+
MessageFactory messageFactory, ScheduledExecutorService executorService) throws IOException {
6363
super(topicDeclaration);
6464
this.nodeIdentifier = nodeIdentifier;
6565
this.messageFactory = messageFactory;
66-
this.subscribers = arrayBlockingQueue;
67-
outgoingMessageQueue = new OutgoingMessageQueue<T>(executorService, arrayBlockingQueue);
66+
this.subscribers = new ArrayBlockingQueue<ChannelHandlerContext>(1024);
67+
outgoingMessageQueue = new OutgoingMessageQueue<T>(executorService, subscribers);
6868
if(DEBUG)
6969
log.info("DefaultPublisher contructed with "+outgoingMessageQueue.getNumberOfChannels()+" channels.");
7070
listeners = new ListenerGroup<PublisherListener<T>>(executorService);
@@ -203,7 +203,19 @@ public void addSubscriber(SubscriberIdentifier subscriberIdentifer, ChannelHandl
203203
//outgoingMessageQueue.addChannel(ctx);
204204
subscribers.add(ctx);
205205
if (DEBUG) {
206-
log.info("Current number of subscribers:"+subscribers.size());
206+
StringBuilder sb = new StringBuilder();
207+
sb.append(subscribers.size());
208+
sb.append("Subscribers for publisher ");
209+
sb.append(toDeclaration());
210+
sb.append(":\r\n");
211+
Object[] sa = subscribers.toArray();
212+
for(int i = 0; i < subscribers.size(); i++) {
213+
sb.append(i);
214+
sb.append(") ");
215+
sb.append(sa[i]);
216+
sb.append("\r\n");
217+
}
218+
log.info(sb.toString());
207219
}
208220
signalOnNewSubscriber(subscriberIdentifer);
209221
}

src/main/java/org/ros/internal/node/topic/DefaultSubscriber.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,7 @@ public void addPublisher(PublisherIdentifier publisherIdentifier, InetSocketAddr
157157
log.info("Defaultsubscriber addPublisher topicParticipantManager DOES NOT CONTAIN "+publisherIdentifier+" at "+address);
158158
topicParticipantManager.addSubscriberConnection(this, publisherIdentifier);
159159
}
160-
tcpClientManager.connect(toString(), address);
161-
// TODO(damonkohler): knownPublishers is duplicate information that is
162-
// already available to the TopicParticipantManager.
163-
//knownPublishers.add(publisherIdentifier);
160+
tcpClientManager.connect(toString(), address);
164161
signalOnNewPublisher(publisherIdentifier);
165162
}
166163
}

src/main/java/org/ros/internal/node/topic/PublisherFactory.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,19 @@ public PublisherFactory(NodeIdentifier nodeIdentifier,
4141
*
4242
* @param <T> the message type associated with the {@link Publisher}
4343
* @param topicDeclaration {@link TopicDeclaration} that is being published
44-
* @param arrayBlockingQueue
4544
* @param messageSerializer the {@link MessageSerializer} used for published messages
4645
* @return a new or cached {@link Publisher} instance
4746
* @throws IOException
4847
*/
4948
@SuppressWarnings("unchecked")
50-
public <T> Publisher<T> newOrExisting(TopicDeclaration topicDeclaration, ArrayBlockingQueue<ChannelHandlerContext> arrayBlockingQueue) throws IOException {
49+
public <T> Publisher<T> newOrExisting(TopicDeclaration topicDeclaration) throws IOException {
5150
GraphName topicName = topicDeclaration.getName();
5251
synchronized (mutex) {
5352
if (topicParticipantManager.hasPublisher(topicName)) {
5453
return (DefaultPublisher<T>) topicParticipantManager.getPublisher(topicName);
5554
} else {
5655
DefaultPublisher<T> publisher =
57-
new DefaultPublisher<T>(nodeIdentifier, topicDeclaration, messageFactory, executorService, arrayBlockingQueue);
56+
new DefaultPublisher<T>(nodeIdentifier, topicDeclaration, messageFactory, executorService);
5857
publisher.addListener(new DefaultPublisherListener<T>() {
5958
@Override
6059
public void onNewSubscriber(Publisher<T> publisher, SubscriberIdentifier subscriberIdentifier) {

src/main/java/org/ros/internal/transport/ChannelHandlerContext.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.Set;
1111
import java.util.concurrent.Executor;
1212

13-
import org.ros.internal.transport.tcp.ChannelGroup;
1413

1514
/**
1615
* This is the ChannelHandlerContext that links the underlying TCP Socket 'channel' to the {@link ChannelPipeline} and the {@link ChannelGroup}
@@ -96,12 +95,6 @@ public interface ChannelHandlerContext {
9695
*/
9796
ChannelPipeline pipeline();
9897

99-
/**
100-
* Return the channel group
101-
*
102-
*/
103-
/*Asynchronous*/ChannelGroup getChannelGroup();
104-
10598
/**
10699
* Determine if this channel is ready for processing, it is configured, has a socket
107100
* and the communication is sound. If the socket breaks this goes false and no writes are
@@ -114,12 +107,6 @@ public interface ChannelHandlerContext {
114107
* @param ready
115108
*/
116109
void setReady(boolean ready);
117-
118-
/**
119-
* Get the Object representing a mutex to use for completion of operation if necessary.
120-
* @return
121-
*/
122-
Object getChannelCompletionMutex();
123110

124111
/**
125112
* Each successive handshake completion will add another message type to this synchronized set.

src/main/java/org/ros/internal/transport/ChannelHandlerContextImpl.java

Lines changed: 40 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
import org.apache.commons.logging.Log;
1717
import org.apache.commons.logging.LogFactory;
18-
import org.ros.internal.transport.tcp.ChannelGroup;
19-
2018

2119
/**
2220
* A handler context contains all the executor, the channel group, the channel, and the pipeline with the handlers.
@@ -30,27 +28,24 @@
3028
* The functions of the system move data through the pipeline, triggering the handlers in the sequence they were
3129
* added.
3230
* Traffic is filtered to subscriber channels via the hash set of requested message types
33-
* @author jg
31+
* @author Jonathan Groff Copyright (C) NeoCoreTechs 2017,2022
3432
*
3533
*/
3634
public class ChannelHandlerContextImpl implements ChannelHandlerContext {
3735
private static final boolean DEBUG = false;
3836
private static final Log log = LogFactory.getLog(ChannelHandlerContextImpl.class);
39-
/*Asynchronous*/ChannelGroup channelGroup;
4037
/*Asynchronous*/Socket/*Channel*/ channel;
38+
private Executor executor;
4139
ChannelPipeline pipeline;
4240
boolean ready = false;
43-
private Object mutex = new Object();
4441
Set<String> outboundMessageTypes;
45-
InputStream is = null;
46-
OutputStream os = null;
47-
ObjectInputStream ois = null;
4842

49-
public ChannelHandlerContextImpl(/*Asynchronous*/ChannelGroup channelGroup2, /*Asynchronous*/Socket channel2) {
50-
channelGroup = channelGroup2;
51-
channel = channel2;
52-
pipeline = new ChannelPipelineImpl(this);
53-
outboundMessageTypes = (Set<String>) new HashSet<String>();
43+
44+
public ChannelHandlerContextImpl(Executor executor, /*Asynchronous*/Socket channel) {
45+
this.executor = executor;
46+
this.channel = channel;
47+
this.pipeline = new ChannelPipelineImpl(this);
48+
this.outboundMessageTypes = (Set<String>) new HashSet<String>();
5449
}
5550

5651
public void setChannel(/*Asynchronous*/Socket/*Channel*/ sock) {
@@ -59,7 +54,7 @@ public void setChannel(/*Asynchronous*/Socket/*Channel*/ sock) {
5954

6055
@Override
6156
public Executor executor() {
62-
return channelGroup.getExecutorService();
57+
return executor;
6358
}
6459

6560
@Override
@@ -115,52 +110,51 @@ public void close() throws IOException {
115110

116111
@Override
117112
public Object read() throws IOException {
118-
is = channel.getInputStream();
119-
//ObjectInputStream ois = new ObjectInputStream(is);
120-
ois = new ObjectInputStream(is);
121-
try {
122-
return ois.readObject();
123-
} catch (ClassNotFoundException e) {
124-
throw new IOException(e);
125-
} catch(StreamCorruptedException sce) {
126-
is = channel.getInputStream();
127-
ois = new ObjectInputStream(is);
113+
InputStream is = channel.getInputStream();
114+
ObjectInputStream ois = new ObjectInputStream(is);
128115
try {
129116
return ois.readObject();
130-
} catch (ClassNotFoundException cnf) {
131-
throw new IOException(cnf);
117+
} catch (ClassNotFoundException e) {
118+
throw new IOException(e);
119+
} catch(StreamCorruptedException sce) {
120+
is = channel.getInputStream();
121+
ois = new ObjectInputStream(is);
122+
try {
123+
return ois.readObject();
124+
} catch (ClassNotFoundException cnf) {
125+
throw new IOException(cnf);
126+
}
132127
}
133-
}
134128
}
135129

136130
@Override
137131
public void write(Object msg) throws IOException {
138-
os = channel.getOutputStream();
139-
ObjectOutputStream oos = new ObjectOutputStream(os);
140-
oos.writeObject(msg);
141-
oos.flush();
132+
OutputStream os = channel.getOutputStream();
133+
ObjectOutputStream oos = new ObjectOutputStream(os);
134+
oos.writeObject(msg);
135+
oos.flush();
142136
}
143137

144138
@Override
145139
public void write(Object msg, CompletionHandler<Integer, Void> handler) {
146-
try {
147-
write(msg);
148-
handler.completed(0, null);
149-
} catch (IOException e) {
150-
handler.failed(e, null);
151-
}
140+
try {
141+
write(msg);
142+
handler.completed(0, null);
143+
} catch (IOException e) {
144+
handler.failed(e, null);
145+
}
152146
}
153147

154148
@Override
155149
public Object read(CompletionHandler<Integer, Void> handler) {
156-
try {
157-
Object o = read();
158-
handler.completed(0, null);
159-
return o;
160-
} catch (IOException e) {
161-
handler.failed(e, null);
162-
}
163-
return null;
150+
try {
151+
Object o = read();
152+
handler.completed(0, null);
153+
return o;
154+
} catch (IOException e) {
155+
handler.failed(e, null);
156+
}
157+
return null;
164158
}
165159

166160

@@ -169,19 +163,14 @@ public ChannelPipeline pipeline() {
169163
return pipeline;
170164
}
171165

172-
@Override
173-
public /*Asynchronous*/ChannelGroup getChannelGroup() {
174-
return channelGroup;
175-
}
176-
177166
@Override
178167
public Socket channel() {
179168
return channel;
180169
}
181170

182171
@Override
183172
public String toString() {
184-
return new String("ChannelHandlerContext:"+channel+" ChannelGroup:"+channelGroup+" ChannelPipeline:"+pipeline+" ready:"+ready);
173+
return new String("ChannelHandlerContext:"+channel+" ChannelPipeline:"+pipeline+" ready:"+ready);
185174
}
186175

187176
@Override
@@ -194,13 +183,6 @@ public boolean isReady() {
194183
*/
195184
@Override
196185
public void setReady(boolean ready) { this.ready = ready;}
197-
198-
/**
199-
* Object to synchronize read and write completion for the channel in this context, since we will have
200-
* multiple outbound writers accessing the same channel
201-
*/
202-
@Override
203-
public Object getChannelCompletionMutex() { return mutex; }
204186

205187
/**
206188
* Get the type of messages we want to send to the attached subscriber, based on the handshakes

src/main/java/org/ros/internal/transport/queue/OutgoingMessageQueue.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
import java.io.IOException;
44
import java.nio.ByteBuffer;
55
import java.nio.channels.Channel;
6-
import java.nio.channels.CompletionHandler;
7-
import java.nio.channels.WritePendingException;
6+
87
import java.util.Iterator;
9-
import java.util.List;
108
import java.util.concurrent.ArrayBlockingQueue;
11-
import java.util.concurrent.CountDownLatch;
129
import java.util.concurrent.ExecutorService;
1310

1411
import org.apache.commons.logging.Log;
@@ -30,7 +27,7 @@
3027
*/
3128
public class OutgoingMessageQueue<T> {
3229

33-
private static final boolean DEBUG = false;
30+
private static final boolean DEBUG = true;
3431
private static final Log log = LogFactory.getLog(OutgoingMessageQueue.class);
3532

3633
private static final int DEQUE_CAPACITY = 16;
@@ -119,14 +116,14 @@ public void failed(Throwable arg0, Void arg1) {
119116
} // loop method
120117
}
121118

122-
public OutgoingMessageQueue(ExecutorService executorService, ArrayBlockingQueue<ChannelHandlerContext> arrayBlockingQueue) throws IOException {
119+
public OutgoingMessageQueue(ExecutorService executorService, ArrayBlockingQueue<ChannelHandlerContext> subscriberQueue) throws IOException {
123120
deque = new CircularBlockingDeque<T>(DEQUE_CAPACITY);
124121
writer = new Writer();
125122
//messageBufferPool = new MessageBufferPool();
126123
latchedBuffer = MessageBuffers.dynamicBuffer();
127124
mutex = new Object();
128125
latchMode = false;
129-
channels = arrayBlockingQueue;
126+
channels = subscriberQueue;
130127
executorService.execute(writer);
131128
}
132129

0 commit comments

Comments
 (0)