/*******************************************************************************
 * Copyright (c) 2000, 2011 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
 *     Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 181546 [Sync Info] Eclipse writes Entries-less metadata in recreated pruned dir
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.resources;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.CVSThreadInfo;
import org.eclipse.team.internal.ccvs.core.util.*;
import org.eclipse.team.internal.core.subscribers.BatchingLock.IFlushOperation;
import org.eclipse.team.internal.core.subscribers.BatchingLock.ThreadInfo;
import org.osgi.framework.Bundle;

/**
 * A synchronizer is responsible for managing synchronization information for local
 * CVS resources.
 * 
 * This class is thread safe but only allows one thread to modify the cache at a time. It
 * doesn't support fine grain locking on a resource basis. Lock ordering between the workspace
 * lock and the synchronizer lock is guaranteed to be deterministic. That is, the workspace
 * lock is *always* acquired before the synchronizer lock. This protects against possible
 * deadlock cases where the synchronizer lock is acquired before a workspace lock.
 * 
 * Special processing has been added for linked folders and their childen so
 * that their CVS meta files are never read or written.
 * 
 * IMPORTANT NOTICE: It is the responsibility of the clients of EclipseSynchronizer
 * to ensure that they have wrapped operations that may modify the workspace in
 * an IWorkspaceRunnable. If this is not done, deltas may fore at inopertune times 
 * and corrupt the sync info. The wrapping could be done within the synchronizer 
 * itself but would require the creation of an inner class for each case that requires
 * it.
 * 
 * @see ResourceSyncInfo
 * @see FolderSyncInfo
 */
public class EclipseSynchronizer implements IFlushOperation {	
	private static final String IS_DIRTY_INDICATOR = SyncInfoCache.IS_DIRTY_INDICATOR;
	private static final String NOT_DIRTY_INDICATOR = SyncInfoCache.NOT_DIRTY_INDICATOR;
	private static final String RECOMPUTE_INDICATOR = SyncInfoCache.RECOMPUTE_INDICATOR; 
		
	// the cvs eclipse synchronizer is a singleton
	private static EclipseSynchronizer instance;
	
	// track resources that have changed in a given operation
	private ILock lock = Job.getJobManager().newLock();
	private ReentrantLock resourceLock = new ReentrantLock();
	
	private SynchronizerSyncInfoCache synchronizerCache = new SynchronizerSyncInfoCache();
	private SessionPropertySyncInfoCache sessionPropertyCache = new SessionPropertySyncInfoCache(synchronizerCache);
	
	/*
	 * Package private constructor to allow specialized subclass for handling folder deletions
	 */
	EclipseSynchronizer() {		
	}
	
	/**
	 * Returns the singleton instance of the synchronizer.
	 */
	public static EclipseSynchronizer getInstance() {		
		if(instance==null) {
			instance = new EclipseSynchronizer();
		}
		return instance;
	}
	
	public SyncInfoCache getSyncInfoCacheFor(IResource resource) {
		if (resource.exists()  && resource.isLocal(IResource.DEPTH_ZERO)) {
			return sessionPropertyCache;
		} else {
			return synchronizerCache;
		}
	}

	private boolean isValid(IResource resource) {
		return resource.exists() || synchronizerCache.isPhantom(resource);
	}
	
	/**
	 * Sets the folder sync info for the specified folder.
	 * The folder must exist and must not be the workspace root.
	 * 
	 * @param folder the folder
	 * @param info the folder sync info, must not be null
	 * @see #getFolderSync, #deleteFolderSync
	 */
	public void setFolderSync(IContainer folder, FolderSyncInfo info) throws CVSException {
		Assert.isNotNull(info); // enforce the use of deleteFolderSync
		// ignore folder sync on the root (i.e. CVSROOT/config/TopLevelAdmin=yes but we just ignore it)
		if (folder.getType() == IResource.ROOT) return;
		if (!isValid(folder)) {
			// This means that the folder doesn't exist and is not a phantom
			// Allow the set if the parent is a CVS folder since
			// this can occur when creating phantom folders
			if (getFolderSync(folder.getParent()) == null) {
				IStatus status = new CVSStatus(IStatus.ERROR, TeamException.UNABLE,
						NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingFolderSync, new String[] { folder.getFullPath().toString() }),folder);
				throw new CVSException(status); 
			}
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder, null);
			try {
				beginOperation();
				// get the old info
				FolderSyncInfo oldInfo = getFolderSync(folder);
				// set folder sync and notify
				getSyncInfoCacheFor(folder).setCachedFolderSync(folder, info, true);
				// if the sync info changed from null, we may need to adjust the ancestors
				if (oldInfo == null) {
					adjustDirtyStateRecursively(folder, RECOMPUTE_INDICATOR);
				}
				folderChanged(folder);
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Gets the folder sync info for the specified folder.
	 * 
	 * @param folder the folder
	 * @return the folder sync info associated with the folder, or null if none.
	 * @see #setFolderSync, #deleteFolderSync
	 */
	public FolderSyncInfo getFolderSync(IContainer folder) throws CVSException {
		if (folder.getType() == IResource.ROOT || !isValid(folder)) return null;
		// Do a check outside the lock for any folder sync info
		FolderSyncInfo info = getSyncInfoCacheFor(folder).getCachedFolderSync(folder, false /* not thread safe */);
		if (info != null)
			return info;
		try {
			beginOperation();
			cacheFolderSync(folder);
			return getSyncInfoCacheFor(folder).getCachedFolderSync(folder, true /* thread safe */);
		} finally {
			endOperation();
		}
	}	

	/**
	 * Deletes the folder sync for the specified folder and the resource sync
	 * for all of its children.  Does not recurse.
	 * 
	 * @param folder the folder
	 * @see #getFolderSync, #setFolderSync
	 */
	public void deleteFolderSync(IContainer folder) throws CVSException {
		if (folder.getType() == IResource.ROOT || !isValid(folder)) return;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder, null);
			try {
				beginOperation();
				// iterate over all children with sync info and prepare notifications
				// this is done first since deleting the folder sync may remove a phantom
				cacheResourceSyncForChildren(folder, true /* can modify workspace */);
				IResource[] children = folder.members(true);
				for (int i = 0; i < children.length; i++) {
					IResource resource = children[i];
					resourceChanged(resource);
					// delete resource sync for all children
					getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, null, true);
				}
				// delete folder sync
				getSyncInfoCacheFor(folder).setCachedFolderSync(folder, null, true);
				folderChanged(folder);
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	private void folderChanged(IContainer folder) {
		resourceLock.folderChanged(folder);
	}

	private void resourceChanged(IResource resource) {
		resourceLock.resourceChanged(resource);
	}

	/**
	 * Sets the resource sync info for the specified resource.
	 * The parent folder must exist and must not be the workspace root.
	 * 
	 * @param resource the resource
	 * @param info the resource sync info, must not be null
	 * @see #getResourceSync, #deleteResourceSync
	 */
	public void setResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		Assert.isNotNull(info); // enforce the use of deleteResourceSync
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) {
			IStatus status = new CVSStatus(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingResourceSync, new String[] { resource.getFullPath().toString() }), resource);
			throw new CVSException(status); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, set for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				setCachedResourceSync(resource, info);
				resourceChanged(resource);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Gets the resource sync info for the specified folder.
	 * 
	 * @param resource the resource
	 * @return the resource sync info associated with the resource, or null if none.
	 * @see #setResourceSync, #deleteResourceSync
	 */
	public ResourceSyncInfo getResourceSync(IResource resource) throws CVSException {
		byte[] info = getSyncBytes(resource);
		if (info == null) return null;
		return new ResourceSyncInfo(info);
	}

