From d09020f2e4e097ee60a30dadac6efa78d2cb7cce Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 23 Mar 2007 10:52:10 +0000 Subject: [PATCH] Fix for 170542, file access by index database not using memory mapped files. --- .../index/tests/TeamSharedIndexTest.java | 34 ++- .../cdt/internal/pdom/tests/BTreeTests.java | 6 +- .../pdom/tests/DBPropertiesTests.java | 4 +- .../cdt/internal/pdom/tests/DBTest.java | 13 +- .../cdt/internal/pdom/tests/PDOMBugsTest.java | 4 +- .../internal/core/model/CModelManager.java | 4 +- .../cdt/internal/core/pdom/Messages.java | 1 + .../eclipse/cdt/internal/core/pdom/PDOM.java | 45 +-- .../cdt/internal/core/pdom/PDOMManager.java | 122 ++++++-- .../core/pdom/TeamPDOMExportOperation.java | 14 +- .../cdt/internal/core/pdom/WritablePDOM.java | 8 +- .../cdt/internal/core/pdom/db/Chunk.java | 106 ++++--- .../cdt/internal/core/pdom/db/ChunkCache.java | 134 ++++++++ .../cdt/internal/core/pdom/db/Database.java | 285 ++++++++++-------- .../internal/core/pdom/messages.properties | 1 + .../cdt/core/CCorePreferenceConstants.java | 22 +- .../core/CCorePreferenceInitializer.java | 5 +- 17 files changed, 540 insertions(+), 268 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ChunkCache.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java index cde18b2b6e5..29cb7c34e07 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java @@ -90,7 +90,7 @@ public class TeamSharedIndexTest extends IndexTestBase { private ICProject recreateProject(final String prjName) throws Exception { final boolean[] changed= {false}; - IElementChangedListener waitListener= new IElementChangedListener() { + final IElementChangedListener listener = new IElementChangedListener() { public void elementChanged(ElementChangedEvent event) { synchronized (changed) { changed[0]= true; @@ -98,23 +98,27 @@ public class TeamSharedIndexTest extends IndexTestBase { } } }; - CoreModel.getDefault().addElementChangedListener(waitListener); final IWorkspace workspace = ResourcesPlugin.getWorkspace(); - final IProject prjHandle= workspace.getRoot().getProject(prjName); - workspace.run(new IWorkspaceRunnable() { - public void run(IProgressMonitor monitor) throws CoreException { - IProjectDescription desc= IDEWorkbenchPlugin.getPluginWorkspace().newProjectDescription(prjName); - prjHandle.create(desc, NPM); - prjHandle.open(0, NPM); - } - }, null); - synchronized(changed) { - if (!changed[0]) { - changed.wait(INDEXER_WAIT_TIME); - assertTrue(changed[0]); + CoreModel.getDefault().addElementChangedListener(listener); + try { + final IProject prjHandle= workspace.getRoot().getProject(prjName); + workspace.run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + IProjectDescription desc= IDEWorkbenchPlugin.getPluginWorkspace().newProjectDescription(prjName); + prjHandle.create(desc, NPM); + prjHandle.open(0, NPM); + } + }, null); + synchronized(changed) { + if (!changed[0]) { + changed.wait(INDEXER_WAIT_TIME); + assertTrue(changed[0]); + } } } - CoreModel.getDefault().removeElementChangedListener(waitListener); + finally { + CoreModel.getDefault().removeElementChangedListener(listener); + } fPDOMManager.joinIndexer(INDEXER_WAIT_TIME, NPM); return CoreModel.getDefault().create(workspace.getRoot().getProject(prjName)); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java index de8685ab20d..a05e76e02e5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Symbian Software Systems and others. + * Copyright (c) 2006, 2007 Symbian 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 @@ -7,6 +7,7 @@ * * Contributors: * Symbian - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -22,6 +23,7 @@ import junit.framework.Test; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; @@ -50,7 +52,7 @@ public class BTreeTests extends BaseTestCase { // and invoke it multiple times per Junit test protected void init(int degree) throws Exception { dbFile = File.createTempFile("pdomtest", "db"); - db = new Database(dbFile); + db = new Database(dbFile, new ChunkCache(), 0); rootRecord = Database.DATA_AREA; comparator = new BTMockRecordComparator(); btree = new BTree(db, rootRecord, degree, comparator); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java index 7a5e7bcc3e5..213eb2fa4cf 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBPropertiesTests.java @@ -7,6 +7,7 @@ * * Contributors: * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -17,6 +18,7 @@ import java.util.Properties; import junit.framework.Test; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.core.runtime.CoreException; @@ -35,7 +37,7 @@ public class DBPropertiesTests extends BaseTestCase { protected void setUp() throws Exception { dbLoc = File.createTempFile("test", "db"); dbLoc.deleteOnExit(); - db = new Database(dbLoc); + db = new Database(dbLoc, new ChunkCache(), 0); } protected void tearDown() throws Exception { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java index feb0e39e66f..8653795fe13 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DBTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 QNX Software Systems + * Copyright (c) 2005, 2007 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 @@ -8,6 +8,7 @@ * Contributors: * QNX Software Systems - initial API and implementation * Andrew Ferguson (Symbian) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -19,6 +20,7 @@ import junit.framework.Test; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; @@ -32,9 +34,10 @@ public class DBTest extends BaseTestCase { protected void setUp() throws Exception { super.setUp(); - db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile()); + db = new Database(getTestDir().append(getName()+System.currentTimeMillis()+".dat").toFile(), + new ChunkCache(), 0); } - + public static Test suite() { return suite(DBTest.class); } @@ -48,9 +51,11 @@ public class DBTest extends BaseTestCase { } protected void tearDown() throws Exception { + db.close(); if(!db.getLocation().delete()) { db.getLocation().deleteOnExit(); } + db= null; } public void testBlockSizeAndFirstBlock() throws Exception { @@ -118,7 +123,7 @@ public class DBTest extends BaseTestCase { // Tests inserting and retrieving strings File f = getTestDir().append("testStrings.dat").toFile(); f.delete(); - final Database db = new Database(f); + final Database db = new Database(f, new ChunkCache(), 0); String[] names = { "ARLENE", diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMBugsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMBugsTest.java index ff3c4ba5445..2500f55f1a9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMBugsTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMBugsTest.java @@ -7,6 +7,7 @@ * * Contributors: * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -25,6 +26,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.WritablePDOM; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.NullProgressMonitor; @@ -91,7 +93,7 @@ public class PDOMBugsTest extends BaseTestCase { IIndexLocationConverter cvr= new ResourceContainerRelativeLocationConverter(cproject.getProject()); CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, tmp, cvr); - IWritableIndexFragment pdom = new WritablePDOM(tmp, cvr); + IWritableIndexFragment pdom = new WritablePDOM(tmp, cvr, new ChunkCache()); pdom.acquireReadLock(); try { String id= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index 72ca99abffe..310ed66e091 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -1181,14 +1181,14 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe // stop the binary runner for this project removeBinaryRunner(project); // stop indexing jobs for this project - CCoreInternals.getPDOMManager().deleteProject(create(project), delta); + CCoreInternals.getPDOMManager().deleteProject(create(project)); } private void closing(IProject project, IResourceDelta delta) { // stop the binary runner for this project removeBinaryRunner(project); // stop indexing jobs for this project - CCoreInternals.getPDOMManager().removeProject(create(project)); + CCoreInternals.getPDOMManager().closeProject(create(project)); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/Messages.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/Messages.java index 4c6163f68dd..56bc7f25b40 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/Messages.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/Messages.java @@ -16,6 +16,7 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.core.pdom.messages"; //$NON-NLS-1$ public static String Checksums_taskComputeChecksums; + public static String PDOMManager_ClosePDOMJob; public static String PDOMManager_ExistingFileCollides; public static String PDOMManager_indexMonitorDetail; public static String PDOMManager_JoinIndexerTask; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 760801715d8..0ae53afe878 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -14,7 +14,6 @@ package org.eclipse.cdt.internal.core.pdom; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; @@ -48,6 +47,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.pdom.db.BTree; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; @@ -114,23 +114,22 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { private IIndexLocationConverter locationConverter; public PDOM(File dbPath, IIndexLocationConverter locationConverter) throws CoreException { - loadDatabase(dbPath); + this(dbPath, locationConverter, ChunkCache.getSharedInstance()); + } + + public PDOM(File dbPath, IIndexLocationConverter locationConverter, ChunkCache cache) throws CoreException { + loadDatabase(dbPath, cache); this.locationConverter = locationConverter; } - private void loadDatabase(File dbPath) throws CoreException { + private void loadDatabase(File dbPath, ChunkCache cache) throws CoreException { fPath= dbPath; - boolean exists= fPath.exists(); - db = new Database(fPath); + db = new Database(fPath, cache, VERSION); + fileIndex= null; // holds on to the database, so clear it. - if (exists) { - int version= db.getVersion(); - if (version == VERSION) { - readLinkages(); - } - } - else { - db.setVersion(VERSION); + int version= db.getVersion(); + if (version == VERSION) { + readLinkages(); } } @@ -138,9 +137,8 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { return locationConverter; } - public boolean versionMismatch() { + public boolean versionMismatch() throws CoreException { if (db.getVersion() != VERSION) { - db.setVersion(VERSION); return true; } else return false; @@ -231,8 +229,8 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { // Zero out the File Index and Linkages clearFileIndex(); + db.setVersion(VERSION); db.putInt(PROPERTIES, 0); - db.putInt(LINKAGES, 0); fLinkageIDCache.clear(); } @@ -242,10 +240,10 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { fLinkageIDCache.clear(); try { db.close(); - } catch (IOException e) { + } catch (CoreException e) { CCorePlugin.log(e); } - loadDatabase(file); + loadDatabase(file, db.getChunkCache()); oldFile.delete(); } @@ -541,6 +539,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { while (lockCount != 0 || waitingReaders > 0) mutex.wait(); --lockCount; + db.setWritable(); } } @@ -549,6 +548,11 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { } public void releaseWriteLock(int establishReadLocks) { + try { + db.setReadOnly(); + } catch (CoreException e) { + CCorePlugin.log(e); + } assert lockCount == -1; lastWriteAccess= System.currentTimeMillis(); synchronized (mutex) { @@ -684,5 +688,10 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { public String getProperty(String propertyName) throws CoreException { return new DBProperties(db, PROPERTIES).getProperty(propertyName); + } + + public void close() throws CoreException { + fLinkageIDCache.clear(); + db.close(); } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 0374a11bacc..b593513809f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Properties; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CCorePreferenceConstants; import org.eclipse.cdt.core.dom.IPDOM; import org.eclipse.cdt.core.dom.IPDOMIndexer; import org.eclipse.cdt.core.dom.IPDOMIndexerTask; @@ -49,6 +50,7 @@ import org.eclipse.cdt.internal.core.index.IndexFactory; import org.eclipse.cdt.internal.core.index.IndexerStateEvent; import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager; import org.eclipse.cdt.internal.core.pdom.PDOM.IListener; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMProjectIndexLocationConverter; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; @@ -59,7 +61,6 @@ import org.eclipse.cdt.internal.core.pdom.indexer.nulli.PDOMNullIndexer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -70,10 +71,13 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.Preferences.IPropertyChangeListener; +import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; @@ -154,6 +158,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { // the model listener is attached outside of the job in // order to avoid a race condition where its not noticed // that new projects are being created + initializeDatabaseCache(); + final CoreModel model = CoreModel.getDefault(); model.addElementChangedListener(fCModelListener); @@ -164,6 +170,32 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } + private void initializeDatabaseCache() { + adjustCacheSize(); + CCorePlugin.getDefault().getPluginPreferences().addPropertyChangeListener( + new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + String prop= event.getProperty(); + if (prop.equals(CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT) || + prop.equals(CCorePreferenceConstants.MAX_INDEX_DB_CACHE_SIZE_MB)) { + adjustCacheSize(); + } + } + } + ); + } + + protected void adjustCacheSize() { + final Preferences prefs= CCorePlugin.getDefault().getPluginPreferences(); + int cachePct= prefs.getInt(CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT); + int cacheMax= prefs.getInt(CCorePreferenceConstants.MAX_INDEX_DB_CACHE_SIZE_MB); + cachePct= Math.max(1, Math.min(50, cachePct)); // 1%-50% + cacheMax= Math.max(1, cacheMax); // >= 1mb + long m1= Runtime.getRuntime().maxMemory()/100L * cachePct; + long m2= Math.min(m1, cacheMax * 1024L * 1024L); + ChunkCache.getSharedInstance().setMaxSize(m2); + } + public IndexProviderManager getIndexProviderManager() { return manager; } @@ -527,28 +559,53 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } } - - public void removeProject(ICProject project) { + + public void deleteProject(ICProject cproject) { + removeProject(cproject, true); + } + + public void closeProject(ICProject cproject) { + removeProject(cproject, false); + } + + + private void removeProject(ICProject project, final boolean delete) { IPDOMIndexer indexer= getIndexer(project); if (indexer != null) { stopIndexer(indexer); } unregisterPreferenceListener(project); - } + WritablePDOM pdom= null; + synchronized (fProjectToPDOM) { + IProject rproject= project.getProject(); + pdom = (WritablePDOM) fProjectToPDOM.remove(rproject); + } - public void deleteProject(ICProject cproject, IResourceDelta delta) { - // Project is about to be deleted. Stop all indexing tasks for it - IPDOMIndexer indexer = getIndexer(cproject); - if (indexer != null) { - stopIndexer(indexer); - } - unregisterPreferenceListener(cproject); - - // remove entry for project from PDOM map - synchronized (fProjectToPDOM) { - IProject project= cproject.getProject(); - fProjectToPDOM.remove(project); - } + if (pdom != null) { + final WritablePDOM finalpdom= pdom; + Job job= new Job(Messages.PDOMManager_ClosePDOMJob) { + protected IStatus run(IProgressMonitor monitor) { + try { + finalpdom.acquireWriteLock(); + try { + finalpdom.close(); + if (delete) { + finalpdom.getDB().getLocation().delete(); + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + finally { + finalpdom.releaseWriteLock(); + } + } catch (InterruptedException e) { + } + return Status.OK_STATUS; + } + }; + job.setSystem(true); + job.schedule(); + } } private void stopIndexer(IPDOMIndexer indexer) { @@ -872,23 +929,26 @@ public class PDOMManager implements IWritableIndexManager, IListener { // overwrite internal location representations final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter()); - - newPDOM.acquireWriteLock(); try { - List notConverted= newPDOM.rewriteLocations(newConverter); - - // remove content where converter returns null - for(Iterator i = notConverted.iterator(); i.hasNext(); ) { - PDOMFile file = (PDOMFile) i.next(); - file.clear(); + newPDOM.acquireWriteLock(); + try { + List notConverted= newPDOM.rewriteLocations(newConverter); + + // remove content where converter returns null + for(Iterator i = notConverted.iterator(); i.hasNext(); ) { + PDOMFile file = (PDOMFile) i.next(); + file.clear(); + } + + // ensure fragment id has a sensible value, in case callee's do not + // overwrite their own values + String oldId= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID); + newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported."+oldId); //$NON-NLS-1$ + } finally { + newPDOM.releaseWriteLock(); } - - // ensure fragment id has a sensible value, in case callee's do not - // overwrite their own values - String oldId= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID); - newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported."+oldId); //$NON-NLS-1$ } finally { - newPDOM.releaseWriteLock(); + newPDOM.close(); } } catch(IOException ioe) { throw new CoreException(CCorePlugin.createStatus(ioe.getMessage())); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMExportOperation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMExportOperation.java index ae9210ccf24..1b114610bd5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMExportOperation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMExportOperation.java @@ -96,8 +96,13 @@ public class TeamPDOMExportOperation implements IWorkspaceRunnable { // create checksums PDOM pdom= new PDOM(tmpPDOM, converter); - monitor.setTaskName(Messages.Checksums_taskComputeChecksums); - createChecksums(fProject, pdom, tmpChecksums, subMonitor(monitor, 94)); + try { + monitor.setTaskName(Messages.Checksums_taskComputeChecksums); + createChecksums(fProject, pdom, tmpChecksums, subMonitor(monitor, 94)); + } + finally { + pdom.close(); + } // create archive createArchive(tmpPDOM, tmpChecksums); @@ -143,11 +148,6 @@ public class TeamPDOMExportOperation implements IWorkspaceRunnable { } finally { pdom.releaseReadLock(); - try { - pdom.getDB().close(); - } catch (IOException e) { - CCorePlugin.log(e); - } } int i=0; IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index b1c5a73d6e7..b02d5b064db 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexLocationConverter; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; +import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -36,8 +37,13 @@ import org.eclipse.core.runtime.CoreException; public class WritablePDOM extends PDOM implements IWritableIndexFragment { public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter) throws CoreException { - super(dbPath, locationConverter); + this(dbPath, locationConverter, ChunkCache.getSharedInstance()); } + + public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter, ChunkCache cache) throws CoreException { + super(dbPath, locationConverter, cache); + } + public IIndexFragmentFile addFile(IIndexFileLocation location) throws CoreException { return super.addFile(location); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java index 76d509c6b5d..7a368e87549 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Chunk.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 QNX Software Systems and others. + * Copyright (c) 2005, 2007 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 @@ -13,113 +13,111 @@ package org.eclipse.cdt.internal.core.pdom.db; import java.io.IOException; -import java.io.RandomAccessFile; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel.MapMode; -import java.util.Set; +import java.nio.ByteBuffer; import org.eclipse.core.runtime.CoreException; /** - * @author Doug Schaefer - * + * Caches the content of a piece of the database. */ -public class Chunk { +final class Chunk { + final private ByteBuffer fBuffer; - private MappedByteBuffer buffer; + final Database fDatabase; + final int fSequenceNumber; - // Cache info - private Database db; - int index; - - Chunk(RandomAccessFile file, int offset) throws CoreException { + boolean fCacheHitFlag= false; + boolean fDirty= false; + boolean fWritable= false; + int fCacheIndex= -1; + + Chunk(Database db, int sequenceNumber) throws CoreException { + fDatabase= db; + fBuffer= ByteBuffer.allocate(Database.CHUNK_SIZE); + fSequenceNumber= sequenceNumber; try { - index = offset / Database.CHUNK_SIZE; - buffer = file.getChannel().map(MapMode.READ_WRITE, offset, Database.CHUNK_SIZE); + fDatabase.getChannel().read(fBuffer, fSequenceNumber*Database.CHUNK_SIZE); } catch (IOException e) { throw new CoreException(new DBStatus(e)); } } + + void flush() throws CoreException { + try { + fBuffer.position(0); + fDatabase.getChannel().write(fBuffer, fSequenceNumber*Database.CHUNK_SIZE); + } catch (IOException e) { + throw new CoreException(new DBStatus(e)); + } + fDirty= false; + } public void putByte(int offset, byte value) { - buffer.put(offset % Database.CHUNK_SIZE, value); + fDirty= true; + fBuffer.put(offset % Database.CHUNK_SIZE, value); } public byte getByte(int offset) { - return buffer.get(offset % Database.CHUNK_SIZE); + return fBuffer.get(offset % Database.CHUNK_SIZE); } public byte[] getBytes(int offset, int length) { byte[] bytes = new byte[length]; - buffer.position(offset % Database.CHUNK_SIZE); - buffer.get(bytes, 0, length); + fBuffer.position(offset % Database.CHUNK_SIZE); + fBuffer.get(bytes, 0, length); return bytes; } public void putBytes(int offset, byte[] bytes) { - buffer.position(offset % Database.CHUNK_SIZE); - buffer.put(bytes, 0, bytes.length); + fDirty= true; + fBuffer.position(offset % Database.CHUNK_SIZE); + fBuffer.put(bytes, 0, bytes.length); } public void putInt(int offset, int value) { - buffer.putInt(offset % Database.CHUNK_SIZE, value); + fDirty= true; + fBuffer.putInt(offset % Database.CHUNK_SIZE, value); } public int getInt(int offset) { - return buffer.getInt(offset % Database.CHUNK_SIZE); + return fBuffer.getInt(offset % Database.CHUNK_SIZE); } public void putShort(int offset, short value) { - buffer.putShort(offset % Database.CHUNK_SIZE, value); + fDirty= true; + fBuffer.putShort(offset % Database.CHUNK_SIZE, value); } public short getShort(int offset) { - return buffer.getShort(offset % Database.CHUNK_SIZE); + return fBuffer.getShort(offset % Database.CHUNK_SIZE); } public long getLong(int offset) { - return buffer.getLong(offset % Database.CHUNK_SIZE); + return fBuffer.getLong(offset % Database.CHUNK_SIZE); } public void putLong(int offset, long value) { - buffer.putLong(offset % Database.CHUNK_SIZE, value); + fDirty= true; + fBuffer.putLong(offset % Database.CHUNK_SIZE, value); } public void putChar(int offset, char value) { - buffer.putChar(offset % Database.CHUNK_SIZE, value); + fDirty= true; + fBuffer.putChar(offset % Database.CHUNK_SIZE, value); } public char getChar(int offset) { - return buffer.getChar(offset % Database.CHUNK_SIZE); + return fBuffer.getChar(offset % Database.CHUNK_SIZE); } public void getCharArray(int offset, char[] result) { - buffer.position(offset % Database.CHUNK_SIZE); - buffer.asCharBuffer().get(result); + fBuffer.position(offset % Database.CHUNK_SIZE); + fBuffer.asCharBuffer().get(result); } void clear(int offset, int length) { - buffer.position(offset % Database.CHUNK_SIZE); - buffer.put(new byte[length]); - } - - /** - * Allow this Chunk to be reclaimed. Objects allocated by thus Chunk - * may be registered with a ReferenceQueue to allow for notification - * on deallocation. References registered with the queue are added to - * the Set references. - * - * @param queue ReferenceQueue to register allocated objects with, or - * null if notification is not required. - * @param references Populated with references which were registered - * with the queue. - */ - void reclaim(ReferenceQueue queue, Set references) { - if (queue != null) { - references.add(new WeakReference(buffer, queue)); - } - buffer = null; + fDirty= true; + fBuffer.position(offset % Database.CHUNK_SIZE); + fBuffer.put(new byte[length]); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ChunkCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ChunkCache.java new file mode 100644 index 00000000000..41e3e469d24 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/ChunkCache.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.pdom.db; + +public final class ChunkCache { + private static ChunkCache sSharedInstance= new ChunkCache(); + + private Chunk[] fPageTable; + private boolean fTableIsFull= false; + private int fPointer= 0; + + public static ChunkCache getSharedInstance() { + return sSharedInstance; + } + + public ChunkCache() { + this(5*1024*1024); + } + + public ChunkCache(long maxSize) { + fPageTable= new Chunk[computeLength(maxSize)]; + } + + public synchronized void add(Chunk chunk, boolean writable) { + if (writable) { + chunk.fWritable= true; + } + if (chunk.fCacheIndex >= 0) { + chunk.fCacheHitFlag= true; + return; + } + if (fTableIsFull) { + evictChunk(); + chunk.fCacheIndex= fPointer; + fPageTable[fPointer]= chunk; + } + else { + chunk.fCacheIndex= fPointer; + fPageTable[fPointer]= chunk; + + fPointer++; + if (fPointer == fPageTable.length) { + fPointer= 0; + fTableIsFull= true; + } + } + } + + /** + * Evicts a chunk from the page table and the chunk table. + * After this method returns, {@link #fPointer} will contain + * the index of the evicted chunk within the page table. + */ + private void evictChunk() { + /* + * Use the CLOCK algorithm to determine which chunk to evict. + * i.e., if the chunk in the current slot of the page table has been + * recently referenced (i.e. the reference flag is set), unset the + * reference flag and move to the next slot. Otherwise, evict the + * chunk in the current slot. + */ + while (true) { + Chunk chunk = fPageTable[fPointer]; + if (chunk.fCacheHitFlag) { + chunk.fCacheHitFlag= false; + fPointer= (fPointer + 1) % fPageTable.length; + } else { + chunk.fDatabase.releaseChunk(chunk); + chunk.fCacheIndex= -1; + fPageTable[fPointer] = null; + return; + } + } + } + + public synchronized void remove(Chunk chunk) { + final int idx= chunk.fCacheIndex; + if (idx >= 0) { + if (fTableIsFull) { + fPointer= fPageTable.length-1; + fTableIsFull= false; + } + else { + fPointer--; + } + chunk.fCacheIndex= -1; + final Chunk move= fPageTable[fPointer]; + fPageTable[idx]= move; + move.fCacheIndex= idx; + fPageTable[fPointer]= null; + } + } + + /** + * Clears the page table and changes it to hold chunks with + * maximum total memory of maxSize. + * @param maxSize the total size of the chunks in bytes. + */ + public synchronized void setMaxSize(long maxSize) { + final int newLength= computeLength(maxSize); + final int oldLength= fTableIsFull ? fPageTable.length : fPointer; + if (newLength > oldLength) { + Chunk[] newTable= new Chunk[newLength]; + System.arraycopy(fPageTable, 0, newTable, 0, oldLength); + fTableIsFull= false; + fPointer= oldLength; + } + else { + for (int i=newLength; i 0; block -= CHUNK_SIZE) { - addBlock(getChunk(block), CHUNK_SIZE, block); - } + try { + getChannel().truncate(CHUNK_SIZE); + } + catch (IOException e) { + CCorePlugin.log(e); } malloced = freed = 0; } - - /** - * Truncate the database as small as possible to reclaim disk space. - * This method returns false if truncation does not succeed within the - * given timeout period (in milliseconds). A timeout of 0 will cause - * this method to block until the database is successfully truncated. - * - * @param timeout maximum amount of milliseconds to wait before giving up; - * 0 means wait indefinitely. - * @return true if truncation succeeds; false if the operation times out. - * @throws CoreException if an IO error occurs during truncation - */ - private boolean truncate(long timeout) throws CoreException { - // Queue all the chunks to be reclaimed. - ReferenceQueue queue = new ReferenceQueue(); - Set references = new HashSet(); - int totalChunks = toc.length; - for (int i = 0; i < toc.length; i++) { - if (toc[i] != null) { - toc[i].reclaim(queue, references); - toc[i] = null; + + private void removeChunksFromCache() { + synchronized (fCache) { + for (int i = 0; i < chunks.length; i++) { + Chunk chunk= chunks[i]; + if (chunk != null) { + fCache.remove(chunk); + chunks[i]= null; + } } } - - System.gc(); - try { - // Wait for each chunk to be reclaimed. - int totalReclaimed = references.size(); - while (totalReclaimed > 0) { - queue.remove(timeout); - totalReclaimed--; - } - - // Truncate everything but the header chunk. - try { - file.getChannel().truncate(CHUNK_SIZE); - // Reinitialize header chunk. - toc = new Chunk[] { new Chunk(file, 0) }; - return true; - } catch (IOException e) { - // Bug 168420: - // Truncation failed so we'll reuse the existing - // file. - toc = new Chunk[totalChunks]; - toc[0] = new Chunk(file, 0); - return false; - } - } - catch (InterruptedException e) { - // Truncation took longer than we wanted, so we'll - // reinitialize the header chunk and leave the file - // size alone. - toc[0] = new Chunk(file, 0); - return false; - } } + /** * Return the Chunk that contains the given offset. - * - * @param offset - * @return + * @throws CoreException */ public Chunk getChunk(int offset) throws CoreException { int index = offset / CHUNK_SIZE; - Chunk chunk = toc[index]; - if (chunk == null) { - chunk = toc[index] = new Chunk(file, index * CHUNK_SIZE); + + // for performance reasons try to find chunk and mark it without + // synchronizing. This means that we might pick up a chunk that + // has been paged out, which is ok. + // Furthermore the hitflag may not be seen by the clock-alorithm, + // which might lead to the eviction of a chunk. With the next + // cache failure we are in sync again, though. + Chunk chunk = chunks[index]; + if (chunk != null && chunk.fWritable == fWritable) { + chunk.fCacheHitFlag= true; + return chunk; } - return chunk; + // here is the safe code that has to be performed if we cannot + // get ahold of the chunk. + synchronized(fCache) { + chunk= chunks[index]; + if (chunk == null) { + chunk = chunks[index] = new Chunk(this, index); + } + fCache.add(chunk, fWritable); + return chunk; + } } /** @@ -229,11 +208,10 @@ public class Database { // get the block Chunk chunk; if (freeblock == 0) { - // Out of memory, allocate a new chunk - int i = createChunk(); - chunk = toc[i]; - freeblock = i * CHUNK_SIZE; + // allocate a new chunk + freeblock= createNewChunk(); blocksize = CHUNK_SIZE; + chunk = getChunk(freeblock); } else { chunk = getChunk(freeblock); removeBlock(chunk, blocksize, freeblock); @@ -254,28 +232,27 @@ public class Database { return freeblock + 4; } - private int createChunk() throws CoreException { + private int createNewChunk() throws CoreException { try { - Chunk[] oldtoc = toc; + Chunk[] oldtoc = chunks; int n = oldtoc.length; int offset = n * CHUNK_SIZE; file.seek(offset); file.write(new byte[CHUNK_SIZE]); - toc = new Chunk[n + 1]; - System.arraycopy(oldtoc, 0, toc, 0, n); - toc[n] = new Chunk(file, offset); - return n; + chunks = new Chunk[n + 1]; + System.arraycopy(oldtoc, 0, chunks, 0, n); + return offset; } catch (IOException e) { throw new CoreException(new DBStatus(e)); } } - private int getFirstBlock(int blocksize) { - return toc[0].getInt((blocksize / MIN_SIZE) * INT_SIZE); + private int getFirstBlock(int blocksize) throws CoreException { + return getChunk(0).getInt((blocksize / MIN_SIZE) * INT_SIZE); } - private void setFirstBlock(int blocksize, int block) { - toc[0].putInt((blocksize / MIN_SIZE) * INT_SIZE, block); + private void setFirstBlock(int blocksize, int block) throws CoreException { + getChunk(0).putInt((blocksize / MIN_SIZE) * INT_SIZE, block); } private void removeBlock(Chunk chunk, int blocksize, int block) throws CoreException { @@ -321,53 +298,43 @@ public class Database { } public void putByte(int offset, byte value) throws CoreException { - Chunk chunk = getChunk(offset); - chunk.putByte(offset, value); + getChunk(offset).putByte(offset, value); } public byte getByte(int offset) throws CoreException { - Chunk chunk = getChunk(offset); - return chunk.getByte(offset); + return getChunk(offset).getByte(offset); } public void putInt(int offset, int value) throws CoreException { - Chunk chunk = getChunk(offset); - chunk.putInt(offset, value); + getChunk(offset).putInt(offset, value); } public int getInt(int offset) throws CoreException { - Chunk chunk = getChunk(offset); - return chunk.getInt(offset); + return getChunk(offset).getInt(offset); } public void putShort(int offset, short value) throws CoreException { - Chunk chunk = getChunk(offset); - chunk.putShort(offset, value); + getChunk(offset).putShort(offset, value); } public short getShort(int offset) throws CoreException { - Chunk chunk = getChunk(offset); - return chunk.getShort(offset); + return getChunk(offset).getShort(offset); } public void putLong(int offset, long value) throws CoreException { - Chunk chunk= getChunk(offset); - chunk.putLong(offset, value); + getChunk(offset).putLong(offset, value); } public long getLong(int offset) throws CoreException { - Chunk chunk = getChunk(offset); - return chunk.getLong(offset); + return getChunk(offset).getLong(offset); } public void putChar(int offset, char value) throws CoreException { - Chunk chunk = getChunk(offset); - chunk.putChar(offset, value); + getChunk(offset).putChar(offset, value); } public char getChar(int offset) throws CoreException { - Chunk chunk = getChunk(offset); - return chunk.getChar(offset); + return getChunk(offset).getChar(offset); } public IString newString(String string) throws CoreException { @@ -392,15 +359,15 @@ public class Database { return new ShortString(this, offset); } - public int getNumChunks() { - return toc.length; + public int getChunkCount() { + return chunks.length; } public void reportFreeBlocks() throws CoreException { - System.out.println("Allocated size: " + toc.length * CHUNK_SIZE); //$NON-NLS-1$ + System.out.println("Allocated size: " + chunks.length * CHUNK_SIZE); //$NON-NLS-1$ System.out.println("malloc'ed: " + malloced); //$NON-NLS-1$ System.out.println("free'd: " + freed); //$NON-NLS-1$ - System.out.println("wasted: " + (toc.length * CHUNK_SIZE - (malloced - freed))); //$NON-NLS-1$ + System.out.println("wasted: " + (chunks.length * CHUNK_SIZE - (malloced - freed))); //$NON-NLS-1$ System.out.println("Free blocks"); //$NON-NLS-1$ for (int bs = MIN_SIZE; bs <= CHUNK_SIZE; bs += MIN_SIZE) { int count = 0; @@ -413,15 +380,23 @@ public class Database { System.out.println("Block size: " + bs + "=" + count); //$NON-NLS-1$ //$NON-NLS-2$ } } - + /** - * Closes the database, releasing the file lock. This is public for testing purposes only. + * Closes the database. *

* The behaviour of any further calls to the Database is undefined * @throws IOException + * @throws CoreException */ - public void close() throws IOException { - file.close(); + public void close() throws CoreException { + setReadOnly(); + removeChunksFromCache(); + chunks= new Chunk[0]; + try { + file.close(); + } catch (IOException e) { + throw new CoreException(new DBStatus(e)); + } } /** @@ -430,4 +405,56 @@ public class Database { public File getLocation() { return location; } + + /** + * Called from any thread via the cache, protected by {@link #fCache}. + */ + void releaseChunk(Chunk chunk) { + if (!chunk.fWritable) + chunks[chunk.fSequenceNumber]= null; + } + + /** + * Returns the cache used for this database. + * @since 4.0 + */ + public ChunkCache getChunkCache() { + return fCache; + } + + public void setWritable() { + fWritable= true; + } + + public void setReadOnly() throws CoreException { + if (fWritable) { + fWritable= false; + flushDirtyChunks(); + } + } + + public void flushDirtyChunks() throws CoreException { + ArrayList dirtyChunks= new ArrayList(); + synchronized (fCache) { + for (int i = 0; i < chunks.length; i++) { + Chunk chunk= chunks[i]; + if (chunk != null && chunk.fWritable) { + chunk.fWritable= false; + if (chunk.fCacheIndex < 0) { + chunks[i]= null; + } + if (chunk.fDirty) { + dirtyChunks.add(chunk); + } + } + } + } + + if (!dirtyChunks.isEmpty()) { + for (Iterator it = dirtyChunks.iterator(); it.hasNext();) { + Chunk chunk = (Chunk) it.next(); + chunk.flush(); + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/messages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/messages.properties index 3305a8f74ad..9c6b42b7cd1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/messages.properties +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/messages.properties @@ -12,6 +12,7 @@ WritablePDOM_error_unknownLinkage=AST specifies unknown linkage ''{0}'' PDOMManager_notifyJob_label=Notify Index Change Listeners PDOMManager_JoinIndexerTask=Join Indexer PDOMManager_StartJob_name=Initialize Indexing +PDOMManager_ClosePDOMJob=Close database PDOMManager_notifyTask_message=Notify Listeners PDOMManager_indexMonitorDetail={0}/{1} sources, {2} headers PDOMManager_ExistingFileCollides=A pdom already exists at location {0} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java index d60fccc193d..1be07179f6d 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 QNX Software Systems and others. + * Copyright (c) 2000, 2007 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 @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core; @@ -44,5 +45,24 @@ public class CCorePreferenceConstants { * Default code formatter */ public static final String DEFAULT_CODE_FORMATTER = CCorePlugin.PLUGIN_ID + ".defaultCodeFormatter"; //$NON-NLS-1$ + + /** + * Cache size for the index in percentage of max memory. + */ + public static final String INDEX_DB_CACHE_SIZE_PCT = CCorePlugin.PLUGIN_ID + ".indexDBCacheSizePct"; //$NON-NLS-1$ + + /** + * Default cache size of the index-db in percentage of max memory. + */ + public static final String DEFAULT_INDEX_DB_CACHE_SIZE_PCT = "10"; //$NON-NLS-1$ + + /** + * Absolute maximum size of the index-db in megabytes. + */ + public static final String MAX_INDEX_DB_CACHE_SIZE_MB = CCorePlugin.PLUGIN_ID + ".maxIndexDBCacheSizeMB"; //$NON-NLS-1$ + /** + * Default absolute maximum size of the index-db in megabytes. + */ + public static final String DEFAULT_MAX_INDEX_DB_CACHE_SIZE_MB = "64"; //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java index e1f7f85259a..0907f914743 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java @@ -42,8 +42,9 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer { defaultOptionsMap.put(CCorePreferenceConstants.TRANSLATION_TASK_TAGS, CCorePreferenceConstants.DEFAULT_TASK_TAG); defaultOptionsMap.put(CCorePreferenceConstants.TRANSLATION_TASK_PRIORITIES, CCorePreferenceConstants.DEFAULT_TASK_PRIORITY); defaultOptionsMap.put(CCorePreferenceConstants.CODE_FORMATTER, CCorePreferenceConstants.DEFAULT_CODE_FORMATTER); - - + defaultOptionsMap.put(CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT, CCorePreferenceConstants.DEFAULT_INDEX_DB_CACHE_SIZE_PCT); + defaultOptionsMap.put(CCorePreferenceConstants.MAX_INDEX_DB_CACHE_SIZE_MB, CCorePreferenceConstants.DEFAULT_MAX_INDEX_DB_CACHE_SIZE_MB); + // Store default values to default preferences IEclipsePreferences defaultPreferences = ((IScopeContext) new DefaultScope()).getNode(CCorePlugin.PLUGIN_ID); for (Iterator iter = defaultOptionsMap.entrySet().iterator(); iter.hasNext();) {