mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
A smarter way to deal with readers/writers of PDOM database, i.e. using scheduling rules and priorities.
This commit is contained in:
parent
595dadd8b4
commit
7d1e89a9fa
6 changed files with 428 additions and 43 deletions
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 QNX Software Systems and others.
|
||||
* 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:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.core.dom;
|
||||
|
||||
import org.eclipse.cdt.core.model.IElementChangedListener;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public interface IPDOMIndexer extends IElementChangedListener {
|
||||
|
||||
public void setPDOM(IPDOM pdom);
|
||||
|
||||
public void reindex();
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@ import org.eclipse.core.resources.IProject;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.QualifiedName;
|
||||
import org.eclipse.core.runtime.jobs.ISchedulingRule;
|
||||
|
||||
/**
|
||||
* The PDOM Database.
|
||||
|
@ -46,6 +47,8 @@ import org.eclipse.core.runtime.QualifiedName;
|
|||
*/
|
||||
public class PDOMDatabase implements IPDOM {
|
||||
|
||||
private final IProject project;
|
||||
|
||||
private final IPath dbPath;
|
||||
private Database db;
|
||||
|
||||
|
@ -60,6 +63,7 @@ public class PDOMDatabase implements IPDOM {
|
|||
= new QualifiedName(CCorePlugin.PLUGIN_ID, "dbName"); //$NON-NLS-1$
|
||||
|
||||
public PDOMDatabase(IProject project, PDOMManager manager) throws CoreException {
|
||||
this.project = project;
|
||||
String dbName = project.getPersistentProperty(dbNameProperty);
|
||||
if (dbName == null) {
|
||||
dbName = project.getName() + "_"
|
||||
|
@ -71,6 +75,10 @@ public class PDOMDatabase implements IPDOM {
|
|||
db = new Database(dbPath.toOSString(), VERSION);
|
||||
}
|
||||
|
||||
public IProject getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public static interface IListener {
|
||||
public void handleChange(PDOMDatabase pdom);
|
||||
}
|
||||
|
@ -241,54 +249,43 @@ public class PDOMDatabase implements IPDOM {
|
|||
return PDOMLinkage.getLinkage(this, record).getBinding(record);
|
||||
}
|
||||
|
||||
// Read-write lock. Since we want to allow reads during a long
|
||||
// running index, readers take precidence.
|
||||
private Object lockMutex = new Object();
|
||||
private int lockCount;
|
||||
private int waitingReaders;
|
||||
private int waitingWriters;
|
||||
|
||||
public void getReadLock(boolean waitForWrites) throws InterruptedException {
|
||||
synchronized (lockMutex) {
|
||||
if (!waitForWrites)
|
||||
++waitingReaders;
|
||||
while (lockCount < 0 || (waitForWrites && waitingWriters > 0))
|
||||
// wait for the writers to finish
|
||||
lockMutex.wait();
|
||||
// free to go
|
||||
++lockCount;
|
||||
if (!waitForWrites)
|
||||
--waitingReaders;
|
||||
// Read-write lock rules. Readers don't conflict with other readers,
|
||||
// Writers conflict with readers, and everyone conflicts with writers.
|
||||
private class ReaderLockRule implements ISchedulingRule {
|
||||
public boolean isConflicting(ISchedulingRule rule) {
|
||||
if (rule == this)
|
||||
return false;
|
||||
else if (rule == getWriterLockRule())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public boolean contains(ISchedulingRule rule) {
|
||||
return rule == this;
|
||||
}
|
||||
}
|
||||
|
||||
public void getWriteLock() throws InterruptedException {
|
||||
synchronized (lockMutex) {
|
||||
++waitingWriters;
|
||||
while (lockCount != 0 || waitingReaders > 0)
|
||||
// wait for everyone to finish
|
||||
// readers get precidence
|
||||
lockMutex.wait();
|
||||
|
||||
// free to go
|
||||
--lockCount;
|
||||
--waitingWriters;
|
||||
private class WriterLockRule implements ISchedulingRule {
|
||||
public boolean isConflicting(ISchedulingRule rule) {
|
||||
if (rule == this || rule == getReaderLockRule())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public boolean contains(ISchedulingRule rule) {
|
||||
return rule == this;
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseReadLock() {
|
||||
synchronized (lockMutex) {
|
||||
if (lockCount > 0)
|
||||
--lockCount;
|
||||
lockMutex.notifyAll();
|
||||
}
|
||||
private ReaderLockRule readerLockRule = new ReaderLockRule();
|
||||
private WriterLockRule writerLockRule = new WriterLockRule();
|
||||
|
||||
public ISchedulingRule getReaderLockRule() {
|
||||
return readerLockRule;
|
||||
}
|
||||
|
||||
public void releaseWriteLock() {
|
||||
synchronized (lockMutex) {
|
||||
if (lockCount < 0)
|
||||
++lockCount;
|
||||
lockMutex.notifyAll();
|
||||
}
|
||||
public ISchedulingRule getWriterLockRule() {
|
||||
return writerLockRule;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 QNX Software Systems and others.
|
||||
* 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:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.indexer.fast;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IPDOM;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOMDatabase;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class PDOMFastAddTU extends Job {
|
||||
|
||||
private final ITranslationUnit tu;
|
||||
private final IPDOM pdom;
|
||||
|
||||
public PDOMFastAddTU(IPDOM pdom, ITranslationUnit tu) {
|
||||
super("PDOM Fast Add TU");
|
||||
this.pdom = pdom;
|
||||
this.tu = tu;
|
||||
}
|
||||
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
PDOMDatabase mypdom = (PDOMDatabase)pdom;
|
||||
mypdom.addSymbols(tu);
|
||||
return Status.OK_STATUS;
|
||||
} catch (CoreException e) {
|
||||
return e.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 QNX Software Systems and others.
|
||||
* 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:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.indexer.fast;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IPDOM;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOMDatabase;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class PDOMFastChangeTU extends Job {
|
||||
|
||||
private final IPDOM pdom;
|
||||
private final ITranslationUnit tu;
|
||||
|
||||
public PDOMFastChangeTU(IPDOM pdom, ITranslationUnit tu) {
|
||||
super("PDOM Fast Change TU");
|
||||
this.pdom = pdom;
|
||||
this.tu = tu;
|
||||
}
|
||||
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
PDOMDatabase mypdom = (PDOMDatabase)pdom;
|
||||
mypdom.removeSymbols(tu);
|
||||
mypdom.addSymbols(tu);
|
||||
return Status.OK_STATUS;
|
||||
} catch (CoreException e) {
|
||||
return e.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 QNX Software Systems and others.
|
||||
* 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:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.indexer.fast;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.IPDOM;
|
||||
import org.eclipse.cdt.core.dom.IPDOMIndexer;
|
||||
import org.eclipse.cdt.core.dom.PDOM;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICElementDelta;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOMDatabase;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IResourceProxy;
|
||||
import org.eclipse.core.resources.IResourceProxyVisitor;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.content.IContentType;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class PDOMFastIndexer implements IPDOMIndexer {
|
||||
|
||||
private PDOMDatabase pdom;
|
||||
|
||||
public void setPDOM(IPDOM pdom) {
|
||||
if (pdom instanceof PDOMDatabase)
|
||||
this.pdom = (PDOMDatabase)pdom;
|
||||
}
|
||||
|
||||
private class ChangeHandler extends Job {
|
||||
private final ICElementDelta delta;
|
||||
private List addedTUs;
|
||||
private List changedTUs;
|
||||
private List removedTUs;
|
||||
|
||||
public ChangeHandler(ElementChangedEvent event) {
|
||||
super("Change Handler");
|
||||
delta = event.getDelta();
|
||||
}
|
||||
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
String taskName = null;
|
||||
processDelta(delta);
|
||||
taskName = "Update PDOM";
|
||||
|
||||
// if (project != null) {
|
||||
// processNewProject(project);
|
||||
// taskName = "Rebuild PDOM";
|
||||
// }
|
||||
|
||||
int count
|
||||
= (addedTUs != null ? addedTUs.size() : 0)
|
||||
+ (changedTUs != null ? changedTUs.size() : 0)
|
||||
+ (removedTUs != null ? removedTUs.size() : 0);
|
||||
|
||||
if (taskName == null || count == 0)
|
||||
return Status.OK_STATUS;
|
||||
|
||||
monitor.beginTask(taskName, count);
|
||||
|
||||
if (addedTUs != null)
|
||||
for (Iterator i = addedTUs.iterator(); i.hasNext();) {
|
||||
if (monitor.isCanceled())
|
||||
return Status.CANCEL_STATUS;
|
||||
ITranslationUnit tu = (ITranslationUnit)i.next();
|
||||
monitor.subTask(String.valueOf(count--)
|
||||
+" files remaining - "
|
||||
+ tu.getPath().toString());
|
||||
new PDOMFastAddTU(pdom, tu).schedule();
|
||||
}
|
||||
|
||||
if (changedTUs != null)
|
||||
for (Iterator i = changedTUs.iterator(); i.hasNext();) {
|
||||
if (monitor.isCanceled())
|
||||
return Status.CANCEL_STATUS;
|
||||
ITranslationUnit tu = (ITranslationUnit)i.next();
|
||||
monitor.subTask(String.valueOf(count--)
|
||||
+" files remaining - "
|
||||
+ tu.getPath().toString());
|
||||
new PDOMFastChangeTU(pdom, tu).schedule();
|
||||
monitor.worked(1);
|
||||
}
|
||||
|
||||
if (removedTUs != null)
|
||||
for (Iterator i = removedTUs.iterator(); i.hasNext();) {
|
||||
if (monitor.isCanceled())
|
||||
return Status.CANCEL_STATUS;
|
||||
ITranslationUnit tu = (ITranslationUnit)i.next();
|
||||
monitor.subTask(String.valueOf(count--)
|
||||
+" files remaining - "
|
||||
+ tu.getPath().toString());
|
||||
new PDOMFastRemoveTU(pdom, tu).schedule();
|
||||
monitor.worked(1);
|
||||
}
|
||||
|
||||
String showTimings = Platform.getDebugOption(CCorePlugin.PLUGIN_ID + "/debug/pdomtimings"); //$NON-NLS-1$
|
||||
if (showTimings!= null)
|
||||
if (showTimings.equalsIgnoreCase("true")) //$NON-NLS-1$
|
||||
System.out.println("Updator Time: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$
|
||||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
private void processDelta(ICElementDelta delta) {
|
||||
// First make sure this project is PDOMable
|
||||
ICElement element = delta.getElement();
|
||||
if (element instanceof ICProject && PDOM.getPDOM(((ICProject)element).getProject()) == null)
|
||||
return;
|
||||
|
||||
// process the children first
|
||||
ICElementDelta[] children = delta.getAffectedChildren();
|
||||
for (int i = 0; i < children.length; ++i)
|
||||
processDelta(children[i]);
|
||||
|
||||
// what have we got
|
||||
if (element.getElementType() == ICElement.C_PROJECT) {
|
||||
switch (delta.getKind()) {
|
||||
case ICElementDelta.ADDED:
|
||||
processNewProject((ICProject)element);
|
||||
break;
|
||||
}
|
||||
} else if (element.getElementType() == ICElement.C_UNIT) {
|
||||
ITranslationUnit tu = (ITranslationUnit)element;
|
||||
if (tu.isWorkingCopy())
|
||||
// Don't care about working copies either
|
||||
return;
|
||||
|
||||
switch (delta.getKind()) {
|
||||
case ICElementDelta.ADDED:
|
||||
if (addedTUs == null)
|
||||
addedTUs = new LinkedList();
|
||||
addedTUs.add(element);
|
||||
break;
|
||||
case ICElementDelta.CHANGED:
|
||||
if (changedTUs == null)
|
||||
changedTUs = new LinkedList();
|
||||
changedTUs.add(element);
|
||||
break;
|
||||
case ICElementDelta.REMOVED:
|
||||
if (removedTUs == null)
|
||||
removedTUs = new LinkedList();
|
||||
removedTUs.add(element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNewProject(final ICProject project) {
|
||||
try {
|
||||
if (!PDOM.isEnabled(project.getProject()))
|
||||
return;
|
||||
project.getProject().accept(new IResourceProxyVisitor() {
|
||||
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||
if (proxy.getType() == IResource.FILE) {
|
||||
String fileName = proxy.getName();
|
||||
IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(fileName);
|
||||
if (contentType == null)
|
||||
return true;
|
||||
String contentTypeId = contentType.getId();
|
||||
|
||||
if (CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId)
|
||||
|| CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId)) {
|
||||
if (addedTUs == null)
|
||||
addedTUs = new LinkedList();
|
||||
addedTUs.add(CoreModel.getDefault().create((IFile)proxy.requestResource()));
|
||||
}
|
||||
// TODO handle header files
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void elementChanged(ElementChangedEvent event) {
|
||||
new ChangeHandler(event).schedule();
|
||||
}
|
||||
|
||||
public void reindex() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 QNX Software Systems and others.
|
||||
* 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:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.indexer.fast;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IPDOM;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOMDatabase;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class PDOMFastRemoveTU extends Job {
|
||||
|
||||
private final IPDOM pdom;
|
||||
private final ITranslationUnit tu;
|
||||
|
||||
public PDOMFastRemoveTU(IPDOM pdom, ITranslationUnit tu) {
|
||||
super("PDOM Fast Remove TU");
|
||||
this.pdom = pdom;
|
||||
this.tu = tu;
|
||||
}
|
||||
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
PDOMDatabase mypdom = (PDOMDatabase)pdom;
|
||||
mypdom.removeSymbols(tu);
|
||||
// TODO delete the file itself from the database
|
||||
// the removeSymbols only removes the names in the file
|
||||
// TODO Auto-generated method stub
|
||||
return Status.OK_STATUS;
|
||||
} catch (CoreException e) {
|
||||
return e.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue