use of org.eclipse.core.runtime.jobs.Job in project eclipse.platform.text by eclipse.
the class TextSearchVisitor method search.
public IStatus search(IFile[] files, IProgressMonitor monitor) {
if (files.length == 0) {
return fStatus;
}
fProgressMonitor = monitor == null ? new NullProgressMonitor() : monitor;
fNumberOfScannedFiles = 0;
fNumberOfFilesToScan = files.length;
fCurrentFile = null;
int maxThreads = fCollector.canRunInParallel() ? NUMBER_OF_LOGICAL_THREADS : 1;
int jobCount = 1;
if (maxThreads > 1) {
jobCount = (files.length + FILES_PER_JOB - 1) / FILES_PER_JOB;
}
// $NON-NLS-1$
final JobGroup jobGroup = new TextSearchJobGroup("Text Search", maxThreads, jobCount);
long startTime = TRACING ? System.currentTimeMillis() : 0;
Job monitorUpdateJob = new Job(SearchMessages.TextSearchVisitor_progress_updating_job) {
private int fLastNumberOfScannedFiles = 0;
@Override
public IStatus run(IProgressMonitor inner) {
while (!inner.isCanceled()) {
// Propagate user cancellation to the JobGroup.
if (fProgressMonitor.isCanceled()) {
jobGroup.cancel();
break;
}
IFile file;
int numberOfScannedFiles;
synchronized (fLock) {
file = fCurrentFile;
numberOfScannedFiles = fNumberOfScannedFiles;
}
if (file != null) {
String fileName = file.getName();
Object[] args = { fileName, Integer.valueOf(numberOfScannedFiles), Integer.valueOf(fNumberOfFilesToScan) };
fProgressMonitor.subTask(Messages.format(SearchMessages.TextSearchVisitor_scanning, args));
int steps = numberOfScannedFiles - fLastNumberOfScannedFiles;
fProgressMonitor.worked(steps);
fLastNumberOfScannedFiles += steps;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return Status.OK_STATUS;
}
}
return Status.OK_STATUS;
}
};
try {
String taskName = fSearchPattern.pattern().length() == 0 ? SearchMessages.TextSearchVisitor_filesearch_task_label : Messages.format(SearchMessages.TextSearchVisitor_textsearch_task_label, fSearchPattern.pattern());
fProgressMonitor.beginTask(taskName, fNumberOfFilesToScan);
monitorUpdateJob.setSystem(true);
monitorUpdateJob.schedule();
try {
fCollector.beginReporting();
Map<IFile, IDocument> documentsInEditors = PlatformUI.isWorkbenchRunning() ? evalNonFileBufferDocuments() : Collections.emptyMap();
int filesPerJob = (files.length + jobCount - 1) / jobCount;
IFile[] filesByLocation = new IFile[files.length];
System.arraycopy(files, 0, filesByLocation, 0, files.length);
// Sorting files to search by location allows to more easily reuse
// search results from one file to the other when they have same location
Arrays.sort(filesByLocation, (o1, o2) -> {
if (o1 == o2) {
return 0;
}
if (o1.getLocation() == o2.getLocation()) {
return 0;
}
if (o1.getLocation() == null) {
return +1;
}
if (o2.getLocation() == null) {
return -1;
}
return o1.getLocation().toString().compareTo(o2.getLocation().toString());
});
for (int first = 0; first < filesByLocation.length; first += filesPerJob) {
int end = Math.min(filesByLocation.length, first + filesPerJob);
Job job = new TextSearchJob(filesByLocation, first, end, documentsInEditors);
job.setJobGroup(jobGroup);
job.schedule();
}
// The monitorUpdateJob is managing progress and cancellation,
// so it is ok to pass a null monitor into the job group.
jobGroup.join(0, null);
if (fProgressMonitor.isCanceled())
throw new OperationCanceledException(SearchMessages.TextSearchVisitor_canceled);
fStatus.addAll(jobGroup.getResult());
return fStatus;
} catch (InterruptedException e) {
throw new OperationCanceledException(SearchMessages.TextSearchVisitor_canceled);
} finally {
monitorUpdateJob.cancel();
}
} finally {
fProgressMonitor.done();
fCollector.endReporting();
if (TRACING) {
Object[] args = { Integer.valueOf(fNumberOfScannedFiles), Integer.valueOf(jobCount), Integer.valueOf(NUMBER_OF_LOGICAL_THREADS), Long.valueOf(System.currentTimeMillis() - startTime) };
System.out.println(Messages.format("[TextSearch] Search duration for {0} files in {1} jobs using {2} threads: {3}ms", // $NON-NLS-1$
args));
}
}
}
use of org.eclipse.core.runtime.jobs.Job in project eclipse.platform.text by eclipse.
the class InternalSearchUI method runSearchInBackground.
public boolean runSearchInBackground(ISearchQuery query, ISearchResultViewPart view) {
if (isQueryRunning(query))
return false;
// prepare view
if (view == null) {
getSearchViewManager().activateSearchView(true);
} else {
getSearchViewManager().activateSearchView(view);
}
addQuery(query);
SearchJobRecord sjr = new SearchJobRecord(query);
fSearchJobs.put(query, sjr);
Job job = new InternalSearchJob(sjr);
job.setPriority(Job.BUILD);
job.setUser(true);
IWorkbenchSiteProgressService service = getProgressService();
if (service != null) {
service.schedule(job, 0, true);
} else {
job.schedule();
}
return true;
}
use of org.eclipse.core.runtime.jobs.Job in project eclipse.platform.text by eclipse.
the class MarkerInformationControl method setInput.
@SuppressWarnings("unchecked")
@Override
public void setInput(Object input) {
this.composites.values().forEach(Composite::dispose);
this.markers = (List<IMarker>) input;
for (IMarker marker : this.markers) {
Composite markerComposite = new Composite(parent, SWT.NONE);
this.composites.put(marker, markerComposite);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
markerComposite.setLayout(gridLayout);
Composite markerLine = new Composite(markerComposite, SWT.NONE);
RowLayout rowLayout = new RowLayout();
rowLayout.marginTop = 0;
rowLayout.marginBottom = 0;
rowLayout.marginLeft = 0;
rowLayout.marginRight = 0;
markerLine.setLayout(rowLayout);
IMarkerResolution[] resolutions = IDE.getMarkerHelpRegistry().getResolutions(marker);
if (resolutions.length > 0) {
Label markerImage = new Label(markerLine, SWT.NONE);
markerImage.setImage(getImage(marker));
}
Label markerLabel = new Label(markerLine, SWT.NONE);
// $NON-NLS-1$
markerLabel.setText(marker.getAttribute(IMarker.MESSAGE, "missing message"));
for (IMarkerResolution resolution : resolutions) {
Composite resolutionComposite = new Composite(markerComposite, SWT.NONE);
GridData layoutData = new GridData();
layoutData.horizontalIndent = 10;
resolutionComposite.setLayoutData(layoutData);
RowLayout resolutionRowLayout = new RowLayout();
resolutionRowLayout.marginBottom = 0;
resolutionComposite.setLayout(resolutionRowLayout);
Label resolutionImage = new Label(resolutionComposite, SWT.NONE);
// TODO: try to retrieve icon from QuickFix command
Image resolutionPic = null;
if (resolution instanceof IMarkerResolution2) {
resolutionPic = ((IMarkerResolution2) resolution).getImage();
}
if (resolutionPic == null) {
resolutionPic = PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OPEN_MARKER);
}
resolutionImage.setImage(resolutionPic);
Link resolutionLink = new Link(resolutionComposite, SWT.NONE);
// $NON-NLS-1$ //$NON-NLS-2$
resolutionLink.setText("<A>" + resolution.getLabel() + "</a>");
resolutionLink.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Job resolutionJob = new // $NON-NLS-1$
Job(// $NON-NLS-1$
"apply resolution - " + resolution.getLabel()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
resolution.run(marker);
return Status.OK_STATUS;
}
};
resolutionJob.setUser(true);
resolutionJob.setSystem(true);
resolutionJob.setPriority(Job.INTERACTIVE);
resolutionJob.schedule();
getShell().dispose();
}
});
}
}
parent.layout(true);
}
use of org.eclipse.core.runtime.jobs.Job in project eclipse.platform.text by eclipse.
the class DocumentLineDiffer method initialize.
/**
* (Re-)initializes the differ using the current reference and <code>DiffInitializer</code>.
*
* @since 3.2 protected for testing reasons, package visible before
*/
protected synchronized void initialize() {
// make new incoming changes go into the queue of stored events, plus signal we can't restore.
fState = INITIALIZING;
if (fRightDocument == null)
return;
// there is no point in receiving updates before the job we get a new copy of the document for diffing
fIgnoreDocumentEvents = true;
if (fLeftDocument != null) {
fLeftDocument.removeDocumentListener(this);
fLeftDocument = null;
fLeftEquivalent = null;
}
// if there already is a job:
// return if it has not started yet, cancel it if already running
final Job oldJob = fInitializationJob;
if (oldJob != null) {
// don't chain up jobs if there is one waiting already.
if (oldJob.getState() == Job.WAITING) {
oldJob.wakeUp(INITIALIZE_DELAY);
return;
}
oldJob.cancel();
}
fInitializationJob = new Job(QuickDiffMessages.quickdiff_initialize) {
/*
* This is run in a different thread. As the documents might be synchronized, never ever
* access the documents in a synchronized section or expect deadlocks. See
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=44692
*/
@Override
public IStatus run(IProgressMonitor monitor) {
// It will return relatively quickly as RangeDifferencer supports canceling
if (oldJob != null)
try {
oldJob.join();
} catch (InterruptedException e) {
// will not happen as no one interrupts our thread
Assert.isTrue(false);
}
// 2: get the reference document
IQuickDiffReferenceProvider provider = fReferenceProvider;
final IDocument left;
try {
left = provider == null ? null : provider.getReference(monitor);
} catch (CoreException e) {
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
clearModel();
fireModelChanged();
return e.getStatus();
}
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
}
// Getting our own copies of the documents for offline diffing.
//
// We need to make sure that we do get all document modifications after
// copying the documents as we want to re-inject them later on to become consistent.
// fRightDocument, but not subject to change
IDocument right = fRightDocument;
// the copy of the actual (right) document
IDocument actual = null;
// the copy of the reference (left) document
IDocument reference = null;
synchronized (DocumentLineDiffer.this) {
// 4: take an early exit if the documents are not valid
if (left == null || right == null) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
clearModel();
fireModelChanged();
return Status.OK_STATUS;
}
// set the reference document
fLeftDocument = left;
// start listening to document events.
fIgnoreDocumentEvents = false;
}
// accessing the reference document from a different thread - reference providers need
// to be able to deal with this.
left.addDocumentListener(DocumentLineDiffer.this);
// create the reference copy - note that any changes on the
// reference will trigger re-initialization anyway
reference = createCopy(left);
if (reference == null)
return Status.CANCEL_STATUS;
// create the actual copy
Object lock = null;
if (right instanceof ISynchronizable)
lock = ((ISynchronizable) right).getLockObject();
if (lock != null) {
// the document
synchronized (lock) {
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
fStoredEvents.clear();
actual = createUnprotectedCopy(right);
}
}
} else {
// b) cannot lock the document
// Now this is fun. The reference documents may be PartiallySynchronizedDocuments
// which will result in a deadlock if they get changed externally before we get
// our exclusive copies.
// Here's what we do: we try over and over (without synchronization) to get copies
// without interleaving modification. If there is a document change, we just repeat.
int i = 0;
do {
// this is an arbitrary emergency exit in case a referenced document goes nuts
if (i++ == 100)
return new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, NLSUtility.format(QuickDiffMessages.quickdiff_error_getting_document_content, new Object[] { left.getClass(), right.getClass() }), null);
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
fStoredEvents.clear();
}
// access documents non synchronized:
// get an exclusive copy of the actual document
actual = createCopy(right);
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
if (fStoredEvents.size() == 0 && actual != null)
break;
}
} while (true);
}
IHashFunction hash = new DJBHashFunction();
DocumentEquivalenceClass leftEquivalent = new DocumentEquivalenceClass(reference, hash);
fLeftEquivalent = leftEquivalent;
IRangeComparator ref = new DocEquivalenceComparator(leftEquivalent, null);
DocumentEquivalenceClass rightEquivalent = new DocumentEquivalenceClass(actual, hash);
fRightEquivalent = rightEquivalent;
IRangeComparator act = new DocEquivalenceComparator(rightEquivalent, null);
ArrayList<QuickDiffRangeDifference> diffs = asQuickDiffRangeDifference(RangeDifferencer.findRanges(fRangeDiffFactory, monitor, ref, act));
// re-inject stored events to get up to date.
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
// set the new differences so we can operate on them
fDifferences = diffs;
}
// re-inject events accumulated in the meantime.
try {
do {
DocumentEvent event;
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
if (fStoredEvents.isEmpty()) {
// we are back in sync with the life documents
fInitializationJob = null;
fState = SYNCHRONIZED;
fLastDifference = null;
// replace the private documents with the actual
leftEquivalent.setDocument(left);
rightEquivalent.setDocument(right);
break;
}
event = fStoredEvents.remove(0);
}
// access documents non synchronized:
IDocument copy = null;
if (event.fDocument == right)
copy = actual;
else if (event.fDocument == left)
copy = reference;
else
Assert.isTrue(false);
// copy the event to inject it into our diff copies
// don't modify the original event! See https://bugs.eclipse.org/bugs/show_bug.cgi?id=134227
event = new DocumentEvent(copy, event.fOffset, event.fLength, event.fText);
handleAboutToBeChanged(event);
// inject the event into our private copy
actual.replace(event.fOffset, event.fLength, event.fText);
handleChanged(event);
} while (true);
} catch (BadLocationException e) {
left.removeDocumentListener(DocumentLineDiffer.this);
clearModel();
initialize();
return Status.CANCEL_STATUS;
}
fireModelChanged();
return Status.OK_STATUS;
}
private boolean isCanceled(IProgressMonitor monitor) {
return fInitializationJob != this || monitor != null && monitor.isCanceled();
}
private void clearModel() {
synchronized (DocumentLineDiffer.this) {
fLeftDocument = null;
fLeftEquivalent = null;
fInitializationJob = null;
fStoredEvents.clear();
fLastDifference = null;
fDifferences.clear();
}
}
/**
* Creates a copy of <code>document</code> and catches any
* exceptions that may occur if the document is modified concurrently.
* Only call this method in a synchronized block if the document is
* an ISynchronizable and has been locked, as document.get() is called
* and may result in a deadlock otherwise.
*
* @param document the document to create a copy of
* @return a copy of the document, or <code>null</code> if an exception was thrown
*/
private IDocument createCopy(IDocument document) {
Assert.isNotNull(document);
// this fixes https://bugs.eclipse.org/bugs/show_bug.cgi?id=56091
try {
return createUnprotectedCopy(document);
} catch (NullPointerException e) {
} catch (ArrayStoreException e) {
} catch (IndexOutOfBoundsException e) {
} catch (ConcurrentModificationException e) {
} catch (NegativeArraySizeException e) {
}
return null;
}
private IDocument createUnprotectedCopy(IDocument document) {
return new Document(document.get());
}
};
fInitializationJob.setSystem(true);
fInitializationJob.setPriority(Job.DECORATE);
fInitializationJob.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
fInitializationJob.schedule(INITIALIZE_DELAY);
}
use of org.eclipse.core.runtime.jobs.Job in project eclipse.platform.text by eclipse.
the class DocumentLineDiffer method suspend.
@Override
public void suspend() {
Job job = fInitializationJob;
if (job != null)
job.cancel();
synchronized (this) {
fInitializationJob = null;
if (fRightDocument != null)
fRightDocument.removeDocumentListener(this);
if (fLeftDocument != null)
fLeftDocument.removeDocumentListener(this);
fLeftDocument = null;
fLeftEquivalent = null;
fLastDifference = null;
fStoredEvents.clear();
fDifferences.clear();
fState = SUSPENDED;
fireModelChanged();
}
}
Aggregations