/******************************************************************************* * Copyright (c) 2005, 2010 QNX Software Systems * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Doug Schaefer (QNX Software Systems) - initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMIndexer; import org.eclipse.cdt.core.dom.IPDOMIndexerTask; import org.eclipse.cdt.internal.core.pdom.indexer.PDOMIndexerTask; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; /** * Job running multiple indexer tasks. */ public class PDOMIndexerJob extends Job { /** * Job updating the progress monitor of the indexer job. */ final class ProgressUpdateJob extends Job { private boolean fStopped= false; private ProgressUpdateJob() { super(CCorePlugin.getResourceString("PDOMIndexerJob.updateMonitorJob")); //$NON-NLS-1$ setSystem(true); } @Override protected IStatus run(IProgressMonitor m) { int currentTick= 0; while(!fStopped && !m.isCanceled()) { currentTick= pdomManager.getMonitorMessage(PDOMIndexerJob.this, currentTick, TOTAL_MONITOR_WORK); try { Thread.sleep(PROGRESS_UPDATE_INTERVAL); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } } return Status.OK_STATUS; } } private static final int PROGRESS_UPDATE_INTERVAL = 500; private static final int TOTAL_MONITOR_WORK = 1000; static volatile String sMonitorDetail= null; private final PDOMManager pdomManager; private IPDOMIndexerTask currentTask; private boolean cancelledByManager= false; private Object taskMutex = new Object(); private IProgressMonitor fMonitor; private final boolean fShowActivity; public PDOMIndexerJob(PDOMManager manager) { super(CCorePlugin.getResourceString("pdom.indexer.name")); //$NON-NLS-1$ this.pdomManager = manager; fShowActivity= PDOMIndexerTask.checkDebugOption(IPDOMIndexerTask.TRACE_ACTIVITY, "true"); //$NON-NLS-1$ setPriority(Job.LONG); } public synchronized void subTask(String msg) { if (fMonitor != null) { fMonitor.subTask(msg); } } public synchronized void worked(int i) { if (fMonitor != null) { fMonitor.worked(i); } } @Override protected IStatus run(IProgressMonitor monitor) { fMonitor = monitor; String taskName = CCorePlugin.getResourceString("pdom.indexer.task"); //$NON-NLS-1$ monitor.beginTask(taskName, TOTAL_MONITOR_WORK); ProgressUpdateJob monitorJob= new ProgressUpdateJob(); monitorJob.schedule(); try { IProgressMonitor npm= new NullProgressMonitor() { @Override public boolean isCanceled() { synchronized (PDOMIndexerJob.this) { return fMonitor == null || fMonitor.isCanceled(); } } @Override public void setCanceled(boolean cancelled) { synchronized (PDOMIndexerJob.this) { if (fMonitor != null) { fMonitor.setCanceled(cancelled); } } } @Override public void subTask(String name) { sMonitorDetail= name; } }; do { synchronized (taskMutex) { currentTask= null; taskMutex.notifyAll(); // user cancel, tell manager and return if (monitor.isCanceled()) { pdomManager.cancelledIndexerJob(cancelledByManager); return Status.CANCEL_STATUS; } // pick up new task currentTask= pdomManager.getNextTask(); } if (currentTask != null) { try { String name= null; long time= 0; if (fShowActivity) { name= getClassName(currentTask); time= -System.currentTimeMillis(); System.out.println("Indexer: start " + name); //$NON-NLS-1$ } currentTask.run(npm); if (fShowActivity) { time += System.currentTimeMillis(); System.out.println("Indexer: completed " + name + "[" + time + "ms]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (OperationCanceledException e) { } } } while (currentTask != null); return Status.OK_STATUS; } catch (RuntimeException e) { CCorePlugin.log(e); pdomManager.cancelledIndexerJob(true); synchronized (taskMutex) { currentTask= null; taskMutex.notifyAll(); } throw e; } catch (Error e) { CCorePlugin.log(e); pdomManager.cancelledIndexerJob(true); synchronized (taskMutex) { currentTask= null; taskMutex.notifyAll(); } throw e; } finally { synchronized (this) { fMonitor= null; } monitorJob.cancel(); monitor.done(); } } private String getClassName(Object obj) { String name= obj.getClass().getName(); name= name.substring(name.lastIndexOf('.') + 1); return name; } public void cancelJobs(IPDOMIndexer indexer, boolean waitUntilCancelled) { synchronized (taskMutex) { if (currentTask != null && (indexer == null || currentTask.getIndexer() == indexer)) { synchronized (this) { if (fMonitor != null) { fMonitor.setCanceled(true); } } cancelledByManager = true; if (waitUntilCancelled) { while (currentTask != null && currentTask.getIndexer() == indexer) { try { taskMutex.wait(); } catch (InterruptedException e) { return; } } } } } } @Override public boolean belongsTo(Object family) { return family == pdomManager; } }