log.log(LogLevel.DEBUG, sessionName + ": synchronous destroy() called"); try { synchronized (progress.getToken()) { synchronized (completionMonitor) {
@Override public void run() { synchronized (progress.getToken()) { try { assert(pendingMessageCount > 0);
public void run() { synchronized (progress.getToken()) { try { scheduledSendCreateVisitors = false;
private void handleCreateVisitorReply(CreateVisitorReply reply) { CreateVisitorMessage msg = (CreateVisitorMessage)reply.getMessage(); BucketId superbucket = msg.getBuckets().get(0); BucketId subBucketProgress = reply.getLastBucket(); log.log(LogLevel.DEBUG, sessionName + ": received CreateVisitorReply for bucket " + superbucket + " with progress " + subBucketProgress); progress.getIterator().update(superbucket, subBucketProgress); params.getControlHandler().onProgress(progress.getToken()); statistics.add(reply.getVisitorStatistics()); params.getControlHandler().onVisitorStatistics(statistics); trace.getRoot().addChild(reply.getTrace().getRoot()); if (params.getDynamicallyIncreaseMaxBucketsPerVisitor() && (reply.getVisitorStatistics().getDocumentsReturned() < params.getMaxFirstPassHits() / 2.0)) { // Attempt to increase parallelism to reduce latency of visiting // Ensure new count is within [1, 128] int newMaxBuckets = Math.max(Math.min((int)(params.getMaxBucketsPerVisitor() * params.getDynamicMaxBucketsIncreaseFactor()), 128), 1); params.setMaxBucketsPerVisitor(newMaxBuckets); log.log(LogLevel.DEBUG, sessionName + ": increasing max buckets per visitor to " + params.getMaxBucketsPerVisitor()); } }
private ReplyHandler createReplyHandler() { return (reply) -> { // Generally, handleReply will run in the context of the // underlying transport layer's processing thread(s), so we // schedule our own reply handling task to avoid blocking it. try { taskExecutor.submitTask(new HandleReplyTask(reply)); } catch (RejectedExecutionException e) { // We cannot reliably handle reply tasks failing to be submitted, since // the reply task performs all our internal state handling logic. As such, // we just immediately go into a failure destruction mode as soon as this // happens, in which we do not wait for any active messages to be replied // to. log.log(LogLevel.WARNING, "Visitor session '" + sessionName + "': failed to submit reply task to executor service! " + "Session cannot reliably continue; terminating it early.", e); synchronized (progress.getToken()) { transitionTo(new StateDescription(State.FAILED, "Failed to submit reply task to executor service: " + e.getMessage())); if (!done) { markSessionCompleted(); } } } }; }
private void markSessionCompleted() { // 'done' is only ever written when token mutex is held, so safe to check // outside of completionMonitor lock. assert(!done) : "Session was marked as completed more than once"; log.log(LogLevel.DEBUG, "Visitor session '" + sessionName + "' has completed"); if (params.getLocalDataHandler() != null) { params.getLocalDataHandler().onDone(); } // If skipFatalErrors is set and a fatal error did occur, fail // the session now with the first encountered error message. if (progress.getToken().containsFailedBuckets()) { transitionTo(new StateDescription(State.FAILED, progress.getToken().getFirstErrorMsg())); } // NOTE: transitioning to COMPLETED will not override a failure // state, so it's safe to always do this. transitionTo(new StateDescription(State.COMPLETED)); params.getControlHandler().onDone(state.toCompletionCode(), state.getDescription()); synchronized (completionMonitor) { done = true; completionMonitor.notifyAll(); } }
private void handleMessageProcessingException(Reply reply, Exception e, String what) { final String errorDesc = formatProcessingException(e, what); final String fullMsg = formatIdentifyingVisitorErrorString(errorDesc); log.log(LogLevel.ERROR, fullMsg, e); int errorCode; synchronized (progress.getToken()) { if (!params.skipBucketsOnFatalErrors()) { errorCode = ErrorCode.APP_FATAL_ERROR; transitionTo(new StateDescription(State.FAILED, errorDesc)); } else { errorCode = DocumentProtocol.ERROR_UNPARSEABLE; } } reply.addError(new Error(errorCode, errorDesc)); }
@Override public ProgressToken getProgress() { return progress.getToken(); }
private void markBucketProgressAsFailed(BucketId bucket, BucketId subProgress, String message) { progress.getToken().addFailedBucket(bucket, subProgress, message); progress.getIterator().update(bucket, ProgressToken.FINISHED_BUCKET); }
@Override public boolean isDone() { synchronized (progress.getToken()) { return done; } }
public void start() { synchronized (progress.getToken()) { this.startTimeNanos = clock.monotonicNanoTime(); if (progress.getIterator().isDone()) { log.log(LogLevel.DEBUG, sessionName + ": progress token indicates " + "session is done before it could even start; no-op"); return; } transitionTo(new StateDescription(State.WORKING)); taskExecutor.submitTask(new SendCreateVisitorsTask(computeBoundedMessageTimeoutMillis(0))); } }
@Override public void abort() { synchronized (progress.getToken()) { transitionTo(new StateDescription(State.ABORTED, "Visitor aborted by user")); } }