Пример #1
0
        private void ConflictHandler(FileCompareObject fco, int fileIndex)
        {
            string src = Path.Combine(fco.GetSmartParentPath(fileIndex), fco.Name);
            string conflictFolder = Path.Combine(fco.GetSmartParentPath(fileIndex), _syncConfig.ConflictDir);
           
            if (!Directory.Exists(conflictFolder))
                Directory.CreateDirectory(conflictFolder);

            string currTime = String.Format("{0:MMddHHmmss}", DateTime.Now) + "_";
            string dest = Path.Combine(conflictFolder, currTime + fco.Name);

            try
            {
                CommonMethods.CopyFile(src, dest); // Copy conflicted file from to the conflict folder
                CommonMethods.DeleteFile(src); // Delete conflicted file
            }
            catch (CopyFileException)
            {
                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying file from " + src + " to " + dest));
            }
            catch (DeleteFileException)
            {
                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting file " + src));
            }
        }
Пример #2
0
 private void PopulateHash(FileCompareObject file, int index)
 {
     if (file.Exists[index])
     {
         // If the metadata exists, and the creation time of the file is equals to that of the metadata, and the last write time is also the same,
         // as well as the length, we assume that the file is unchanged, and simply use the hash info from the metadata instead of re-hashing. This
         // saves a lot of time.
         if (file.MetaExists[index] && file.CreationTimeUtc[index] == file.MetaCreationTimeUtc[index] && file.LastWriteTimeUtc[index] == file.MetaLastWriteTimeUtc[index] && file.Length[index] == file.MetaLength[index])
         {
             file.Hash[index] = file.MetaHash[index];
         }
         else
         {
             try
             {
                 // Calculate the hash of the file
                 file.Hash[index] = CommonMethods.CalculateMD5Hash(Path.Combine(file.GetSmartParentPath(index), file.Name));
             }
             catch (HashFileException)
             {
                 // If there is an error hashing, we set the FinalState to error, and make it invalid so it is excluded from all comparison and
                 // syncing.
                 ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error hashing " + Path.Combine(file.GetSmartParentPath(index), file.Name + ".")));
                 file.FinalState[index] = FinalState.Error;
                 file.Invalid = true;
             }
         }
     }
 }
Пример #3
0
        /// <summary>
        /// Visit implementaton for <see cref="FileCompareObject"/>.
        /// </summary>
        /// <param name="file">The <see cref="FileCompareObject"/> to process.</param>
        /// <param name="numOfPaths">The total number of folders to sync.</param>
        public void Visit(FileCompareObject file, int numOfPaths)
        {
            _nodesCount++;
            _syncProgress.Message = file.Name;
            if (file.Invalid)
            {
                _syncProgress.Fail();
                return;
            }

            int maxPriorityPos = file.SourcePosition; // Get the position of the source file.

            if (file.Priority[maxPriorityPos] > 0)
            {
                switch (file.ChangeType[maxPriorityPos])
                {
                    case MetaChangeType.Delete:
                        DeleteFile(file, numOfPaths, maxPriorityPos);
                        break;
                    case MetaChangeType.New:
                    case MetaChangeType.Update:
                    case MetaChangeType.NoChange:
                        CopyFile(file, numOfPaths, maxPriorityPos);
                        break;
                    case MetaChangeType.Rename:
                        MoveFile(file, numOfPaths, maxPriorityPos);
                        break;
                }
            }
            _syncProgress.Complete();
        }
Пример #4
0
        /// <summary>
        /// Visit implementation for <see cref="FileCompareObject"/>.
        /// </summary>
        /// <param name="file">The <see cref="FileCompareObject"/> to process.</param>
        /// <param name="numOfPaths"></param>
        public void Visit(FileCompareObject file, int numOfPaths)
        {
            if (file.ConflictPositions == null || file.ConflictPositions.Count == 0)
                return;

            foreach (int i in file.ConflictPositions)
                ConflictHandler(file, i);
        }
Пример #5
0
 /// <summary>
 /// Visit implementation for <see cref="FileCompareObject"/>.
 /// </summary>
 /// <param name="file">The <see cref="FileCompareObject"/> to process.</param>
 /// <param name="numOfPaths">The total number of folders to sync.</param>
 public void Visit(FileCompareObject file, int numOfPaths)
 {
     for (int i = 0; i < numOfPaths; i++)
     {
         PopulateHash(file, i);
         ProcessFileMetaData(file, i);
     }
 }
Пример #6
0
        /// <summary>
        /// Visit implementation for <see cref="FileCompareObject"/>.
        /// </summary>
        /// <param name="file">The <see cref="FileCompareObject"/> to process.</param>
        /// <param name="numOfPaths">The total number of folders to keep in sync.</param>
        public void Visit(FileCompareObject file, int numOfPaths)
        {
            if (file.Invalid)
                return;

            DetectFileRename(file, numOfPaths);
            CompareFiles(file, numOfPaths);
            _totalNodes++;
        }
Пример #7
0
        /// <summary>
        /// Visits each file node and return them and it will update the values either through the meta data
        /// or the last known state document
        /// </summary>
        /// <param name="file"></param>
        /// <param name="numOfPaths"></param>
        public void Visit(FileCompareObject file, int numOfPaths)
        {
            XmlDocument xmlDoc = new XmlDocument();

            for (int i = 0; i < numOfPaths; i++)
            {
                string path = Path.Combine(file.GetSmartParentPath(i), CommonXMLConstants.MetadataPath);

                if (!File.Exists(path))
                    continue;

                CommonMethods.LoadXML(ref xmlDoc, path);
                file = PopulateFileWithMetaData(xmlDoc, file, i);
            }
        }
