View | Details | Raw Unified | Return to bug 301563 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/internal/resources/Project.java (-7 / +35 lines)
Lines 921-934 Link Here
921
				}
921
				}
922
				startup();
922
				startup();
923
				//request a refresh if the project is new and has unknown members on disk
923
				//request a refresh if the project is new and has unknown members on disk
924
				// or restore of the project is not fully succesfull
924
				// or restore of the project is not fully successful
925
				if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
925
				if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
926
					//refresh either in background or foreground
926
					boolean refreshed = false;
927
					if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
927
					if (!used) {
928
						workspace.refreshManager.refresh(this);
928
						// if a new project and refresh snapshot is present, load it and skip the refresh
929
						monitor.worked(Policy.opWork * 80 / 100);
929
						refreshed = workspace.getSaveManager().restoreFromRefreshSnapshot(
930
					} else {
930
								this, Policy.subMonitorFor(monitor, Policy.opWork * 80 / 100));
931
						refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 80 / 100));
931
					}
932
					if (!refreshed) {
933
						//refresh either in background or foreground
934
						if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
935
							workspace.refreshManager.refresh(this);
936
							monitor.worked(Policy.opWork * 80 / 100);
937
						} else {
938
							refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 80 / 100));
939
						}
932
					}
940
					}
933
				}
941
				}
934
				//creation of this project may affect overlapping resources
942
				//creation of this project may affect overlapping resources
Lines 1199-1204 Link Here
1199
		}
1207
		}
1200
	}
1208
	}
1201
1209
1210
	/**
1211
	 * Writes a snapshot of the project's refresh information to disk.
1212
	 */
1213
	public void writeRefreshSnapshot(IProgressMonitor monitor) throws CoreException {
1214
		monitor = Policy.monitorFor(monitor);
1215
		try {
1216
			String msg = NLS.bind(Messages.resources_copying, getName());
1217
			monitor.beginTask(msg, Policy.totalWork);
1218
			try {
1219
				IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
1220
				workspace.getSaveManager().writeRefreshSnapshot(this, sub);
1221
				monitor.worked(Policy.opWork / 2);
1222
			} catch (OperationCanceledException e) {
1223
				workspace.getWorkManager().operationCanceled();
1224
				throw e;
1225
			}
1226
		} finally {
1227
			monitor.done();
1228
		}
1229
	}
1202
	/*
1230
	/*
1203
	 * (non-Javadoc)
1231
	 * (non-Javadoc)
1204
	 * 
1232
	 * 
(-)src/org/eclipse/core/internal/resources/SaveManager.java (+122 lines)
Lines 12-17 Link Here
12
12
13
import java.io.*;
13
import java.io.*;
14
import java.util.*;
14
import java.util.*;
15
import java.util.zip.*;
15
import org.eclipse.core.internal.events.*;
16
import org.eclipse.core.internal.events.*;
16
import org.eclipse.core.internal.localstore.*;
17
import org.eclipse.core.internal.localstore.*;
17
import org.eclipse.core.internal.utils.*;
18
import org.eclipse.core.internal.utils.*;
Lines 708-713 Link Here
708
	}
709
	}
709
710
710
	/**
711
	/**
712
	 * Restores the contents of this project from a refresh snapshot. Throw an exception
713
	 * if the snapshot is found but an error occurs when reading the file.
714
	 * @return <code><code>true</code> if the project data was restored successfully,
715
	 * and <code>false</code> if the refresh snapshot was not found or could not be opened.
716
	 * @exception CoreException if an error occurred reading the snapshot file.
717
	 */
718
	protected boolean restoreFromRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
719
		boolean status = true;
720
		if (Policy.DEBUG_RESTORE)
721
			System.out.println("Restore project " + project.getFullPath() + ": starting..."); //$NON-NLS-1$ //$NON-NLS-2$
722
		long start = System.currentTimeMillis();
723
		monitor = Policy.monitorFor(monitor);
724
		try {
725
			monitor.beginTask("", 40); //$NON-NLS-1$
726
			status = restoreTreeFromRefreshSnapshot(project, Policy.subMonitorFor(monitor, 40));
727
			if (status) {
728
				// load the project description and set internal description
729
				ProjectDescription description = workspace.getFileSystemManager().read(project, true);
730
				project.internalSetDescription(description, false);
731
			}
732
		} finally {
733
			monitor.done();
734
		}
