try { scheduledSendCreateVisitors = false; while (progress.getIterator().hasNext()) { VisitorIterator.BucketProgress bucket = progress.getIterator().getNext(); Result result = sender.send(createMessage(bucket)); if (result.isAccepted()) { progress.getIterator().update(bucket.getSuperbucket(), bucket.getProgress()); break;
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 void handleWrongDistributionReply(WrongDistributionReply reply) { try { ClusterState newState = new ClusterState(reply.getSystemState()); int stateBits = newState.getDistributionBitCount(); if (stateBits != progress.getIterator().getDistributionBitCount()) { log.log(LogLevel.DEBUG, "System state changed; now at " + stateBits + " distribution bits"); // Update the internal state of the visitor iterator. If we're increasing // the number of distribution bits, this may lead to splitting of pending // buckets. If we're decreasing, it may lead to merging of pending buckets // and potential loss of sub-bucket progress. In either way, the iterator // will not let any new buckets out before all active buckets have been // updated. progress.getIterator().setDistributionBitCount(stateBits); } } catch (Exception e) { log.log(LogLevel.ERROR, "Failed to parse new system state string: " + reply.getSystemState()); transitionTo(new StateDescription(State.FAILED, "Failed to parse cluster state '" + reply.getSystemState() + "'")); } }
public MessageBusVisitorSession(VisitorParameters visitorParameters, AsyncTaskExecutor taskExecutor, SenderFactory senderFactory, ReceiverFactory receiverFactory, RoutingTable routingTable, Clock clock) throws ParseException { this.params = visitorParameters; // TODO(vekterli): make copy? legacy impl does not copy initializeRoute(routingTable); this.sender = senderFactory.createSender(createReplyHandler(), this.params); this.receiver = receiverFactory.createReceiver(createMessageHandler(), sessionName); this.taskExecutor = taskExecutor; this.progress = createVisitingProgress(params); this.statistics = new VisitorStatistics(); this.state = new StateDescription(State.NOT_STARTED); this.clock = clock; initializeHandlers(); trace = new Trace(visitorParameters.getTraceLevel()); dataDestination = (params.getLocalDataHandler() == null ? params.getRemoteDataHandler() : receiver.getConnectionSpec()); validateSessionParameters(); // If we're already done, no need to do anything at all! if (progress.getIterator().isDone()) { markSessionCompleted(); } }
private void handleErrorReply(Reply reply) { CreateVisitorMessage msg = (CreateVisitorMessage)reply.getMessage(); // Must reset bucket progress back to what it was before sending. BucketId bucket = msg.getBuckets().get(0); BucketId subProgress = msg.getBuckets().get(1); progress.getIterator().update(bucket, subProgress); String message = getErrorMessage(reply.getError(0)); log.log(LogLevel.DEBUG, sessionName + ": received error reply for bucket " + bucket + " with message '" + message + "'"); if (isFatalError(reply)) { if (params.skipBucketsOnFatalErrors()) { markBucketProgressAsFailed(bucket, subProgress, message); } else { reportVisitorError(message); transitionTo(new StateDescription(State.FAILED, message)); return; // no additional visitors will be scheduled post-failure } } if (isErrorOfType(reply, DocumentProtocol.ERROR_WRONG_DISTRIBUTION)) { handleWrongDistributionReply((WrongDistributionReply)reply); } else { if (shouldReportError(reply)) { reportVisitorError(message); } // Wait 100ms before new visitor task is executed. Will prevent // visitors from being scheduled from caller. scheduleSendCreateVisitorsIfApplicable(100, TimeUnit.MILLISECONDS); } }
/** * A session is considered completed if one or more of the following holds true: * - All buckets have been visited (i.e. no active or pending visitors). * - Visiting has failed fatally (or has been aborted) AND there are no * active visitors remaining. 'Active' here means that we're waiting * for a reply. * - We have received sufficient number of documents (set via visitor * parameters) from the buckets already visited AND there are no * active visitors remaining. * @return true if visiting has completed, false otherwise */ private boolean visitingCompleted() { return (pendingMessageCount == 0) && (progress.getIterator().isDone() || state.failed() || enoughHitsReceived()); }
private void markBucketProgressAsFailed(BucketId bucket, BucketId subProgress, String message) { progress.getToken().addFailedBucket(bucket, subProgress, message); progress.getIterator().update(bucket, ProgressToken.FINISHED_BUCKET); }
private boolean mayScheduleCreateVisitorsTask() { return ! (scheduledSendCreateVisitors || !progress.getIterator().hasNext() || state.failed() || enoughHitsReceived()); }
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))); } }