diff --git a/core/org.eclipse.cdt.core/search/ChangeLog b/core/org.eclipse.cdt.core/search/ChangeLog index 8490ec656df..0381f36a5c0 100644 --- a/core/org.eclipse.cdt.core/search/ChangeLog +++ b/core/org.eclipse.cdt.core/search/ChangeLog @@ -1,3 +1,9 @@ +2004-05-14 Andrew Niefer + bug 56411 - Added IndexingJob show that indexing shows up in the process view + - this allows for the index job to be cancelled, which pauses indexing until someone requests something + - if a request was waiting on the indexer and the indexer gets paused from a user canceling it, then the + request is forced immediate. + 2004-05-06 Bogdan Gheorghe Added friend to ICSearchConstants Created IMatchLocator to allow search users to pass in their own match locators diff --git a/core/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/SearchEngine.java b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/SearchEngine.java index d2acb3c6fce..202898be132 100644 --- a/core/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/SearchEngine.java +++ b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/core/search/SearchEngine.java @@ -206,6 +206,10 @@ public class SearchEngine implements ICSearchConstants{ if( progressMonitor != null && progressMonitor.isCanceled() ) throw new InterruptedException(); + //indexer might have had a # files left to index subtask, replace that with searching again + if( progressMonitor != null ) + progressMonitor.subTask( Util.bind( "engine.searching" ) ); + //TODO: BOG Filter Working Copies... matchLocator.locateMatches( pathCollector.getPaths(), workspace, this.workingCopies, matches); } finally { diff --git a/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/IndexingJob.java b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/IndexingJob.java new file mode 100644 index 00000000000..9f7406f4fb8 --- /dev/null +++ b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/IndexingJob.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +/* + * Created on May 12, 2004 + */ +package org.eclipse.cdt.internal.core.search.processing; + +import org.eclipse.cdt.internal.core.Util; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.jobs.Job; + +/** + * @author aniefer + */ +public class IndexingJob extends Job { + /* (non-Javadoc) + * @see org.eclipse.core.internal.jobs.InternalJob#run(org.eclipse.core.runtime.IProgressMonitor) + */ + IProgressMonitor progressMonitor = null; + JobManager jobManager = null; + Thread indexThread = null; + + int ticks = 0; + int maxTicks = 0; + int workDone = 0; + + public IndexingJob( Thread thread, JobManager manager ) + { + super( "Indexer" ); + jobManager = manager; + indexThread = thread; + setPriority( LONG ); + tickUp(); + schedule(); + } + + protected IStatus run(IProgressMonitor monitor) { + progressMonitor = monitor; + setThread( indexThread ); + progressMonitor.beginTask( "", 100 ); + return ASYNC_FINISH; + } + + public void tickUp(){ + if( progressMonitor != null && progressMonitor.isCanceled() ){ + jobManager.pause(); + return; + } + ticks++; + if( ticks > maxTicks ) + maxTicks = ticks; + updateRemainingCount(); + } + + public void setTicks( int n ){ + ticks = n; + if( maxTicks < ticks ) + maxTicks = ticks; + + updatePercentage(); + updateRemainingCount(); + } + + public int tickDown(){ + if( progressMonitor != null && progressMonitor.isCanceled() ){ + jobManager.pause(); + return 0; + } + ticks--; + + updatePercentage(); + updateRemainingCount(); + return ticks; + } + + private void updateRemainingCount(){ + if( progressMonitor == null ) + return; + + progressMonitor.subTask( Util.bind("manager.filesToIndex", Integer.toString(ticks)) ); + } + + private void updatePercentage(){ + if( progressMonitor == null ) + return; + + int work = (( maxTicks - ticks ) * 100 / maxTicks ) - workDone; + if( work > 0 ){ + workDone += work; + progressMonitor.worked( work ); + } + } +} diff --git a/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/JobManager.java b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/JobManager.java index d0d477e2491..4f3d231d56d 100644 --- a/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/JobManager.java +++ b/core/org.eclipse.cdt.core/search/org/eclipse/cdt/internal/core/search/processing/JobManager.java @@ -14,11 +14,13 @@ package org.eclipse.cdt.internal.core.search.processing; import java.util.HashSet; + import org.eclipse.cdt.core.ICLogConstants; import org.eclipse.cdt.internal.core.Util; -import org.eclipse.cdt.internal.core.search.indexing.IndexRequest; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; public abstract class JobManager implements Runnable { @@ -33,7 +35,10 @@ public abstract class JobManager implements Runnable { protected Thread thread; /* flag indicating whether job execution is enabled or not */ - private boolean enabled = true; + private static final int ENABLED = 1; + private static final int DISABLED = 0; + private static final int WAITING = 2; + private int enabled = ENABLED; public static boolean VERBOSE = false; /* flag indicating that the activation has completed */ @@ -43,6 +48,11 @@ public abstract class JobManager implements Runnable { protected HashSet jobSet; + protected IndexingJob indexJob = null; + + static private final IStatus OK_STATUS = new Status( IStatus.OK, "org.eclipse.cdt.core", IStatus.OK, "", null ); + static private final IStatus ERROR_STATUS = new Status( IStatus.ERROR, "org.eclipse.cdt.core", IStatus.ERROR, "", null ); + public static void verbose(String log) { System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$//$NON-NLS-2$ } @@ -71,7 +81,7 @@ public abstract class JobManager implements Runnable { */ public synchronized IJob currentJob() { - if (!enabled) + if ( enabled != ENABLED ) return null; if (jobStart <= jobEnd) { @@ -81,7 +91,7 @@ public abstract class JobManager implements Runnable { } public synchronized void disable() { - enabled = false; + enabled = DISABLED; if (VERBOSE) JobManager.verbose("DISABLING background indexing"); //$NON-NLS-1$ } @@ -94,7 +104,7 @@ public abstract class JobManager implements Runnable { if (VERBOSE) JobManager.verbose("DISCARD background job family - " + jobFamily); //$NON-NLS-1$ - boolean wasEnabled = isEnabled(); + boolean wasEnabled = ( enabledState() == ENABLED ); try { IJob currentJob; // cancel current job if it belongs to the given family @@ -137,7 +147,7 @@ public abstract class JobManager implements Runnable { jobEnd = loc; } } finally { - if (wasEnabled) + if ( wasEnabled ) enable(); } if (VERBOSE) @@ -145,14 +155,25 @@ public abstract class JobManager implements Runnable { } public synchronized void enable() { - enabled = true; + if( enabled == WAITING ){ + //stop waiting, restore the indexing Job for progress + indexJob = new IndexingJob( thread, this ); + indexJob.setTicks( jobSet.size() ); + } + enabled = ENABLED; if (VERBOSE) JobManager.verbose("ENABLING background indexing"); //$NON-NLS-1$ } - public synchronized boolean isEnabled() { + public synchronized int enabledState() { return enabled; } + + public synchronized void pause(){ + enabled = WAITING; + if( VERBOSE ) + JobManager.verbose("WAITING pausing background indexing"); //$NON-NLS-1$ + } /** * Advance to the next available job, once the current one has been completed. * Note: clients awaiting until the job count is zero are still waiting at this point. @@ -168,6 +189,10 @@ public abstract class JobManager implements Runnable { jobEnd = -1; } } + if( indexJob != null && indexJob.tickDown() == 0 ){ + indexJob.done( OK_STATUS ); + indexJob = null; + } } /** * When idle, give chance to do something @@ -208,90 +233,106 @@ public abstract class JobManager implements Runnable { progress.beginTask("", concurrentJobWork); //$NON-NLS-1$ boolean status = IJob.FAILED; if (awaitingJobsCount() > 0) { - switch (waitingPolicy) { - - case IJob.ForceImmediate : - if (VERBOSE) - JobManager.verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$ - boolean wasEnabled = isEnabled(); - try { - disable(); // pause indexing - status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork)); - } finally { - if (wasEnabled) - enable(); - } - if (VERBOSE) - JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$ - return status; - - case IJob.CancelIfNotReady : - if (VERBOSE) - JobManager.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$ - if (progress != null) progress.setCanceled(true); - if (VERBOSE) - JobManager.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$ - throw new OperationCanceledException(); - - case IJob.WaitUntilReady : - int awaitingWork; - IJob previousJob = null; - IJob currentJob; - IProgressMonitor subProgress = null; - int totalWork = this.awaitingJobsCount(); - if (progress != null && totalWork > 0) { - subProgress = new SubProgressMonitor(progress, concurrentJobWork / 2); - subProgress.beginTask("", totalWork); //$NON-NLS-1$ - concurrentJobWork = concurrentJobWork / 2; - } - int originalPriority = this.thread.getPriority(); - try { - synchronized(this) { - - // use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method) - Thread t = this.thread; - if (t != null) { - t.setPriority(Thread.currentThread().getPriority()); - } - this.awaitingClients++; - } - while (((awaitingWork = awaitingJobsCount()) > 0) - && (!jobShouldBeIgnored(jobToIgnore))) { - if (subProgress != null && subProgress.isCanceled()) - throw new OperationCanceledException(); - 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) - JobManager.verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$ - if (subProgress != null) { - subProgress.subTask( - Util.bind("manager.filesToIndex", Integer.toString(awaitingWork))); //$NON-NLS-1$ - subProgress.worked(1); - } - previousJob = currentJob; - } - try { - Thread.sleep(50); - } catch (InterruptedException e) { - } - } - } finally { - synchronized(this) { - this.awaitingClients--; - - // use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method) - Thread t = this.thread; - if (t != null) { - t.setPriority(originalPriority); - } - } - } - if (subProgress != null) { - subProgress.done(); - } + if( enabledState() == WAITING ){ + //the indexer is paused, resume now that we have been asked for something + enable(); } - } + boolean attemptPolicy = true; + policy: while( attemptPolicy ){ + attemptPolicy = false; + switch (waitingPolicy) { + + case IJob.ForceImmediate : + if (VERBOSE) + JobManager.verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$ + boolean wasEnabled = ( enabledState() == ENABLED ); + try { + if( wasEnabled ) + disable(); // pause indexing + status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork)); + } finally { + if(wasEnabled) + enable(); + } + if (VERBOSE) + JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$ + return status; + + case IJob.CancelIfNotReady : + if (VERBOSE) + JobManager.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$ + if (progress != null) progress.setCanceled(true); + if (VERBOSE) + JobManager.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$ + throw new OperationCanceledException(); + + case IJob.WaitUntilReady : + int awaitingWork; + IJob previousJob = null; + IJob currentJob; + IProgressMonitor subProgress = null; + int totalWork = this.awaitingJobsCount(); + if (progress != null && totalWork > 0) { + subProgress = new SubProgressMonitor(progress, concurrentJobWork / 2); + subProgress.beginTask("", totalWork); //$NON-NLS-1$ + concurrentJobWork = concurrentJobWork / 2; + } + int originalPriority = this.thread.getPriority(); + try { + synchronized(this) { + + // use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method) + Thread t = this.thread; + if (t != null) { + t.setPriority(Thread.currentThread().getPriority()); + } + this.awaitingClients++; + } + while (((awaitingWork = awaitingJobsCount()) > 0) + && (!jobShouldBeIgnored(jobToIgnore))) { + if (subProgress != null && subProgress.isCanceled()) + throw new OperationCanceledException(); + 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) + JobManager.verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$ + if (subProgress != null) { + subProgress.subTask( + Util.bind("manager.filesToIndex", Integer.toString(awaitingWork))); //$NON-NLS-1$ + subProgress.worked(1); + } + previousJob = currentJob; + } + + if( enabledState() == WAITING ){ + //user canceled the index we are waiting on, force immediate + waitingPolicy = IJob.ForceImmediate; + attemptPolicy = true; + continue policy; + } + try { + Thread.sleep(50); + } catch (InterruptedException e) { + } + } + } finally { + synchronized(this) { + this.awaitingClients--; + + // use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method) + Thread t = this.thread; + if (t != null) { + t.setPriority(originalPriority); + } + } + if (subProgress != null) { + subProgress.done(); + } + } + }//switch + } //while + } // if status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork)); if (progress != null) { progress.done(); @@ -324,11 +365,6 @@ public abstract class JobManager implements Runnable { return; } - IndexRequest tempJob = null; - if (job instanceof IndexRequest) - tempJob = (IndexRequest) job; - - // append the job to the list of ones to process later on int size = awaitingJobs.length; if (++jobEnd == size) { // when growing, relocate jobs starting at position 0 @@ -342,6 +378,13 @@ public abstract class JobManager implements Runnable { jobStart = 0; } awaitingJobs[jobEnd] = job; + + if( indexJob == null ){ + indexJob = new IndexingJob( thread, this ); + } else { + indexJob.tickUp(); + } + if (VERBOSE) JobManager.verbose("REQUEST background job - " + job); //$NON-NLS-1$ @@ -366,6 +409,7 @@ public abstract class JobManager implements Runnable { jobSet = new HashSet(); } + /** * Infinite loop performing resource indexing */ @@ -409,6 +453,10 @@ public abstract class JobManager implements Runnable { } } } catch (RuntimeException e) { + if( indexJob != null ){ + indexJob.done( ERROR_STATUS ); + indexJob = null; + } if (this.thread != null) { // if not shutting down // log exception org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery", ICLogConstants.PDE); //$NON-NLS-1$ @@ -420,6 +468,10 @@ public abstract class JobManager implements Runnable { } throw e; } catch (Error e) { + if( indexJob != null ){ + indexJob.done( ERROR_STATUS ); + indexJob = null; + } if (this.thread != null && !(e instanceof ThreadDeath)) { // log exception org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery", ICLogConstants.PDE); //$NON-NLS-1$