Пример #8
0
        /// <summary>
        /// It calls ProcessMetaChangeType method and if either needLastKnownState or the method is true,
        /// it will call GenerateFileLastKnownState method to write a last known state document 
        /// </summary>
        /// <param name="file"></param>
        /// <param name="numOfPaths"></param>
        public void Visit(FileCompareObject file, int numOfPaths)
        {
            if (file.Invalid)
                return;

            bool needLastKnownState = false;

            for (int i = 0; i < numOfPaths; i++)
            {
                _progress.Message = Path.Combine(file.GetSmartParentPath(i), file.Name);
                needLastKnownState = ProcessMetaChangeType(file, i) || needLastKnownState;
            }

            if (needLastKnownState)
                GenerateFileLastKnownState(file, numOfPaths);

            _progress.Complete();
        }
Пример #9
0
        private void DeleteFile(FileCompareObject fco, int numOfPaths, int srcFilePos)
        {
            bool changed = false;

            // Loop through all the files under this node.
            for (int i = 0; i < numOfPaths; i++)
            {
                if (i != srcFilePos && fco.Priority[i] != fco.Priority[srcFilePos])
                {
                    string destFile = Path.Combine(fco.GetSmartParentPath(i), fco.Name);

                    try
                    {
                        if (_syncConfig.ArchiveLimit > 0)
                        {
                            CommonMethods.ArchiveFile(destFile, _syncConfig.ArchiveName, _syncConfig.ArchiveLimit);
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "File archived " + destFile));
                        }
                    }
                    catch (ArchiveFileException)
                    {
                        fco.FinalState[i] = FinalState.Error;
                        ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving file " + destFile));
                    }

                    try
                    {
                        if (_syncConfig.Recycle)
                            CommonMethods.DeleteFileToRecycleBin(destFile);
                        else
                            CommonMethods.DeleteFile(destFile);

                        fco.Exists[i] = false; // Update the state of the node after it has been deleted.
                        fco.FinalState[i] = FinalState.Deleted; //Set the FinalState to deleted.
                        changed = true; // Since at least one file has changed, set changed to true.

                        if (_syncConfig.Recycle)
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted to recycle bin " + destFile));
                        else
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted " + destFile));
                    }
                    catch (DeleteFileException)
                    {
                        fco.FinalState[i] = FinalState.Error;
                        ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting file " + destFile));
                    }
                }
                else // If the priority is equal, it will also mean that the file at position i has been deleted.
                {
                    fco.FinalState[i] = fco.MetaExists[i] ? FinalState.Deleted : FinalState.Unchanged; // If meta exists, set the change type to deleted. Otherwise set it as unchanged.
                    changed = true;
                }
            }
            fco.FinalState[srcFilePos] = changed ? FinalState.Deleted : FinalState.Unchanged; // If at least one file has been deleted (changed), set the finalstate of the source file to deleted. Otherwise set it as unchanged.
        }
Пример #10
0
        private void CopyFile(FileCompareObject fco, int numOfPaths, int srcFilePos)
        {
            string src = Path.Combine(fco.GetSmartParentPath(srcFilePos), fco.Name);

            // Loop through all the files under this node.
            for (int i = 0; i < numOfPaths; i++)
            {
                if (i != srcFilePos && fco.Parent.FinalState[i] != FinalState.Deleted)
                {
                    // Only process if the priority is not equal (implies lower priority actually).
                    if (fco.Priority[i] != fco.Priority[srcFilePos])
                    {
                        string destFile = Path.Combine(fco.GetSmartParentPath(i), fco.Name);
                        bool fileExists = fco.Exists[i];

                        try
                        {
                            if (fileExists)
                            {
                                if (_syncConfig.ArchiveLimit > 0)
                                {
                                    CommonMethods.ArchiveFile(destFile, _syncConfig.ArchiveName, _syncConfig.ArchiveLimit);
                                    ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "File archived " + destFile));
                                }
                                if (_syncConfig.Recycle)
                                {
                                    CommonMethods.DeleteFileToRecycleBin(destFile);
                                    ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "File deleted to recycle bin " + destFile));
                                }
                            }

                        }
                        catch (ArchiveFileException)
                        {
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving file " + destFile));
                        }
                        catch (DeleteFileException)
                        {
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error delete file to recycle bin " + destFile));
                        }

                        try
                        {
                            CommonMethods.CopyFile(src, destFile);

                            fco.CreationTimeUtc[i] = File.GetCreationTimeUtc(destFile).Ticks; // Creation time will be different since it's a new file, thus we get it from the actual file.
                            fco.LastWriteTimeUtc[i] = File.GetLastWriteTimeUtc(destFile).Ticks; // Last modified/write time may be different, thus we get it from the actual file.

                            // Duplicate source file information to the destination
                            fco.Exists[i] = true;
                            fco.FinalState[i] = fileExists ? FinalState.Updated : FinalState.Created;
                            fco.Hash[i] = fco.Hash[srcFilePos];
                            fco.Length[i] = fco.Length[srcFilePos];

                            if (fileExists)
                                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_MODIFIED, "File updated from " + src + " to " + destFile));
                            else
                                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "File copied from " + src + " to " + destFile));
                        }
                        catch (CopyFileException)
                        {
                            fco.FinalState[i] = FinalState.Error;

                            if (fileExists)
                                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error updating file from " + src + " to " + destFile));
                            else
                                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying file from " + src + " to " + destFile));
                        }
                    }
                    else
                    {
                        // Set FinalState to Unchanged if the hash in the metadata is the same as the actual file.
                        // Otherwise, it is possible that it is the exact same file as the source file, but was not saved to
                        // meta previously, thus we set the FinalState to created.
                        fco.FinalState[i] = (fco.MetaHash[i] == fco.Hash[i]) ? FinalState.Unchanged : FinalState.Created;
                    }
                }
            }
            // Set the FinalState to Unchanged if it already exists in metadata, and the hash in the metadata is the same as that of the actual file.
            // Otherwise set it to Created.
            fco.FinalState[srcFilePos] = (fco.MetaExists[srcFilePos] && fco.MetaHash[srcFilePos] == fco.Hash[srcFilePos]) ? FinalState.Unchanged : FinalState.Created;
        }
