private static void SyncFile(AutoSyncRequest request) { string sourceFullPath = Path.Combine(request.SourceParent, request.ChangeType == AutoSyncRequestType.Rename ? request.NewName : request.SourceName); if (File.Exists(sourceFullPath)) { switch (request.ChangeType) { case AutoSyncRequestType.New: case AutoSyncRequestType.Update: HandleCreateUpdate(request, sourceFullPath); break; case AutoSyncRequestType.Rename: HandleFileRename(request, sourceFullPath); break; case AutoSyncRequestType.Delete: HandleFileDelete(request); break; } } else if (request.ChangeType == AutoSyncRequestType.Delete) { HandleFileDelete(request); } }
/// <summary> /// Adds a AutoSyncRequest to the queue. /// </summary> /// <param name="item">AutoSyncRequest</param> /// <exception cref="ArgumentNullException">Thrown when AutoSyncRequest is null</exception> public void AddSyncJob(AutoSyncRequest item) { if (item == null) throw new ArgumentNullException("item"); lock (Locker) { _jobs.Enqueue(item); } _wh.Set(); }
/// <summary> /// Handles some basic logic to decide whether the incoming request is a file or folder request. /// </summary> /// <param name="request">The <see cref="AutoSyncRequest"/> to process.</param> public static void Sync(AutoSyncRequest request) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.SYNC_STARTED, "Started Auto Sync for " + request.SourceName)); _metaUpdated = DateTime.UtcNow.Ticks; bool? isFolder = request.IsFolder; bool isFldr; if (isFolder.HasValue) isFldr = (bool)isFolder; else isFldr = IsFolder(request.SourceName, request.DestinationFolders); if (isFldr) SyncFolder(request); else SyncFile(request); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.SYNC_STOPPED, "Completed Auto Sync for " + request.SourceName)); }
/// <summary> /// Worker thread to dequeue and process jobs in the queue. /// </summary> private void Work() { while (true) { lock (Locker) { if (_jobs.Count > 0) { _currJob = _jobs.Dequeue(); if (_currJob == null) return; } } if (_currJob != null) { SeamlessSyncer.Sync(_currJob); _currJob = null; } else { _wh.WaitOne(); } } }
private void SendAutoRequest(AutoSyncRequest request) { #region debug region /* if (request.ChangeType == AutoSyncRequestType.New || request.ChangeType == AutoSyncRequestType.Update) { string output = string.Format("=====================================================\nAuto Request sent : \nName of File : ({0}){1}\nSource : {2}{3}\nDestination:", (request.ChangeType == AutoSyncRequestType.New ? "New" : "Update"), request.SourceName, request.SourceParent, request.SourceName); foreach (string destination in request.DestinationFolders) { output += "\n" + destination + "\\" + request.SourceName; } output += "\n================================================================"; ServiceLocator.GetLogger(ServiceLocator.DEVELOPER_LOG).Write(output); } else if (request.ChangeType == AutoSyncRequestType.Rename) { string output = string.Format("=====================================================\nAuto Request sent : \nName of File : (Renamed){0}\\\\{1}\nSource : {2}{3}---{4}\nDestination:", request.OldName, request.NewName, request.SourceParent, request.OldName, request.NewName); foreach (string destination in request.DestinationFolders) { output += "\n" + destination + "\\" + request.OldName + " =>" + request.NewName; } output += "\n================================================================"; ServiceLocator.GetLogger(ServiceLocator.DEVELOPER_LOG).Write(output); } else if (request.ChangeType == AutoSyncRequestType.Delete) { string output = string.Format("=====================================================\nAuto Request sent : \nName of File : (Delete){0}\nSource : {1}{2}\nDestination:", request.SourceName, request.SourceParent, request.SourceName); foreach (string destination in request.DestinationFolders) { output += "\n" + destination + "\\" + request.SourceName; } output += "\n================================================================"; ServiceLocator.GetLogger(ServiceLocator.DEVELOPER_LOG).Write(output); } */ #endregion CompareAndSyncController.Instance.Sync(request); }
private void HandleRootFolderDeleteEvent(FolderChangeEvent dce) { MonitorLayer.Instance.UnMonitorPath(dce.OldPath.FullName); //Find the logical Address for the old path //Do not create the logical address if not found. string logicalAddress = ProfilingLayer.Instance.ConvertPhysicalToLogical(dce.OldPath.FullName, false); //Get all the tag that contains this logicalAddress inside the tag. List<Tag> tag = TaggingLayer.Instance.RetrieveParentTagByPath(logicalAddress); //If tag count is 0 return as there is nothing to process. if (tag.Count == 0) { return; } //Find the similiar paths for the logical Path //The return is physical address List<string> convertedList = FindSimilarSeamlessPathForFile(logicalAddress); convertedList.Remove(dce.OldPath.FullName); //////// Massive Path Table Code ///////////// for (int i = 0; i < convertedList.Count; i++) { string dest = convertedList[i]; if (_pathTable.JustPop(dce.OldPath.FullName, dest, TableType.Delete)) { convertedList.Remove(dest); i--; continue; } } ///////////////// For each Path in the converted List /////////////////// ///////////////////////////////// Create a entry such that source = convertedPath and destination is the original Path /////////// ///////////////////////For each other path , create a Source + dest pair ////////// ///////////////// Create an additional Path Entry for each of the Siblings //////////////// for (int i = 0; i < convertedList.Count; i++) { _pathTable.AddPathPair(convertedList[i], dce.OldPath.FullName, TableType.Delete); for (int j = i + 1; j < convertedList.Count; j++) { _pathTable.AddPathPair(convertedList[i], convertedList[j], TableType.Delete); _pathTable.AddPathPair(convertedList[j], convertedList[i], TableType.Delete); } } ///////// End of Path Table Code //////////////// //For each path in the convertedList , extract the parent Path. List<string> parentList = new List<string>(); foreach (string path in convertedList) { FileInfo info = new FileInfo(PathHelper.RemoveTrailingSlash(path)); string parent = info.Directory == null ? "" : info.Directory.FullName; parentList.Add(parent); } //If the parent list if empty , it means that there is nothing to sync and thus return. if (parentList.Count == 0) { return; } //Create the request and Send it. Debug.Assert(dce.OldPath.Parent != null); AutoSyncRequest request = new AutoSyncRequest(dce.OldPath.Name, dce.OldPath.Parent.FullName, parentList, AutoSyncRequestType.Delete, SyncConfig.Instance, ConvertTagListToTagString(tag)); SendAutoRequest(request); FindAndCleanDeletedPaths(); _userInterface.TagsChanged(); }
/// <summary> /// The method is called when there is an auto/seamless request. /// </summary> /// <param name="request">The <see cref="AutoSyncRequest"/> to synchronize.</param> public void Sync(AutoSyncRequest request) { SeamlessQueueControl.Instance.AddSyncJob(request); }
// Helper method to handle created and updated files. private static void HandleCreateUpdate(AutoSyncRequest request, string sourceFullPath) { try { FileInfo currFile = new FileInfo(sourceFullPath); // Write the source file to XML first. switch (request.ChangeType) { case AutoSyncRequestType.New: SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, request.SourceParent, CommonMethods.CalculateMD5Hash(currFile), currFile.Length, currFile.CreationTimeUtc.Ticks, currFile.LastWriteTimeUtc.Ticks, MetaChangeType.New, _metaUpdated)); break; case AutoSyncRequestType.Update: SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, request.SourceParent, CommonMethods.CalculateMD5Hash(currFile), currFile.Length, currFile.CreationTimeUtc.Ticks, currFile.LastWriteTimeUtc.Ticks, MetaChangeType.Update, _metaUpdated)); break; default: break; } } catch (HashFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error hashing " + sourceFullPath + ".")); } foreach (string dest in request.DestinationFolders) { string destFullPath = Path.Combine(dest, request.SourceName); // If do sync is true if (DoSync(sourceFullPath, destFullPath)) { try { try { // Archive file if required if (request.Config.ArchiveLimit > 0 && File.Exists(destFullPath)) { CommonMethods.ArchiveFile(destFullPath, request.Config.ArchiveName, request.Config.ArchiveLimit); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "File archived " + destFullPath)); } // Delete file to recycle bin if needed if (request.Config.Recycle && File.Exists(destFullPath)) { CommonMethods.DeleteFileToRecycleBin(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted to recycle bin " + destFullPath)); } } catch (ArchiveFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving file " + destFullPath)); } catch (DeleteFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting file " + destFullPath)); } bool fileExists = File.Exists(destFullPath); // Copy the file over CommonMethods.CopyFile(sourceFullPath, destFullPath); if (fileExists) ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_MODIFIED, "File updated from " + sourceFullPath + " to " + destFullPath)); else ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "File copied from " + sourceFullPath + " to " + destFullPath)); // Update the XML for this file FileInfo destFile = new FileInfo(destFullPath); SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, dest, CommonMethods.CalculateMD5Hash(destFile), destFile.Length, destFile.CreationTimeUtc.Ticks, destFile.LastWriteTimeUtc.Ticks, request.ChangeType == AutoSyncRequestType.New ? MetaChangeType.New : MetaChangeType.Update, _metaUpdated)); } catch (CopyFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying file from " + sourceFullPath + " to " + destFullPath)); } catch (MoveFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error renaming file from " + sourceFullPath + " to " + destFullPath)); } catch (HashFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error hashing " + sourceFullPath + ".")); } } } }
// Helper method to handle folder deletions private static void HandleFolderDelete(AutoSyncRequest request) { SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.SourceName, request.SourceParent, MetaChangeType.Delete, _metaUpdated)); foreach (string dest in request.DestinationFolders) { string destFullPath = Path.Combine(dest, request.SourceName); if (Directory.Exists(destFullPath)) { try { if (request.Config.ArchiveLimit > 0) { CommonMethods.ArchiveFolder(destFullPath, request.Config.ArchiveName, request.Config.ArchiveLimit); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "Folder archived " + destFullPath)); } } catch (ArchiveFolderException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving folder " + destFullPath)); } try { if (request.Config.Recycle) { CommonMethods.DeleteFolderToRecycleBin(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "Folder deleted to recycle bin " + destFullPath)); } else { CommonMethods.DeleteFolder(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "Folder deleted " + destFullPath)); } SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.SourceName, dest, MetaChangeType.Delete, _metaUpdated)); } catch (DeleteFolderException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting folder " + destFullPath)); } } } }
// Helper method to handle folder renames private static void HandleFolderRename(AutoSyncRequest request) { SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.OldName, request.NewName, request.SourceParent, MetaChangeType.Rename, _metaUpdated)); foreach (string dest in request.DestinationFolders) { string oldFullPath = string.Empty; string newFullPath = string.Empty; try { oldFullPath = Path.Combine(dest, request.OldName); newFullPath = Path.Combine(dest, request.NewName); if (!Directory.Exists(newFullPath)) { CommonMethods.MoveFolder(oldFullPath, newFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "Folder renamed from " + oldFullPath + " to " + newFullPath)); SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.OldName, request.NewName, dest, MetaChangeType.Rename, _metaUpdated)); } } catch (MoveFolderException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error renaming folder from " + oldFullPath + " to " + newFullPath)); } } }
// Helper method to handle folder creations private static void HandleFolderCreate(AutoSyncRequest request, string sourceFullPath) { // Update the xml for the source folder first SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.SourceName, request.SourceParent, Directory.GetCreationTimeUtc(sourceFullPath).Ticks, MetaChangeType.New, _metaUpdated)); foreach (string dest in request.DestinationFolders) { string destFullPath = Path.Combine(dest, request.SourceName); try { CommonMethods.CreateFolder(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "Folder created " + destFullPath)); SeamlessXMLHelper.UpdateXML(new XMLWriteFolderObject(request.SourceName, dest, Directory.GetCreationTimeUtc(destFullPath).Ticks, MetaChangeType.New, _metaUpdated)); } catch (CreateFolderException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error creating folder " + destFullPath)); } } }
private static void SyncFolder(AutoSyncRequest request) { string sourceFullPath = Path.Combine(request.SourceParent, request.ChangeType == AutoSyncRequestType.Rename ? request.NewName : request.SourceName); if (Directory.Exists(sourceFullPath)) { switch (request.ChangeType) { case AutoSyncRequestType.New: HandleFolderCreate(request, sourceFullPath); break; case AutoSyncRequestType.Rename: HandleFolderRename(request); break; } } else if (request.ChangeType == AutoSyncRequestType.Delete) { HandleFolderDelete(request); } }
// Handle file delete private static void HandleFileDelete(AutoSyncRequest request) { // Update the XML for the source of deletion SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, request.SourceParent, MetaChangeType.Delete, _metaUpdated)); foreach (string dest in request.DestinationFolders) { string destFullPath = Path.Combine(dest, request.SourceName); // If the file exists in the destination, then we proceed with the deletion if (File.Exists(destFullPath)) { try { if (request.Config.ArchiveLimit > 0) { CommonMethods.ArchiveFile(destFullPath, request.Config.ArchiveName, request.Config.ArchiveLimit); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "File archived " + destFullPath)); } } catch (ArchiveFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving file " + destFullPath)); } try { if (request.Config.Recycle) { CommonMethods.DeleteFileToRecycleBin(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted to recycle bin " + destFullPath)); } else { CommonMethods.DeleteFile(destFullPath); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted " + destFullPath)); } SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, dest, MetaChangeType.Delete, _metaUpdated)); } catch (DeleteFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting file " + destFullPath)); } } } }
// Helper method to handle file renames private static void HandleFileRename(AutoSyncRequest request, string sourceFullPath) { // Update the XML for the source first SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.OldName, request.NewName, request.SourceParent, MetaChangeType.Rename, _metaUpdated)); foreach (string dest in request.DestinationFolders) { //string destFullPath = Path.Combine(dest, request.SourceName); string oldFullPath = Path.Combine(dest, request.OldName); string newFullPath = Path.Combine(dest, request.NewName); try { // If the file with the old name in the destination directory does not exist if (!File.Exists(oldFullPath)) { CommonMethods.CopyFile(sourceFullPath, newFullPath); // Copy over the file FileInfo destFile = new FileInfo(newFullPath); SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.SourceName, dest, CommonMethods.CalculateMD5Hash(destFile), destFile.Length, destFile.CreationTimeUtc.Ticks, destFile.LastWriteTimeUtc.Ticks, MetaChangeType.New, _metaUpdated)); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_MODIFIED, "File copied from " + sourceFullPath + " to " + newFullPath)); } else { // If the file with the old name in the destination directory exists CommonMethods.MoveFile(oldFullPath, newFullPath); // Rename the file SeamlessXMLHelper.UpdateXML(new XMLWriteFileObject(request.OldName, request.NewName, dest, MetaChangeType.Rename, _metaUpdated)); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_MODIFIED, "File renamed from " + oldFullPath + " to " + newFullPath)); } } catch (CopyFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying file from " + sourceFullPath + " to " + newFullPath)); } catch (MoveFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error renaming file from " + oldFullPath + " to " + newFullPath)); } catch (HashFileException) { ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error hashing " + newFullPath + ".")); } } }