735
		if (Policy.DEBUG_RESTORE)
736
			System.out.println("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
737
		return status;
738
	}
739
740
	/**
711
	 * Reads the markers which were originally saved
741
	 * Reads the markers which were originally saved
712
	 * for the tree rooted by the given resource.
742
	 * for the tree rooted by the given resource.
713
	 */
743
	 */
Lines 970-975 Link Here
970
		return true;
1000
		return true;
971
	}
1001
	}
972
	
1002
	
1003
	/**
1004
	 * Restores a tree saved as a refresh snapshot to a local file.
1005
	 * @return <code>true</code> if the snapshot exists, <code>false</code> otherwise.
1006
	 * @exception CoreException if the project could not be restored.
1007
	 */
1008
	protected boolean restoreTreeFromRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
1009
		long start = System.currentTimeMillis();
1010
		monitor = Policy.monitorFor(monitor);
1011
		String message;
1012
		try {
1013
			monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
1014
			IPath projectLocation = project.getLocation();
1015
			if (projectLocation == null){
1016
				//TODO handle case where project is on remote store
1017
				return false;
1018
			}
1019
			IPath snapshotLocation = projectLocation.append(IProject.REFRESH_SNAPSHOT_FILE_LOCATION);
1020
			java.io.File zipFile = snapshotLocation.toFile();
1021
			if (!zipFile.exists())
1022
				return false;
1023
			ZipFile zip = new ZipFile(zipFile);
1024
			ZipEntry treeEntry = zip.getEntry("resource-index.tree"); //$NON-NLS-1$
1025
			if (treeEntry == null) {
1026
				zip.close();
1027
				return false;
1028
			}
1029
			InputStream is = zip.getInputStream(treeEntry);
1030
			DataInputStream input = new DataInputStream(is);
1031
			try {
1032
				WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt());
1033
				reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork));
1034
			} finally {
1035
				input.close();
1036
				zip.close();
1037
			}
1038
		} catch (IOException e) {
1039
			message = NLS.bind(Messages.resources_readMeta, project.getFullPath());
1040
			throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, project.getFullPath(), message, e);
1041
		} finally {
1042
			monitor.done();
1043
		}
1044
		if (Policy.DEBUG_RESTORE_TREE) {
1045
			System.out.println("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1046
		}
1047
		return true;
1048
	}
1049
	
973
	class InternalMonitorWrapper extends ProgressMonitorWrapper{
1050
	class InternalMonitorWrapper extends ProgressMonitorWrapper{
974
		private boolean ignoreCancel;
1051
		private boolean ignoreCancel;
975
		
1052
		
Lines 1640-1645 Link Here
1640
		info.writeTo(output);
1717
		info.writeTo(output);
1641
	}
1718
	}
1642
1719
1720
	public void writeRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
1721
		String snapshotPath = IProject.REFRESH_SNAPSHOT_FILE_LOCATION;
1722
		IPath snapshotLocation = project.getLocation().append(snapshotPath);
1723
		java.io.File tmpTree = null;
1724
		try {
1725
			tmpTree = java.io.File.createTempFile("tmp", ".tree");	//$NON-NLS-1$//$NON-NLS-2$
1726
		} catch (IOException e) {
1727
			throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotLocation, Messages.resources_copyProblem, e);
1728
		}
1729
		java.io.File snapshotLocationFile = snapshotLocation.toFile();
1730
		snapshotLocationFile.delete();
1731
		ZipOutputStream out = null;
1732
		try {
1733
			FileOutputStream fis = new FileOutputStream(tmpTree);
1734
			DataOutputStream output = new DataOutputStream(fis);
1735
			try {
1736
				output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
1737
				writeTree(project, output, null);
1738
			} finally {
1739
				output.close();
1740
			}
1741
			snapshotLocationFile.getParentFile().mkdirs();
1742
			out = new ZipOutputStream(new FileOutputStream(snapshotLocationFile));
1743
			out.setLevel(Deflater.BEST_COMPRESSION);
1744
			ZipEntry e = new ZipEntry("resource-index.tree"); //$NON-NLS-1$
1745
			out.putNextEntry(e);
1746
			int read = 0;
1747
			byte[] buffer = new byte[4096];
1748
			InputStream in = new FileInputStream(tmpTree);
1749
			try {
1750
				while ((read = in.read(buffer)) >= 0) {
1751
					out.write(buffer, 0, read);
1752
				}
1753
				out.closeEntry();
1754
			} finally {
1755
				in.close();
1756
			}
1757
			out.close();
1758
			tmpTree.delete();
1759
		} catch (IOException e) {
1760
			throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotLocation, Messages.resources_copyProblem, e);
