/// <summary>
        /// Called when a file or folder is created in the remote storage.
        /// </summary>
        /// <remarks>In this method we create a new file/folder in user file system.</remarks>
        private async void CreatedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                string userFileSystemPath       = Mapping.ReverseMapPath(remoteStoragePath);
                string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);

                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                // Here we also check that the folder content was loaded into user file system (the folder is not offline).
                if (Directory.Exists(userFileSystemParentPath) &&
                    !new DirectoryInfo(userFileSystemParentPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
                {
                    if (!FsPath.AvoidSync(remoteStoragePath))
                    {
                        FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);
                        await UserFileSystemItem.CreateAsync(userFileSystemParentPath, remoteStorageItem);

                        LogMessage("Created succesefully:", userFileSystemPath);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed:", remoteStoragePath, ex);
            }
        }
Example #2
0
        /// <summary>
        /// Recursively synchronizes all files and folders with the server.
        /// Synchronizes only folders already loaded into the user file system.
        /// </summary>
        /// <param name="userFileSystemFolderPath">Folder path in user file system.</param>
        private async Task SyncronizeFolderAsync(string userFileSystemFolderPath)
        {
            // In case of on-demand loading the user file system contains only a subset of the server files and folders.
            // Here we sync folder only if its content already loaded into user file system (folder is not offline).
            // The folder content is loaded inside IFolder.GetChildrenAsync() method.
            if (new DirectoryInfo(userFileSystemFolderPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
            {
                LogMessage("Folder offline, skipping:", userFileSystemFolderPath);
                return;
            }

            IEnumerable <string> userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemFolderPath, "*");

            LogMessage("Synchronizing:", userFileSystemFolderPath);

            string remoteStorageFolderPath = Mapping.MapPath(userFileSystemFolderPath);
            IEnumerable <FileSystemInfo> remoteStorageChildrenItems = new DirectoryInfo(remoteStorageFolderPath).EnumerateFileSystemInfos("*");

            // Delete files/folders in user file system.
            foreach (string userFileSystemPath in userFileSystemChildren)
            {
                try
                {
                    string         remoteStoragePath = Mapping.MapPath(userFileSystemPath);
                    FileSystemInfo remoteStorageItem = remoteStorageChildrenItems.FirstOrDefault(x => x.FullName.Equals(remoteStoragePath, StringComparison.InvariantCultureIgnoreCase));
                    if (remoteStorageItem == null)
                    {
                        LogMessage("Deleting item:", userFileSystemPath);
                        await new UserFileSystemItem(userFileSystemPath).DeleteAsync();
                        LogMessage("Deleted succesefully:", userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Delete failed:", userFileSystemPath, ex);
                }
            }

            // Create new files/folders in user file system.
            foreach (FileSystemInfo remoteStorageItem in remoteStorageChildrenItems)
            {
                try
                {
                    string userFileSystemPath = Mapping.ReverseMapPath(remoteStorageItem.FullName);
                    if (!FsPath.Exists(userFileSystemPath))
                    {
                        LogMessage("Creating new item:", userFileSystemPath);
                        await UserFileSystemItem.CreateAsync(userFileSystemFolderPath, remoteStorageItem);

                        LogMessage("Created succesefully:", userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Creation failed:", remoteStorageItem.FullName, ex);
                }
            }

            // Update files/folders in user file system and sync subfolders.
            userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemFolderPath, "*");
            foreach (string userFileSystemPath in userFileSystemChildren)
            {
                try
                {
                    string         remoteStoragePath = Mapping.MapPath(userFileSystemPath);
                    FileSystemInfo remoteStorageItem = remoteStorageChildrenItems.FirstOrDefault(x => x.FullName.Equals(remoteStoragePath, StringComparison.InvariantCultureIgnoreCase));

                    // The item was deleted or moved/renamed on the server, but it may still exists in the user file system.
                    // This is just to avoid extra exceptions in the log.
                    if (remoteStorageItem == null)
                    {
                        continue;
                    }

                    // Update existing files/folders info.
                    if (!await new UserFileSystemItem(userFileSystemPath).EqualsAsync(remoteStorageItem))
                    {
                        LogMessage("Item modified:", remoteStoragePath);
                        await new UserFileSystemItem(userFileSystemPath).UpdateAsync(remoteStorageItem);
                        LogMessage("Updated succesefully:", userFileSystemPath);
                    }

                    // Hydrate / dehydrate the file.
                    else
                    {
                        bool?hydrated = await new UserFileSystemItem(userFileSystemPath).UpdateHydrationAsync();
                        if (hydrated != null)
                        {
                            string hydrationDescrition = (bool)hydrated ? "Hydrated" : "Dehydrated";
                            LogMessage($"{hydrationDescrition} succesefully:", userFileSystemPath);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogError("Update failed:", userFileSystemPath, ex);
                }

                // Synchronize subfolders.
                try
                {
                    if (FsPath.IsFolder(userFileSystemPath))
                    {
                        await SyncronizeFolderAsync(userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Folder sync failed:", userFileSystemPath, ex);
                }
            }
        }