Пример #11
0
 // Do nothing for file
 public void Visit(FileCompareObject file, int numOfPaths)
 {
 }
Пример #12
0
        /// <summary>
        /// Processes and adds files to the tree.
        /// </summary>
        /// <param name="folder"><see cref="FolderCompareObject"/> to process and add files to.</param>
        /// <param name="numOfPaths">The total number of sync folders.</param>
        /// <param name="f">The <see cref="DirectoryInfo"/> to process and get files from.</param>
        /// <param name="index">The index indicating which sync folder it belongs to.</param>
        private void ProcessFiles(FolderCompareObject folder, int numOfPaths, DirectoryInfo f, int index)
        {
            try
            {
                FileInfo[] fileInfos = f.GetFiles();

                foreach (FileInfo info in fileInfos)
                {
                    if (_filterChain.ApplyFilter(_filter, info.FullName))
                    {
                        if (_progress != null)
                        {
                            _progress.Message = info.FullName;
                            _progress.Update();
                        }

                        BaseCompareObject o = folder.GetChild(info.Name); // Gets a child with the same name.
                        FileCompareObject fco = null;
                        bool conflict = false;

                        if (o == null) // If o is null, create a new file compare object
                            fco = new FileCompareObject(info.Name, numOfPaths, folder);
                        else
                        {
                            try
                            {
                                fco = (FileCompareObject)o; // Case o to a FileCompareObject is o is not null
                            }
                            catch (InvalidCastException)
                            // If invalid cast, it means there is a FolderCompareObject with the exact same name.
                            {
                                _typeConflicts.Add(info.FullName); // Add to to conflicts
                                conflict = true;
                                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(
                                    new LogData(LogEventType.FSCHANGE_CONFLICT,
                                                "Conflicted file detected " + info.FullName));
                            }
                        }

                        if (!conflict)
                        {
                            fco.CreationTimeUtc[index] = info.CreationTimeUtc.Ticks;
                            fco.LastWriteTimeUtc[index] = info.LastWriteTimeUtc.Ticks;
                            fco.Length[index] = info.Length;
                            fco.Exists[index] = true;

                            if (o == null)
                                folder.AddChild(fco); // Add the newly created FileCompareObject to this current folder
                        }
                    }
                }
            }
            catch (UnauthorizedAccessException e)
            {
                ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e);
                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.UNKNOWN, "Error retrieving contents of folder due to unauthorized access."));
            }
            catch (DirectoryNotFoundException e)
            {
                ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e);
                ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.UNKNOWN, "Error retrieving contents of folder due to directory not being found."));
            }
        }
Пример #13
0
        // Sets the parent of a file to dirty if necessary
        private static void SetFileParentDirty(FileCompareObject file, int numOfPaths)
        {
            int numExists = 0;
            int posExists = -1;
            SetFileSystemObjectDirty(file, numOfPaths, ref numExists, ref posExists);

            if (numExists == 1)
            {
                if (file.ChangeType[posExists] == MetaChangeType.New || file.ChangeType[posExists] == MetaChangeType.Update)
                    file.Parent.Dirty = true;
            }
        }
Пример #14
0
        // Loads the xml document , and populate the file's data from the meta data
        private void PopulateFromMetaData(FileCompareObject file, XmlNode node, int counter)
        {
            XmlNodeList childNodeList = node.ChildNodes;
            for (int i = 0; i < childNodeList.Count; i++)
            {
                XmlNode childNode = childNodeList[i];

                switch (childNode.Name)
                {
                    case CommonXMLConstants.NodeSize:
                        file.MetaLength[counter] = long.Parse(childNode.InnerText);
                        break;
                    case CommonXMLConstants.NodeHash:
                        file.MetaHash[counter] = childNode.InnerText;
                        break;
                    case CommonXMLConstants.NodeLastModifiedUtc:
                        file.MetaLastWriteTimeUtc[counter] = long.Parse(childNode.InnerText);
                        break;
                    case CommonXMLConstants.NodeLastCreatedUtc:
                        file.MetaCreationTimeUtc[counter] = long.Parse(childNode.InnerText);
                        break;
                    case CommonXMLConstants.NodeLastUpdatedUtc:
                        file.MetaUpdated[counter] = long.Parse(childNode.InnerText);
                        break;
                }
            }

            file.MetaExists[counter] = true;
        }
