}
}
+ internal class ObjectInfoComparer:EqualityComparer<ObjectInfo>
+ {
+ public override bool Equals(ObjectInfo x, ObjectInfo y)
+ {
+ return (x.Account == y.Account &&
+ x.Container == y.Container &&
+ x.Name == y.Name);
+ }
+
+ public override int GetHashCode(ObjectInfo obj)
+ {
+ return String.Join("/",obj.Account,obj.Container,obj.Name).GetHashCode();
+ }
+ }
+
+ Dictionary<string, List<ObjectInfo>> _currentSnapshot = new Dictionary<string, List<ObjectInfo>>();
+ Dictionary<string, List<ObjectInfo>> _previousSnapshot = new Dictionary<string, List<ObjectInfo>>();
+
/// <summary>
/// Deletes local files that are not found in the list of cloud files
/// </summary>
throw new ArgumentNullException("cloudFiles");
Contract.EndContractBlock();
- //Check the Modified date to ensure that were just created and haven't been uploaded yet
- //NOTE: The NHibernate LINQ provider doesn't support custom functions so we need to break the query
- //in two steps
- //NOTE: DON'T return files that are already in conflict. The first poll would mark them as
- //"In Conflict" but subsequent polls would delete them
-/* var t=FileState.Find(new Guid("{cd664c9a-5f17-47c9-b27f-3bcbcb0595ff}"));
+ if (_previousSnapshot.ContainsKey(accountInfo.UserName) && _currentSnapshot.ContainsKey(accountInfo.UserName))
+ _previousSnapshot[accountInfo.UserName] = _currentSnapshot[accountInfo.UserName] ?? new List<ObjectInfo>();
+ else
+ {
+ _previousSnapshot[accountInfo.UserName]=new List<ObjectInfo>();
+ }
- var d0 = FileState.Queryable
- .Where(state =>
- state.FilePath.StartsWith(accountInfo.AccountPath)).ToList();
-
- var d1 = FileState.Queryable
- .Where(state => state.Modified <= pollTime).ToList();
- var d2= FileState.Queryable
- .Where(state => state.Modified <= pollTime
- &&
- state.FilePath.StartsWith(accountInfo.AccountPath)).ToList();*/
-
- //Consider for deleteion only files modified before the PREVIOUS poll
- //A user may perform a file creation or rename at roughly the same time as a poll. In such a case
- //the new file will appear as deleted
- var previousPollTime = pollTime.Subtract(TimeSpan.FromMilliseconds(Settings.PollingInterval));
-
- //Only consider files that are not being modified, ie they are in the Unchanged state
- var deleteCandidates = FileState.Queryable.Where(state =>
- state.Modified <= previousPollTime
- && state.FilePath.StartsWith(accountInfo.AccountPath)
- && state.FileStatus == FileStatus.Unchanged).ToList();
-
- //TODO: filesToDelete must take into account the Others container
- var filesToDelete = (from deleteCandidate in deleteCandidates
- let localFile = FileInfoExtensions.FromPath(deleteCandidate.FilePath)
- let relativeFilePath = localFile.AsRelativeTo(accountInfo.AccountPath)
- let agentActions = _agent.GetEnumerable()
- where
- !_lastSeen.ContainsKey(localFile.FullName)
- && !cloudFiles.Any(r => r.RelativeUrlToFilePath(accountInfo.UserName) == relativeFilePath )
- //Exclude files enqueued for uploading
- //Large files will not appear on the server for multiple polls. They must not be marked as deleted
- && !agentActions.Any(action => action.LocalFile.WithProperCapitalization().FullName == localFile.FullName)
- //Do NOT delete files modified since the previous poll
- && localFile.LastAccessTime < previousPollTime
- select localFile).ToList();
-
+ _currentSnapshot[accountInfo.UserName] = cloudFiles.ToList();
+
+ var deletedObjects = _previousSnapshot[accountInfo.UserName].Except(_currentSnapshot[accountInfo.UserName], new ObjectInfoComparer()).ToList();
+
//On the first run
if (_firstPoll)
{
+ //Only consider files that are not being modified, ie they are in the Unchanged state
+ var deleteCandidates = FileState.Queryable.Where(state =>
+ state.FilePath.StartsWith(accountInfo.AccountPath)
+ && state.FileStatus == FileStatus.Unchanged).ToList();
+
+
+ //TODO: filesToDelete must take into account the Others container
+ var filesToDelete = (from deleteCandidate in deleteCandidates
+ let localFile = FileInfoExtensions.FromPath(deleteCandidate.FilePath)
+ let relativeFilePath = localFile.AsRelativeTo(accountInfo.AccountPath)
+ where
+ !cloudFiles.Any(r => r.RelativeUrlToFilePath(accountInfo.UserName) == relativeFilePath)
+ select localFile).ToList();
+
+
+
//Set the status of missing files to Conflict
foreach (var item in filesToDelete)
{
}
UpdateStatus(PithosStatus.HasConflicts);
StatusNotification.NotifyConflicts(filesToDelete, String.Format("{0} local files are missing from Pithos, possibly because they were deleted",filesToDelete.Count));
+ StatusNotification.NotifyForFiles(filesToDelete, String.Format("{0} files were deleted", filesToDelete.Count), TraceLevel.Info);
}
else
{
- foreach (var item in filesToDelete)
+ var deletedFiles = new List<FileSystemInfo>();
+ foreach (var objectInfo in deletedObjects)
{
+ var relativePath = objectInfo.RelativeUrlToFilePath(accountInfo.UserName);
+ var item = GetFileAgent(accountInfo).GetFileSystemInfo(relativePath);
if (item.Exists)
{
//Try to acquire a gate on the file, to take into account files that have been dequeued
//and are being processed
//TODO: The gate is not enough. Perhaps we need to keep a journal of processed files and check against
//that as well.
+/*
using (var gate = NetworkGate.Acquire(item.FullName, NetworkOperation.Deleting))
{
if (gate.Failed)
continue;
+*/
if ((item.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
item.Attributes = item.Attributes & ~FileAttributes.ReadOnly;
}
item.Delete();
+ DateTime lastDate;
+ _lastSeen.TryRemove(item.FullName, out lastDate);
+ deletedFiles.Add(item);
+/*
}
+*/
}
StatusKeeper.ClearFileStatus(item.FullName);
+
}
- StatusNotification.NotifyForFiles(filesToDelete, String.Format("{0} files were deleted",filesToDelete.Count),TraceLevel.Info);
+ StatusNotification.NotifyForFiles(deletedFiles, String.Format("{0} files were deleted", deletedFiles.Count), TraceLevel.Info);
}
}
}
+ //Returns true if an action concerns a file that was deleted
private bool IsDeletedFile(CloudAction action)
- {
+ {
+ //Doesn't work for actions targeting shared files
+ if (action.IsShared)
+ return false;
var key = GetFileKey(action.CloudFile);
DateTime entryDate;
if (_deletedFiles.TryGetValue(key, out entryDate))