Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance message system with StaticType #1289

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/main/java/org/myrobotlab/codec/CodecUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.myrobotlab.framework.MethodCache;
import org.myrobotlab.framework.Platform;
import org.myrobotlab.framework.StaticType;
import org.myrobotlab.framework.interfaces.ServiceInterface;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.logging.LoggingFactory;
Expand Down Expand Up @@ -488,7 +489,6 @@ public static String getFullName(String name) {
if (name == null) {
return null;
}

if (getId(name) == null) {
return name + '@' + Platform.getLocalInstance().getId();
} else {
Expand All @@ -499,7 +499,7 @@ public static String getFullName(String name) {
/**
* Checks whether two service names are equal by first normalizing each. If a
* name does not have a runtime ID, it is assumed to be a local service.
*
*
* @param name1
* The first service name
* @param name2
Expand All @@ -510,6 +510,7 @@ public static boolean checkServiceNameEquality(String name1, String name2) {
return Objects.equals(getFullName(name1), getFullName(name2));
}


/**
* Converts a topic method name to the name of the method that is used for
* callbacks. Usually this involves prepending the string "on", removing any
Expand Down Expand Up @@ -674,6 +675,14 @@ static public String getServiceType(String inType) {
// falls back to virt class field
boolean useVirtClassField = clazz == null;
if (!useVirtClassField) {
// For blocking send return type checking
ServiceInterface si = Runtime.getService(serviceName);
String blockingKey = String.format("%s.%s", msg.getFullName(), msg.getMethod());
if (si != null && Message.MSG_TYPE_RETURN.equals(msg.msgType) && si.getInbox().blockingList.containsKey(blockingKey)) {
msg.data[0] = fromJson((String) msg.data[0], si.getInbox().blockingList.get(blockingKey).second);
msg.encoding = null;
return msg;
}
try {
Object[] params = MethodCache.getInstance().getDecodedJsonParameters(clazz, msg.method, msg.data);
if (params == null)
Expand Down
25 changes: 18 additions & 7 deletions src/main/java/org/myrobotlab/framework/Inbox.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.myrobotlab.framework.interfaces.MessageListener;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.utils.ObjectTypePair;
import org.slf4j.Logger;

public class Inbox implements Serializable {
Expand All @@ -50,9 +52,16 @@ public class Inbox implements Serializable {
// value

// support remote blocking... in-process blocking uses invoke
public HashMap<String, Object[]> blockingList = new HashMap<>();
/**
* Maps blocking keys ("fullName.method") to an
* ObjectTypePair that is used to store the return
* type and return value. DO NOT SET THE VALUE
* TO A NEW OBJECT, we are synchronizing on the values,
* doing so will result in the threads never waking up.
*/
public Map<String, ObjectTypePair<?>> blockingList = new HashMap<>();

List<MessageListener> listeners = new ArrayList<MessageListener>();
List<MessageListener> listeners = new ArrayList<>();

public Inbox() {
this("Inbox");
Expand All @@ -62,6 +71,7 @@ public Inbox(String name) {
this.name = name;
}

@SuppressWarnings("unchecked")
public void add(Message msg) {
/**
* <pre>
Expand All @@ -74,16 +84,17 @@ public void add(Message msg) {
*/

// --- sendBlocking support begin --------------------
// TODO - possible safety check msg.status == Message.RETURN
// &&
String blockingKey = String.format("%s.%s", msg.getFullName(), msg.getMethod());
if (blockingList.containsKey(blockingKey)) {
Object[] returnContainer = blockingList.get(blockingKey);
// Generates an unchecked warning because of generic invariance, but we don't care
ObjectTypePair<Object> returnContainer = (ObjectTypePair<Object>) blockingList.get(blockingKey);
if (msg.data == null) {
returnContainer[0] = null;
returnContainer.first = null;
} else {
// transferring data
returnContainer[0] = msg.data[0];
// Would not be able to do this if returnContainer had wildcard generic type,
// which is why it's Object
returnContainer.first = msg.data[0];
}

synchronized (returnContainer) {
Expand Down
35 changes: 26 additions & 9 deletions src/main/java/org/myrobotlab/framework/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ public class Message implements Serializable {

private static final long serialVersionUID = 1L;

/**
* A message has this type if it is sent with the expectation that a return
* message will be received. Services should always respond
* with a return message after invoking the blocking message.
*
* @see #MSG_TYPE_RETURN
*/
public static final String MSG_TYPE_BLOCKING = "BLOCKING";

/**
* A message has this type when it contains a single data
* element meant to represent a service method return value.
* The type of the return value is not explicitly carried with the message,
* since it can cross language boundaries.
*/
public static final String MSG_TYPE_RETURN = "RETURN";

// FIXME msgId should be a String encoded value of src and an atomic increment
// ROS comes with a seq Id, a timestamp, and a frame Id
/**
Expand Down Expand Up @@ -74,8 +91,7 @@ public class Message implements Serializable {
* history of the message, its routing stops and Services it passed through.
* This is important to prevent endless looping of messages. Turns out
* ArrayList is quicker than HashSet on small sets
* http://www.javacodegeeks.com
* /2010/08/java-best-practices-vector-arraylist.html
* <a href="http://www.javacodegeeks.com/2010/08/java-best-practices-vector-arraylist.html">Java Best Practices</a>
*/
protected List<String> historyList;

Expand All @@ -88,11 +104,12 @@ public class Message implements Serializable {

/**
* status is currently used for BLOCKING message calls the current valid state
* it can be in is null | BLOCKING | RETURN FIXME - this should be msgType not
* status
* it can be in is null | BLOCKING | RETURN
*
* @see #MSG_TYPE_BLOCKING
* @see #MSG_TYPE_RETURN
*/

public String status;
public String msgType;

public String encoding; // null == none |json|cli|xml|stream ...

Expand Down Expand Up @@ -151,7 +168,7 @@ final public void set(final Message other) {
historyList = new ArrayList<String>();
historyList.addAll(other.historyList);

status = other.status;
msgType = other.msgType;
encoding = other.encoding;
method = other.method;
// you know the dangers of reference copy
Expand Down Expand Up @@ -299,7 +316,7 @@ public boolean equals(Object o) {
&& Objects.equals(sendingMethod, message.sendingMethod)
&& Objects.equals(historyList, message.historyList)
&& Objects.equals(properties, message.properties)
&& Objects.equals(status, message.status)
&& Objects.equals(msgType, message.msgType)
&& Objects.equals(encoding, message.encoding)
&& Objects.equals(method, message.method)
&& Arrays.deepEquals(data, message.data);
Expand All @@ -310,7 +327,7 @@ public int hashCode() {
int result = Objects.hash(
msgId, name, sender,
sendingMethod, historyList,
properties, status, encoding,
properties, msgType, encoding,
method
);
result = 31 * result + Arrays.hashCode(data);
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/org/myrobotlab/framework/Outbox.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ public void run() {
continue;
}

for (int i = 0; i < subList.size(); ++i) {
MRLListener listener = subList.get(i);
for (MRLListener listener : subList) {
msg.setName(listener.callbackName);
msg.method = listener.callbackMethod;

Expand Down
Loading