Пример #15
0
        //Populates the file from meta data. If it does not exist, try to look it up from the last known state
        //instead
        private FileCompareObject PopulateFileWithMetaData(XmlDocument xmlDoc, FileCompareObject file, int counter)
        {
            XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFile + "[name=" + CommonMethods.ParseXPathString(file.Name) + "]");
            if (node != null)
            {

                PopulateFromMetaData(file, node, counter);
            }
            else
            {
                PopulateFromLastKnownState(file, counter);
            }

            return file;
        }
Пример #16
0
        // For any XMLCompareObjects in the list , create them as a node and append them to the folder node
        private void AddFileToChild(List<XMLCompareObject> xmlFileList, FolderCompareObject folder, int counter, int length)
        {
            for (int i = 0; i < xmlFileList.Count; i++)
            {
                BaseCompareObject o = folder.GetChild(xmlFileList[i].Name);
                FileCompareObject fco;

                if (o == null)
                    fco = new FileCompareObject(xmlFileList[i].Name, length, folder);
                else
                    fco = (FileCompareObject)o;

                fco.MetaCreationTimeUtc[counter] = xmlFileList[i].CreatedTimeUtc;
                fco.MetaHash[counter] = xmlFileList[i].Hash;
                fco.MetaLastWriteTimeUtc[counter] = xmlFileList[i].LastModifiedTimeUtc;
                fco.MetaLength[counter] = xmlFileList[i].Size;
                fco.MetaUpdated[counter] = xmlFileList[i].LastUpdatedTimeUtc;
                fco.MetaExists[counter] = true;

                if (o == null)
                    folder.AddChild(fco);
            }
        }
Пример #17
0
        // Based on the file and counter , it will load the xml document and delete the file node
        private void DeleteFileObject(FileCompareObject file, int counter)
        {
            XmlDocument xmlDoc = new XmlDocument();
            string parentPath = file.GetSmartParentPath(counter);
            string xmlPath = Path.Combine(parentPath, CommonXMLConstants.MetadataPath);

            if (File.Exists(xmlPath))
            {
                CommonMethods.LoadXML(ref xmlDoc, xmlPath);
                XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFile + "[name=" + CommonMethods.ParseXPathString(file.Name) + "]");

                if (node == null)
                    return;

                node.ParentNode.RemoveChild(node);
                CommonMethods.SaveXML(ref xmlDoc, xmlPath);
            }
        }
Пример #18
0
        // Based on the file and counter , it will load the xml document and rename the file iin the meta data
        private void RenameFileObject(FileCompareObject file, int counter)
        {
            XmlDocument xmlDoc = new XmlDocument();
            string xmlPath = Path.Combine(file.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath);
            CommonMethods.CreateFileIfNotExist(file.GetSmartParentPath(counter));
            CommonMethods.LoadXML(ref xmlDoc, xmlPath);
            XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFile + "[name=" + CommonMethods.ParseXPathString(file.Name) + "]");

            if (node == null)
            {
                CreateFileObject(file, counter, true);
                return;
            }

            XmlNodeList childNodeList = node.ChildNodes;

            for (int i = 0; i < childNodeList.Count; i++)
            {
                XmlNode nodes = childNodeList[i];
                switch (nodes.Name)
                {
                    case CommonXMLConstants.NodeName:
                        nodes.InnerText = file.NewName;
                        break;
                    case CommonXMLConstants.NodeLastUpdatedUtc:
                        nodes.InnerText = _dateTime.ToString();
                        break;
                }
            }

            CommonMethods.SaveXML(ref xmlDoc, xmlPath);
        }
Пример #19
0
        // Based on the file and the counter , load the xml document and create a new file node
        private void CreateFileObject(FileCompareObject file, int counter, bool useNewName)
        {
            XmlDocument xmlDoc = new XmlDocument();
            string xmlPath = Path.Combine(file.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath);
            CommonMethods.CreateFileIfNotExist(file.GetSmartParentPath(counter));
            CommonMethods.LoadXML(ref xmlDoc, xmlPath);
            CommonMethods.DoFileCleanUp(xmlDoc, useNewName ? file.NewName : file.Name);

            XmlText hashText = xmlDoc.CreateTextNode(file.Hash[counter]);
            XmlText nameText = xmlDoc.CreateTextNode(useNewName ? file.NewName : file.Name);
            XmlText sizeText = xmlDoc.CreateTextNode(file.Length[counter].ToString());
            XmlText lastModifiedUtcText = xmlDoc.CreateTextNode(file.LastWriteTimeUtc[counter].ToString());
            XmlText lastCreatedUtcText = xmlDoc.CreateTextNode(file.CreationTimeUtc[counter].ToString());
            XmlText lastUpdatedUtcText = xmlDoc.CreateTextNode(_dateTime.ToString());

            XmlElement fileElement = xmlDoc.CreateElement(CommonXMLConstants.NodeFile);
            XmlElement hashElement = xmlDoc.CreateElement(CommonXMLConstants.NodeHash);
            XmlElement nameElement = xmlDoc.CreateElement(CommonXMLConstants.NodeName);
            XmlElement sizeElement = xmlDoc.CreateElement(CommonXMLConstants.NodeSize);
            XmlElement lastModifiedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastModifiedUtc);
            XmlElement lastCreatedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastCreatedUtc);
            XmlElement lastUpdatedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastUpdatedUtc);

            hashElement.AppendChild(hashText);
            nameElement.AppendChild(nameText);
            sizeElement.AppendChild(sizeText);
            lastModifiedElement.AppendChild(lastModifiedUtcText);
            lastCreatedElement.AppendChild(lastCreatedUtcText);
            lastUpdatedElement.AppendChild(lastUpdatedUtcText);

            fileElement.AppendChild(nameElement);
            fileElement.AppendChild(sizeElement);
            fileElement.AppendChild(hashElement);
            fileElement.AppendChild(lastModifiedElement);
            fileElement.AppendChild(lastCreatedElement);
            fileElement.AppendChild(lastUpdatedElement);

            XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr);

            if (node == null)
                return;

            node.AppendChild(fileElement);
            CommonMethods.SaveXML(ref xmlDoc, xmlPath);
            DeleteFileLastKnownState(file, counter);
        }
