All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.documentapi.VisitorControlHandler Maven / Gradle / Ivy

// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
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 Håkon Humberset
 */
public class VisitorControlHandler {
    /** Possible completion codes for visiting. */
    public enum CompletionCode {
        /** Visited all specified data successfully. */
        SUCCESS,
        /** Aborted by user. */
        ABORTED,
        /** Fatal failure. */
        FAILURE,
        /** Create visitor reply did not return within the specified timeframe, or the session timed out. */
        TIMEOUT
    };

    /**
     * The result of the visitor, containing a completion code and an optional
     * error message.
     */
    public class Result {
        public CompletionCode code;
        public String message;

        public String toString() {
            switch(code) {
            case SUCCESS:
                return "OK: " + message;
            case ABORTED:
                return "ABORTED: " + message;
            case FAILURE:
                return "FAILURE: " + message;
            case TIMEOUT:
                return "TIMEOUT: " + message;
            }

            return "Unknown error";
        }

        public CompletionCode getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }
    };

    private VisitorControlSession session;
    private ProgressToken currentProgress;
    private boolean completed = false;
    private Result result;
    private VisitorStatistics currentStatistics;

    /**
     * Called before the visitor starts. Override this method if you need
     * to reset local data. Remember to call the superclass' method as well.
     */
    public void reset() {
        synchronized (this) {
            session = null;
            currentProgress = null;
            completed = false;
            result = null;
        }
    }

    /**
     * Callback called when progress has changed.
     *
     * @param token the most recent progress token for this visitor
     */
    public void onProgress(ProgressToken token) {
        currentProgress = token;
    }

    /**
     * Callback for visitor error messages.
     *
     * @param message the error message
     */
    public void onVisitorError(String message) {
    }

    /**
     * Callback for visitor statistics updates.
     *
     * @param vs The current statistics for this visitor.
     */
    public void onVisitorStatistics(VisitorStatistics vs) {
        currentStatistics = vs;
    }

    /**
     * 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
     * @param message an optional error message
     */
    public void onDone(CompletionCode code, String message) {
        synchronized (this) {
            completed = true;
            result = new Result();
            result.code = code;
            result.message = message;
            notifyAll();
        }
    }

    /** @param session the visitor session used for this visitor */
    public void setSession(VisitorControlSession session) {
        this.session = session;
    }

    /** @return Retrieves the last progress token gotten for this visitor. If visitor has not been started, returns null.*/
    public ProgressToken getProgress() { return currentProgress; }

    public VisitorStatistics getVisitorStatistics() { return currentStatistics; }

    /** @return True if the visiting is done (either by error or success). */
    public boolean isDone() {
        synchronized (this) {
            return completed;
        }
    }

    /**
     * Waits until visiting is done, or the given timeout (in ms) expires.
     * Will wait forever if timeout is 0.
     *
     * @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(Duration timeout) throws InterruptedException {
        synchronized (this) {
            if (completed) {
                return true;
            }
            if (timeout.isZero()) {
                while (!completed) {
                    wait();
                }
            } else {
                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(); }

    /**
       @return The result of the visiting, if done. If not done, returns null.
    */
    public Result getResult() { return result; };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy