/**
   * Applies all modifications to the index in parallel using the workers executor
   *
   * @throws ExecutionException
   * @throws InterruptedException
   */
  private void applyUpdates() throws InterruptedException, ExecutionException {
    AbstractWorkspaceImpl workspace = resources.getWorkspace();

    ErrorContextBuilder errorContextBuilder = new ErrorContextBuilder();
    errorContextBuilder.allWorkToBeDone(workList);

    IndexWriter indexWriter = workspace.getIndexWriter(errorContextBuilder);
    if (indexWriter == null) {
      log.cannotOpenIndexWriterCausePreviousError();
      return;
    }

    boolean taskExecutionSuccessful = true;

    try {
      if (workList.size() == 1) {
        taskExecutionSuccessful = runSingleTask(workList.get(0), indexWriter, errorContextBuilder);
      } else {
        taskExecutionSuccessful = runMultipleTasks(indexWriter, errorContextBuilder);
      }
      if (!taskExecutionSuccessful) {
        resources.getErrorHandler().handle(errorContextBuilder.createErrorContext());
      } else {
        workspace.optimizerPhase();
      }
    } finally {
      workspace.afterTransactionApplied(!taskExecutionSuccessful, false);
    }
  }
 private void assertEfficientIndexingUsed(SearchIntegrator searchIntegrator, Class<?> clazz) {
   DirectoryBasedIndexManager im =
       (DirectoryBasedIndexManager) searchIntegrator.getIndexBinding(clazz).getIndexManagers()[0];
   LuceneBackendQueueProcessor bqp = (LuceneBackendQueueProcessor) im.getBackendQueueProcessor();
   LuceneBackendResources indexResources = bqp.getIndexResources();
   IndexWorkVisitor<Void, LuceneWorkExecutor> visitor = indexResources.getWorkVisitor();
   assertTrue(
       TestingUtil.extractField(visitor, "updateDelegate") instanceof ByTermUpdateWorkExecutor);
 }
 LuceneBackendQueueTask(
     List<LuceneWork> workList, LuceneBackendResources resources, IndexingMonitor monitor) {
   this.workList = workList;
   this.resources = resources;
   this.monitor = monitor;
   this.modificationLock = resources.getParallelModificationLock();
 }
  /**
   * Applies each modification in parallel using the backend workers pool
   *
   * @throws InterruptedException
   */
  private boolean runMultipleTasks(
      final IndexWriter indexWriter, final ErrorContextBuilder errorContextBuilder)
      throws InterruptedException {
    final int queueSize = workList.size();
    final ExecutorService executor = resources.getWorkersExecutor();
    final Future<LuceneWork>[] submittedTasks = new Future[queueSize];

    for (int i = 0; i < queueSize; i++) {
      LuceneWork luceneWork = workList.get(i);
      SingleTaskRunnable task = new SingleTaskRunnable(luceneWork, resources, indexWriter, monitor);
      submittedTasks[i] = executor.submit(task, luceneWork);
    }

    boolean allTasksSuccessful = true;

    // now wait for all tasks being completed before releasing our lock
    // (this thread waits even in async backend mode)
    for (int i = 0; i < queueSize; i++) {
      Future<LuceneWork> task = submittedTasks[i];
      try {
        LuceneWork work = task.get();
        errorContextBuilder.workCompleted(work);
      } catch (ExecutionException e) {
        errorContextBuilder.addWorkThatFailed(workList.get(i));
        errorContextBuilder.errorThatOccurred(e.getCause());
        allTasksSuccessful = false;
      }
    }

    return allTasksSuccessful;
  }
 private void handleException(Exception e) {
   ErrorContextBuilder builder = new ErrorContextBuilder();
   builder.allWorkToBeDone(workList);
   builder.errorThatOccurred(e);
   resources.getErrorHandler().handle(builder.createErrorContext());
 }