Пример #20
0
        // Checks the File's FinalState and process them accordingly
        private bool ProcessMetaChangeType(FileCompareObject file, int counter)
        {
            FinalState? changeType = file.FinalState[counter];
            bool needLastKnownState = false;

            switch (changeType)
            {
                case FinalState.Created:
                    CreateFileObject(file, counter, false);
                    break;
                case FinalState.Updated:
                    UpdateFileObject(file, counter);
                    break;
                case FinalState.Deleted:
                    DeleteFileObject(file, counter);
                    needLastKnownState = true;
                    break;
                case FinalState.Renamed:
                    RenameFileObject(file, counter);
                    needLastKnownState = true;
                    break;
                case FinalState.CreatedRenamed:
                    CreateFileObject(file, counter, true);
                    DeleteFileObject(file, counter);
                    needLastKnownState = true;
                    break;
            }

            return needLastKnownState;
        }
Пример #21
0
        /// <summary>
        /// For every FileCompareObject, check which path has the max priority and then decide
        /// what sync operation should be approriate for each FileCompareObject. Once the path of the max
        /// priority has been set, for every other path which is not the max priority, populate the datagrid
        /// with by adding a DataRow for each operation that needs to be done.
        /// </summary>
        /// <param name="fco">FileCompareObject to be visited</param>
        /// <param name="numOfPaths">Total number of paths present in the particular FileCompareObject</param>
        public void Visit(FileCompareObject fco, int numOfPaths)
        {
            if (fco.Invalid)
                return;

            // find max priortiy position
            int maxPriorityPos = fco.SourcePosition;

            if (fco.Priority[maxPriorityPos] > 0)
            {
                for (int i = 0; i < numOfPaths; i++)
                {
                    if (i != maxPriorityPos && fco.Priority[i] != fco.Priority[maxPriorityPos])
                    {
                        string operation = string.Empty, source = string.Empty, dest = string.Empty, tooltip = string.Empty;
                        DataRow row = SyncData.NewRow();

                        switch (fco.ChangeType[maxPriorityPos])
                        {
                            // if the MetaChangeType is of New, Update, Change
                            case MetaChangeType.New:
                            case MetaChangeType.Update:
                            case MetaChangeType.NoChange:
                                source = Path.Combine(fco.GetSmartParentPath(maxPriorityPos), fco.Name);
                                dest = Path.Combine(fco.GetSmartParentPath(i), fco.Name);
                                operation = fco.Exists[i] ? UpdateArrow : CopyArrow;
                                tooltip = fco.Exists[i] ? FileUpdateToolTip : FileCopyToolTip;
                                break;
                            // if the MetaChangeType is of Delete type
                            case MetaChangeType.Delete:
                                source = Path.Combine(fco.GetSmartParentPath(maxPriorityPos), fco.Name);
                                dest = Path.Combine(fco.GetSmartParentPath(i), fco.Name);
                                operation = DeleteArrow;
                                tooltip = FileDeleteToolTip;
                                break;
                            // if the MetaChangeType is of Rename type
                            case MetaChangeType.Rename:
                                string oldName = Path.Combine(fco.GetSmartParentPath(i), fco.Name);
                                source = File.Exists(oldName) ? oldName : Path.Combine(fco.GetSmartParentPath(maxPriorityPos), fco.NewName);
                                dest = Path.Combine(fco.GetSmartParentPath(i), fco.NewName);
                                operation = File.Exists(oldName) ? RenameArrow : CopyArrow;
                                tooltip = File.Exists(oldName) ? FileRenameToolTip : FileCopyToolTip;
                                break;
                        }
                        
                        // set all properties of the DataRow which has been decided by the switch case above

                        row[Source] = source;
                        row[Operation] = operation;
                        row[Dest] = dest;
                        row[Tooltip] = tooltip;
                        row[SourceIcon] = FileIcon;
                        row[DestIcon] = FileIcon;
                        
                        // Set Date/Time/Length of FCO.
                        DateTime sourceDateTime = new DateTime(fco.LastWriteTimeUtc[maxPriorityPos]);
                        row[SourceLastModifiedDate] = sourceDateTime.ToShortDateString();
                        row[SourceLastModifiedTime] = sourceDateTime.ToShortTimeString();
                        row[SourceSize] = fco.Length[maxPriorityPos];

                        // Check if a particular file path exists
                        if (fco.Exists[i])
                        {
                            DateTime destDateTime = new DateTime(fco.LastWriteTimeUtc[i]);
                            row[DestLastModifiedDate] = destDateTime.ToShortDateString();
                            row[DestLastModifiedTime] = destDateTime.ToShortTimeString();
                            row[DestSize] = fco.Length[i];
                        }
                        else
                        {
                            row[DestLastModifiedDate] = "-";
                            row[DestSize] = "-";
                        }

                        SyncData.Rows.Add(row);
                    }
                }

            }
        }
