Refactor, add documentation; fix timeouts
diff --git a/src/main/java/com/intel/jndn/utils/Client.java b/src/main/java/com/intel/jndn/utils/Client.java
index 269fe5c..3425950 100644
--- a/src/main/java/com/intel/jndn/utils/Client.java
+++ b/src/main/java/com/intel/jndn/utils/Client.java
@@ -26,6 +26,7 @@
import org.apache.logging.log4j.Logger;
/**
+ * Provide a client to simplify information retrieval over the NDN network.
*
* @author Andrew Brown <andrew.brown@intel.com>
*/
@@ -34,6 +35,19 @@
public static final long DEFAULT_SLEEP_TIME = 20;
public static final long DEFAULT_TIMEOUT = 2000;
private static final Logger logger = LogManager.getLogger();
+ private static Client defaultInstance;
+
+ /**
+ * Singleton access for simpler client use
+ *
+ * @return
+ */
+ public static Client getDefault() {
+ if (defaultInstance == null) {
+ defaultInstance = new Client();
+ }
+ return defaultInstance;
+ }
/**
* Synchronously retrieve the Data for an Interest; this will block until
@@ -46,23 +60,19 @@
public Data getSync(Face face, Interest interest) {
// setup event
long startTime = System.currentTimeMillis();
- final ClientObservableEvent event = new ClientObservableEvent(); // this event is used without observer/observables for speed; just serves as a final reference into the callbacks
+ final ClientEvent event = new ClientEvent(); // this event is used without observer/observables for speed; just serves as a final reference into the callbacks
// send interest
try {
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
- event.setTimestamp(System.currentTimeMillis());
- event.setSuccess(true);
- event.setPacket(data);
+ event.fromPacket(data);
}
}, new OnTimeout() {
@Override
public void onTimeout(Interest interest) {
- event.setTimestamp(System.currentTimeMillis());
- event.setSuccess(false);
- event.setPacket(new Object());
+ event.fromPacket(new Exception("Interest timed out: " + interest.getName().toUri()));
}
});
} catch (IOException e) {
@@ -70,7 +80,7 @@
return null;
}
- // process events until a response is received or timeout
+ // process eventCount until a response is received or timeout
while (event.getPacket() == null) {
try {
synchronized (face) {
@@ -103,8 +113,19 @@
/**
* Asynchronously retrieve the Data for a given interest; use the returned
- * ClientObserver to handle the Data when it arrives. E.g.: Client.get(face,
- * interest).then((data) -> doSomething(data));
+ * ClientObserver to handle the Data when it arrives. For example (with lambdas):
+ * <pre><code>
+ * Client.getDefault().get(face, interest).then((event) -> doSomething(event));
+ * </code></pre>
+ *
+ * If you want to block until the response returns, try something like:
+ * <pre><code>
+ * ClientObserver observer = Client.getDefault().get(face, interest);
+ * while(observer.eventCount() == 0){
+ * Thread.sleep(50);
+ * }
+ * doSomething(observer.getFirst());
+ * </code></pre>
*
* @param face
* @param interest
@@ -128,8 +149,8 @@
eventHandler.notify(e);
}
- // process events until a response is received or timeout
- while (observer.responses() == 0 && observer.errors() == 0 && !observer.mustStop()) {
+ // process eventCount until a response is received or timeout
+ while (observer.dataCount() == 0 && observer.errorCount() == 0 && !observer.mustStop()) {
try {
synchronized (face) {
face.processEvents();
@@ -140,7 +161,7 @@
}
sleep();
}
-
+
// finished
logger.trace("Received response; stopping thread.");
}
@@ -178,7 +199,7 @@
// setup event
long startTime = System.currentTimeMillis();
final String dataName = data.getName().toUri();
- final ClientObservableEvent event = new ClientObservableEvent();
+ final ClientEvent event = new ClientEvent();
// setup flags
ForwardingFlags flags = new ForwardingFlags();
@@ -213,7 +234,7 @@
event.fromPacket(e);
}
- // process events until one response is sent or error
+ // process eventCount until one response is sent or error
while (event.getPacket() == null) {
try {
synchronized (face) {
@@ -284,15 +305,15 @@
eventHandler.onError(e);
}
- // process events until a request is received
- while (observer.requests() == 0 && observer.errors() == 0 && !observer.mustStop()) {
+ // process eventCount until a request is received
+ while (observer.interestCount() == 0 && observer.errorCount() == 0 && !observer.mustStop()) {
try {
synchronized (face) {
face.processEvents();
}
} catch (IOException | EncodingException e) {
logger.warn("Failed to process events.", e);
- observer.update(eventHandler, new ClientObservableEvent());
+ observer.update(eventHandler, new ClientEvent());
}
sleep();
}
diff --git a/src/main/java/com/intel/jndn/utils/ClientEvent.java b/src/main/java/com/intel/jndn/utils/ClientEvent.java
new file mode 100644
index 0000000..a125286
--- /dev/null
+++ b/src/main/java/com/intel/jndn/utils/ClientEvent.java
@@ -0,0 +1,77 @@
+/*
+ * File name: ClientEvent.java
+ *
+ * Purpose: Signals a Client event for observers to act on
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.utils;
+
+/**
+ * Signals a Client event for observers to act on
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class ClientEvent<T> {
+
+ protected boolean success;
+ protected long timestamp;
+ protected T packet;
+
+ /**
+ * Constructor
+ */
+ public ClientEvent() {
+ timestamp = System.currentTimeMillis();
+ success = false; // an event without a packet is a failed event
+ }
+
+ /**
+ * Constructor
+ *
+ * @param packet
+ */
+ public ClientEvent(T packet) {
+ fromPacket(packet);
+ }
+
+ /**
+ * Build this event from a passed packet; the event is considered a failure
+ * if the packet is any type of Exception
+ *
+ * @param packet
+ */
+ public final void fromPacket(T packet) {
+ this.timestamp = System.currentTimeMillis();
+ this.success = !Exception.class.isInstance(packet);
+ this.packet = packet;
+ }
+
+ /**
+ * Retrieve success status
+ *
+ * @return
+ */
+ public boolean isSuccess() {
+ return success;
+ }
+
+ /**
+ * Retrieve event timestamp
+ *
+ * @return
+ */
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * Retrieve event packet
+ *
+ * @return
+ */
+ public T getPacket() {
+ return packet;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/utils/ClientObservable.java b/src/main/java/com/intel/jndn/utils/ClientObservable.java
index ce6beda..0a4b341 100644
--- a/src/main/java/com/intel/jndn/utils/ClientObservable.java
+++ b/src/main/java/com/intel/jndn/utils/ClientObservable.java
@@ -26,7 +26,7 @@
*/
public class ClientObservable extends Observable implements OnData, OnTimeout, OnInterest {
- protected List<ClientObservableEvent> events = new ArrayList<>();
+ protected List<ClientEvent> events = new ArrayList<>();
protected List<Interest> incomingInterestPackets = new ArrayList<>();
protected List<Data> incomingDataPackets;
@@ -38,7 +38,7 @@
*/
public <T> void notify(T packet) {
setChanged();
- notifyObservers(new ClientObservableEvent(packet));
+ notifyObservers(new ClientEvent(packet));
}
/**
@@ -68,7 +68,7 @@
*/
@Override
public void onTimeout(Interest interest) {
- notify(interest);
+ notify(new Exception("Interest timed out: " + interest.getName().toUri()));
}
/**
diff --git a/src/main/java/com/intel/jndn/utils/ClientObservableEvent.java b/src/main/java/com/intel/jndn/utils/ClientObservableEvent.java
deleted file mode 100644
index af2a614..0000000
--- a/src/main/java/com/intel/jndn/utils/ClientObservableEvent.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * File name: ClientObservableEvent.java
- *
- * Purpose:
- *
- * © Copyright Intel Corporation. All rights reserved.
- * Intel Corporation, 2200 Mission College Boulevard,
- * Santa Clara, CA 95052-8119, USA
- */
-package com.intel.jndn.utils;
-
-/**
- *
- * @author Andrew Brown <andrew.brown@intel.com>
- */
-public class ClientObservableEvent<T> {
-
- boolean success;
- long timestamp;
- T packet;
-
- public ClientObservableEvent(T packet) {
- fromPacket(packet);
- }
-
- public ClientObservableEvent() {
- timestamp = System.currentTimeMillis();
- success = false;
- }
-
- public final void fromPacket(T packet_) {
- timestamp = System.currentTimeMillis();
- success = !Exception.class.isInstance(packet_);
- packet = packet_;
- }
-
- public boolean isSuccess() {
- return success;
- }
-
- public void setSuccess(boolean success) {
- this.success = success;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public void setTimestamp(long timestamp) {
- this.timestamp = timestamp;
- }
-
- public T getPacket() {
- return packet;
- }
-
- public void setPacket(T packet) {
- this.packet = packet;
- }
-
-}
diff --git a/src/main/java/com/intel/jndn/utils/ClientObserver.java b/src/main/java/com/intel/jndn/utils/ClientObserver.java
index 0ed4e11..9bfdd7e 100644
--- a/src/main/java/com/intel/jndn/utils/ClientObserver.java
+++ b/src/main/java/com/intel/jndn/utils/ClientObserver.java
@@ -1,7 +1,7 @@
/*
* File name: ClientObserver.java
*
- * Purpose:
+ * Purpose: Track asynchronous events from Client and provide simplified API
*
* © Copyright Intel Corporation. All rights reserved.
* Intel Corporation, 2200 Mission College Boulevard,
@@ -23,9 +23,9 @@
*/
public class ClientObserver implements Observer {
- protected List<ClientObservableEvent> events = new ArrayList<>();
+ protected List<ClientEvent> events = new ArrayList<>();
protected long timestamp;
- protected OnData then;
+ protected OnEvent then;
protected boolean stopThread;
/**
@@ -43,26 +43,62 @@
*/
@Override
public void update(Observable o, Object arg) {
- ClientObservableEvent event = (ClientObservableEvent) arg;
+ ClientEvent event = (ClientEvent) arg;
events.add(event);
// call onData callbacks
if (Data.class.isInstance(event.packet) && then != null) {
- then.onData(null, (Data) event.packet);
+ then.onEvent(event);
}
}
/**
- * Register a handler for data packets
+ * Register a handler for events
*
- * @param handler
+ * @param callback
* @return
*/
- public ClientObserver then(OnData handler) {
- then = handler;
+ public ClientObserver then(OnEvent callback) {
+ then = callback;
return this;
}
/**
+ * Count the number of eventCount observed
+ *
+ * @return
+ */
+ public int eventCount() {
+ return events.size();
+ }
+
+ /**
+ * Count the number of interest packets observed (received or sent)
+ *
+ * @return
+ */
+ public int interestCount() {
+ return count(Interest.class);
+ }
+
+ /**
+ * Count the number of Data packets observed
+ *
+ * @return
+ */
+ public int dataCount() {
+ return count(Data.class);
+ }
+
+ /**
+ * Count the number of errors observed
+ *
+ * @return
+ */
+ public int errorCount() {
+ return count(Exception.class);
+ }
+
+ /**
* Count the number of observed packets by type
*
* @param type
@@ -70,7 +106,7 @@
*/
public int count(Class type) {
int count = 0;
- for (ClientObservableEvent event : events) {
+ for (ClientEvent event : events) {
if (type.isInstance(event.packet)) {
count++;
}
@@ -79,34 +115,8 @@
}
/**
- * Count the number of interest packets observed (received or sent)
- *
- * @return
- */
- public int requests() {
- return count(Interest.class);
- }
-
- /**
- * Count the number of Data packets observed
- *
- * @return
- */
- public int responses() {
- return count(Data.class);
- }
-
- /**
- * Count the number of errors
- *
- * @return
- */
- public int errors() {
- return count(Exception.class);
- }
-
- /**
- * Get time since observer start
+ * Calculate time elapsed since observer started observing until this method
+ * is called
*
* @return
*/
@@ -118,11 +128,20 @@
}
/**
- * Retrieve first event
+ * Retrieve a list of observed events
*
* @return event or null
*/
- public ClientObservableEvent getFirst() {
+ public List<ClientEvent> getEvents() {
+ return events;
+ }
+
+ /**
+ * Retrieve the first event
+ *
+ * @return event or null
+ */
+ public ClientEvent getFirst() {
if (events.size() > 0) {
return events.get(0);
}
@@ -130,11 +149,11 @@
}
/**
- * Retrieve last event
+ * Retrieve the last event
*
* @return event or null
*/
- public ClientObservableEvent getLast() {
+ public ClientEvent getLast() {
if (events.size() > 0) {
return events.get(events.size() - 1);
}
@@ -142,14 +161,16 @@
}
/**
- * Stop the current Client thread
+ * Stop the current Client thread; used by asynchronous Client methods to
+ * stop the request/response thread
*/
public void stop() {
stopThread = true;
}
/**
- * Check the current stop status
+ * Check the current stop status; used by asynchronous Client methods to
+ * stop the request/response thread
*
* @return
*/
diff --git a/src/main/java/com/intel/jndn/utils/OnEvent.java b/src/main/java/com/intel/jndn/utils/OnEvent.java
new file mode 100644
index 0000000..e9c7f67
--- /dev/null
+++ b/src/main/java/com/intel/jndn/utils/OnEvent.java
@@ -0,0 +1,20 @@
+/*
+ * File name: OnEvent.java
+ *
+ * Purpose: Interface for registering generic event handlers
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.utils;
+
+/**
+ * Interface for registering generic event handlers. E.g.: observer.then((event)
+ * => doSomething(event.getFirst()));
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public interface OnEvent {
+ public void onEvent(ClientEvent event);
+}