1761
		}
1762
		monitor.worked(1);
1763
	}
1764
	
1643
	protected void writeTree(Map statesToSave, DataOutputStream output, IProgressMonitor monitor) throws IOException, CoreException {
1765
	protected void writeTree(Map statesToSave, DataOutputStream output, IProgressMonitor monitor) throws IOException, CoreException {
1644
		monitor = Policy.monitorFor(monitor);
1766
		monitor = Policy.monitorFor(monitor);
1645
		try {
1767
		try {
(-)src/org/eclipse/core/resources/IProject.java (-7 / +29 lines)
Lines 42-47 Link Here
42
 */
42
 */
43
public interface IProject extends IContainer, IAdaptable {
43
public interface IProject extends IContainer, IAdaptable {
44
	/**
44
	/**
45
	 * The location of the refresh snapshot used when opening a new
46
	 * project to skip the normal refresh of resources.
47
	 */
48
	public static final String REFRESH_SNAPSHOT_FILE_LOCATION =
49
		".settings/resource-index.zip"; //$NON-NLS-1$
50
	/**
45
	 * Invokes the <code>build</code> method of the specified builder 
51
	 * Invokes the <code>build</code> method of the specified builder 
46
	 * for this project. Does nothing if this project is closed.  If this project
52
	 * for this project. Does nothing if this project is closed.  If this project
47
	 * has multiple builders on its build spec matching the given name, only
53
	 * has multiple builders on its build spec matching the given name, only
Lines 621-633 Link Here
621
	 * of its resources from information stored on disk.
627
	 * of its resources from information stored on disk.
622
	 * </p>
628
	 * </p>
623
	 * <p>
629
	 * <p>
624
	 * The <code>BACKGROUND_REFRESH</code> update flag controls how
630
	 * When a project is opened for the first time, initial information about the
625
	 * this method behaves when a project is opened for the first time on a location
631
	 * project's existing resources can be obtained in the following ways:
626
	 * that has existing resources on disk.  If this flag is specified, resources on disk
632
	 * <ul><li>When a refresh snapshot file written with
627
	 * will be added to the project in the background after this method returns.
633
	 * {@link #writeRefreshSnapshot(IProgressMonitor)} is found, resources are restored
628
	 * Child resources of the project may not be available until this background
634
	 * from that file.<li>Otherwise, when the {@link IResource#BACKGROUND_REFRESH} flag
629
	 * refresh completes. If this flag is not specified, resources on disk are added 
635
	 * is specified, resources on disk will be added to the project in the background
630
	 * to the project in the foreground before this method returns.
636
	 * after this method returns. Child resources of the project may not be available
637
	 * until this background refresh completes.<li>Otherwise, resource information 
638
	 * is obtained with a refresh operation in the foreground, before this method returns.</ul>
631
	 * </p>
639
	 * </p>
632
	 * This method changes resources; these changes will be reported
640
	 * This method changes resources; these changes will be reported
633
	 * in a subsequent resource change event that includes
641
	 * in a subsequent resource change event that includes
Lines 852-855 Link Here
852
	 * @since 3.6
860
	 * @since 3.6
853
	 */
861
	 */
854
	public IPathVariableManager getPathVariableManager();
862
	public IPathVariableManager getPathVariableManager();
863
864
	/**
865
	 * Writes a snapshot of project refresh info for this project.
866
	 * 
867
	 * @param monitor a progress monitor, or <code>null</code> if progress
868
	 *		reporting is not desired
869
	 * @exception CoreException if this method fails. Reasons include:
870
	 * <ul>
871
	 * <li> This project does not exist.</li>
872
	  * </ul>
873
	 * @exception OperationCanceledException if the operation is canceled. 
874
	 * @since 3.6
875
	 */
876
	public void writeRefreshSnapshot(IProgressMonitor monitor) throws CoreException;
855
}
877
}

Return to bug 301563