Пример #22
0
        private void MoveFile(FileCompareObject fco, int numOfPaths, int srcFilePos)
        {
            bool changed = false;

            for (int i = 0; i < numOfPaths; i++)
            {
                if (i != srcFilePos && fco.Priority[i] != fco.Priority[srcFilePos])
                {
                    string oldName = Path.Combine(fco.GetSmartParentPath(i), fco.Name);
                    string newName = Path.Combine(fco.GetSmartParentPath(i), fco.NewName);
                    string srcName = Path.Combine(fco.GetSmartParentPath(srcFilePos), fco.NewName);

                    try
                    {
                        if (File.Exists(oldName)) // If the old file exists, simply rename it.
                        {
                            CommonMethods.MoveFile(oldName, newName);
                            fco.FinalState[i] = FinalState.Renamed;
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_RENAMED, "File renamed from " + oldName + " to " + newName));
                        }
                        else // If the old file does not exists, copy the source file over instead.
                        {
                            CommonMethods.CopyFile(srcName, newName);
                            FileCompareObject srcFile = fco.Parent.GetChild(fco.NewName) as FileCompareObject;
                            fco.CreationTimeUtc[i] = File.GetCreationTimeUtc(newName).Ticks;
                            fco.LastWriteTimeUtc[i] = File.GetLastAccessTimeUtc(newName).Ticks;
                            fco.Exists[i] = true;
                            fco.Hash[i] = srcFile.Hash[srcFilePos];
                            fco.Length[i] = srcFile.Length[srcFilePos];
                            fco.FinalState[i] = FinalState.CreatedRenamed;
                            ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "File copied from " + srcName + " to " + newName));
                        }

                        changed = true; // Set changed to true since the change has propagated to at least one file
                    }
                    catch (MoveFileException)
                    {
                        fco.FinalState[i] = FinalState.Error;
                        ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error renaming file from " + oldName + " to " + newName));
                    }
                    catch (CopyFileException)
                    {
                        fco.FinalState[i] = FinalState.Error;
                        ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying file from " + srcName + " to " + newName));
                    }
                }
                else
                {
                    fco.FinalState[i] = FinalState.Renamed; // Set the FinalState to renamed if the file has the same priority, implying it has the same name as the new file name
                    changed = true;
                }
            }
            fco.FinalState[srcFilePos] = changed ? FinalState.Renamed : FinalState.Unchanged; // Set the FinalState to renamed if at least one file has changed. Otherwise, set it as unchanged.
        }
Пример #23
0
        // Helper method to handle file deletes.
        private static bool FileDeleteHelper(FileCompareObject file, int numOfPaths)
        {
            List<int> deleteIndexes = new List<int>(); // Used to store the indexes of deleted files
            bool stop = false;

            for (int i = 0; i < numOfPaths; i++)
            {
                if (stop)
                    break;

                if (file.ChangeType[i] == MetaChangeType.Delete)
                {
                    deleteIndexes.Add(i);

                    for (int j = 0; j < numOfPaths; j++)
                    {
                        if (file.Exists[j]) // If file exists in one of the indexes
                        {
                            if (file.MetaUpdated[j] > file.MetaUpdated[i]) // If the meta updated of j is more than i, void the delete
                            {
                                deleteIndexes.Clear(); // Clear all delete indexes
                                stop = true;
                                break;
                            }
                        }
                    }
                }
                else if (file.ChangeType[i] != MetaChangeType.NoChange && file.ChangeType[i] != null)
                {
                    deleteIndexes.Clear(); // Clear the delete indexes as long as there's a rename/update/new detected
                    break;
                }
            }

            if (deleteIndexes.Count > 0)
            {
                file.SourcePosition = deleteIndexes[0]; // Set the source position to the first delete index found (convenience)

                foreach (int i in deleteIndexes)
                    file.Priority[i] = 1; // Set all delete indexes to priority 1.

                return true; // Return true since delete operation will occur
            }
            return false; // Return false since delete operation will not occur
        }
