예제 #1
0
  public synchronized void request(IJob job) {

    job.ensureReadyToRun();

    // append the job to the list of ones to process later on
    int size = this.awaitingJobs.length;
    if (++this.jobEnd == size) { // when growing, relocate jobs starting at position 0
      this.jobEnd -= this.jobStart; // jobEnd now equals the number of jobs
      if (this.jobEnd < 50 && this.jobEnd < this.jobStart) {
        // plenty of free space in the queue so shift the remaining jobs to the beginning instead of
        // growing it
        System.arraycopy(this.awaitingJobs, this.jobStart, this.awaitingJobs, 0, this.jobEnd);
        for (int i = this.jobStart; i < size; i++) this.awaitingJobs[i] = null;
      } else {
        System.arraycopy(
            this.awaitingJobs,
            this.jobStart,
            this.awaitingJobs = new IJob[size * 2],
            0,
            this.jobEnd);
      }
      this.jobStart = 0;
    }
    this.awaitingJobs[this.jobEnd] = job;
    if (VERBOSE) {
      Util.verbose("REQUEST   background job - " + job); // $NON-NLS-1$
      Util.verbose("AWAITING JOBS count: " + awaitingJobsCount()); // $NON-NLS-1$
    }
    notifyAll(); // wake up the background thread if it is waiting
  }
예제 #2
0
  /**
   * This API is allowing to run one job in concurrence with background processing. Indeed since
   * other jobs are performed in background, resource sharing might be an issue.Therefore, this
   * functionality allows a given job to be run without colliding with background ones. Note:
   * multiple thread might attempt to perform concurrent jobs at the same time, and should
   * synchronize (it is deliberately left to clients to decide whether concurrent jobs might
   * interfere or not. In general, multiple read jobs are ok).
   *
   * <p>Waiting policy can be: IJobConstants.ForceImmediateSearch
   * IJobConstants.CancelIfNotReadyToSearch IJobConstants.WaitUntilReadyToSearch
   */
  public boolean performConcurrentJob(
      IJob searchJob, int waitingPolicy, IProgressMonitor progress) {
    if (VERBOSE) Util.verbose("STARTING  concurrent job - " + searchJob); // $NON-NLS-1$

    searchJob.ensureReadyToRun();

    boolean status = IJob.FAILED;
    try {
      int concurrentJobWork = 100;
      if (progress != null) progress.beginTask("", concurrentJobWork); // $NON-NLS-1$
      if (awaitingJobsCount() > 0) {
        switch (waitingPolicy) {
          case IJob.ForceImmediate:
            if (VERBOSE)
              Util.verbose("-> NOT READY - forcing immediate - " + searchJob); // $NON-NLS-1$
            try {
              disable(); // pause indexing
              status =
                  searchJob.execute(
                      progress == null
                          ? null
                          : new SubProgressMonitor(progress, concurrentJobWork));
            } finally {
              enable();
            }
            if (VERBOSE) Util.verbose("FINISHED  concurrent job - " + searchJob); // $NON-NLS-1$
            return status;

          case IJob.CancelIfNotReady:
            if (VERBOSE) Util.verbose("-> NOT READY - cancelling - " + searchJob); // $NON-NLS-1$
            if (VERBOSE) Util.verbose("CANCELED concurrent job - " + searchJob); // $NON-NLS-1$
            throw new OperationCanceledException();

          case IJob.WaitUntilReady:
            IProgressMonitor subProgress = null;
            try {
              int totalWork = 1000;
              if (progress != null) {
                subProgress = new SubProgressMonitor(progress, concurrentJobWork * 8 / 10);
                subProgress.beginTask("", totalWork); // $NON-NLS-1$
                concurrentJobWork = concurrentJobWork * 2 / 10;
              }
              // use local variable to avoid potential NPE (see bug 20435 NPE when searching java
              // method
              // and bug 42760 NullPointerException in JobManager when searching)
              Thread t = this.processingThread;
              int originalPriority = t == null ? -1 : t.getPriority();
              try {
                if (t != null) t.setPriority(Thread.currentThread().getPriority());
                synchronized (this) {
                  this.awaitingClients++;
                }
                IJob previousJob = null;
                int awaitingJobsCount;
                int lastJobsCount = totalWork;
                float lastWorked = 0;
                float totalWorked = 0;
                while ((awaitingJobsCount = awaitingJobsCount()) > 0) {
                  if ((subProgress != null && subProgress.isCanceled())
                      || this.processingThread == null) throw new OperationCanceledException();
                  IJob currentJob = currentJob();
                  // currentJob can be null when jobs have been added to the queue but job manager
                  // is not enabled
                  if (currentJob != null && currentJob != previousJob) {
                    if (VERBOSE)
                      Util.verbose(
                          "-> NOT READY - waiting until ready - " + searchJob); // $NON-NLS-1$
                    if (subProgress != null) {
                      String indexing =
                          Messages.bind(
                              Messages.jobmanager_filesToIndex,
                              currentJob.getJobFamily(),
                              Integer.toString(awaitingJobsCount));
                      subProgress.subTask(indexing);
                      // ratio of the amount of work relative to the total work
                      float ratio =
                          awaitingJobsCount < totalWork
                              ? 1
                              : ((float) totalWork) / awaitingJobsCount;
                      if (lastJobsCount > awaitingJobsCount) {
                        totalWorked += (lastJobsCount - awaitingJobsCount) * ratio;
                      } else {
                        // more jobs were added, just increment by the ratio
                        totalWorked += ratio;
                      }
                      if (totalWorked - lastWorked >= 1) {
                        subProgress.worked((int) (totalWorked - lastWorked));
                        lastWorked = totalWorked;
                      }
                      lastJobsCount = awaitingJobsCount;
                    }
                    previousJob = currentJob;
                  }
                  try {
                    if (VERBOSE) Util.verbose("-> GOING TO SLEEP - " + searchJob); // $NON-NLS-1$
                    Thread.sleep(50);
                  } catch (InterruptedException e) {
                    // ignore
                  }
                }
              } finally {
                synchronized (this) {
                  this.awaitingClients--;
                }
                if (t != null && originalPriority > -1 && t.isAlive())
                  t.setPriority(originalPriority);
              }
            } finally {
              if (subProgress != null) subProgress.done();
            }
        }
      }
      status =
          searchJob.execute(
              progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
    } finally {
      if (progress != null) progress.done();
      if (VERBOSE) Util.verbose("FINISHED  concurrent job - " + searchJob); // $NON-NLS-1$
    }
    return status;
  }