	/**
	 * Gets the resource sync info for the specified folder.
	 * 
	 * @param resource the resource
	 * @return the resource sync info associated with the resource, or null if none.
	 * @see #setResourceSync, #deleteResourceSync
	 */
	public byte[] getSyncBytes(IResource resource) throws CVSException {
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) return null;
		// Do a quick check outside the lock to see if there are sync butes for the resource.
		byte[] info = getSyncInfoCacheFor(resource).getCachedSyncBytes(resource, false /* not thread safe */);
		if (info != null)
			return info;
		try {
			beginOperation();
			// cache resource sync for siblings, then return for self
			try {
				cacheResourceSyncForChildren(parent, false /* cannot modify workspace */);
			} catch (CVSException e) {
				if (isCannotModifySynchronizer(e) || isResourceNotFound(e)) {
					// We will resort to loading the sync info for the requested resource from disk
					byte[] bytes =  getSyncBytesFromDisk(resource);
					if (!resource.exists() && bytes != null && !ResourceSyncInfo.isDeletion(bytes)) {
						bytes = ResourceSyncInfo.convertToDeletion(bytes);
					}
					return bytes;
				} else {
					throw e;
				}
			}
			return getCachedSyncBytes(resource);
		} finally {
			endOperation();
		}
	}

	/**
	 * Sets the resource sync info for the specified resource.
	 * The parent folder must exist and must not be the workspace root.
	 * 
	 * @param resource the resource
	 * @param info the resource sync info, must not be null
	 * @see #getResourceSync, #deleteResourceSync
	 */
	public void setSyncBytes(IResource resource, byte[] syncBytes) throws CVSException {
		Assert.isNotNull(syncBytes); // enforce the use of deleteResourceSync
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) {
			IStatus status = new CVSStatus(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingResourceSync, new String[] { resource.getFullPath().toString() }),resource);
			throw new CVSException(status); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, set for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				setCachedSyncBytes(resource, syncBytes);
				resourceChanged(resource);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
		
	/**
	 * Deletes the resource sync info for the specified resource, if it exists.
	 * 
	 * @param resource the resource
	 * @see #getResourceSync, #setResourceSync
	 */
	public void deleteResourceSync(IResource resource) throws CVSException {
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) return;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, delete for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				if (getCachedSyncBytes(resource) != null) { // avoid redundant notifications
					setCachedSyncBytes(resource, null);
					clearDirtyIndicator(resource);
					resourceChanged(resource);
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	/**
	 * @param resource
	 */
	private void clearDirtyIndicator(IResource resource) throws CVSException {
		getSyncInfoCacheFor(resource).flushDirtyCache(resource);
		adjustDirtyStateRecursively(resource.getParent(), RECOMPUTE_INDICATOR);
	}

	/**
	 * Gets the array of ignore patterns for the specified folder.
	 * 
	 * @param folder the folder
	 * @return the patterns, or an empty array if none
	 * @see #addIgnored
	 */
	public boolean isIgnored(IResource resource) throws CVSException {
		if (resource.getType() == IResource.ROOT || 
			resource.getType() == IResource.PROJECT || 
			! resource.exists()) {
			return false;
		}
		IContainer parent = resource.getParent();
		FileNameMatcher matcher = sessionPropertyCache.getFolderIgnores(parent, false /* not thread safe */);
		if (matcher == null) {
			try {
				beginOperation();
				matcher = cacheFolderIgnores(parent);
			} finally {
				endOperation();
			}
		}
		return matcher.match(resource.getName());
	}
	
	/**
	 * Adds a pattern to the set of ignores for the specified folder.
	 * 
	 * @param folder the folder
	 * @param pattern the pattern
	 */
	public void addIgnored(IContainer folder, String pattern) throws CVSException {
		if (folder.getType() == IResource.ROOT || ! folder.exists()) {
			IStatus status = new CVSStatus(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingIgnorePattern, new String[] { folder.getFullPath().toString() }),folder);
			throw new CVSException(status); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder.getFile(new Path(SyncFileWriter.IGNORE_FILE)), null);
			try {
				beginOperation();
				String[] ignores = SyncFileWriter.readCVSIgnoreEntries(folder);
				if (ignores != null) {
					// verify that the pattern has not already been added
					for (int i = 0; i < ignores.length; i++) {
						if (ignores[i].equals(pattern)) return;
					}
					// add the pattern
					String[] oldIgnores = ignores;
					ignores = new String[oldIgnores.length + 1];
					System.arraycopy(oldIgnores, 0, ignores, 0, oldIgnores.length);
					ignores[oldIgnores.length] = pattern;
				} else {
					ignores = new String[] { pattern };
				}
				setCachedFolderIgnores(folder, ignores);
				SyncFileWriter.writeCVSIgnoreEntries(folder, ignores);
				// broadcast changes to unmanaged children - they are the only candidates for being ignored
				List<IResource> possibleIgnores = new ArrayList<>();
				accumulateNonManagedChildren(folder, possibleIgnores);
				ResourceStateChangeListeners.getListener().resourceSyncInfoChanged(possibleIgnores.toArray(new IResource[possibleIgnores.size()]));
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Returns the members of this folder including deleted resources with sync info,
	 * but excluding special resources such as CVS subdirectories.
	 *
	 * @param folder the container to list
	 * @return the array of members
	 */
	public IResource[] members(IContainer folder) throws CVSException {
		if (! isValid(folder)) return new IResource[0];
		try {				
			beginOperation();
			if (folder.getType() != IResource.ROOT) {
				// ensure that the sync info is cached so any required phantoms are created
				cacheResourceSyncForChildren(folder, false);
			}
		} catch (CVSException e) {
			if (!isCannotModifySynchronizer(e) && !isResourceNotFound(e)) {
				throw e;
			}
		} finally {
			endOperation();
		}
		try {
			
			return synchronizerCache.members(folder);
			
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	private boolean isCannotModifySynchronizer(CVSException e) {
		// IResourceStatus.WORKSPACE_LOCKED can occur if the resource sync is loaded 
		// during the POST_CHANGE delta phase.
		// CVSStatus.FAILED_TO_CACHE_SYNC_INFO can occur if the resource sync is loaded
		// when no scheduling rule is held.
		return (e.getStatus().getCode() == IResourceStatus.WORKSPACE_LOCKED 
				|| e.getStatus().getCode() == CVSStatus.FAILED_TO_CACHE_SYNC_INFO);
	}
	
	private boolean isResourceNotFound(CVSException e) {
		return e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND;
	}
	
	/**
	 * Begins a batch of operations in order to optimize sync file writing. 
	 * The provided scheduling rule indicates the resources
	 * that the resources affected by the operation while the returned scheduling rule
	 * is the rule obtained by the lock. It may differ from the provided rule as it must
	 * encompass any sync files that may change as a result of the operation.
	 */
	public ISchedulingRule beginBatching(ISchedulingRule resourceRule, IProgressMonitor monitor) {
		return resourceLock.acquire(resourceRule, this /* IFlushOperation */, monitor);
	}
	
	/**
	 * Ends a batch of operations. The provided rule must be the one that was returned
	 * by the corresponding call to beginBatching.
	 * <p>
	 * Progress cancellation is ignored while writting the cache to disk. This
	 * is to ensure cache to disk consistency.
	 * </p>
	 * 
	 * @param monitor the progress monitor, may be null
	 * @exception CVSException with a status with code <code>COMMITTING_SYNC_INFO_FAILED</code>
	 * if all the CVS sync information could not be written to disk.
	 */
	public void endBatching(ISchedulingRule rule, IProgressMonitor monitor) throws CVSException {
		try {
			resourceLock.release(rule, monitor);
		} catch (TeamException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/* 
	 * Callback which is invoked when the batching resource lock is released 
	 * or when a flush is requested (see beginBatching(IResource)).
	 * 
	 * @see org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.IRunnableOnExit#run(org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.ThreadInfo, org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public void flush(final ThreadInfo info, IProgressMonitor monitor) throws CVSException {
		if (info != null && !info.isEmpty()) {
			try {
				ResourcesPlugin.getWorkspace().run((IWorkspaceRunnable) pm -> {
					IStatus status = commitCache(info, pm);
					if (!status.isOK()) {
						throw new CVSException(status);
					}
				}, null, 0 /* no flags */, monitor);
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			}
		}
	}
	
	/*
	 * Begin an access to the internal data structures of the synchronizer
	 */
	private void beginOperation() {
		try {
			// Do not try to acquire the lock if the resources tree is locked
			// The reason for this is that during the resource delta phase (i.e. when the tree is locked)
			// the workspace lock is held. If we obtain our lock, there is 
			// a chance of dealock. It is OK if we don't as we are still protected
			// by scheduling rules and the workspace lock.
			if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
		} catch (RuntimeException e) {
			// If we are not active, throw a cancel. Otherwise, propogate it.
			// (see bug 78303)
			if (Platform.getBundle(CVSProviderPlugin.ID).getState() == Bundle.ACTIVE) {
				throw e;
			} else {
				throw new OperationCanceledException();
			}
		}
		lock.acquire();
	}
	
	/*
	 * End an access to the internal data structures of the synchronizer
	 */
	private void endOperation() {
		try {
			// See beginOperation() for a description of why the lock is not obtained when the tree is locked
			if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
		} catch (RuntimeException e) {
			// If we are not active, throw a cancel. Otherwise, propogate it.
			// (see bug 78303)
			if (Platform.getBundle(CVSProviderPlugin.ID).getState() == Bundle.ACTIVE) {
				throw e;
			} else {
				throw new OperationCanceledException();
			}
		}
		lock.release();
	}
	
	/**
	 * Flush the sync information from the in-memory cache to disk and purge
	 * the entries from the cache.
	 * <p>
	 * Recursively flushes the sync information for all resources 
	 * below the root to disk and purges the entries from memory
	 * so that the next time it is accessed it will be retrieved from disk.
	 * May flush more sync information than strictly needed, but never less.
	 * </p>
	 * 
	 * @param root the root of the subtree to purge
	 * @param deep purge sync from child folders
	 * @param monitor the progress monitor, may be null
	 */
	public void flush(IContainer root, boolean deep, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 10);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(root, Policy.subMonitorFor(monitor, 1));
			try {
				beginOperation();
				try {
					// Flush changes to disk
					resourceLock.flush(Policy.subMonitorFor(monitor, 8));
				} catch (TeamException e) {
					throw CVSException.wrapException(e);
				} finally {
					// Purge the in-memory cache
					sessionPropertyCache.purgeCache(root, deep);
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 1));
			monitor.done();
		}
	}

	public void deconfigure(final IProject project, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(project, Policy.subMonitorFor(monitor, 10));
			// Flush the sync info
			flush(project, true /* deep */, Policy.subMonitorFor(monitor, 80));
			
			purgeDirtyCache(project, Policy.subMonitorFor(monitor, 5));
				
			// forget about pruned folders however the top level pruned folder will have resource sync (e.g. 
			// a line in the Entry file). As a result the folder is managed but is not a CVS folder.
			synchronizerCache.purgeCache(project, true);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}

	/**
	 * Called to notify the synchronizer that meta files have changed on disk, outside 
	 * of the workbench. The cache will be flushed for this folder and it's immediate
	 * children and appropriate state change events are broadcasts to state change
	 * listeners.
	 */
	public void ignoreFilesChanged(IContainer[] roots) throws CVSException {
		for (int i = 0; i < roots.length; i++) {
			IContainer container = roots[i];
			if (container.exists()) {
				ISchedulingRule rule = null;
				try {
					Set<IResource> changed = new HashSet<>();
					rule = beginBatching(container, null);
					try {
						beginOperation();
						
						// Record the previous ignore pattterns
						FileNameMatcher oldIgnores = null;
						if (sessionPropertyCache.isFolderSyncInfoCached(container)) {
							oldIgnores = cacheFolderIgnores(container);
						}
						
						// Purge the cached state for direct children of the container
						changed.addAll(Arrays.asList(
							sessionPropertyCache.purgeCache(container, oldIgnores == null /*flush deeply if the old patterns are not known*/)));
						
						// Purge the state for any children of previously ignored containers
						if (oldIgnores != null) {
							FileNameMatcher newIgnores = cacheFolderIgnores(container);
							try {
								IResource[] members = container.members();
								for (int j = 0; j < members.length; j++) {
									IResource resource = members[j];
									if (resource.getType() == IResource.FOLDER) {
										String name = resource.getName();
										if (oldIgnores.match(name) && !newIgnores.match(name)) {
											changed.addAll(Arrays.asList(
													sessionPropertyCache.purgeCache((IContainer)resource, true /*flush deeply*/)));
										}
									}
								}
							} catch (CoreException e) {
								// Just log and continue
								CVSProviderPlugin.log(e);
							}
						}
					} finally {
						endOperation();
					}
					if (!changed.isEmpty()) {
						ResourceStateChangeListeners.getListener().resourceSyncInfoChanged(
							changed.toArray(new IResource[changed.size()]));
					}
				} finally {
					if (rule != null) endBatching(rule, null);
				}
			}
		}
	}
	
	public void syncFilesChangedExternally(IContainer[] changedMetaFiles, IFile[] externalDeletions) throws CVSException {
		List<IResource> changed = new ArrayList<>();
		for (int i = 0; i < changedMetaFiles.length; i++) {
			IContainer container = changedMetaFiles[i];
			if (!isWithinActiveOperationScope(container)) {
				changed.addAll(Arrays.asList(
					sessionPropertyCache.purgeCache(container, false /*don't flush children*/)));
			}
		}
		for (int i = 0; i < externalDeletions.length; i++) {
			IFile file = externalDeletions[i];
			if (!isWithinActiveOperationScope(file)) {
				sessionPropertyCache.purgeCache(file.getParent(), false /*don't flush children*/);
				changed.add(file);
			}
		}
		if (!changed.isEmpty()) {
			ResourceStateChangeListeners.getListener().externalSyncInfoChange(
					changed.toArray(new IResource[changed.size()]));
		}
	}
	
	/*
	 * The resource is about to be deleted by the move delete hook.
	 * In all cases (except when the resource doesn't exist), this method 
	 * will indicate that the dirty state of the parent needs to be recomputed.
	 * For managed resources, it will move the cached sync info from the session
	 * property cache into the synchronizer cache, purging the session cache.
	 * @param resource the resource about to be deleted.
	 * <p>
	 * Note that this method is not recursive. Hence, for managed resources
	 * 
	 * @returns whether children need to be prepared
	 * @throws CVSException
	 */
	/* private */ boolean prepareForDeletion(IResource resource) throws CVSException {
		if (!resource.exists()) return false;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// Flush the dirty info for the resource and it's ancestors.
				// Although we could be smarter, we need to do this because the
				// deletion may fail.
				adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
				if (resource.getType() == IResource.FILE) {
					byte[] syncBytes = getSyncBytes(resource);
					if (syncBytes != null) {
						if (ResourceSyncInfo.isAddition(syncBytes)) {
							deleteResourceSync(resource);
						} else {
							syncBytes = convertToDeletion(syncBytes);
							synchronizerCache.setCachedSyncBytes(resource, syncBytes, true);
						}
						sessionPropertyCache.purgeResourceSyncCache(resource);
						resourceChanged(resource);
					}
					return false;
				} else {
					IContainer container = (IContainer)resource;
					if (container.getType() == IResource.PROJECT) {
						synchronizerCache.flush((IProject)container);
						return false;
					} else {
						// Move the folder sync info into phantom space
						FolderSyncInfo info = getFolderSync(container);
						if (info == null) return false;
						synchronizerCache.setCachedFolderSync(container, info, true);
						folderChanged(container);
						// move the resource sync as well
						byte[] syncBytes = getSyncBytes(resource);
						synchronizerCache.setCachedSyncBytes(resource, syncBytes, true);
						sessionPropertyCache.purgeResourceSyncCache(container);
						sessionPropertyCache.purgeCache(container, false);
						return true;
					}
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * The resource has been deleted. Make sure any cached state is cleared.
	 * This is needed because the move/delete hook is not invoked in all situations
	 * (e.g. external deletion).
	 * 
	 * @param resource
	 * @throws CVSException
	 */
	protected void handleDeleted(IResource resource) throws CVSException {
		if (resource.exists()) return;
		try {
			beginOperation();
			adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
		} finally {
			endOperation();
		}
	}
	
	/**
	 * The resource has been added. Make sure any cached state is cleared.
	 * This is needed because the add hook is not invoked in all situations
	 * (e.g. external addition).
	 * 
	 * @param resource
	 * @throws CVSException
	 */
	protected void handleAdded(IResource resource) throws CVSException {
		if (!resource.exists()) return;
		try {
			beginOperation();
			adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
		} finally {
			endOperation();
		}
	}
	
	/**
	 * Prepare for the deletion of the target resource from within 
	 * the move/delete hook. The method is invoked by both the 
	 * deleteFile/Folder methods and for the source resource
	 * of moveFile/Folder. This method will move the cached sync info
	 * into the phantom (ISynchronizer) cache so that outgoing deletions
	 * and known remote folders are preserved.
	 * 
	 * @param resource
	 * @param monitor
	 * @throws CVSException
	 */
	public void prepareForDeletion(IResource resource, IProgressMonitor monitor) throws CVSException {
		// Move sync info to phantom space for the resource and all it's children
		monitor = Policy.monitorFor(monitor);
		try {
			beginOperation();
			monitor.beginTask(null, 100);
			try {
				resource.accept(new IResourceVisitor() {
					public boolean visit(IResource innerResource) throws CoreException {
						try {
							return prepareForDeletion(innerResource);
						} catch (CVSException e) {
							CVSProviderPlugin.log(e);
							throw new CoreException(e.getStatus());
						}
					}
				});
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			}
		} finally {
			endOperation();
			monitor.done();
		}
	}
	
	/**
	 * If not already cached, loads and caches the resource sync for the children of the container.
	 * Folder must exist and must not be the workspace root.
	 *
	 * @param container the container
	 */
	private void cacheResourceSyncForChildren(IContainer container, boolean canModifyWorkspace) throws CVSException {
		// don't try to load if the information is already cached
		if (! getSyncInfoCacheFor(container).isResourceSyncInfoCached(container)) {
			// load the sync info from disk
			byte[][] infos;
			// do not load the sync info for resources that are linked
			if (isLinkedResource(container)) {
				infos = null;
			} else {
				infos = SyncFileWriter.readAllResourceSync(container);
			}
			try {
				if (infos != null) {
					for (int i = 0; i < infos.length; i++) {
						byte[] syncBytes = infos[i];
						IPath name = new Path(null, getName(syncBytes));
						IResource resource;
						if (isFolder(syncBytes)) {
							resource = container.getFolder(name);
						} else {
							resource = container.getFile(name);
						}
						getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, canModifyWorkspace);
					}
				}
				getSyncInfoCacheFor(container).setResourceSyncInfoCached(container);
			} catch (CVSException e) {
				if (Policy.DEBUG_METAFILE_CHANGES) {
					System.err.println("Failed to cache Entries for folder " + container.getFullPath()); //$NON-NLS-1$
				}
				throw e;
			}
		}
	}
	
	/**
	 * If not already cached, loads and caches the folder sync for the
	 * container. Folder must exist and must not be the workspace root.
	 *
	 * @param container the container
	 */
	private void cacheFolderSync(IContainer container) throws CVSException {
		// don't try to load if the information is already cached
		if (! getSyncInfoCacheFor(container).isFolderSyncInfoCached(container)) {
			// load the sync info from disk
			FolderSyncInfo info;
			// do not load the sync info for resources that are linked
			if (isLinkedResource(container)) {
				info = null;
			} else {
				info = SyncFileWriter.readFolderSync(container);
			}
			getSyncInfoCacheFor(container).setCachedFolderSync(container, info, false);
		}
	}
	
	private boolean isLinkedResource(IResource resource) {
		return CVSWorkspaceRoot.isLinkedResource(resource);
	}

	/**
	 * Load the sync info for the given resource from disk
	 * @param resource
	 * @return byte[]
	 */
	private byte[] getSyncBytesFromDisk(IResource resource) throws CVSException {
		byte[][] infos = SyncFileWriter.readAllResourceSync(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			byte[] syncBytes = infos[i];
			if (resource.getName().equals(getName(syncBytes))) {
				return syncBytes;
			}
		}
		return null;
	}
	
	/**
	 * Commits the cache after a series of operations.
	 * 
	 * Will return STATUS_OK unless there were problems writting sync 
	 * information to disk. If an error occurs a multistatus is returned
	 * with the list of reasons for the failures. Failures are recovered,
	 * and all changed resources are given a chance to be written to disk.
	 * 
	 * @param monitor the progress monitor, may be null
	 */
	/* internal use only */ IStatus commitCache(ThreadInfo threadInfo, IProgressMonitor monitor) {
		if (threadInfo.isEmpty()) {
			return SyncInfoCache.STATUS_OK;
		}
		List<IStatus> errors = new ArrayList<>();
		try {
			/*** prepare operation ***/
			// find parents of changed resources
			IResource[] changedResources = threadInfo.getChangedResources();
			IContainer[] changedFolders;
			if (threadInfo instanceof CVSThreadInfo) {
				changedFolders = ((CVSThreadInfo)threadInfo).getChangedFolders();
			} else {
				changedFolders = new IContainer[0];
			}
			Set<IContainer> dirtyParents = new HashSet<>();
			for (int i = 0; i < changedResources.length; i++) {
				IResource resource = changedResources[i];
				IContainer folder = resource.getParent();
				dirtyParents.add(folder);
			}
			
			monitor = Policy.monitorFor(monitor);
			int numDirty = dirtyParents.size();
			int numResources = changedFolders.length + numDirty;
			monitor.beginTask(null, numResources);
			if(monitor.isCanceled()) {
				monitor.subTask(CVSMessages.EclipseSynchronizer_UpdatingSyncEndOperationCancelled); 
			} else {
				monitor.subTask(CVSMessages.EclipseSynchronizer_UpdatingSyncEndOperation); 
			}
			
			/*** write sync info to disk ***/
			// folder sync info changes
			for (int i = 0; i < changedFolders.length; i++) {
				IContainer folder = changedFolders[i];
				if (folder.exists() && folder.getType() != IResource.ROOT) {
					try {
						beginOperation();
						FolderSyncInfo info = sessionPropertyCache.getCachedFolderSync(folder, true);
						// Do not write the folder sync for linked resources
						if (info == null) {
							// deleted folder sync info since we loaded it
							// (but don't overwrite the sync info for linked folders
							if (!isLinkedResource(folder))
								SyncFileWriter.deleteFolderSync(folder);
							dirtyParents.remove(folder);
						} else {
							// modified or created new folder sync info since we loaded it
							SyncFileWriter.writeFolderSync(folder, info);
						}
					} catch(CVSException e) {					
						try {
							sessionPropertyCache.purgeCache(folder, true /* deep */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}
						errors.add(e.getStatus());
					} finally {
						endOperation();
					}
				}
				monitor.worked(1);
			}

			// update progress for parents we will skip because they were deleted
			monitor.worked(numDirty - dirtyParents.size());

			// resource sync info changes
			for (Iterator it = dirtyParents.iterator(); it.hasNext();) {
				IContainer folder = (IContainer) it.next();
				if (folder.exists() && folder.getType() != IResource.ROOT) {
					// write sync info for all children in one go
					try {
						beginOperation();
						List<byte[]> infos = new ArrayList<>();
						IResource[] children = folder.members(true);
						for (int i = 0; i < children.length; i++) {
							IResource resource = children[i];
							byte[] syncBytes = getSyncBytes(resource);
							if (syncBytes != null) {
								infos.add(syncBytes);
							}
						}
						// do not overwrite the sync info for linked resources
						if (infos.size() > 0 || !isLinkedResource(folder))
							SyncFileWriter.writeAllResourceSync(folder,
								infos.toArray(new byte[infos.size()][]));
					} catch(CVSException e) {
						try {
							sessionPropertyCache.purgeCache(folder, false /* depth 1 */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}							
						errors.add(e.getStatus());
					} catch (CoreException e) {
						try {
							sessionPropertyCache.purgeCache(folder, false /* depth 1 */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}							
						errors.add(e.getStatus());
					} finally {
						endOperation();
					}
				}
				monitor.worked(1);
			}
			
			/*** broadcast events ***/
			monitor.subTask(CVSMessages.EclipseSynchronizer_NotifyingListeners); 
			Set<IResource> allChanges = new HashSet<>();
			allChanges.addAll(Arrays.asList(changedResources));
			allChanges.addAll(Arrays.asList(changedFolders));
			allChanges.addAll(dirtyParents);	
			IResource[] resources = allChanges.toArray(
				new IResource[allChanges.size()]);
			broadcastResourceStateChanges(resources);
			if ( ! errors.isEmpty()) {
				MultiStatus status = new MultiStatus(CVSProviderPlugin.ID, 
											CVSStatus.COMMITTING_SYNC_INFO_FAILED, 
											CVSMessages.EclipseSynchronizer_ErrorCommitting, 
											null);
				for (int i = 0; i < errors.size(); i++) {
					status.merge(errors.get(i));
				}
				return status;
			}
			return SyncInfoCache.STATUS_OK;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Broadcasts the resource state changes for the given resources to CVS Provider Plugin
	 */
	void broadcastResourceStateChanges(IResource[] resources) {
		if (resources.length > 0) {
			ResourceStateChangeListeners.getListener().resourceSyncInfoChanged(resources);
		}
	}

	/**
	 * Returns the resource sync info for the resource; null if none.
	 * Parent must exist and must not be the workspace root.
	 * The resource sync info for the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @return the resource sync info for the resource, or null
	 * @see #cacheResourceSyncForChildren
	 */
	private byte[] getCachedSyncBytes(IResource resource) throws CVSException {
		return getSyncInfoCacheFor(resource).getCachedSyncBytes(resource, true);
	}

	/**
	 * Returns the resource sync info for the resource; null if none.
	 * Parent must exist and must not be the workspace root.
	 * The resource sync info for the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @return the resource sync info for the resource, or null
	 * @see #cacheResourceSyncForChildren
	 */
	private void setCachedSyncBytes(IResource resource, byte[] syncBytes) throws CVSException {
		getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, true);
		resourceChanged(resource);
	}
		
	/**
	 * Sets the resource sync info for the resource; if null, deletes it. Parent
	 * must exist and must not be the workspace root. The resource sync info for
	 * the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @param info the new resource sync info
	 * @see #cacheResourceSyncForChildren
	 */
	private void setCachedResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		//todo
		byte[] syncBytes = null;
		if (info != null) syncBytes = info.getBytes();
		getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, true);
	}
	
	/**
	 * If not already cached, loads and caches the folder ignores sync for the container.
	 * Folder must exist and must not be the workspace root.
	 * 
	 * @param container the container
	 * @return the folder ignore patterns, or an empty array if none
	 */
	private FileNameMatcher cacheFolderIgnores(IContainer container) throws CVSException {
		return sessionPropertyCache.getFolderIgnores(container, true);
	}
	
	/**
	 * Sets the array of folder ignore patterns for the container, must not be null.
	 * Folder must exist and must not be the workspace root.
	 * 
	 * @param container the container
	 * @param ignores the array of ignore patterns
	 */
	private void setCachedFolderIgnores(IContainer container, String[] ignores) throws CVSException {
		sessionPropertyCache.setCachedFolderIgnores(container, ignores);
	}
	
	/*
	 * Recursively adds to the possibleIgnores list all children of the given 
	 * folder that can be ignored. This method may only be invoked when a 
	 * schedling rule for the given foldr is held and when the CVs sync lock is
	 * held.
	 * 
	 * @param folder the folder to be searched
	 * @param possibleIgnores the list of IResources that can be ignored
	 */
	private void accumulateNonManagedChildren(IContainer folder, List<IResource> possibleIgnores) throws CVSException {
		try {
			cacheResourceSyncForChildren(folder, true /* can modify workspace */);
			IResource[] children = folder.members();
			List<IResource> folders = new ArrayList<>();
			// deal with all files first and then folders to be otimized for caching scheme
			for (int i = 0; i < children.length; i++) {
				IResource child = children[i];
				if(getCachedSyncBytes(child)==null) {
					possibleIgnores.add(child);
				}
				if(child.getType()!=IResource.FILE) {
					folders.add(child);
				}
			}
			for (Iterator iter = folders.iterator(); iter.hasNext();) {
				IContainer child = (IContainer) iter.next();
				accumulateNonManagedChildren(child, possibleIgnores);
			}
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/**
	 * Add the entry to the CVS/Notify file. We are not initially concerned with efficiency
	 * since edit/unedit are typically issued on a small set of files.
	 * 
	 * XXX If there was a previous notify entry for the resource, it is replaced. This is
	 * probably not the proper behavior (see EclipseFile).
	 * 
	 * A value of null for info indicates that any entry for the given
	 * resource is to be removed from the Notify file.
	 * 
	 * @param resource
	 * @param info
	 */
	public void setNotifyInfo(IResource resource, NotifyInfo info) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) {
			// if the file is empty and we are removing an entry, just return;
			if (info == null) return;
			infos = new NotifyInfo[] { info };
		} else {
			Map<String, NotifyInfo> infoMap = new HashMap<>();
			for (int i = 0; i < infos.length; i++) {
				NotifyInfo notifyInfo = infos[i];
				infoMap.put(notifyInfo.getName(), notifyInfo);
			}
			if (info == null) {
				// if the info is null, remove the entry
				infoMap.remove(resource.getName());
			} else {
				// add the new entry to the list
				infoMap.put(info.getName(), info);
			}
			
			NotifyInfo[] newInfos = new NotifyInfo[infoMap.size()];
			int i = 0;
			for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
				newInfos[i++] = (NotifyInfo) iter.next();
			}
			infos = newInfos;
		}
		SyncFileWriter.writeAllNotifyInfo(resource.getParent(), infos);
	}

	/**
	 * Method getNotifyInfo.
	 * @param resource
	 * @return NotifyInfo
	 */
	public NotifyInfo getNotifyInfo(IResource resource) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			NotifyInfo notifyInfo = infos[i];
			if (notifyInfo.getName().equals(resource.getName())) {
				return notifyInfo;
			}
		}
		return null;
	}

	/**
	 * Method deleteNotifyInfo.
	 * @param resource
	 */
	public void deleteNotifyInfo(IResource resource) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) return;
		Map<String, NotifyInfo> infoMap = new HashMap<>();
		for (int i = 0; i < infos.length; i++) {
			NotifyInfo notifyInfo = infos[i];
			infoMap.put(notifyInfo.getName(), notifyInfo);
		}
		infoMap.remove(resource.getName());
		NotifyInfo[] newInfos = new NotifyInfo[infoMap.size()];
		int i = 0;
		for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
			newInfos[i++] = (NotifyInfo) iter.next();
		}
		SyncFileWriter.writeAllNotifyInfo(resource.getParent(), newInfos);
	}
	
	/**
	 * Add the entry to the CVS/Baserev file. We are not initially concerned
	 * with efficiency since edit/unedit are typically issued on a small set of
	 * files.
	 *
	 * XXX If there was a previous notify entry for the resource, it is replaced. This is
	 * probably not the proper behavior (see EclipseFile).
	 *
	 * @param resource
	 * @param info
	 */
	public void setBaserevInfo(IResource resource, BaserevInfo info) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) {
			infos = new BaserevInfo[] { info };
		} else {
			Map<String, BaserevInfo> infoMap = new HashMap<>();
			for (int i = 0; i < infos.length; i++) {
				infoMap.put(infos[i].getName(), infos[i]);
			}
			infoMap.put(info.getName(), info);
			BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()];
			int i = 0;
			for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
				newInfos[i++] = (BaserevInfo) iter.next();
			}
			infos = newInfos;
		}
		SyncFileWriter.writeAllBaserevInfo(resource.getParent(), infos);
	}

	/**
	 * Method getBaserevInfo.
	 * @param resource
	 * @return BaserevInfo
	 */
	public BaserevInfo getBaserevInfo(IResource resource) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			BaserevInfo info = infos[i];
			if (info.getName().equals(resource.getName())) {
				return info;
			}
		}
		return null;
	}
			
	/**
	 * Method deleteNotifyInfo.
	 * @param resource
	 */
	public void deleteBaserevInfo(IResource resource) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) return;
		Map<String, BaserevInfo> infoMap = new HashMap<>();
		for (int i = 0; i < infos.length; i++) {
			infoMap.put(infos[i].getName(), infos[i]);
		}
		infoMap.remove(resource.getName());
		BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()];
		int i = 0;
		for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
			newInfos[i++] = (BaserevInfo) iter.next();
		}
		SyncFileWriter.writeAllBaserevInfo(resource.getParent(), newInfos);
	}

	public void copyFileToBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(file, Policy.subMonitorFor(monitor, 10));
			ResourceSyncInfo info = getResourceSync(file);
			// The file must exist remotely and locally
			if (info == null || info.isAdded() || info.isDeleted())
				return;
			SyncFileWriter.writeFileToBaseDirectory(file, Policy.subMonitorFor(monitor, 80));
			resourceChanged(file);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 10));
			monitor.done();
		}
	}
	
	public void restoreFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(file, Policy.subMonitorFor(monitor, 10));
			ResourceSyncInfo info = getResourceSync(file);
			// The file must exist remotely
			if (info == null || info.isAdded())
				return;
			SyncFileWriter.restoreFileFromBaseDirectory(file, Policy.subMonitorFor(monitor, 80));
			resourceChanged(file);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 10));
			monitor.done();
		}
	}
	
	public void deleteFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		ResourceSyncInfo info = getResourceSync(file);
		// The file must exist remotely
		if (info == null || info.isAdded())
			return;
		SyncFileWriter.deleteFileFromBaseDirectory(file, monitor);
	}
	
	/**
	 * Method isSyncInfoLoaded returns true if all the sync info for the
	 * provided resources is loaded into the internal cache.
	 * 
	 * @param resources
	 * @param i
	 * @return boolean
	 */
	public boolean isSyncInfoLoaded(IResource[] resources, int depth) throws CVSException {
		// get the folders involved
		IContainer[] folders = getParentFolders(resources, depth);
		// for all folders that have a CVS folder, ensure the sync info is cached
		for (int i = 0; i < folders.length; i++) {
			IContainer parent = folders[i];
			if (!getSyncInfoCacheFor(parent).isSyncInfoLoaded(parent)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Method ensureSyncInfoLoaded loads all the relevent sync info into the cache.
	 * This method can only be invoked when the workspace is open for modification.
	 * in other words it cannot be invoked from inside a POST_CHANGE delta listener.
	 * @param resources
	 * @param i
	 * @return Object
	 */
	public void ensureSyncInfoLoaded(IResource[] resources, int depth) throws CVSException {
		// get the folders involved
		IContainer[] folders = getParentFolders(resources, depth);
		// Cache the sync info for all the folders
		for (int i = 0; i < folders.length; i++) {
			IContainer parent = folders[i];
			ISchedulingRule rule = null;
			try {
				rule = beginBatching(parent, null);
				try {
					beginOperation();
					cacheResourceSyncForChildren(parent, true /* can modify workspace */);
					cacheFolderSync(parent);
					cacheFolderIgnores(parent);
				} finally {
					endOperation();
				}
			} finally {
				if (rule != null) endBatching(rule, null);
			}
		}
	}

	/*
	 * Collect the projects and parent folders of the resources since 
	 * thats were the sync info is kept.
	 */
	private IContainer[] getParentFolders(IResource[] resources, int depth) throws CVSException {
		final Set<IResource> folders = new HashSet<>();
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			folders.add(resource.getProject());
			if (resource.getType() != IResource.PROJECT) {
				folders.add(resource.getParent());
			}
			// use the depth to gather child folders when appropriate
			if (depth != IResource.DEPTH_ZERO) {
				try {
					resource.accept(new IResourceVisitor() {
						public boolean visit(IResource innerResource) throws CoreException {
							if (innerResource.getType() == IResource.FOLDER)
								folders.add(innerResource);
							// let the depth determine who we visit
							return true;
						}
					}, depth, false);
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
			}
		}
		return folders.toArray(new IContainer[folders.size()]);
	}
	
	/**
	 * Perform sync info batching within the context of the given resource
	 * scheduling rule while running the given ICVSRunnable.
	 * @param runnable
	 * @param monitor
	 * @throws CVSException
	 */
	public void run(ISchedulingRule resourceRule, ICVSRunnable runnable, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = beginBatching(resourceRule, Policy.subMonitorFor(monitor, 1));
		try {
			runnable.run(Policy.subMonitorFor(monitor, 98));
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 1));
			monitor.done();
		}
	}
	
	/**
	 * Method isEdited returns true if a "cvs edit" was performed on the given
	 * file and no commit or unedit has yet been performed.
	 * @param iResource
	 * @return boolean
	 */
	public boolean isEdited(IFile resource) {
		return SyncFileWriter.isEdited(resource);
	}
	
	/* package */ void adjustDirtyStateRecursively(IResource resource, String indicator) throws CVSException {
		if (resource.getType() == IResource.ROOT) return;
		try {
			beginOperation();
			
			if (getSyncInfoCacheFor(resource).cachesDirtyState()) {
				if (indicator == getDirtyIndicator(resource)) {
					return;
				}
				getSyncInfoCacheFor(resource).setDirtyIndicator(resource, indicator);	
			} 					
			
			if (Policy.DEBUG_DIRTY_CACHING) {
				debug(resource, indicator, "adjusting dirty state"); //$NON-NLS-1$
			}									

			IContainer parent = resource.getParent();
			if(indicator == NOT_DIRTY_INDICATOR) {
				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
			}
			
			if(indicator == RECOMPUTE_INDICATOR) {
				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
			} 
			
			if(indicator == IS_DIRTY_INDICATOR) {
				adjustDirtyStateRecursively(parent, indicator);
			} 
		} finally {
			endOperation();
		}
	}

	protected String getDirtyIndicator(IResource resource) throws CVSException {
		// Do a check outside the lock for the dirty indicator
		String indicator = getSyncInfoCacheFor(resource).getDirtyIndicator(resource, false /* not thread safe */);
		if (indicator != null)
			return indicator;
		try {
			beginOperation();
			return getSyncInfoCacheFor(resource).getDirtyIndicator(resource, true);
		} finally {
			endOperation();
		}
	}
	
	/*
	 * Mark the given resource as either modified or clean using a persistant
	 * property. Do nothing if the modified state is already what we want.
	 * Return true if the modification state was changed.
	 */
	protected void setDirtyIndicator(IResource resource, boolean modified) throws CVSException {
		String indicator = modified ? IS_DIRTY_INDICATOR : NOT_DIRTY_INDICATOR;
		// set the dirty indicator and adjust the parent accordingly			
		adjustDirtyStateRecursively(resource, indicator);
	}

	/**
	 * Method getName.
	 * @param syncBytes
	 */
	private String getName(byte[] syncBytes) throws CVSException {
		return ResourceSyncInfo.getName(syncBytes);
	}
	
	/**
	 * Method isFolder.
	 * @param syncBytes
	 * @return boolean
	 */
	private boolean isFolder(byte[] syncBytes) {
		return ResourceSyncInfo.isFolder(syncBytes);
	}
		
	/**
	 * Method convertToDeletion.
	 * @param syncBytes
	 * @return byte[]
	 */
	private byte[] convertToDeletion(byte[] syncBytes) throws CVSException {
		return ResourceSyncInfo.convertToDeletion(syncBytes);
	}

	static public void debug(IResource resource, String indicator, String string) {
		String di = EclipseSynchronizer.IS_DIRTY_INDICATOR;
		if(indicator == EclipseSynchronizer.IS_DIRTY_INDICATOR) {
			di = "dirty";	//$NON-NLS-1$
		} else if(indicator == EclipseSynchronizer.NOT_DIRTY_INDICATOR) {
			di = "clean";	//$NON-NLS-1$
		} else {
			di = "needs recomputing";	//$NON-NLS-1$
		} 
		System.out.println("["+string + ":" + di + "]  "  + resource.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}
	
	/**
	 * @param file
	 * @return int
	 */
	public int getModificationState(IResource resource) throws CVSException {
		String indicator =  getDirtyIndicator(resource);
		if (Policy.DEBUG_DIRTY_CACHING) {
			debug(resource, indicator, "getModificationState"); //$NON-NLS-1$
		}
		if (indicator == null || indicator == RECOMPUTE_INDICATOR) {
			return ICVSFile.UNKNOWN;
		} else if (indicator == IS_DIRTY_INDICATOR) {
			return ICVSFile.DIRTY;
		} else if (indicator == NOT_DIRTY_INDICATOR) {
			return ICVSFile.CLEAN;
		} else {
			return ICVSFile.UNKNOWN;
		}
	}

	/**
	 * Return whether the resource is within the scope of a currently active
	 * CVS operation.
	 * @param resource
	 * @return
	 */
	public boolean isWithinActiveOperationScope(IResource resource) {
		return resourceLock.isWithinActiveOperationScope(resource);
	}
	
	/**
	 * Set the timestamp of the given file and set it to be CLEAN. It is
	 * assumed that this method is only invoked to reset the file timestamp
	 * to the timestamp that is in the CVS/Entries file.
	 * @param file
	 * @param time
	 * @throws CVSException
	 */
	public void setTimeStamp(EclipseFile cvsFile, long time) throws CVSException {
		ISchedulingRule rule = null;
		IFile file = (IFile)cvsFile.getIResource();
		try {
			rule = beginBatching(file, null);
			try {
				beginOperation();
				try {
					file.setLocalTimeStamp(time);
					setModified(cvsFile, ICVSFile.CLEAN);
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
				resourceChanged(file);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	/**
	 * React to a resource that was just moved by the move/delete hook.
	 * @param resource the resource that was moved (at its new location)
	 */
	public void postMove(IResource resource) throws CVSException {
		try {
			beginOperation();
			if (resource.getType() == IResource.FILE) {
				// Purge any copied sync info so true sync info will 
				// be obtained from the synchronizer cache
				sessionPropertyCache.purgeResourceSyncCache(resource);
			} else {
				IContainer container = (IContainer)resource;
				// Purge any copied sync info
				sessionPropertyCache.purgeCache(container, true /* deep */);
				// Dirty all resources so old sync info will be rewritten to disk
				try {
					container.accept(new IResourceVisitor() {
						public boolean visit(IResource resource) throws CoreException {
							if (getSyncBytes(resource) != null) {
								resourceChanged(resource);
							}
							if (resource.getType() != IResource.FILE) {
								if (getFolderSync((IContainer)resource) != null) {
									folderChanged((IContainer)resource);
									return true;
								}
							}
							return false;
						}
					});
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
				// Flush the sync info to disk
				flush(container, true /* deep */, null);
			}
		} finally {
			endOperation();
		}
	}
	
	/**
	 * This method is to be invoked only from the move/delete hook. Its purpose is to obtain the
	 * sync look in order to prevent other threads from accessing sync info while the move/delete is
	 * taking place.
	 * 
	 * @param runnable
	 * @param monitor
	 * @throws CVSException
	 */
	public void performMoveDelete(ICVSRunnable runnable, IProgressMonitor monitor) throws CVSException {
		ISchedulingRule rule = null;
		try {
			monitor.beginTask(null, 100);
			rule = beginBatching(null, null);
			try {
				beginOperation();
				runnable.run(Policy.subMonitorFor(monitor, 95));
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}
	
	/**
	 * Compute the modification state for the given file. If the modificationState is
	 * ICVSFile.UNKNOWN, it is computed. However, if it is CLEAN or DIRTY, 
	 * it is set accordingly. CLEAN or DIRTY can only be used if the caller is protected
	 * from resource modifications (either by a scheduling rule or inside a delta handler).
	 * @param file
	 * @param modificationState
	 * @return true if the file is dirty
	 */
	public boolean setModified(EclipseFile cvsFile, int modificationState) throws CVSException {
		try {
			beginOperation();
			boolean dirty;
			if (modificationState == ICVSFile.UNKNOWN) {
				dirty = cvsFile.isDirty();
			} else {
				dirty = modificationState == ICVSFile.DIRTY;
			}
			setDirtyIndicator(cvsFile.getIResource(), dirty);
			return dirty;
		} finally {
			endOperation();
		}

	}

	/**
	 * Set the modified state of the folder. This method can be called when no resource locks are
	 * held. It will check the cached modification state of all the folder's children before setting.
	 * If the states of the children do not match, the state for the folder is not cached.
	 * @param folder
	 * @param modified
	 */
	public void setModified(ICVSFolder cvsFolder, boolean modified) throws CVSException {
		try {
			beginOperation();
			IContainer folder = (IContainer)cvsFolder.getIResource();
			// The drop out condition for clean or dirty are the opposite.
			// (i.e. if modified and a dirty is found we can set the indicator
			// and if not modified and a dirty or unknown is found we cannot set the indicator)
			boolean okToSet = !modified;
			// Obtain the children while we're locked to ensure some were not added or changed
			ICVSResource[] children = cvsFolder.members(ICVSFolder.ALL_UNIGNORED_MEMBERS);
			for (int i = 0; i < children.length; i++) {
				IResource resource = children[i].getIResource();
				if (modified) {
					if (getDirtyIndicator(resource) == IS_DIRTY_INDICATOR) {
						okToSet = true;
						break;
					}
				} else {
					if (getDirtyIndicator(resource) != NOT_DIRTY_INDICATOR) {
						okToSet = false;
						break;
					}
				}
			}
			if (okToSet) {
				setDirtyIndicator(folder, modified);
			}
		} finally {
			endOperation();
		}
	}
	
	public boolean wasPhantom(IResource resource) {
		if (resource.exists()) {
			try {
				return (synchronizerCache.getCachedSyncBytes(resource, true) != null 
					|| (resource.getType() == IResource.FOLDER
							&& synchronizerCache.hasCachedFolderSync((IContainer)resource)));
			} catch (CVSException e) {
				// Log and assume resource is not a phantom
				CVSProviderPlugin.log(e);
			}
		}
		return false;
	}
	
	/**
	 * Method called from background handler when resources that are mapped to CVS are recreated
	 * @param resources
	 * @param monitor
	 * @throws CVSException
	 */
	public void resourcesRecreated(IResource[] resources, IProgressMonitor monitor) throws CVSException {
		if (resources.length == 0) return;
		ISchedulingRule rule = null;
		ISchedulingRule projectsRule = getProjectRule(resources);
		try {
			monitor = Policy.monitorFor(monitor);
			monitor.beginTask(null, 100);
			rule = beginBatching(projectsRule, monitor);
			for (int i = 0; i < resources.length; i++) {
				IResource resource = resources[i];
				try {
					created(resource);
				} catch (CVSException e) {
					CVSProviderPlugin.log(e);
				}
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}
	
	private ISchedulingRule getProjectRule(IResource[] resources) {
		HashSet<IProject> set = new HashSet<>();
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			set.add(resource.getProject());
		}
		IProject[] projects = set.toArray(new IProject[set.size()]);
		if (projects.length == 1) {
			return projects[0];
		}
		return new MultiRule(projects);
	}

	protected void created(IResource resource) throws CVSException {
		try {
			beginOperation();
			if (resource.exists()) {
				restoreResourceSync(resource);
				if (resource.getType() == IResource.FOLDER) {
					restoreFolderSync((IFolder)resource);
				}
			}
		} finally {
			endOperation();
		}
	}
	
	/*
	 * Restore the folder sync info for the given folder
	 */
	private void restoreFolderSync(IFolder folder) throws CVSException {
		try {
			// set the dirty count using what was cached in the phantom it
			beginOperation();
			FolderSyncInfo folderInfo = synchronizerCache.getCachedFolderSync(folder, true);
			if (folderInfo != null) {
				// There is folder sync info to restore
				if (folder.getFolder(SyncFileWriter.CVS_DIRNAME).exists()) {
					// There is already a CVS subdirectory which indicates that
					// either the folder was recreated by an external tool or that
					// a folder with CVS information was copied from another location.
					// To know the difference, we need to compare the folder sync info.
					// If they are mapped to the same root and repository then just
					// purge the phantom info. Otherwise, keep the original sync info.

					// Get the new folder sync info
					FolderSyncInfo newFolderInfo = getFolderSync(folder);
					if (newFolderInfo.getRoot().equals(folderInfo.getRoot())
							&& newFolderInfo.getRepository().equals(folderInfo.getRepository())) {
						// The folder is the same so use what is on disk.
						// Fall through to ensure that the Root and Repository files exist
					} else {
						// The folder is mapped to a different location.
						// Purge new resource sync before restoring from phantom
						ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder);
						ICVSResource[] children = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS);
						for (int i = 0; i < children.length; i++) {
							ICVSResource resource = children[i];
							deleteResourceSync(resource.getIResource());
						}
					}
				}

				// set the sync info using what was cached in the phantom
				setFolderSync(folder, folderInfo);
				// purge the dirty cache so any old persisted dirty state is purged
				sessionPropertyCache.purgeDirtyCache(folder);
				// Indicate that a member has changed so the entries file gets written (see bug 181546)
				IResource[] members = members(folder);
				IResource changedResource = null;
				for (int i = 0; i < members.length; i++) {
					IResource resource = members[i];
					if (getSyncBytes(resource) != null) {
						changedResource = resource;
						break;
					}
				}
				if (changedResource == null) {
					changedResource = folder.getFile("dummy"); //$NON-NLS-1$
				}
				resourceChanged(changedResource);
			}
		} finally {
			try {
				endOperation();
			} finally {
				synchronizerCache.flush(folder);
			}
		}
	}

	/*
	 * Restore the resource sync info for the given resource.
	 */
	private void restoreResourceSync(IResource resource) throws CVSException {
		try {
			beginOperation();
			byte[] syncBytes = synchronizerCache.getCachedSyncBytes(resource, true);
			if (syncBytes != null) {
				if (!ResourceSyncInfo.isFolder(syncBytes)) {
					syncBytes = ResourceSyncInfo.convertFromDeletion(syncBytes);
				}
				byte[] newBytes = getSyncBytes(resource);
				if (newBytes != null && !ResourceSyncInfo.isFolder(newBytes)) {
					newBytes = ResourceSyncInfo.convertFromDeletion(newBytes);
				}
				if (newBytes == null || Util.equals(syncBytes, newBytes)) {
					// only move the sync info if there is no new sync info
					setSyncBytes(resource, syncBytes);
				}
			}
		} finally {
			try {
				endOperation();
			} finally {
				synchronizerCache.setCachedSyncBytes(resource, null, true);
			}
		}
	}
	
	private void purgeDirtyCache(IProject project, IProgressMonitor monitor) throws CVSException {
		sessionPropertyCache.purgeDirtyCache(project);
	}
}