Пример #24
0
        // Helper method to handle file creations and updates
        private static void FileCreateUpdateHelper(FileCompareObject file, int numOfPaths)
        {
            int mostUpdatedPos = 0;

            for (int i = 0; i < numOfPaths; i++)
            {
                if (file.Exists[i])
                {
                    mostUpdatedPos = i; // Set the most update position to the first file that exists
                    break;
                }
            }

            file.Priority[mostUpdatedPos] = 1; // Set the priority of the first file that exists to 1. All other indexes will be 0.

            for (int i = mostUpdatedPos + 1; i < numOfPaths; i++)
            {
                if (!file.Exists[i])
                {
                    file.Priority[i] = -1; // If file does not exists we set the priority to -1.
                    continue;
                }

                if (file.Length[mostUpdatedPos] != file.Length[i] || file.Hash[mostUpdatedPos] != file.Hash[i])
                {
                    // If last write time of i is more updated than that of the most updated position
                    if (file.LastWriteTimeUtc[i] > file.LastWriteTimeUtc[mostUpdatedPos])
                    {
                        file.Priority[i] = file.Priority[mostUpdatedPos] + 1; // Set the priority of i as the priority of most updated position + 1
                        mostUpdatedPos = i; // Set the most updated position to i
                    }
                    else if (file.LastWriteTimeUtc[i] == file.LastWriteTimeUtc[mostUpdatedPos]) // If the hash/length is not equal but the last modified time is, it is a conflict.
                    {
                        //Conflict
                        file.Priority[i] = file.Priority[mostUpdatedPos] - 1; // Decrement the priority of this conflicted file
                        file.ConflictPositions.Add(i); // Add this conflicted file to the list of conflict positions
                        ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CONFLICT, "Conflicted file detected " + Path.Combine(file.GetSmartParentPath(i), file.Name)));
                    }
                }
                else
                {
                    file.Priority[i] = file.Priority[mostUpdatedPos]; // If length and hash are equal, set the priority of i to the priority of most updated position
                }
            }

            file.SourcePosition = mostUpdatedPos; // Set the source position to the most updated position
        }
Пример #25
0
        // Populate the file's details from the last known state
        private void PopulateFromLastKnownState(FileCompareObject file, int counter)
        {
            string path = Path.Combine(file.GetSmartParentPath(counter), CommonXMLConstants.LastKnownStatePath);

            if (File.Exists(path))
            {
                XmlDocument lastKnownXMLDoc = new XmlDocument();
                CommonMethods.LoadXML(ref lastKnownXMLDoc, path);
                XmlNode fileNode = lastKnownXMLDoc.SelectSingleNode(CommonXMLConstants.XPathLastKnownState + CommonXMLConstants.XPathFile + "[name=" + CommonMethods.ParseXPathString(file.Name) + "]");

                if (fileNode != null)
                {
                    XmlNodeList nodeList = fileNode.ChildNodes;
                    for (int i = 0; i < nodeList.Count; i++)
                    {
                        XmlNode childNode = nodeList[i];
                        switch (childNode.Name)
                        {
                            case CommonXMLConstants.NodeAction:
                                string action = childNode.InnerText;
                                file.LastKnownState[counter] = action.Equals(CommonXMLConstants.ActionDeleted) ? LastKnownState.Deleted : LastKnownState.Renamed;
                                break;
                            case CommonXMLConstants.NodeLastModifiedUtc:
                                file.MetaLastWriteTimeUtc[counter] = long.Parse(childNode.InnerText);
                                break;
                            case CommonXMLConstants.NodeHash:
                                file.MetaHash[counter] = childNode.InnerText;
                                break;
                            case CommonXMLConstants.NodeLastUpdatedUtc:
                                file.MetaUpdated[counter] = long.Parse(childNode.InnerText);
                                break;
                        }
                    }
                }
            }
        }
Пример #26
0
        // Deletes a file node by searching for the name in the last known state file. 
        private void DeleteFileLastKnownState(FileCompareObject file, int counter)
        {
            string todoXMLPath = Path.Combine(file.GetSmartParentPath(counter), CommonXMLConstants.LastKnownStatePath);

            if (!File.Exists(todoXMLPath))
                return;

            XmlDocument todoXMLDoc = new XmlDocument();
            CommonMethods.LoadXML(ref todoXMLDoc, todoXMLPath);
            XmlNode fileNode = todoXMLDoc.SelectSingleNode(CommonXMLConstants.XPathLastKnownState + CommonXMLConstants.XPathFile + "[name=" + CommonMethods.ParseXPathString(file.Name) + "]");

            if (fileNode != null)
                fileNode.ParentNode.RemoveChild(fileNode);

            CommonMethods.SaveXML(ref todoXMLDoc, todoXMLPath);
        }
Пример #27
0
 // Checks if the last known state document exists and calls the AppendActionFileLastKnownState method
 private void GenerateFileLastKnownState(FileCompareObject file, int numOfPaths)
 {
     for (int i = 0; i < numOfPaths; i++)
     {
         string parentPath = file.GetSmartParentPath(i);
         XmlDocument xmlTodoDoc = new XmlDocument();
         string todoPath = Path.Combine(parentPath, CommonXMLConstants.LastKnownStatePath);
         CommonMethods.CreateLastKnownStateFile(parentPath);
         CommonMethods.LoadXML(ref xmlTodoDoc, todoPath);
         CommonMethods.DoFileLastKnownCleanUp(xmlTodoDoc,file.Name);
         AppendActionFileLastKnownState(xmlTodoDoc, file, i, CommonXMLConstants.ActionDeleted);
         CommonMethods.SaveXML(ref xmlTodoDoc, todoPath);
     }
 }
