X-Git-Url: https://code.grnet.gr/git/pithos-ms-client/blobdiff_plain/81c5c3103c8046362017f216027eb56169ae3b33..1cc1e8c52a2712aacfb99eb535180126c9f85350:/trunk/Pithos.Core/Agents/StatusAgent.cs diff --git a/trunk/Pithos.Core/Agents/StatusAgent.cs b/trunk/Pithos.Core/Agents/StatusAgent.cs index 299b41f..b95645d 100644 --- a/trunk/Pithos.Core/Agents/StatusAgent.cs +++ b/trunk/Pithos.Core/Agents/StatusAgent.cs @@ -107,9 +107,11 @@ namespace Pithos.Core.Agents private static void MigrateOldDb(string dbPath, string appDataPath) { - Contract.Requires(!String.IsNullOrWhiteSpace(dbPath)); - Contract.Requires(!String.IsNullOrWhiteSpace(appDataPath)); - + if(String.IsNullOrWhiteSpace(dbPath)) + throw new ArgumentNullException("dbPath"); + if(String.IsNullOrWhiteSpace(appDataPath)) + throw new ArgumentNullException("appDataPath"); + Contract.EndContractBlock(); var oldDbPath = Path.Combine(appDataPath, "Pithos", "pithos.db"); var oldDbInfo = new FileInfo(oldDbPath); @@ -344,6 +346,12 @@ namespace Pithos.Core.Agents command.Parameters.AddWithValue("path", path); var affected = command.ExecuteNonQuery(); + if (affected == 0) + { + var createdState = FileState.CreateFor(FileInfoExtensions.FromPath(path)); + createdState.FileStatus = status; + createdState.Create(); + } return affected; } } @@ -355,7 +363,7 @@ namespace Pithos.Core.Agents } } - private int UpdateStatusDirect(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus) + private int UpdateStatusDirect(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus, string conflictReason) { using (log4net.ThreadContext.Stacks["StatusAgent"].Push("UpdateStatusDirect")) { @@ -368,15 +376,24 @@ namespace Pithos.Core.Agents using ( var command = new SQLiteCommand( - "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE ", + "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus,ConflictReason= :conflictReason where FilePath = :path COLLATE NOCASE ", connection)) { command.Parameters.AddWithValue("path", absolutePath); command.Parameters.AddWithValue("fileStatus", fileStatus); command.Parameters.AddWithValue("overlayStatus", overlayStatus); + command.Parameters.AddWithValue("conflictReason", conflictReason); var affected = command.ExecuteNonQuery(); + if (affected == 0) + { + var createdState=FileState.CreateFor(FileInfoExtensions.FromPath(absolutePath)); + createdState.FileStatus = fileStatus; + createdState.OverlayStatus = overlayStatus; + createdState.ConflictReason = conflictReason; + createdState.Create(); + } return affected; } } @@ -567,7 +584,7 @@ namespace Pithos.Core.Agents _persistenceAgent.Post(() =>FileState.RenameState(oldPath, newPath)); }*/ - public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus) + public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus, string conflictReason) { if (String.IsNullOrWhiteSpace(path)) throw new ArgumentNullException("path"); @@ -578,7 +595,7 @@ namespace Pithos.Core.Agents Debug.Assert(!path.Contains(FolderConstants.CacheFolder)); Debug.Assert(!path.EndsWith(".ignore")); - _persistenceAgent.Post(() => UpdateStatusDirect(path, fileStatus, overlayStatus)); + _persistenceAgent.Post(() => UpdateStatusDirect(path, fileStatus, overlayStatus, conflictReason)); } /* @@ -650,19 +667,18 @@ namespace Pithos.Core.Agents else { command.CommandText = - "INSERT INTO FileState (Id,FilePath,Checksum,Version,VersionTimeStamp,ShortHash,FileStatus,OverlayStatus) VALUES (:id,:path,:checksum,:version,:versionTimeStamp,:shortHash,:fileStatus,:overlayStatus)"; + "INSERT INTO FileState (Id,FilePath,Checksum,Version,VersionTimeStamp,ShortHash,FileStatus,OverlayStatus,ObjectID) VALUES (:id,:path,:checksum,:version,:versionTimeStamp,:shortHash,:fileStatus,:overlayStatus,:objectID)"; command.Parameters.AddWithValue("id", Guid.NewGuid()); } command.Parameters.AddWithValue("path", path); - command.Parameters.AddWithValue("checksum", objectInfo.Hash); - command.Parameters.AddWithValue("shortHash", ""); + command.Parameters.AddWithValue("checksum", objectInfo.X_Object_Hash); + command.Parameters.AddWithValue("shortHash", objectInfo.ETag); command.Parameters.AddWithValue("version", objectInfo.Version); - command.Parameters.AddWithValue("versionTimeStamp", - objectInfo.VersionTimestamp); + command.Parameters.AddWithValue("versionTimeStamp", objectInfo.VersionTimestamp); command.Parameters.AddWithValue("fileStatus", FileStatus.Unchanged); - command.Parameters.AddWithValue("overlayStatus", - FileOverlayStatus.Normal); + command.Parameters.AddWithValue("overlayStatus", FileOverlayStatus.Normal); + command.Parameters.AddWithValue("objectID",objectInfo.UUID); var affected = command.ExecuteNonQuery(); return; @@ -744,7 +760,7 @@ namespace Pithos.Core.Agents if (!Path.IsPathRooted(path)) throw new ArgumentException("The path must be rooted", "path"); Contract.EndContractBlock(); - + //TODO: May throw if the agent is cleared for some reason. Should never happen _persistenceAgent.Post(() => DeleteFolderDirect(path)); } @@ -842,6 +858,65 @@ namespace Pithos.Core.Agents _persistenceAgent.Post(() => FileState.UpdateChecksum(path, shortHash,checksum)); } + + public void CleanupOrphanStates() + { + //Orphan states are those that do not correspond to an account, ie. their paths + //do not start with the root path of any registered account + + var roots=(from account in Settings.Accounts + select account.RootPath).ToList(); + + var allStates = from state in FileState.Queryable + select state.FilePath; + + foreach (var statePath in allStates) + { + if (!roots.Any(root=>statePath.StartsWith(root,StringComparison.InvariantCultureIgnoreCase))) + this.DeleteDirect(statePath); + } + } + + public void CleanupStaleStates(AccountInfo accountInfo, List objectInfos) + { + if (accountInfo == null) + throw new ArgumentNullException("accountInfo"); + if (objectInfos == null) + throw new ArgumentNullException("objectInfos"); + Contract.EndContractBlock(); + + + + //Stale states are those that have no corresponding local or server file + + + var agent=FileAgent.GetFileAgent(accountInfo); + + var localFiles=agent.EnumerateFiles(); + var localSet = new HashSet(localFiles); + + //RelativeUrlToFilePath will fail for + //infos of accounts, containers which have no Name + + var serverFiles = from info in objectInfos + where info.Name != null + select Path.Combine(accountInfo.AccountPath,info.RelativeUrlToFilePath(accountInfo.UserName)); + var serverSet = new HashSet(serverFiles); + + var allStates = from state in FileState.Queryable + where state.FilePath.StartsWith(agent.RootPath) + select state.FilePath; + var stateSet = new HashSet(allStates); + stateSet.ExceptWith(serverSet); + stateSet.ExceptWith(localSet); + + foreach (var remainder in stateSet) + { + DeleteDirect(remainder); + } + + + } }