diff options
author | Michael Valenta | 2002-04-18 21:23:08 +0000 |
---|---|---|
committer | Michael Valenta | 2002-04-18 21:23:08 +0000 |
commit | e9656cb090dcc33bbcdf72662ab2cc6fc889c42f (patch) | |
tree | 6ca87dc387aa6f18d0a9e912514077c99cdb8392 /bundles | |
parent | 1f18c75f2b546958aa5bf8bfbf7d350cd5802461 (diff) | |
download | eclipse.platform.team-e9656cb090dcc33bbcdf72662ab2cc6fc889c42f.tar.gz eclipse.platform.team-e9656cb090dcc33bbcdf72662ab2cc6fc889c42f.tar.xz eclipse.platform.team-e9656cb090dcc33bbcdf72662ab2cc6fc889c42f.zip |
13854: OutOfMemoryError when checkout files > 8.125 MB
Diffstat (limited to 'bundles')
3 files changed, 156 insertions, 11 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java index 22e3bf387..7435b729b 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java @@ -10,6 +10,8 @@ ******************************************************************************/ package org.eclipse.team.internal.ccvs.core; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -22,11 +24,13 @@ import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPluginDescriptor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.client.Command; @@ -60,6 +64,9 @@ public class CVSProviderPlugin extends Plugin { public static final String PT_AUTHENTICATOR = "authenticator"; //$NON-NLS-1$ public static final String PT_CONNECTIONMETHODS = "connectionmethods"; //$NON-NLS-1$ + // Directory to cache file contents + private static final String CACHE_DIRECTORY = ".cache"; //$NON-NLS-1$ + private QuietOption quietness; private int compressionLevel = DEFAULT_COMPRESSION_LEVEL; private KSubstOption defaultTextKSubstOption = DEFAULT_TEXT_KSUBST_OPTION; @@ -244,6 +251,8 @@ public class CVSProviderPlugin extends Plugin { workspace.addResourceChangeListener(metaFileSyncListener, IResourceChangeEvent.PRE_AUTO_BUILD); workspace.addResourceChangeListener(addDeleteMoveListener, IResourceChangeEvent.POST_AUTO_BUILD); CVSProviderPlugin.getPlugin().addResourceStateChangeListener(addDeleteMoveListener); + + createCacheDirectory(); } /** @@ -258,6 +267,8 @@ public class CVSProviderPlugin extends Plugin { workspace.removeResourceChangeListener(projectDescriptionListener); workspace.removeResourceChangeListener(metaFileSyncListener); workspace.removeResourceChangeListener(addDeleteMoveListener); + + deleteCacheDirectory(); } /* @@ -463,5 +474,43 @@ public class CVSProviderPlugin extends Plugin { this.replaceUnmanaged = replaceUnmanaged; } + private void createCacheDirectory() { + try { + IPath cacheLocation = getStateLocation().append(CACHE_DIRECTORY); + File file = cacheLocation.toFile(); + if (file.exists()) { + deleteFile(file); + } + file.mkdir(); + } catch (IOException e) { + log(new Status(IStatus.ERROR, ID, 0, Policy.bind("CVSProviderPlugin.errorCreatingCache", e.getMessage()), e)); //$NON-NLS-1$ + } + } + + private void deleteCacheDirectory() { + try { + IPath cacheLocation = getStateLocation().append(CACHE_DIRECTORY); + File file = cacheLocation.toFile(); + if (file.exists()) { + deleteFile(file); + } + } catch (IOException e) { + log(new Status(IStatus.ERROR, ID, 0, Policy.bind("CVSProviderPlugin.errorDeletingCache", e.getMessage()), e)); //$NON-NLS-1$ + } + } + + private void deleteFile(File file) throws IOException { + if (file.isDirectory()) { + File[] children = file.listFiles(); + for (int i = 0; i < children.length; i++) { + deleteFile(children[i]); + } + } + file.delete(); + } + + public File getCacheFileFor(String path) throws IOException { + return new File(getStateLocation().append(CACHE_DIRECTORY).toFile(), path); + } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties index b2f93a483..3860978ab 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties @@ -49,6 +49,8 @@ PServerConnection.noResponse=No response from server PServerConnection.authenticating=Authenticating using pserver CVSProviderPlugin.cannotUpdateDescription=Error updating project description +CVSProviderPlugin.errorDeletingCache=Error occured deleting cache: {0} +CVSProviderPlugin.errorCreatingCache=Error occured creating cache: {0} CVSProvider.exception=Internal error occured. CVSProvider.invalidResource=Resource {0} is not a CVS resource @@ -107,6 +109,7 @@ RemoteFolder.errorFetchingRevisions=Error fetching file revisions RemoteFolder.doesNotExist=Folder {0} does not exist remotely RemoteFile.noContentsReceived=No contents received from server for {0} +RemoteFile.errorRetrievingFromCache=Error occured retrieving cached contents: {0} RemoteFolderTreeBuilder.buildingBase=Collecting local synchronization information RemoteFolderTreeBuilder.receivingDelta=Receiving delta for {0} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java index 876807459..03b791bb7 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java @@ -5,8 +5,13 @@ package org.eclipse.team.internal.ccvs.core.resources; * All Rights Reserved. */ +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -14,9 +19,9 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.sync.IRemoteResource; @@ -48,6 +53,9 @@ import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; */ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { + // Contents will be cahced to disk when this thrshold is exceeded + private static final int CACHING_THRESHOLD = 32768; + // cache for file contents received from the server private byte[] contents; // cach the log entry for the remote file @@ -162,8 +170,26 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /** * @see ICVSRemoteFile#getContents() */ - public InputStream getContents(IProgressMonitor monitor) { + public InputStream getContents(IProgressMonitor monitor) throws CVSException { if (contents == null) { + // First, check to see if there's a cached contents for the file + try { + try { + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + return new BufferedInputStream(new FileInputStream(ioFile)); + } + } catch (IOException e) { + // Try to purge the cache and continue + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + ioFile.delete(); + } + } + } catch (IOException e) { + // We will end up here if we couldn't read or delete the cache file + throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ + } monitor = Policy.monitorFor(monitor); monitor.beginTask(Policy.bind("RemoteFile.getContents"), 100); //$NON-NLS-1$ try { @@ -194,10 +220,19 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { // If the update succeeded but no contents were retreived from the server // than we can assume that the remote file has no contents. if (contents == null) { - contents = new byte[0]; + // The above is true unless there is a cache file + try { + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + return new BufferedInputStream(new FileInputStream(ioFile)); + } else { + contents = new byte[0]; + } + } catch (IOException e) { + // Something is wrong with the cached file so signal an error. + throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ + } } - } catch(CVSException e) { - return null; } finally { monitor.done(); } @@ -374,6 +409,17 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { } public InputStream getContents() throws CVSException { + if (contents == null) { + // Check for cached contents for the file + try { + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + return new BufferedInputStream(new FileInputStream(ioFile)); + } + } catch (IOException e) { + throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ + } + } return new ByteArrayInputStream(contents == null ? new byte[0] : contents); } @@ -381,14 +427,48 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { try { try { byte[] buffer = new byte[1024]; - ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + OutputStream out = byteStream; int read; - while ((read = stream.read(buffer)) >= 0) { - Policy.checkCanceled(monitor); - out.write(buffer, 0, read); + try { + try { + while ((read = stream.read(buffer)) >= 0) { + Policy.checkCanceled(monitor); + out.write(buffer, 0, read); + // Detect when the file is getting too big to keep in memory + // and switch to a caching strategy for the contents of the file + if (out == byteStream && byteStream.size() > CACHING_THRESHOLD) { + // Get the cache file to write to + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if ( ! ioFile.getParentFile().exists()) { + ioFile.getParentFile().mkdirs(); + } + // Switch streams + byteStream.close(); + out = new BufferedOutputStream(new FileOutputStream(ioFile)); + // Write what we've read so far + out.write(byteStream.toByteArray()); + // Continue looping until the whole file is read + } + } + } finally { + out.close(); + } + } catch (IOException e) { + // Make sure we don't leave the cache file around as it may not have the right contents + if (byteStream != out) { + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + ioFile.delete(); + } + } + throw e; + } + + // Set the contents if we didn't cahce them + if (out == byteStream) { + contents = byteStream.toByteArray(); } - out.close(); - contents = out.toByteArray(); } finally { stream.close(); } @@ -476,4 +556,17 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { RemoteFile remote = (RemoteFile) target; return super.equals(target) && remote.getRevision().equals(getRevision()); } + + /* + * Return the cache relative path for the receiver as + * host/cvs/root/module/path/.#filename revision + */ + private String getCacheRelativePath() { + ICVSRepositoryLocation location = getRepository(); + IPath path = new Path(location.getHost()); + path = path.append(location.getRootDirectory()); + path = path.append(parent.getRepositoryRelativePath()); + path = path.append(getName() + ' ' + getRevision()); + return path.toString(); + } }
\ No newline at end of file |