Пример #28
0
        /// <summary>
        /// Detects possible file renames and handles them accordingly.
        /// </summary>
        /// <param name="file">The <see cref="FileCompareObject"/> to process.</param>
        /// <param name="numOfPaths">The total number of folders to sync.</param>
        private static void DetectFileRename(FileCompareObject file, int numOfPaths)
        {
            FileCompareObject result = null;
            Dictionary<string, List<int>> newNames = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
            List<int> unchangedIndexes = new List<int>();

            for (int i = 0; i < numOfPaths; i++)
            {
                switch (file.ChangeType[i])
                {
                    case MetaChangeType.New:
                    case MetaChangeType.Update:
                        return; // Return as long as one of the meta change type is new or updated.
                }
            }

            for (int i = 0; i < numOfPaths; i++)
            {
                switch (file.ChangeType[i])
                {
                    case MetaChangeType.Delete:
                        // All deletes are also possible renames, thus we call GetIdenticalFile to look for an identical file with a different name, if any
                        FileCompareObject f = file.Parent.GetIdenticalFile(file.Name, file.MetaHash[i], file.MetaCreationTimeUtc[i], i);
                        
                        // If an identical file is found
                        if (f != null)
                        {
                            List<int> pos;
                            if (newNames.TryGetValue(f.Name, out pos))
                            {
                                pos.Add(i); // Add the position to the existing list of names
                            }
                            else
                            {
                                // Create a new list to add the position if the name does not currently exist
                                pos = new List<int>();
                                pos.Add(i);
                                newNames.Add(f.Name, pos);
                                result = f; // Point result to f
                            }
                        }
                        break;
                    case MetaChangeType.NoChange:
                        unchangedIndexes.Add(i);
                        break;
                }
            }

            if (newNames.Count == 1) // Meaning only one new/possible rename was detected, proceed with the rename.
            {
                file.NewName = result.Name; // Set the new name of this file to the name of the found file.

                foreach (int i in newNames[result.Name])
                    file.ChangeType[i] = MetaChangeType.Rename; // Set all the positions to change type rename.

                result.Invalid = true; // Set the found file to invalid, no need to process it.
                file.Parent.Dirty = true; // Set the current file's parent to dirty.
            }
            else if (newNames.Count > 1) // Meaning multiple renames are detected, void all the renames and treat each type as new.
            {
                foreach (int i in unchangedIndexes)
                    file.ChangeType[i] = MetaChangeType.New; // Set all the unchanged to new since they will be treated as new,
            }

        }
Пример #29
0
        // For each XMLCompareObjects in the list , create a node and append them to the root node
        private void AddFileToRoot(List<XMLCompareObject> xmlFileList, RootCompareObject root, int counter, int length)
        {
            if (xmlFileList.Count == 0)
                return;

            for (int i = 0; i < xmlFileList.Count; i++)
            {
                BaseCompareObject o = root.GetChild(xmlFileList[i].Name);
                FileCompareObject fco;

                if (o == null)
                    fco = new FileCompareObject(xmlFileList[i].Name, length, root);
                else
                    fco = (FileCompareObject)o;

                fco.MetaCreationTimeUtc[counter] = xmlFileList[i].CreatedTimeUtc;
                fco.MetaHash[counter] = xmlFileList[i].Hash;
                fco.MetaLastWriteTimeUtc[counter] = xmlFileList[i].LastModifiedTimeUtc;
                fco.MetaLength[counter] = xmlFileList[i].Size;
                fco.MetaUpdated[counter] = xmlFileList[i].LastUpdatedTimeUtc;
                fco.MetaExists[counter] = true;

                if (o == null)
                    root.AddChild(fco);
            }
        }
Пример #30
0
        // Creates a file node in the last known state file based on the values in FileCompareObject
        private void AppendActionFileLastKnownState(XmlDocument xmlDoc, FileCompareObject file, int counter, string changeType)
        {
            XmlText hashText = xmlDoc.CreateTextNode(file.MetaHash[counter]);
            XmlText actionText = xmlDoc.CreateTextNode(changeType);
            XmlText lastModifiedUtcText = xmlDoc.CreateTextNode(file.MetaLastWriteTimeUtc[counter].ToString());
            XmlText nameText = xmlDoc.CreateTextNode(file.Name);
            XmlText lastUpdatedUtcText = xmlDoc.CreateTextNode(_dateTime.ToString());

            XmlElement fileElement = xmlDoc.CreateElement(CommonXMLConstants.NodeFile);
            XmlElement nameElement = xmlDoc.CreateElement(CommonXMLConstants.NodeName);
            XmlElement hashElement = xmlDoc.CreateElement(CommonXMLConstants.NodeHash);
            XmlElement actionElement = xmlDoc.CreateElement(CommonXMLConstants.NodeAction);
            XmlElement lastModifiedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastModifiedUtc);
            XmlElement lastUpdatedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastUpdatedUtc);

            hashElement.AppendChild(hashText);
            actionElement.AppendChild(actionText);
            lastModifiedElement.AppendChild(lastModifiedUtcText);
            nameElement.AppendChild(nameText);
            lastUpdatedElement.AppendChild(lastUpdatedUtcText);

            fileElement.AppendChild(nameElement);
            fileElement.AppendChild(actionElement);
            fileElement.AppendChild(hashElement);
            fileElement.AppendChild(lastModifiedElement);
            fileElement.AppendChild(lastUpdatedElement);

            XmlNode rootNode = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathLastKnownState);
            if (rootNode == null)
                return;
            rootNode.AppendChild(fileElement);
        }