/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Francis Lynch (Wind River) - [301563] Save and load tree snapshots
 *     Francis Lynch (Wind River) - [305718] Allow reading snapshot into renamed project
 *     Baltasar Belyavsky (Texas Instruments) - [361675] Order mismatch when saving/restoring workspace trees
 *     Broadcom Corporation - ongoing development
 *     Sergey Prigogin (Google) - [437005] Out-of-date .snap file prevents Eclipse from running
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
 *     Mickael Istria (Red Hat Inc.) - Bug 488937
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.io.*;
import java.io.File;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.zip.*;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.internal.events.*;
import org.eclipse.core.internal.localstore.*;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.internal.watson.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;

public class SaveManager implements IElementInfoFlattener, IManager, IStringPoolParticipant {
	class MasterTable extends Properties {
		private static final long serialVersionUID = 1L;

		@Override
		public synchronized Object put(Object key, Object value) {
			Object prev = super.put(key, value);
			if (prev != null && ROOT_SEQUENCE_NUMBER_KEY.equals(key)) {
				int prevSeqNum = Integer.parseInt((String) prev);
				int currSeqNum = Integer.parseInt((String) value);
				if (prevSeqNum > currSeqNum) {
					//revert last put operation
					super.put(key, prev);
					//notify about the problem, do not throw exception but add the exception to know where it occurred
					String message = "Cannot set lower sequence number for root (previous: " + prevSeqNum + ", new: " + currSeqNum + "). Ignoring the new value."; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					Policy.log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, new IllegalArgumentException(message)));
				}
			}
			return prev;
		}
	}

	protected static final String ROOT_SEQUENCE_NUMBER_KEY = Path.ROOT + LocalMetaArea.F_TREE;
	protected static final String CLEAR_DELTA_PREFIX = "clearDelta_"; //$NON-NLS-1$
	protected static final String DELTA_EXPIRATION_PREFIX = "deltaExpiration_"; //$NON-NLS-1$
	protected static final int DONE_SAVING = 3;

	/**
	 * The minimum delay, in milliseconds, between workspace snapshots
	 */
	private static final long MIN_SNAPSHOT_DELAY = 1000 * 30L; //30 seconds

	/**
	 * The number of empty operations that are equivalent to a single non-
	 * trivial operation.
	 */
	protected static final int NO_OP_THRESHOLD = 20;

	/** constants */
	protected static final int PREPARE_TO_SAVE = 1;
	protected static final int ROLLBACK = 4;
	protected static final String SAVE_NUMBER_PREFIX = "saveNumber_"; //$NON-NLS-1$
	protected static final int SAVING = 2;
	protected ElementTree lastSnap;
	protected MasterTable masterTable;

	/**
	 * A flag indicating that a save operation is occurring.  This is a signal
	 * that snapshot should not be scheduled if a nested operation occurs during
	 * save.
	 */
	private volatile boolean isSaving = false;

	/**
	 * The number of empty (non-changing) operations since the last snapshot.
	 */
	protected int noopCount = 0;
	/**
	 * The number of non-trivial operations since the last snapshot.
	 */
	protected int operationCount = 0;

	// Count up the time taken for all saves/snaps on markers and sync info
	protected long persistMarkers = 0l;
	protected long persistSyncInfo = 0l;

	/**
	 * In-memory representation of plugins saved state. Maps String (plugin id)-> SavedState.
	 * This map is accessed from API that is not synchronized, so it requires
	 * independent synchronization. This is accomplished using a synchronized
	 * wrapper map.
	 */
	protected Map<String, SavedState> savedStates;

	/**
	 * Ids of plugins that participate on a workspace save. Maps String (plugin id)-> ISaveParticipant.
	 * This map is accessed from API that is not synchronized, so it requires
	 * independent synchronization. This is accomplished using a synchronized
	 * wrapper map.
	 */
	protected Map<String, ISaveParticipant> saveParticipants;

	protected final DelayedSnapshotJob snapshotJob;

	protected volatile boolean snapshotRequested;
	private IStatus snapshotRequestor;
	protected Workspace workspace;
	//declare debug messages as fields to get sharing
	private static final String DEBUG_START = " starting..."; //$NON-NLS-1$
	private static final String DEBUG_FULL_SAVE = "Full save on workspace: "; //$NON-NLS-1$
	private static final String DEBUG_PROJECT_SAVE = "Save on project "; //$NON-NLS-1$
	private static final String DEBUG_SNAPSHOT = "Snapshot: "; //$NON-NLS-1$
	private static final int TREE_BUFFER_SIZE = 1024 * 64;//64KB buffer

	public SaveManager(Workspace workspace) {
		this.workspace = workspace;
		this.masterTable = new MasterTable();
		this.snapshotJob = new DelayedSnapshotJob(this);
		snapshotRequested = false;
		snapshotRequestor = null;
		saveParticipants = Collections.synchronizedMap(new HashMap<>(10));
	}

	public ISavedState addParticipant(String pluginId, ISaveParticipant participant) throws CoreException {
		// If the plugin was already registered as a save participant we return null
		if (saveParticipants.put(pluginId, participant) != null)
			return null;
		SavedState state = savedStates.get(pluginId);
		if (state != null) {
			if (isDeltaCleared(pluginId)) {
				// this plugin was marked not to receive deltas
				state.forgetTrees();
				removeClearDeltaMarks(pluginId);
			} else {
				try {
					// thread safety: (we need to guarantee that the tree is immutable when computing deltas)
					// so, the tree inside the saved state needs to be immutable
					workspace.prepareOperation(null, null);
					workspace.beginOperation(true);
					state.newTree = workspace.getElementTree();
				} finally {
					workspace.endOperation(null, false);
				}
				return state;
			}
		}
		// if the plug-in has a previous save number, we return a state, otherwise we return null
		if (getSaveNumber(pluginId) > 0)
			return new SavedState(workspace, pluginId, null, null);
		return null;
	}

	protected void broadcastLifecycle(final int lifecycle, Map<String, SaveContext> contexts, final MultiStatus warnings, IProgressMonitor monitor) {
		SubMonitor subMonitor = SubMonitor.convert(monitor, contexts.size());
		try {
			for (final Iterator<Map.Entry<String, SaveContext>> it = contexts.entrySet().iterator(); it.hasNext();) {
				Map.Entry<String, SaveContext> entry = it.next();
				String pluginId = entry.getKey();
				final ISaveParticipant participant = saveParticipants.get(pluginId);
				// save participants can be removed concurrently
				if (participant == null) {
					subMonitor.worked(1);
					continue;
				}
				final SaveContext context = entry.getValue();
				/* Be extra careful when calling lifecycle method on arbitrary plugin */
				ISafeRunnable code = new ISafeRunnable() {

					@Override
					public void handleException(Throwable e) {
						String message = Messages.resources_saveProblem;
						IStatus status = new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES,
								IResourceStatus.INTERNAL_ERROR, message, e);
						warnings.add(status);

						/* Remove entry for defective plug-in from this save operation */
						it.remove();
					}

					@Override
					public void run() throws Exception {
						executeLifecycle(lifecycle, participant, context);
					}
				};
				SafeRunner.run(code);
				subMonitor.worked(1);
			}
		} finally {
			subMonitor.done();
		}
	}

	/**
	 * Remove the delta expiration timestamp from the master table, either
	 * because the saved state has been processed, or the delta has expired.
	 */
	protected void clearDeltaExpiration(String pluginId) {
		masterTable.remove(DELTA_EXPIRATION_PREFIX + pluginId);
	}

	protected void cleanMasterTable() {
		//remove tree file entries for everything except closed projects
		for (Iterator<Object> it = masterTable.keySet().iterator(); it.hasNext();) {
			String key = (String) it.next();
			if (!key.endsWith(LocalMetaArea.F_TREE))
				continue;
			String prefix = key.substring(0, key.length() - LocalMetaArea.F_TREE.length());
			//always save the root tree entry
			if (prefix.equals(Path.ROOT.toString()))
				continue;
			IProject project = workspace.getRoot().getProject(prefix);
			if (!project.exists() || project.isOpen())
				it.remove();
		}
		IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES);
		IPath backup = workspace.getMetaArea().getBackupLocationFor(location);
		try {
			saveMasterTable(ISaveContext.FULL_SAVE, backup);
		} catch (CoreException e) {
			Policy.log(e.getStatus());
			backup.toFile().delete();
			return;
		}
		if (location.toFile().exists() && !location.toFile().delete())
			return;
		try {
			saveMasterTable(ISaveContext.FULL_SAVE, location);
		} catch (CoreException e) {
			Policy.log(e.getStatus());
			location.toFile().delete();
			return;
		}
		backup.toFile().delete();
	}

	/**
	 * Marks the current participants to not receive deltas next time they are registered
	 * as save participants. This is done in order to maintain consistency if we crash
	 * after a snapshot. It would force plug-ins to rebuild their state.
	 */
	protected void clearSavedDelta() {
		synchronized (saveParticipants) {
			for (String pluginId : saveParticipants.keySet()) {
				masterTable.setProperty(CLEAR_DELTA_PREFIX + pluginId, "true"); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Collects the set of ElementTrees we are still interested in,
	 * and removes references to any other trees.
	 */
	protected void collapseTrees(Map<String, SaveContext> contexts) throws CoreException {
		//collect trees we're interested in

		//forget saved trees, if they are not used by registered participants
		synchronized (savedStates) {
			for (SaveContext context : contexts.values()) {
				forgetSavedTree(context.getPluginId());
			}
		}

		//trees for plugin saved states
		ArrayList<ElementTree> trees = new ArrayList<>();
		synchronized (savedStates) {
			for (SavedState state : savedStates.values()) {
				if (state.oldTree != null) {
					trees.add(state.oldTree);
				}
			}
		}

		//trees for builders
		IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects) {
			if (project.isOpen()) {
				ArrayList<BuilderPersistentInfo> builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project);
				if (builderInfos != null) {
					for (BuilderPersistentInfo info : builderInfos) {
						trees.add(info.getLastBuiltTree());
					}
				}
			}
		}

		//no need to collapse if there are no trees at this point
		if (trees.isEmpty())
			return;

		//the complete tree
		trees.add(workspace.getElementTree());

		//collapse the trees
		//sort trees in topological order, and set the parent of each
		//tree to its parent in the topological ordering.
		ElementTree[] treeArray = new ElementTree[trees.size()];
		trees.toArray(treeArray);
		ElementTree[] sorted = sortTrees(treeArray);
		// if there was a problem sorting the tree, bail on trying to collapse.
		// We will be able to GC the layers at a later time.
		if (sorted == null)
			return;
		for (int i = 1; i < sorted.length; i++)
			sorted[i].collapseTo(sorted[i - 1]);
	}

	protected void commit(Map<String, SaveContext> contexts) throws CoreException {
		for (SaveContext saveContext : contexts.values())
			saveContext.commit();
	}

	/**
	 * Given a collection of save participants, compute the collection of
	 * <code>SaveContexts</code> to use during the save lifecycle.
	 * The keys are plugins and values are SaveContext objects.
	 */
	protected Map<String, SaveContext> computeSaveContexts(String[] pluginIds, int kind, IProject project) {
		HashMap<String, SaveContext> result = new HashMap<>(pluginIds.length);
		for (String pluginId : pluginIds) {
			try {
				SaveContext context = new SaveContext(pluginId, kind, project);
				result.put(pluginId, context);
			} catch (CoreException e) {
				// FIXME: should return a status to the user and not just log it
				Policy.log(e.getStatus());
			}
		}
		return result;
	}

	/**
	 * Returns a table mapping having the plug-in id as the key and the old tree
	 * as the value.
	 * This table is based on the union of the current savedStates</code>
	 * and the given table of contexts.  The specified tree is used as the tree for
	 * any newly created saved states.  This method is used to compute the set of
	 * saved states to be written out.
	 */
	protected Map<String, ElementTree> computeStatesToSave(Map<String, SaveContext> contexts, ElementTree current) {
		HashMap<String, ElementTree> result = new HashMap<>(savedStates.size() * 2);
		synchronized (savedStates) {
			for (SavedState state : savedStates.values()) {
				if (state.oldTree != null)
					result.put(state.pluginId, state.oldTree);
			}
		}
		for (SaveContext context : contexts.values()) {
			if (!context.isDeltaNeeded())
				continue;
			String pluginId = context.getPluginId();
			result.put(pluginId, current);
		}
		return result;
	}

	protected void executeLifecycle(int lifecycle, ISaveParticipant participant, SaveContext context) throws CoreException {
		switch (lifecycle) {
			case PREPARE_TO_SAVE :
				participant.prepareToSave(context);
				break;
			case SAVING :
				try {
					if (ResourceStats.TRACE_SAVE_PARTICIPANTS)
						ResourceStats.startSave(participant);
					participant.saving(context);
				} finally {
					if (ResourceStats.TRACE_SAVE_PARTICIPANTS)
						ResourceStats.endSave();
				}
				break;
			case DONE_SAVING :
				participant.doneSaving(context);
				break;
			case ROLLBACK :
				participant.rollback(context);
				break;
			default :
				Assert.isTrue(false, "Invalid save lifecycle code"); //$NON-NLS-1$
		}
	}

	public void forgetSavedTree(String pluginId) {
		if (pluginId == null) {
			synchronized (savedStates) {
				for (SavedState savedState : savedStates.values())
					savedState.forgetTrees();
			}
		} else {
			SavedState state = savedStates.get(pluginId);
			if (state != null)
				state.forgetTrees();
		}
	}

	/**
	 * Used in the policy for cleaning up tree's of plug-ins that are not often activated.
	 */
	protected long getDeltaExpiration(String pluginId) {
		String result = masterTable.getProperty(DELTA_EXPIRATION_PREFIX + pluginId);
		return (result == null) ? System.currentTimeMillis() : Long.parseLong(result);
	}

	protected Properties getMasterTable() {
		return masterTable;
	}

	public int getSaveNumber(String pluginId) {
		String value = masterTable.getProperty(SAVE_NUMBER_PREFIX + pluginId);
		return (value == null) ? 0 : Integer.parseInt(value);
	}

	protected String[] getSaveParticipantPluginIds() {
		synchronized (saveParticipants) {
			return saveParticipants.keySet().toArray(new String[saveParticipants.size()]);
		}
	}

	/**
	 * Hooks the end of a save operation, for debugging and performance
	 * monitoring purposes.
	 */
	private void hookEndSave(int kind, IProject project, long start) {
		if (ResourceStats.TRACE_SNAPSHOT && kind == ISaveContext.SNAPSHOT)
			ResourceStats.endSnapshot();
		if (Policy.DEBUG_SAVE) {
			String endMessage = null;
			switch (kind) {
				case ISaveContext.FULL_SAVE :
					endMessage = DEBUG_FULL_SAVE;
					break;
				case ISaveContext.SNAPSHOT :
					endMessage = DEBUG_SNAPSHOT;
					break;
				case ISaveContext.PROJECT_SAVE :
					endMessage = DEBUG_PROJECT_SAVE + project.getFullPath() + ": "; //$NON-NLS-1$
					break;
			}
			if (endMessage != null)
				Policy.debug(endMessage + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$
		}
	}

	/**
	 * Hooks the start of a save operation, for debugging and performance
	 * monitoring purposes.
	 */
	private void hookStartSave(int kind, Project project) {
		if (ResourceStats.TRACE_SNAPSHOT && kind == ISaveContext.SNAPSHOT)
			ResourceStats.startSnapshot();
		if (Policy.DEBUG_SAVE) {
			switch (kind) {
				case ISaveContext.FULL_SAVE :
					Policy.debug(DEBUG_FULL_SAVE + DEBUG_START);
					break;
				case ISaveContext.SNAPSHOT :
					Policy.debug(DEBUG_SNAPSHOT + DEBUG_START);
					break;
				case ISaveContext.PROJECT_SAVE :
					Policy.debug(DEBUG_PROJECT_SAVE + project.getFullPath() + DEBUG_START);
					break;
			}
		}
	}

	/**
	 * Initializes the snapshot mechanism for this workspace.
	 */
	protected void initSnap(IProgressMonitor monitor) {
		// Discard any pending snapshot request.
		snapshotJob.cancel();
		// The "lastSnap" tree must be frozen as the exact tree obtained from startup,
		// otherwise ensuing snapshot deltas may be based on an incorrect tree (see bug 12575).
		lastSnap = workspace.getElementTree();
		lastSnap.immutable();
		workspace.newWorkingTree();
		operationCount = 0;
		// Delete the snapshot files, if any.
		IPath location = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot());
		java.io.File target = location.toFile().getParentFile();
		FilenameFilter filter = (dir, name) -> {
			if (!name.endsWith(LocalMetaArea.F_SNAP))
				return false;
			for (int i = 0; i < name.length() - LocalMetaArea.F_SNAP.length(); i++) {
				char c = name.charAt(i);
				if (c < '0' || c > '9')
					return false;
			}
			return true;
		};
		String[] candidates = target.list(filter);
		if (candidates != null)
			removeFiles(target, candidates, Collections.<String> emptyList());
	}

	protected boolean isDeltaCleared(String pluginId) {
		String clearDelta = masterTable.getProperty(CLEAR_DELTA_PREFIX + pluginId);
		return clearDelta != null && clearDelta.equals("true"); //$NON-NLS-1$
	}

	protected boolean isOldPluginTree(String pluginId) {
		// first, check if this plug-ins was marked not to receive a delta
		if (isDeltaCleared(pluginId))
			return false;
		//see if the plugin is still installed
		if (Platform.getBundle(pluginId) == null)
			return true;

		//finally see if the delta has past its expiry date
		long deltaAge = System.currentTimeMillis() - getDeltaExpiration(pluginId);
		return deltaAge > workspace.internalGetDescription().getDeltaExpiration();
	}

	/**
	 * @see IElementInfoFlattener#readElement(IPath, DataInput)
	 */
	@Override
	public Object readElement(IPath path, DataInput input) throws IOException {
		Assert.isNotNull(path);
		Assert.isNotNull(input);
		// read the flags and pull out the type.
		int flags = input.readInt();
		int type = (flags & ICoreConstants.M_TYPE) >> ICoreConstants.M_TYPE_START;
		ResourceInfo info = workspace.newElement(type);
		info.readFrom(flags, input);
		return info;
	}

	private void rememberSnapshotRequestor() {
		if (Policy.DEBUG_SAVE)
			Policy.debug(new RuntimeException("Scheduling workspace snapshot")); //$NON-NLS-1$
		if (snapshotRequestor == null) {
			String msg = "The workspace will exit with unsaved changes in this session."; //$NON-NLS-1$
			snapshotRequestor = new ResourceStatus(ICoreConstants.CRASH_DETECTED, msg);
		}
	}

	/**
	 * Remove marks from current save participants. This marks prevent them to receive their
	 * deltas when they register themselves as save participants.
	 */
	protected void removeClearDeltaMarks() {
		synchronized (saveParticipants) {
			for (String pluginId : saveParticipants.keySet()) {
				removeClearDeltaMarks(pluginId);
			}
		}
	}

	protected void removeClearDeltaMarks(String pluginId) {
		masterTable.setProperty(CLEAR_DELTA_PREFIX + pluginId, "false"); //$NON-NLS-1$
	}

	protected void removeFiles(java.io.File root, String[] candidates, List<String> exclude) {
		for (String candidate : candidates) {
			boolean delete = true;
			for (ListIterator<String> it = exclude.listIterator(); it.hasNext();) {
				String s = it.next();
				if (s.equals(candidate)) {
					it.remove();
					delete = false;
					break;
				}
			}
			if (delete)
				new java.io.File(root, candidate).delete();
		}
	}

	private void removeGarbage(DataOutputStream output, IPath location, IPath tempLocation) throws IOException {
		if (output.size() == 0) {
			output.close();
			location.toFile().delete();
			tempLocation.toFile().delete();
		}
	}

	public void removeParticipant(String pluginId) {
		saveParticipants.remove(pluginId);
	}

	protected void removeUnusedSafeTables() {
		List<String> valuables = new ArrayList<>(10);
		IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES);
		valuables.add(location.lastSegment()); // add master table
		for (Enumeration<Object> e = masterTable.keys(); e.hasMoreElements();) {
			String key = (String) e.nextElement();
			if (key.startsWith(SAVE_NUMBER_PREFIX)) {
				String pluginId = key.substring(SAVE_NUMBER_PREFIX.length());
				valuables.add(workspace.getMetaArea().getSafeTableLocationFor(pluginId).lastSegment());
			}
		}
		java.io.File target = location.toFile().getParentFile();
		String[] candidates = target.list();
		if (candidates == null)
			return;
		removeFiles(target, candidates, valuables);
	}

	protected void removeUnusedTreeFiles() {
		// root resource
		List<String> valuables = new ArrayList<>(10);
		IPath location = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false);
		valuables.add(location.lastSegment());
		java.io.File target = location.toFile().getParentFile();
		FilenameFilter filter = (dir, name) -> name.endsWith(LocalMetaArea.F_TREE);
		String[] candidates = target.list(filter);
		if (candidates != null)
			removeFiles(target, candidates, valuables);

		// projects
		IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects) {
			location = workspace.getMetaArea().getTreeLocationFor(project, false);
			valuables.add(location.lastSegment());
			target = location.toFile().getParentFile();
			candidates = target.list(filter);
			if (candidates != null)
				removeFiles(target, candidates, valuables);
		}
	}

	protected void reportSnapshotRequestor() {
		if (snapshotRequestor != null)
			Policy.log(snapshotRequestor);
	}

	public void requestSnapshot() {
		snapshotRequested = true;
	}

	/**
	 * Reset the snapshot mechanism for the non-workspace files. This
	 * includes the markers and sync info.
	 */
	protected void resetSnapshots(IResource resource) throws CoreException {
		Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT);
		String message;

		// delete the snapshot file, if any
		java.io.File file = workspace.getMetaArea().getMarkersSnapshotLocationFor(resource).toFile();
		if (file.exists())
			file.delete();
		if (file.exists()) {
			message = Messages.resources_resetMarkers;
			throw new ResourceException(IResourceStatus.FAILED_DELETE_METADATA, resource.getFullPath(), message, null);
		}

		// delete the snapshot file, if any
		file = workspace.getMetaArea().getSyncInfoSnapshotLocationFor(resource).toFile();
		if (file.exists())
			file.delete();
		if (file.exists()) {
			message = Messages.resources_resetSync;
			throw new ResourceException(IResourceStatus.FAILED_DELETE_METADATA, resource.getFullPath(), message, null);
		}

		// if we have the workspace root then recursive over the projects.
		// only do open projects since closed ones are saved elsewhere
		if (resource.getType() == IResource.PROJECT)
			return;
		IProject[] projects = ((IWorkspaceRoot) resource).getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects)
			resetSnapshots(project);
	}

	/**
	 * Restores the state of this workspace by opening the projects
	 * which were open when it was last saved.
	 */
	protected void restore(IProgressMonitor monitor) throws CoreException {
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore workspace: starting..."); //$NON-NLS-1$
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask("", 50); //$NON-NLS-1$
			// need to open the tree to restore, but since we're not
			// inside an operation, be sure to close it afterwards
			workspace.newWorkingTree();
			try {
				String msg = Messages.resources_startupProblems;
				MultiStatus problems = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_READ_METADATA, msg, null);

				restoreMasterTable();
				// restore the saved tree and overlay the snapshots if any
				restoreTree(Policy.subMonitorFor(monitor, 10));
				restoreSnapshots(Policy.subMonitorFor(monitor, 10));

				// tolerate failure for non-critical information
				// if startup fails, the entire workspace is shot
				try {
					restoreMarkers(workspace.getRoot(), false, Policy.subMonitorFor(monitor, 10));
				} catch (CoreException e) {
					problems.merge(e.getStatus());
				}
				try {
					restoreSyncInfo(workspace.getRoot(), Policy.subMonitorFor(monitor, 10));
				} catch (CoreException e) {
					problems.merge(e.getStatus());
				}
				// restore meta info last because it might close a project if its description is not readable
				restoreMetaInfo(problems, Policy.subMonitorFor(monitor, 10));
				IProject[] roots = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
				for (IProject root : roots)
					((Project) root).startup();
				if (!problems.isOK())
					Policy.log(problems);
			} finally {
				workspace.getElementTree().immutable();
			}
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Restores the contents of this project.  Throw
	 * an exception if the project could not be restored.
	 * @return <code><code>true</code> if the project data was restored successfully,
	 * and <code>false</code> if non-critical problems occurred while restoring.
	 * @exception CoreException if the project could not be restored.
	 */
	protected boolean restore(Project project, IProgressMonitor monitor) throws CoreException {
		boolean status = true;
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore project " + project.getFullPath() + ": starting..."); //$NON-NLS-1$ //$NON-NLS-2$
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask("", 40); //$NON-NLS-1$
			if (project.isOpen()) {
				status = restoreTree(project, Policy.subMonitorFor(monitor, 10));
			} else {
				monitor.worked(10);
			}
			restoreMarkers(project, true, Policy.subMonitorFor(monitor, 10));
			restoreSyncInfo(project, Policy.subMonitorFor(monitor, 10));
			// restore meta info last because it might close a project if its description is not found
			restoreMetaInfo(project, Policy.subMonitorFor(monitor, 10));
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		return status;
	}

	/**
	 * Restores the contents of this project from a refresh snapshot, if possible.
	 * Throws an exception if the snapshot is found but an error occurs when reading
	 * the file.
	 * @return <code><code>true</code> if the project data was restored successfully,
	 * and <code>false</code> if the refresh snapshot was not found or could not be opened.
	 * @exception CoreException if an error occurred reading the snapshot file.
	 */
	protected boolean restoreFromRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
		boolean status = true;
		IPath snapshotPath = workspace.getMetaArea().getRefreshLocationFor(project);
		java.io.File snapshotFile = snapshotPath.toFile();
		if (!snapshotFile.exists())
			return false;
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore project " + project.getFullPath() + ": starting..."); //$NON-NLS-1$ //$NON-NLS-2$
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask("", 40); //$NON-NLS-1$
			status = restoreTreeFromRefreshSnapshot(project, snapshotFile, Policy.subMonitorFor(monitor, 40));
			if (status) {
				// load the project description and set internal description
				ProjectDescription description = workspace.getFileSystemManager().read(project, true);
				project.internalSetDescription(description, false);
				workspace.getMetaArea().clearRefresh(project);
			}
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE)
			Policy.debug("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		return status;
	}

	/**
	 * Reads the markers which were originally saved
	 * for the tree rooted by the given resource.
	 */
	protected void restoreMarkers(IResource resource, boolean generateDeltas, IProgressMonitor monitor) throws CoreException {
		Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT);
		long start = System.currentTimeMillis();
		MarkerManager markerManager = workspace.getMarkerManager();
		// when restoring a project, only load markers if it is open
		if (resource.isAccessible())
			markerManager.restore(resource, generateDeltas, monitor);

		// if we have the workspace root then restore markers for its projects
		if (resource.getType() == IResource.PROJECT) {
			if (Policy.DEBUG_RESTORE_MARKERS) {
				Policy.debug("Restore Markers for " + resource.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			return;
		}
		IProject[] projects = ((IWorkspaceRoot) resource).getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects)
			if (project.isAccessible())
				markerManager.restore(project, generateDeltas, monitor);
		if (Policy.DEBUG_RESTORE_MARKERS) {
			Policy.debug("Restore Markers for workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	protected void restoreMasterTable() throws CoreException {
		long start = System.currentTimeMillis();
		masterTable.clear();
		IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES);
		java.io.File target = location.toFile();
		if (!target.exists()) {
			location = workspace.getMetaArea().getBackupLocationFor(location);
			target = location.toFile();
			if (!target.exists())
				return;
		}
		try (SafeChunkyInputStream input = new SafeChunkyInputStream(target)) {
			masterTable.load(input);
		} catch (IOException e) {
			String message = Messages.resources_exMasterTable;
			throw new ResourceException(IResourceStatus.INTERNAL_ERROR, null, message, e);
		}
		if (Policy.DEBUG_RESTORE_MASTERTABLE)
			Policy.debug("Restore master table for " + location + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * Restores the state of this workspace by opening the projects
	 * which were open when it was last saved.
	 */
	protected void restoreMetaInfo(MultiStatus problems, IProgressMonitor monitor) {
		if (Policy.DEBUG_RESTORE_METAINFO)
			Policy.debug("Restore workspace metainfo: starting..."); //$NON-NLS-1$
		long start = System.currentTimeMillis();
		IProject[] roots = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject root : roots) {
			//fatal to throw exceptions during startup
			try {
				restoreMetaInfo((Project) root, monitor);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_readMeta, root.getName());
				problems.merge(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, root.getFullPath(), message, e));
			}
		}
		if (Policy.DEBUG_RESTORE_METAINFO)
			Policy.debug("Restore workspace metainfo: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Restores the contents of this project.  Throw an exception if the
	 * project description could not be restored.
	 */
	protected void restoreMetaInfo(Project project, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		ProjectDescription description = null;
		CoreException failure = null;
		try {
			if (project.isOpen())
				description = workspace.getFileSystemManager().read(project, true);
			else
				//for closed projects, just try to read the legacy .prj file,
				//because the project location is stored there.
				description = workspace.getMetaArea().readOldDescription(project);
		} catch (CoreException e) {
			failure = e;
		}
		// If we had an open project and there was an error reading the description
		// from disk, close the project and give it a default description. If the project
		// was already closed then just set a default description.
		if (description == null) {
			description = new ProjectDescription();
			description.setName(project.getName());
			//try to read private metadata and add to the description
			workspace.getMetaArea().readPrivateDescription(project, description);
		}
		project.internalSetDescription(description, false);
		if (failure != null) {
			// write the project tree ...
			writeTree(project, IResource.DEPTH_INFINITE);
			// ... and close the project
			project.internalClose(monitor);
			throw failure;
		}
		if (Policy.DEBUG_RESTORE_METAINFO)
			Policy.debug("Restore metainfo for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * Restores the workspace tree from snapshot files in the event
	 * of a crash.  The workspace tree must be open when this method
	 * is called, and will be open at the end of this method.  In the
	 * event of a crash recovery, the snapshot file is not deleted until
	 * the next successful save.
	 */
	protected void restoreSnapshots(IProgressMonitor monitor) {
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		String message;
		try {
			monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
			IPath snapLocation = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot());
			java.io.File localFile = snapLocation.toFile();

			if (!localFile.exists()) {
				// The snapshot corresponding to the current tree version doesn't exist.
				// Try the legacy non-versioned snapshot, but ignore it if it is older than
				// the tree.
				snapLocation = workspace.getMetaArea().getLegacySnapshotLocationFor(workspace.getRoot());
				localFile = snapLocation.toFile();
				if (!localFile.exists() || isSnapshotOlderThanTree(localFile)) {
					// If the snapshot file doesn't exist, there was no crash.
					// Just initialize the snapshot file and return.
					initSnap(Policy.subMonitorFor(monitor, Policy.totalWork / 2));
					return;
				}
			}
			// If we have a snapshot file, the workspace was shutdown without being saved or crashed.
			workspace.setCrashed(true);
			try {
				/* Read each of the snapshots and lay them on top of the current tree.*/
				ElementTree complete = workspace.getElementTree();
				complete.immutable();
				try (
					DataInputStream input = new DataInputStream(new SafeChunkyInputStream(localFile));
				) {
					WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt());
					complete = reader.readSnapshotTree(input, complete, monitor);
				} finally {
					//reader returned an immutable tree, but since we're inside
					//an operation, we must return an open tree
					lastSnap = complete;
					complete = complete.newEmptyDelta();
					workspace.tree = complete;
				}
			} catch (Exception e) {
				// only log the exception, we should not fail restoring the snapshot
				message = Messages.resources_snapRead;
				Policy.log(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, null, message, e));
			}
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE_SNAPSHOTS)
			Policy.debug("Restore snapshots for workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Checks if the given snapshot file is older than the tree file.
	 *
	 * @param snapshot the snapshot file to check
	 * @return {@code true} if the snapshot file is older than the tree file or the tree file
	 *     does not exist
	 */
	private boolean isSnapshotOlderThanTree(File snapshot) {
		IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false);
		File tree = treeLocation.toFile();
		if (!tree.exists()) {
			treeLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation);
			tree = treeLocation.toFile();
			if (!tree.exists())
				return false;
		}
		return snapshot.lastModified() < tree.lastModified();
	}

	/**
	 * Reads the sync info which was originally saved
	 * for the tree rooted by the given resource.
	 */
	protected void restoreSyncInfo(IResource resource, IProgressMonitor monitor) throws CoreException {
		Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT);
		long start = System.currentTimeMillis();
		Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer();
		// when restoring a project, only load sync info if it is open
		if (resource.isAccessible())
			synchronizer.restore(resource, monitor);

		// restore sync info for all projects if we were given the workspace root.
		if (resource.getType() == IResource.PROJECT) {
			if (Policy.DEBUG_RESTORE_SYNCINFO) {
				Policy.debug("Restore SyncInfo for " + resource.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			return;
		}
		IProject[] projects = ((IWorkspaceRoot) resource).getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects)
			if (project.isAccessible())
				synchronizer.restore(project, monitor);
		if (Policy.DEBUG_RESTORE_SYNCINFO) {
			Policy.debug("Restore SyncInfo for workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Reads the contents of the tree rooted by the given resource from the
	 * file system. This method is used when restoring a complete workspace
	 * after workspace save/shutdown.
	 * @exception CoreException if the workspace could not be restored.
	 */
	protected void restoreTree(IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false);
		IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation);
		if (!treeLocation.toFile().exists() && !tempLocation.toFile().exists()) {
			savedStates = Collections.synchronizedMap(new HashMap<>(10));
			return;
		}
		try (DataInputStream input = new DataInputStream(new SafeFileInputStream(treeLocation.toOSString(), tempLocation.toOSString(), TREE_BUFFER_SIZE))) {
			WorkspaceTreeReader.getReader(workspace, input.readInt()).readTree(input, monitor);
		} catch (IOException e) {
			String msg = NLS.bind(Messages.resources_readMeta, treeLocation.toOSString());
			throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, treeLocation, msg, e);
		}
		if (Policy.DEBUG_RESTORE_TREE) {
			Policy.debug("Restore Tree for workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Restores the trees for the builders of this project from the local disk.
	 * Does nothing if the tree file does not exist (this means the
	 * project has never been saved).  This method is
	 * used when restoring a saved/closed project.  restoreTree(Workspace) is
	 * used when restoring a complete workspace after workspace save/shutdown.
	 * @return <code>true</code> if the tree file exists, <code>false</code> otherwise.
	 * @exception CoreException if the project could not be restored.
	 */
	protected boolean restoreTree(Project project, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		String message;
		try {
			monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
			IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(project, false);
			IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation);
			if (!treeLocation.toFile().exists() && !tempLocation.toFile().exists())
				return false;
			try (
				DataInputStream input = new DataInputStream(new SafeFileInputStream(treeLocation.toOSString(), tempLocation.toOSString()));
			) {
				WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt());
				reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork));
			}
		} catch (IOException e) {
			message = NLS.bind(Messages.resources_readMeta, project.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, project.getFullPath(), message, e);
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE_TREE) {
			Policy.debug("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return true;
	}

	/**
	 * Restores a tree saved as a refresh snapshot to a specified URI.
	 * @return <code>true</code> if the snapshot exists, <code>false</code> otherwise.
	 * @exception CoreException if the project could not be restored.
	 */
	protected boolean restoreTreeFromRefreshSnapshot(Project project, java.io.File snapshotFile, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		monitor = Policy.monitorFor(monitor);
		String message;
		IPath snapshotPath = null;
		try {
			monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
			InputStream snapIn = new FileInputStream(snapshotFile);
			ZipInputStream zip = new ZipInputStream(snapIn);
			ZipEntry treeEntry = zip.getNextEntry();
			if (treeEntry == null || !treeEntry.getName().equals("resource-index.tree")) { //$NON-NLS-1$
				zip.close();
				return false;
			}
			try (
				DataInputStream input = new DataInputStream(zip);
			) {
				WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt(), true);
				reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork));
			} finally {
				zip.close();
			}
		} catch (IOException e) {
			snapshotPath = new Path(snapshotFile.getPath());
			message = NLS.bind(Messages.resources_readMeta, snapshotPath);
			throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, snapshotPath, message, e);
		} finally {
			monitor.done();
		}
		if (Policy.DEBUG_RESTORE_TREE) {
			Policy.debug("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return true;
	}

	class InternalMonitorWrapper extends ProgressMonitorWrapper {
		private boolean ignoreCancel;

		public InternalMonitorWrapper(IProgressMonitor monitor) {
			super(SubMonitor.convert(monitor));
		}

		public void ignoreCancelState(boolean ignore) {
			this.ignoreCancel = ignore;
		}

		@Override
		public boolean isCanceled() {
			return ignoreCancel ? false : super.isCanceled();
		}
	}

	public IStatus save(int kind, Project project, IProgressMonitor monitor) throws CoreException {
		return save(kind, false, project, monitor);
	}

	public IStatus save(int kind, boolean keepConsistencyWhenCanceled, Project project, IProgressMonitor parentMonitor) throws CoreException {
		InternalMonitorWrapper monitor = new InternalMonitorWrapper(parentMonitor);
		monitor.ignoreCancelState(keepConsistencyWhenCanceled);
		try {
			isSaving = true;
			String message = Messages.resources_saving_0;
			monitor.beginTask(message, 7);
			message = Messages.resources_saveWarnings;
			MultiStatus warnings = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.WARNING, message, null);
			ISchedulingRule rule = project != null ? (IResource) project : workspace.getRoot();
			try {
				workspace.prepareOperation(rule, monitor);
				workspace.beginOperation(false);
				hookStartSave(kind, project);
				long start = System.currentTimeMillis();
				Map<String, SaveContext> contexts = computeSaveContexts(getSaveParticipantPluginIds(), kind, project);
				broadcastLifecycle(PREPARE_TO_SAVE, contexts, warnings, Policy.subMonitorFor(monitor, 1));
				try {
					broadcastLifecycle(SAVING, contexts, warnings, Policy.subMonitorFor(monitor, 1));
					switch (kind) {
						case ISaveContext.FULL_SAVE :
							// save the complete tree and remember all of the required saved states
							saveTree(contexts, Policy.subMonitorFor(monitor, 1));
							// reset the snapshot state.
							initSnap(null);
							snapshotRequestor = null;
							//save master table right after saving tree to ensure correct tree number is saved
							cleanMasterTable();
							// save all of the markers and all sync info in the workspace
							persistMarkers = 0l;
							persistSyncInfo = 0l;
							visitAndSave(workspace.getRoot());
							monitor.worked(1);
							if (Policy.DEBUG_SAVE) {
								Policy.debug("Total Save Markers: " + persistMarkers + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
								Policy.debug("Total Save Sync Info: " + persistSyncInfo + "ms"); //$NON-NLS-1$	 //$NON-NLS-2$
							}
							// reset the snap shot files
							resetSnapshots(workspace.getRoot());
							//remove unused files
							removeUnusedSafeTables();
							removeUnusedTreeFiles();

							// history pruning can be always canceled
							monitor.ignoreCancelState(false);
							workspace.getFileSystemManager().getHistoryStore().clean(Policy.subMonitorFor(monitor, 1));
							monitor.ignoreCancelState(keepConsistencyWhenCanceled);

							// write out all metainfo (e.g., workspace/project descriptions)
							saveMetaInfo(warnings, Policy.subMonitorFor(monitor, 1));
							break;
						case ISaveContext.SNAPSHOT :
							snapTree(workspace.getElementTree(), Policy.subMonitorFor(monitor, 1));
							// snapshot the markers and sync info for the workspace
							persistMarkers = 0l;
							persistSyncInfo = 0l;
							visitAndSnap(workspace.getRoot());
							monitor.worked(1);
							if (Policy.DEBUG_SAVE) {
								Policy.debug("Total Snap Markers: " + persistMarkers + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
								Policy.debug("Total Snap Sync Info: " + persistSyncInfo + "ms"); //$NON-NLS-1$	 //$NON-NLS-2$
							}
							collapseTrees(contexts);
							clearSavedDelta();
							// write out all metainfo (e.g., workspace/project descriptions)
							saveMetaInfo(warnings, Policy.subMonitorFor(monitor, 1));
							break;
						case ISaveContext.PROJECT_SAVE :
							writeTree(project, IResource.DEPTH_INFINITE);
							monitor.worked(1);
							// save markers and sync info
							visitAndSave(project);
							monitor.worked(1);
							// reset the snapshot file
							resetSnapshots(project);
							IStatus result = saveMetaInfo(project, null);
							if (!result.isOK())
								warnings.merge(result);
							monitor.worked(1);
							break;
					}
					// save contexts
					commit(contexts);
					if (kind == ISaveContext.FULL_SAVE)
						removeClearDeltaMarks();
					//this must be done after committing save contexts to update participant save numbers
					saveMasterTable(kind);
					broadcastLifecycle(DONE_SAVING, contexts, warnings, Policy.subMonitorFor(monitor, 1));
					hookEndSave(kind, project, start);
					return warnings;
				} catch (CoreException e) {
					broadcastLifecycle(ROLLBACK, contexts, warnings, Policy.subMonitorFor(monitor, 1));
					// rollback ResourcesPlugin master table
					restoreMasterTable();
					throw e; // re-throw
				}
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.endOperation(rule, false);
			}
		} finally {
			isSaving = false;
			monitor.done();
		}
	}

	protected void saveMasterTable(int kind) throws CoreException {
		saveMasterTable(kind, workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES));
	}

	protected void saveMasterTable(int kind, IPath location) throws CoreException {
		long start = System.currentTimeMillis();
		java.io.File target = location.toFile();
		try {
			if (kind == ISaveContext.FULL_SAVE || kind == ISaveContext.SNAPSHOT)
				validateMasterTableBeforeSave(target);
			try (
				SafeChunkyOutputStream output = new SafeChunkyOutputStream(target);
			) {
				masterTable.store(output, "master table"); //$NON-NLS-1$
				output.succeed();
			}
		} catch (IOException e) {
			throw new ResourceException(IResourceStatus.INTERNAL_ERROR, null, NLS.bind(Messages.resources_exSaveMaster, location.toOSString()), e);
		}
		if (Policy.DEBUG_SAVE_MASTERTABLE)
			Policy.debug("Save master table for " + location + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * Writes the metainfo (e.g. descriptions) of the given workspace and
	 * all projects to the local disk.
	 */
	protected void saveMetaInfo(MultiStatus problems, IProgressMonitor monitor) throws CoreException {
		if (Policy.DEBUG_SAVE_METAINFO)
			Policy.debug("Save workspace metainfo: starting..."); //$NON-NLS-1$
		long start = System.currentTimeMillis();
		// save preferences (workspace description, path variables, etc)
		ResourcesPlugin.getPlugin().savePluginPreferences();
		// save projects' meta info
		IProject[] roots = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject root : roots)
			if (root.isAccessible()) {
				IStatus result = saveMetaInfo((Project) root, null);
				if (!result.isOK())
					problems.merge(result);
			}
		if (Policy.DEBUG_SAVE_METAINFO)
			Policy.debug("Save workspace metainfo: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Ensures that the project meta-info is saved.  The project meta-info
	 * is usually saved as soon as it changes, so this is just a sanity check
	 * to make sure there is something on disk before we shutdown.
	 *
	 * @return Status object containing non-critical warnings, or an OK status.
	 */
	protected IStatus saveMetaInfo(Project project, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		//if there is nothing on disk, write the description
		if (!workspace.getFileSystemManager().hasSavedDescription(project)) {
			workspace.getFileSystemManager().writeSilently(project);
			String msg = NLS.bind(Messages.resources_missingProjectMetaRepaired, project.getName());
			return new ResourceStatus(IResourceStatus.MISSING_DESCRIPTION_REPAIRED, project.getFullPath(), msg);
		}
		if (Policy.DEBUG_SAVE_METAINFO)
			Policy.debug("Save metainfo for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		return Status.OK_STATUS;
	}

	/**
	 * Writes a snapshot of project refresh information to the specified
	 * location.
	 * @param project the project to write a refresh snapshot for
	 * @param monitor progress monitor
	 * @exception CoreException if there is a problem writing the snapshot.
	 */
	public void saveRefreshSnapshot(Project project, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
		IFileStore store = EFS.getStore(snapshotLocation);
		IPath snapshotPath = new Path(snapshotLocation.getPath());
		java.io.File tmpTree = null;
		try {
			tmpTree = java.io.File.createTempFile("tmp", ".tree"); //$NON-NLS-1$//$NON-NLS-2$
		} catch (IOException e) {
			throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotPath, Messages.resources_copyProblem, e);
		}
		ZipOutputStream out = null;
		try {
			FileOutputStream fis = new FileOutputStream(tmpTree);
			try (
				DataOutputStream output = new DataOutputStream(fis);
			) {
				output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
				writeTree(project, output, monitor);
			}
			OutputStream snapOut = store.openOutputStream(EFS.NONE, monitor);
			out = new ZipOutputStream(snapOut);
			out.setLevel(Deflater.BEST_COMPRESSION);
			ZipEntry e = new ZipEntry("resource-index.tree"); //$NON-NLS-1$
			out.putNextEntry(e);
			int read = 0;
			byte[] buffer = new byte[4096];
			try (
				InputStream in = new FileInputStream(tmpTree);
			) {
				while ((read = in.read(buffer)) >= 0) {
					out.write(buffer, 0, read);
				}
				out.closeEntry();
			}
			out.close();
		} catch (IOException e) {
			throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotPath, Messages.resources_copyProblem, e);
		} finally {
			FileUtil.safeClose(out);
			if (tmpTree != null)
				tmpTree.delete();
		}
	}

	/**
	 * Writes the current state of the entire workspace tree to disk.
	 * This is used during workspace save.  saveTree(Project)
	 * is used to save the state of an individual project.
	 * @exception CoreException if there is a problem writing the tree to disk.
	 */
	protected void saveTree(Map<String, SaveContext> contexts, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), true);
		try {
			IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation);
			try (
				DataOutputStream output = new DataOutputStream(new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString()));
			) {
				output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
				writeTree(computeStatesToSave(contexts, workspace.getElementTree()), output, monitor);
			}
		} catch (Exception e) {
			String msg = NLS.bind(Messages.resources_writeWorkspaceMeta, treeLocation);
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, Path.ROOT, msg, e);
		}
		if (Policy.DEBUG_SAVE_TREE)
			Policy.debug("Save Workspace Tree: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Should only be used for read purposes.
	 */
	void setPluginsSavedState(HashMap<String, SavedState> savedStates) {
		this.savedStates = Collections.synchronizedMap(savedStates);
	}

	protected void setSaveNumber(String pluginId, int number) {
		masterTable.setProperty(SAVE_NUMBER_PREFIX + pluginId, Integer.toString(number));
	}

	@Override
	public void shareStrings(StringPool pool) {
		lastSnap.shareStrings(pool);
	}

	@Override
	public void shutdown(final IProgressMonitor monitor) {
		// do a last snapshot if it was scheduled
		// we force it in the same thread because it would not
		// help if the job runs after we close the workspace
		int state = snapshotJob.getState();
		if (state == Job.WAITING || state == Job.SLEEPING)
			// we cannot pass null to Job#run
			snapshotJob.run(SubMonitor.convert(monitor));
		// cancel the snapshot job
		snapshotJob.cancel();
	}

	/**
	 * Performs a snapshot if one is deemed necessary.
	 * Encapsulates rules for determining when a snapshot is needed.
	 * This should be called at the end of every top level operation.
	 */
	public void snapshotIfNeeded(boolean hasTreeChanges) {
		// never schedule a snapshot while save is occurring.
		if (isSaving)
			return;
		if (snapshotRequested || operationCount >= workspace.internalGetDescription().getOperationsPerSnapshot()) {
			rememberSnapshotRequestor();
			if (snapshotJob.getState() == Job.NONE)
				snapshotJob.schedule();
			else
				snapshotJob.wakeUp();
		} else {
			if (hasTreeChanges) {
				operationCount++;
				if (snapshotJob.getState() == Job.NONE) {
					rememberSnapshotRequestor();
					long interval = workspace.internalGetDescription().getSnapshotInterval();
					snapshotJob.schedule(Math.max(interval, MIN_SNAPSHOT_DELAY));
				}
			} else {
				//only increment the operation count if we've had a sufficient number of no-ops
				if (++noopCount > NO_OP_THRESHOLD) {
					operationCount++;
					noopCount = 0;
				}
			}
		}
	}

	/**
	 * Performs a snapshot of the workspace tree.
	 */
	protected void snapTree(ElementTree tree, IProgressMonitor monitor) throws CoreException {
		long start = System.currentTimeMillis();
		String message;
		SubMonitor subMonitor = SubMonitor.convert(monitor, Policy.totalWork);
		try {
			// the tree must be immutable
			tree.immutable();
			// don't need to snapshot if there are no changes
			if (tree == lastSnap)
				return;
			operationCount = 0;
			IPath snapPath = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot());
			ElementTreeWriter writer = new ElementTreeWriter(this);
			java.io.File localFile = snapPath.toFile();
			try {
				SafeChunkyOutputStream safeStream = new SafeChunkyOutputStream(localFile);
				try (DataOutputStream out = new DataOutputStream(safeStream);) {
					out.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
					writeWorkspaceFields(out, subMonitor);
					writer.writeDelta(tree, lastSnap, Path.ROOT, ElementTreeWriter.D_INFINITE, out,
							ResourceComparator.getSaveComparator());
					safeStream.succeed();
					out.close();
				}
			} catch (IOException e) {
				message = NLS.bind(Messages.resources_writeWorkspaceMeta, localFile.getAbsolutePath());
				throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, Path.ROOT, message, e);
			}
			lastSnap = tree;
			if (Policy.DEBUG_SAVE_TREE)
				Policy.debug("Snapshot Workspace Tree: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		} finally {
			subMonitor.done();
		}
	}

	/**
	 * Sorts the given array of trees so that the following rules are true:
	 * 	 - The first tree has no parent
	 * 	 - No tree has an ancestor with a greater index in the array.
	 * If there are no missing parents in the given trees array, this means
	 * that in the resulting array, the i'th tree's parent will be tree i-1.
	 * The input tree array may contain duplicate trees.
	 */
	protected ElementTree[] sortTrees(ElementTree[] trees) {
		/* the sorted list */
		int numTrees = trees.length;
		ElementTree[] sorted = new ElementTree[numTrees];

		/* first build a table of ElementTree -> List of Integers(indices in trees array) */
		Map<ElementTree, List<Integer>> table = new HashMap<>(numTrees * 2 + 1);
		for (int i = 0; i < trees.length; i++) {
			List<Integer> indices = table.get(trees[i]);
			if (indices == null) {
				indices = new ArrayList<>(10);
				table.put(trees[i], indices);
			}
			indices.add(i);
		}

		/* find the oldest tree (a descendent of all other trees) */
		ElementTree oldest = trees[ElementTree.findOldest(trees)];

		/**
		 * Walk through the chain of trees from oldest to newest,
		 * adding them to the sorted list as we go.
		 */
		int i = numTrees - 1;
		while (i >= 0) {
			/* add all instances of the current oldest tree to the sorted list */
			List<Integer> indices = table.remove(oldest);
			for (Enumeration<Integer> e = Collections.enumeration(indices); e.hasMoreElements();) {
				e.nextElement();
				sorted[i] = oldest;
				i--;
			}
			if (i >= 0) {
				/* find the next tree in the list */
				ElementTree parent = oldest.getParent();
				while (parent != null && table.get(parent) == null) {
					parent = parent.getParent();
				}
				if (parent == null) {
					Exception e = new NullPointerException("null parent found while collapsing trees"); //$NON-NLS-1$
					IStatus status = new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, e.getMessage(), e);
					Policy.log(status);
					return null;
				}
				oldest = parent;
			}
		}
		return sorted;
	}

	@Override
	public void startup(IProgressMonitor monitor) throws CoreException {
		restore(monitor);
		java.io.File table = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES).toFile();
		if (!table.exists())
			table.getParentFile().mkdirs();
	}

	/**
	 * Update the expiration time for the given plug-in's tree.  If the tree was never
	 * loaded, use the current value in the master table. If the tree has been loaded,
	 * use the provided new timestamp.
	 *
	 * The timestamp is used in the policy for cleaning up tree's of plug-ins that are
	 * not often activated.
	 */
	protected void updateDeltaExpiration(String pluginId) {
		String key = DELTA_EXPIRATION_PREFIX + pluginId;
		if (!masterTable.containsKey(key))
			masterTable.setProperty(key, Long.toString(System.currentTimeMillis()));
	}

	private void validateMasterTableBeforeSave(java.io.File target) throws IOException {
		if (target.exists()) {
			MasterTable previousMasterTable = new MasterTable();
			try (
				SafeChunkyInputStream input = new SafeChunkyInputStream(target);
			) {
				previousMasterTable.load(input);
				String stringValue = previousMasterTable.getProperty(ROOT_SEQUENCE_NUMBER_KEY);
				// if there was a full save, then there must be a non-null entry for root
				if (stringValue != null) {
					int valueInFile = Integer.parseInt(stringValue);
					int valueInMemory = Integer.parseInt(masterTable.getProperty(ROOT_SEQUENCE_NUMBER_KEY));
					// new master table must provide greater or equal sequence number for root
					// throw exception if new value is lower than previous one - we cannot allow to desynchronize master table on disk
					if (valueInMemory < valueInFile) {
						String message = getBadSequenceNumberErrorMessage(target, valueInFile, valueInMemory, masterTable, previousMasterTable);
						Assert.isLegal(false, message);
					}
				}
			}
		}
	}

	private static String getBadSequenceNumberErrorMessage(java.io.File target, int valueInFile, int valueInMemory, MasterTable currentMasterTable, MasterTable previousMasterTable) {
		StringBuilder messageBuffer = new StringBuilder();
		messageBuffer.append("Cannot set lower sequence number for root (previous: "); //$NON-NLS-1$
		messageBuffer.append(valueInFile);
		messageBuffer.append(", new: "); //$NON-NLS-1$
		messageBuffer.append(valueInMemory);
		messageBuffer.append("). Location: "); //$NON-NLS-1$
		messageBuffer.append(target.getAbsolutePath());
		try {
			messageBuffer.append("Timestamps and tree sequence numbers from file:"); //$NON-NLS-1$
			java.nio.file.Path targetPath = Paths.get(target.getAbsolutePath());
			List<String> masterTableFileContents = Files.readAllLines(targetPath, Charset.defaultCharset());
			for (String line : masterTableFileContents) {
				if (line != null) {
					boolean isPropertiesTimestamp = line.startsWith("#"); //$NON-NLS-1$
					boolean isTreeProperty = line.startsWith(ROOT_SEQUENCE_NUMBER_KEY);
					if (isPropertiesTimestamp || isTreeProperty) {
						messageBuffer.append(System.lineSeparator());
						messageBuffer.append(line);
					}
				}
			}
		} catch (IOException e) {
			ILog log = ResourcesPlugin.getPlugin().getLog();
			String errorMessage = "Error occurred while reading master table file"; //$NON-NLS-1$
			IStatus errorStatus = new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, errorMessage, e);
			log.log(errorStatus);
		}
		return messageBuffer.toString();
	}

	/**
	 * Visit the given resource (to depth infinite) and write out extra information
	 * like markers and sync info. To be called during a full save and project save.
	 *
	 * FIXME: This method is ugly. Fix it up and look at merging with #visitAndSnap
	 */
	public void visitAndSave(final IResource root) throws CoreException {
		// Ensure we have either a project or the workspace root
		Assert.isLegal(root.getType() == IResource.ROOT || root.getType() == IResource.PROJECT);
		// only write out info for accessible resources
		if (!root.isAccessible())
			return;

		// Setup variables
		final Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer();
		final MarkerManager markerManager = workspace.getMarkerManager();
		IPath markersLocation = workspace.getMetaArea().getMarkersLocationFor(root);
		IPath markersTempLocation = workspace.getMetaArea().getBackupLocationFor(markersLocation);
		IPath syncInfoLocation = workspace.getMetaArea().getSyncInfoLocationFor(root);
		IPath syncInfoTempLocation = workspace.getMetaArea().getBackupLocationFor(syncInfoLocation);
		final List<String> writtenTypes = new ArrayList<>(5);
		final List<QualifiedName> writtenPartners = new ArrayList<>(synchronizer.registry.size());
		DataOutputStream o1 = null;
		DataOutputStream o2 = null;
		String message;

		// Create the output streams
		try {
			o1 = new DataOutputStream(new SafeFileOutputStream(markersLocation.toOSString(), markersTempLocation.toOSString()));
			// we don't store the sync info for the workspace root so don't create
			// an empty file
			if (root.getType() != IResource.ROOT)
				o2 = new DataOutputStream(new SafeFileOutputStream(syncInfoLocation.toOSString(), syncInfoTempLocation.toOSString()));
		} catch (IOException e) {
			FileUtil.safeClose(o1);
			FileUtil.safeClose(o2);
			message = NLS.bind(Messages.resources_writeMeta, root.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e);
		}

		final DataOutputStream markersOutput = o1;
		final DataOutputStream syncInfoOutput = o2;
		// The following 2 piece array will hold a running total of the times
		// taken to save markers and syncInfo respectively.  This will cut down
		// on the number of statements printed out as we would get 2 statements
		// for each resource otherwise.
		final long[] saveTimes = new long[2];

		// Create the visitor
		IElementContentVisitor visitor = (tree, requestor, elementContents) -> {
			ResourceInfo info = (ResourceInfo) elementContents;
			if (info != null) {
				try {
					// save the markers
					long start = System.currentTimeMillis();
					markerManager.save(info, requestor, markersOutput, writtenTypes);
					long markerSaveTime = System.currentTimeMillis() - start;
					saveTimes[0] += markerSaveTime;
					persistMarkers += markerSaveTime;
					// save the sync info - if we have the workspace root then the output stream will be null
					if (syncInfoOutput != null) {
						start = System.currentTimeMillis();
						synchronizer.saveSyncInfo(info, requestor, syncInfoOutput, writtenPartners);
						long syncInfoSaveTime = System.currentTimeMillis() - start;
						saveTimes[1] += syncInfoSaveTime;
						persistSyncInfo += syncInfoSaveTime;
					}
				} catch (IOException e) {
					throw new WrappedRuntimeException(e);
				}
			}
			// don't continue if the current resource is the workspace root, only continue for projects
			return root.getType() != IResource.ROOT;
		};

		// Call the visitor
		try {
			try {
				new ElementTreeIterator(workspace.getElementTree(), root.getFullPath()).iterate(visitor);
			} catch (WrappedRuntimeException e) {
				throw (IOException) e.getTargetException();
			}
			if (Policy.DEBUG_SAVE_MARKERS)
				Policy.debug("Save Markers for " + root.getFullPath() + ": " + saveTimes[0] + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			if (Policy.DEBUG_SAVE_SYNCINFO)
				Policy.debug("Save SyncInfo for " + root.getFullPath() + ": " + saveTimes[1] + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			removeGarbage(markersOutput, markersLocation, markersTempLocation);
			// if we have the workspace root the output stream will be null and we
			// don't have to perform cleanup code
			if (syncInfoOutput != null) {
				removeGarbage(syncInfoOutput, syncInfoLocation, syncInfoTempLocation);
				syncInfoOutput.close();
			}
			markersOutput.close();
		} catch (IOException e) {
			message = NLS.bind(Messages.resources_writeMeta, root.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e);
		} finally {
			FileUtil.safeClose(markersOutput);
			FileUtil.safeClose(syncInfoOutput);
		}

		// recurse over the projects in the workspace if we were given the workspace root
		if (root.getType() == IResource.PROJECT)
			return;
		IProject[] projects = ((IWorkspaceRoot) root).getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects)
			visitAndSave(project);
	}

	/**
	 * Visit the given resource (to depth infinite) and write out extra information
	 * like markers and sync info. To be called during a snapshot
	 *
	 * FIXME: This method is ugly. Fix it up and look at merging with #visitAndSnap
	 */
	public void visitAndSnap(final IResource root) throws CoreException {
		// Ensure we have either a project or the workspace root
		Assert.isLegal(root.getType() == IResource.ROOT || root.getType() == IResource.PROJECT);
		// only write out info for accessible resources
		if (!root.isAccessible())
			return;

		// Setup variables
		final Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer();
		final MarkerManager markerManager = workspace.getMarkerManager();
		IPath markersLocation = workspace.getMetaArea().getMarkersSnapshotLocationFor(root);
		IPath syncInfoLocation = workspace.getMetaArea().getSyncInfoSnapshotLocationFor(root);
		SafeChunkyOutputStream safeMarkerStream = null;
		SafeChunkyOutputStream safeSyncInfoStream = null;
		DataOutputStream o1 = null;
		DataOutputStream o2 = null;
		String message;

		// Create the output streams
		try {
			safeMarkerStream = new SafeChunkyOutputStream(markersLocation.toFile());
			o1 = new DataOutputStream(safeMarkerStream);
			// we don't store the sync info for the workspace root so don't create
			// an empty file
			if (root.getType() != IResource.ROOT) {
				safeSyncInfoStream = new SafeChunkyOutputStream(syncInfoLocation.toFile());
				o2 = new DataOutputStream(safeSyncInfoStream);
			}
		} catch (IOException e) {
			FileUtil.safeClose(o1);
			message = NLS.bind(Messages.resources_writeMeta, root.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e);
		}

		final DataOutputStream markersOutput = o1;
		final DataOutputStream syncInfoOutput = o2;
		int markerFileSize = markersOutput.size();
		int syncInfoFileSize = safeSyncInfoStream == null ? -1 : syncInfoOutput.size();
		// The following 2 piece array will hold a running total of the times
		// taken to save markers and syncInfo respectively.  This will cut down
		// on the number of statements printed out as we would get 2 statements
		// for each resource otherwise.
		final long[] snapTimes = new long[2];

		IElementContentVisitor visitor = (tree, requestor, elementContents) -> {
			ResourceInfo info = (ResourceInfo) elementContents;
			if (info != null) {
				try {
					// save the markers
					long start = System.currentTimeMillis();
					markerManager.snap(info, requestor, markersOutput);
					long markerSnapTime = System.currentTimeMillis() - start;
					snapTimes[0] += markerSnapTime;
					persistMarkers += markerSnapTime;
					// save the sync info - if we have the workspace root then the output stream will be null
					if (syncInfoOutput != null) {
						start = System.currentTimeMillis();
						synchronizer.snapSyncInfo(info, requestor, syncInfoOutput);
						long syncInfoSnapTime = System.currentTimeMillis() - start;
						snapTimes[1] += syncInfoSnapTime;
						persistSyncInfo += syncInfoSnapTime;
					}
				} catch (IOException e) {
					throw new WrappedRuntimeException(e);
				}
			}
			// don't continue if the current resource is the workspace root, only continue for projects
			return root.getType() != IResource.ROOT;
		};

		try {
			// Call the visitor
			try {
				new ElementTreeIterator(workspace.getElementTree(), root.getFullPath()).iterate(visitor);
			} catch (WrappedRuntimeException e) {
				throw (IOException) e.getTargetException();
			}
			if (Policy.DEBUG_SAVE_MARKERS)
				Policy.debug("Snap Markers for " + root.getFullPath() + ": " + snapTimes[0] + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			if (Policy.DEBUG_SAVE_SYNCINFO)
				Policy.debug("Snap SyncInfo for " + root.getFullPath() + ": " + snapTimes[1] + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			if (markerFileSize != markersOutput.size())
				safeMarkerStream.succeed();
			if (safeSyncInfoStream != null && syncInfoFileSize != syncInfoOutput.size()) {
				safeSyncInfoStream.succeed();
				syncInfoOutput.close();
			}
			markersOutput.close();
		} catch (IOException e) {
			message = NLS.bind(Messages.resources_writeMeta, root.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e);
		} finally {
			FileUtil.safeClose(markersOutput);
			FileUtil.safeClose(syncInfoOutput);
		}

		// recurse over the projects in the workspace if we were given the workspace root
		if (root.getType() == IResource.PROJECT)
			return;
		IProject[] projects = ((IWorkspaceRoot) root).getProjects(IContainer.INCLUDE_HIDDEN);
		for (IProject project : projects)
			visitAndSnap(project);
	}

	/**
	 * Writes out persistent information about all builders for which a last built
	 * tree is available. File format is:
	 * int - number of builders
	 * for each builder:
	 *    UTF - project name
	 *    UTF - fully qualified builder extension name
	 *    int - number of interesting projects for builder
	 *    For each interesting project:
	 *       UTF - interesting project name
	 */
	private void writeBuilderPersistentInfo(DataOutputStream output, List<BuilderPersistentInfo> builders, IProgressMonitor monitor) throws IOException {
		// write the number of builders we are saving
		int numBuilders = builders.size();
		output.writeInt(numBuilders);
		for (int i = 0; i < numBuilders; i++) {
			BuilderPersistentInfo info = builders.get(i);
			output.writeUTF(info.getProjectName());
			output.writeUTF(info.getBuilderName());
			// write interesting projects
			IProject[] interestingProjects = info.getInterestingProjects();
			output.writeInt(interestingProjects.length);
			for (IProject interestingProject : interestingProjects)
				output.writeUTF(interestingProject.getName());
		}
	}

	@Override
	public void writeElement(IPath path, Object element, DataOutput output) throws IOException {
		Assert.isNotNull(path);
		Assert.isNotNull(element);
		Assert.isNotNull(output);
		ResourceInfo info = (ResourceInfo) element;
		output.writeInt(info.getFlags());
		info.writeTo(output);
	}

	/**
	 * Discovers the trees which need to be saved for the passed in project's builders.
	 * In a pre-3.7 workspace, only one tree is saved per builder.
	 * Since 3.7 one tree may be persisted per build configuration per multi-config builder.
	 *
	 * We still provide one tree per builder first so the workspace can be opened in an older Eclipse.
	 * Newer eclipses will be able to load the additional per-configuration trees.
	 * @param project project to fetch builder trees for
	 * @param trees list of trees to be persisted
	 * @param builderInfos list of builder infos; one per builder
	 * @param configNames configuration names persisted for builder infos above
	 * @param additionalTrees remaining trees to be persisted for other configurations
	 * @param additionalBuilderInfos remaining builder infos for other configurations
	 * @param additionalConfigNames configuration names of the remaining per-configuration trees
	 * @throws CoreException
	 */
	private void getTreesToSave(IProject project, List<ElementTree> trees, List<BuilderPersistentInfo> builderInfos, List<String> configNames, List<ElementTree> additionalTrees, List<BuilderPersistentInfo> additionalBuilderInfos, List<String> additionalConfigNames) throws CoreException {
		if (project.isOpen()) {
			String activeConfigName = project.getActiveBuildConfig().getName();
			List<BuilderPersistentInfo> infos = workspace.getBuildManager().createBuildersPersistentInfo(project);
			if (infos != null) {
				for (BuilderPersistentInfo info : infos) {
					// Nothing to persist if there isn't a previous delta tree.
					// There used to be code which serialized the current workspace tree
					// but this will result in the next build of the builder getting an empty delta...
					if (info.getLastBuiltTree() == null)
						continue;

					// Add to the correct list of builders info and add to the configuration names
					String configName = info.getConfigName() == null ? activeConfigName : info.getConfigName();
					if (configName.equals(activeConfigName)) {
						// Serializes the active configurations's build tree
						// TODO could probably do better by serializing the 'oldest' tree
						builderInfos.add(info);
						configNames.add(configName);
						trees.add(info.getLastBuiltTree());
					} else {
						additionalBuilderInfos.add(info);
						additionalConfigNames.add(configName);
						additionalTrees.add(info.getLastBuiltTree());
					}
				}
			}
		}
	}

	/**
	 * Attempts to save plugin info, builder info and build states for all projects
	 * in the workspace.
	 *
	 * The following is written to the output stream:
	 * <ul>
	 * <li> Workspace information </li>
	 * <li> A list of plugin info </li>
	 * <li> Builder info for all the builders for each project's active build config </li>
	 * <li> Workspace trees for all plugins and builders </li>
	 * <li> And since 3.7: </li>
	 * <li> Builder info for all the builders of all the other project's buildConfigs </li>
	 * <li> The names of the buildConfigs for each of the builders </li>
	 * </ul>
	 * This format is designed to work with WorkspaceTreeReader versions 2.
	 *
	 * @see WorkspaceTreeReader_2
	 */
	protected void writeTree(Map<String, ElementTree> statesToSave, DataOutputStream output, IProgressMonitor monitor)
			throws IOException, CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, 10);
		boolean wasImmutable = false;
		try {
			// Create an array of trees to save. Ensure that the current one is in the list
			ElementTree current = workspace.getElementTree();
			wasImmutable = current.isImmutable();
			current.immutable();
			ArrayList<ElementTree> trees = new ArrayList<>(statesToSave.size() * 2); // pick a number
			subMonitor.worked(1);

			// write out the workspace fields
			writeWorkspaceFields(output, subMonitor.newChild(2));

			// save plugin info
			output.writeInt(statesToSave.size()); // write the number of plugins we are saving
			for (Map.Entry<String, ElementTree> entry : statesToSave.entrySet()) {
				String pluginId = entry.getKey();
				output.writeUTF(pluginId);
				trees.add(entry.getValue()); // tree
				updateDeltaExpiration(pluginId);
			}
			subMonitor.worked(1);

			// Get the the builder info and configuration names, and add all the associated
			// workspace trees in the correct order
			IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
			List<BuilderPersistentInfo> builderInfos = new ArrayList<>(projects.length * 2);
			List<String> configNames = new ArrayList<>(projects.length);
			List<ElementTree> additionalTrees = new ArrayList<>(projects.length * 2);
			List<BuilderPersistentInfo> additionalBuilderInfos = new ArrayList<>(projects.length * 2);
			List<String> additionalConfigNames = new ArrayList<>(projects.length);
			for (IProject project : projects)
				getTreesToSave(project, trees, builderInfos, configNames, additionalTrees, additionalBuilderInfos,
						additionalConfigNames);

			// Save the version 2 builders info
			writeBuilderPersistentInfo(output, builderInfos, subMonitor.newChild(1));

			// Builder infos of non-active configurations are persisted after the active
			// configuration's builder infos. So, their trees have to follow the same order.
			trees.addAll(additionalTrees);

			// add the current tree in the list as the last tree in the chain
			trees.add(current);

			/* save the forest! */
			ElementTreeWriter writer = new ElementTreeWriter(this);
			ElementTree[] treesToSave = trees.toArray(new ElementTree[trees.size()]);
			writer.writeDeltaChain(treesToSave, Path.ROOT, ElementTreeWriter.D_INFINITE, output,
					ResourceComparator.getSaveComparator());
			subMonitor.worked(4);

			// Since 3.7: Save the additional builders info
			writeBuilderPersistentInfo(output, additionalBuilderInfos, subMonitor.newChild(1));

			// Save the configuration names for the builders in the order they were saved
			for (String string : configNames)
				output.writeUTF(string);
			for (String string : additionalConfigNames)
				output.writeUTF(string);
		} finally {
			subMonitor.done();
			if (!wasImmutable)
				workspace.newWorkingTree();
		}
	}

	/**
	 * Attempts to save all the trees for the given project. This includes the current
	 * workspace tree and a tree for each builder that has previously built state information.
	 *
	 * The following is written to the output stream:
	 * <ul>
	 * <li> Builder info for all the builders for the project's active build configuration </li>
	 * <li> Workspace trees for all the project's builders </li>
	 * <li> Since 3.7: </li>
	 * <li> Builder info for all the builders of all the other project's buildConfigs </li>
	 * <li> Name of the project's buildConfigs </li>
	 * </ul>
	 * This format is designed to work with WorkspaceTreeReader versions 2.
	 *
	 * @throws IOException if anything went wrong during save.
	 * @see WorkspaceTreeReader_2
	 */
	protected void writeTree(Project project, DataOutputStream output, IProgressMonitor monitor)
			throws IOException, CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, 10);
		boolean wasImmutable = false;
		try {
			// Create an array of trees to save and ensure that the current one is immutable
			// before we add other trees
			ElementTree current = workspace.getElementTree();
			wasImmutable = current.isImmutable();
			current.immutable();
			List<ElementTree> trees = new ArrayList<>(2);
			subMonitor.worked(1);

			// Get the the builder info and configuration names, and add all the associated
			// workspace trees in the correct order
			List<String> configNames = new ArrayList<>(5);
			List<BuilderPersistentInfo> builderInfos = new ArrayList<>(5);
			List<String> additionalConfigNames = new ArrayList<>(5);
			List<BuilderPersistentInfo> additionalBuilderInfos = new ArrayList<>(5);
			List<ElementTree> additionalTrees = new ArrayList<>(5);
			getTreesToSave(project, trees, builderInfos, configNames, additionalTrees, additionalBuilderInfos,
					additionalConfigNames);

			// Save the version 2 builders info
			writeBuilderPersistentInfo(output, builderInfos, subMonitor.newChild(2));

			// Builder infos of non-active configurations are persisted after the active
			// configuration's builder infos. So, their trees have to follow the same order.
			trees.addAll(additionalTrees);

			// Add the current tree in the list as the last tree in the chain
			trees.add(current);

			// Save the trees
			ElementTreeWriter writer = new ElementTreeWriter(this);
			ElementTree[] treesToSave = trees.toArray(new ElementTree[trees.size()]);
			writer.writeDeltaChain(treesToSave, project.getFullPath(), ElementTreeWriter.D_INFINITE, output,
					ResourceComparator.getSaveComparator());
			subMonitor.worked(5);

			// Since 3.7: Save the builders info and get the workspace trees associated with
			// those builders
			writeBuilderPersistentInfo(output, additionalBuilderInfos, subMonitor.newChild(2));

			// Save configuration names for the builders in the order they were saved
			for (String string : configNames)
				output.writeUTF(string);
			for (String string : additionalConfigNames)
				output.writeUTF(string);
		} finally {
			subMonitor.done();
			if (!wasImmutable)
				workspace.newWorkingTree();
		}
	}

	protected void writeTree(Project project, int depth) throws CoreException {
		long start = System.currentTimeMillis();
		IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(project, true);
		IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation);
		try {
			SafeFileOutputStream safe = new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString());
			try (
				DataOutputStream output = new DataOutputStream(safe);
			) {
				output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
				writeTree(project, output, null);
			}
		} catch (IOException e) {
			String msg = NLS.bind(Messages.resources_writeMeta, project.getFullPath());
			throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, treeLocation, msg, e);
		}
		if (Policy.DEBUG_SAVE_TREE)
			Policy.debug("Save tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	protected void writeWorkspaceFields(DataOutputStream output, IProgressMonitor monitor) throws IOException {
		// save the next node id
		output.writeLong(workspace.nextNodeId);
		// save the modification stamp (no longer used)
		output.writeLong(0L);
		// save the marker id counter
		output.writeLong(workspace.nextMarkerId);
		// save the registered sync partners in the synchronizer
		((Synchronizer) workspace.getSynchronizer()).savePartners(output);
	}
}
