aboutsummaryrefslogtreecommitdiffstats
path: root/documentapi
diff options
context:
space:
mode:
Diffstat (limited to 'documentapi')
-rw-r--r--documentapi/src/main/java/com/yahoo/documentapi/VisitorControlHandler.java64
-rw-r--r--documentapi/src/main/java/com/yahoo/documentapi/VisitorControlSession.java2
-rwxr-xr-xdocumentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java11
-rw-r--r--documentapi/src/test/java/com/yahoo/documentapi/messagebus/test/VisitorControlHandlerTest.java39
4 files changed, 103 insertions, 13 deletions
diff --git a/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlHandler.java b/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlHandler.java
index b46308e0daf..4d05125f417 100644
--- a/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlHandler.java
+++ b/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlHandler.java
@@ -3,13 +3,15 @@ package com.yahoo.documentapi;
import com.yahoo.vdslib.VisitorStatistics;
+import java.time.Duration;
+
/**
* A class for controlling a visitor supplied through visitor parameters when
* creating the visitor session. The class defines callbacks for reporting
* progress and that the visitor is done. If you want to reimplement the
* default behavior of those callbacks, you can write your own subclass.
*
- * @author <a href="mailto:humbe@yahoo-inc.com">H&aring;kon Humberset</a>
+ * @author Håkon Humberset
*/
public class VisitorControlHandler {
/** Possible completion codes for visiting. */
@@ -46,6 +48,14 @@ public class VisitorControlHandler {
return "Unknown error";
}
+
+ public CompletionCode getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
};
private VisitorControlSession session;
@@ -94,6 +104,17 @@ public class VisitorControlHandler {
}
/**
+ * Returns true iff the statistics reported by the visiting session indicates at least one
+ * bucket has been completely visited.
+ *
+ * Not thread safe, so should only be called on a quiescent session after waitUntilDone
+ * has completed successfully.
+ */
+ public boolean hasVisitedAnyBuckets() {
+ return ((currentStatistics != null) && (currentStatistics.getBucketsVisited() > 0));
+ }
+
+ /**
* Callback called when the visitor is done.
*
* @param code the completion code
@@ -130,25 +151,52 @@ public class VisitorControlHandler {
* Waits until visiting is done, or the given timeout (in ms) expires.
* Will wait forever if timeout is 0.
*
- * @param timeoutMs The maximum amount of milliseconds to wait.
- * @return True if visiting is done (either by error or success).
- * @throws InterruptedException If an interrupt signal was received while waiting.
+ * @param timeout Maximum time duration to wait before returning.
+ * @return True if visiting is done (either by error or success), false if session has timed out.
+ * @throws InterruptedException If an interrupt signal was received while waiting.
*/
- public boolean waitUntilDone(long timeoutMs) throws InterruptedException {
+ public boolean waitUntilDone(Duration timeout) throws InterruptedException {
synchronized (this) {
- if (completed) return true;
- if (timeoutMs == 0) {
+ if (completed) {
+ return true;
+ }
+ if (timeout.isZero()) {
while (!completed) {
wait();
}
} else {
- wait(timeoutMs);
+ wait(timeout.toMillis());
}
return completed;
}
}
/**
+ * Waits until visiting is done, or the given timeout (in ms) expires.
+ * Will wait forever if timeout is 0.
+ *
+ * @param timeoutMs The maximum amount of milliseconds to wait.
+ * @return True if visiting is done (either by error or success), false if session has timed out.
+ * @throws InterruptedException If an interrupt signal was received while waiting.
+ *
+ * TODO deprecate this in favor of waitUntilDone(Duration)
+ */
+ public boolean waitUntilDone(long timeoutMs) throws InterruptedException {
+ return waitUntilDone(Duration.ofMillis(timeoutMs));
+ }
+
+ /**
+ * Waits until visiting is done. Session timeout implicitly completes
+ * the visitor session, but will set an unsuccessful result code.
+ *
+ * @throws InterruptedException If an interrupt signal was received while waiting.
+ */
+ public void waitUntilDone() throws InterruptedException {
+ final boolean done = waitUntilDone(Duration.ZERO);
+ assert done : "Infinite waitUntilDone timeout should always complete";
+ }
+
+ /**
* Abort this visitor
*/
public void abort() { session.abort(); }
diff --git a/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlSession.java b/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlSession.java
index 4296407d633..4218417437c 100644
--- a/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlSession.java
+++ b/documentapi/src/main/java/com/yahoo/documentapi/VisitorControlSession.java
@@ -10,7 +10,7 @@ package com.yahoo.documentapi;
* kinds of visitor sessions, such as acking visitor data and aborting the
* session.
*
- * @author <a href="mailto:humbe@yahoo-inc.com">H&aring;kon Humberset</a>
+ * @author Håkon Humberset
*/
public interface VisitorControlSession {
/**
diff --git a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
index 306103f2912..56edc7eb42a 100755
--- a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
+++ b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
@@ -883,8 +883,7 @@ public class MessageBusVisitorSession implements VisitorSession {
if (isFatalError(reply)) {
if (params.skipBucketsOnFatalErrors()) {
- progress.getToken().addFailedBucket(bucket, subProgress, message);
- progress.getIterator().update(bucket, ProgressToken.FINISHED_BUCKET);
+ markBucketProgressAsFailed(bucket, subProgress, message);
} else {
reportVisitorError(message);
transitionTo(new StateDescription(State.FAILED, message));
@@ -903,6 +902,11 @@ public class MessageBusVisitorSession implements VisitorSession {
}
}
+ private void markBucketProgressAsFailed(BucketId bucket, BucketId subProgress, String message) {
+ progress.getToken().addFailedBucket(bucket, subProgress, message);
+ progress.getIterator().update(bucket, ProgressToken.FINISHED_BUCKET);
+ }
+
private boolean enoughHitsReceived() {
if (params.getMaxFirstPassHits() != -1
&& statistics.getDocumentsReturned() >= params.getMaxFirstPassHits())
@@ -1024,7 +1028,6 @@ public class MessageBusVisitorSession implements VisitorSession {
private void handleWrongDistributionReply(WrongDistributionReply reply) {
try {
- // Classnames clash with documentapi classes, so be explicit
ClusterState newState = new ClusterState(reply.getSystemState());
int stateBits = newState.getDistributionBitCount();
if (stateBits != progress.getIterator().getDistributionBitCount()) {
@@ -1123,7 +1126,7 @@ public class MessageBusVisitorSession implements VisitorSession {
synchronized (completionMonitor) {
// If we are destroying the session before it has completed (e.g. because
// waitUntilDone timed out or an interactive visiting was interrupted)
- // set us to aborted state so that we'll seize
+ // set us to aborted state so that we'll seize sending new visitors.
if (!done) {
transitionTo(new StateDescription(State.ABORTED, "Session explicitly destroyed before completion"));
}
diff --git a/documentapi/src/test/java/com/yahoo/documentapi/messagebus/test/VisitorControlHandlerTest.java b/documentapi/src/test/java/com/yahoo/documentapi/messagebus/test/VisitorControlHandlerTest.java
new file mode 100644
index 00000000000..d8340e6a3f6
--- /dev/null
+++ b/documentapi/src/test/java/com/yahoo/documentapi/messagebus/test/VisitorControlHandlerTest.java
@@ -0,0 +1,39 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.documentapi.messagebus.test;
+
+import com.yahoo.documentapi.VisitorControlHandler;
+import com.yahoo.vdslib.VisitorStatistics;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class VisitorControlHandlerTest {
+
+ @Test
+ public void has_visited_any_buckets_is_false_if_no_bucket_stats_recorded() {
+ VisitorControlHandler handler = new VisitorControlHandler();
+ assertFalse(handler.hasVisitedAnyBuckets());
+ }
+
+ @Test
+ public void has_visited_any_buckets_is_false_if_zero_buckets_visited() {
+ VisitorControlHandler handler = new VisitorControlHandler();
+ VisitorStatistics stats = new VisitorStatistics();
+ stats.setBucketsVisited(0);
+ handler.onVisitorStatistics(stats);
+
+ assertFalse(handler.hasVisitedAnyBuckets());
+ }
+
+ @Test
+ public void has_visited_any_buckets_is_true_if_more_than_zero_buckets_visited() {
+ VisitorControlHandler handler = new VisitorControlHandler();
+ VisitorStatistics stats = new VisitorStatistics();
+ stats.setBucketsVisited(1);
+ handler.onVisitorStatistics(stats);
+
+ assertTrue(handler.hasVisitedAnyBuckets());
+ }
+
+}