/// <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); } }
/// <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); } } }