private void InternalRefreshFolderCacheContent(FileNode CFN) { var Result = ListRemoteServerFolderContent(CFN); RemoveRefreshTask(CFN); //Server parsing operation has been made. The filenode status is now parsed if (!Result.Success) { return; } lock (CacheLock) { CFN.IsParsed = true; CFN.LastRefresh = DateTime.Now; if (FileNodeCache == null) { return; //Handle the case when the thread is still performing while the class has been unloaded } String Filter = FileNode.IsRepositoryRootPath(CFN.RepositoryPath) ? "\\" : CFN.LocalPath + "\\"; //Refresh from server result foreach (var Node in Result.Content) { if (!FileNodeCache.ContainsKey(Node.Item2.LocalPath)) { this.AddFileNodeNoLock(Node.Item2); } else { //Refresh node with updated properties //TODO : Should more properties be updated ? var KnownCachedItem = FileNodeCache[Node.Item2.LocalPath]; if (!KnownCachedItem.HasUnflushedData) { KnownCachedItem.FileInfo = Node.Item2.FileInfo; } } } //Supprimer les entrées de FileNodeCache qui ne sont plus dans Result.Content foreach (var s in FileNodeCache.Where(x => x.Key != CFN.LocalPath && x.Key.StartsWith(Filter) && x.Key.LastIndexOf('\\').Equals(Filter.Length - 1)).ToList()) { if (Result.Content.FirstOrDefault(x => x.Item2.LocalPath.Equals(s.Value.LocalPath)) == null) { DeleteFileNode(s.Value); } } CFN.LastRefresh = DateTime.Now; } }
/// <summary> /// Return folder content in the form of a list fo FileNodes /// If the folder as not already been parsed, we parse it from the server /// If the folder has been parsed, we serve content from the cache and update the cache from the server in a background task. So that we have a refreshed view for next call /// </summary> public (bool Success, List <Tuple <String, FileNode> > Content, String ErrorMessage) GetFolderContent(FileNode CurrentFolder, String Marker) { List <FileNode> FileNodeToRefreshList = new List <FileNode>(); List <Tuple <String, FileNode> > ReturnList = null; if (_mode == CacheMode.Disabled) { var Result = ListRemoteServerFolderContent(CurrentFolder); if (!Result.Success) { return(Result); } else { return(true, Result.Content, null); } } lock (CacheLock) { if (!CurrentFolder.IsParsed) { var Result = ListRemoteServerFolderContent(CurrentFolder); if (!Result.Success) { return(Result); } CurrentFolder.IsParsed = true; CurrentFolder.LastRefresh = DateTime.Now; //Caching the folder content foreach (var Node in Result.Content) { this.AddFileNodeNoLock(Node.Item2); } //Handling . & .. if (!FileNode.IsRepositoryRootPath(CurrentFolder.RepositoryPath)) { //if this is not the root directory add the dot entries if (Marker == null) { Result.Content.Add(new Tuple <String, FileNode>(".", CurrentFolder)); } if (Marker == null || Marker == ".") { String ParentPath = FileNode.ConvertRepositoryPathToLocalPath(FileNode.GetRepositoryParentPath(CurrentFolder.RepositoryPath)); if (ParentPath != null) { if (FileNodeCache.ContainsKey(ParentPath)) { Result.Content.Add(new Tuple <String, FileNode>("..", FileNodeCache[ParentPath])); } } } } ReturnList = Result.Content; } else { String FolderNameForSearch = CurrentFolder.LocalPath; if (FolderNameForSearch != "\\") { FolderNameForSearch += "\\"; } ReturnList = new List <Tuple <String, FileNode> >(); ReturnList.Add(new Tuple <string, FileNode>(".", CurrentFolder)); //TODO : Add .. from cache ReturnList.AddRange(FileNodeCache.Where(x => x.Key != CurrentFolder.LocalPath && x.Key.StartsWith($"{FolderNameForSearch}") && x.Key.LastIndexOf('\\').Equals(FolderNameForSearch.Length - 1)).Select(x => new Tuple <String, FileNode>(x.Value.Name, x.Value))); if ((DateTime.Now - CurrentFolder.LastRefresh).TotalSeconds > CacheDurationInSeconds) { FileNodeToRefreshList.Add(CurrentFolder); //Refresh current directory if the cache is too old } } //Sort list by path (mandatory if we want to handle a potential marker correctly) ReturnList = ReturnList.OrderBy(x => x.Item1).ToList(); if (!String.IsNullOrEmpty(Marker)) //Dealing with potential marker { var WantedTuple = ReturnList.FirstOrDefault(x => x.Item1.Equals(Marker)); var WantedTupleIndex = ReturnList.IndexOf(WantedTuple); if (WantedTupleIndex + 1 < ReturnList.Count) { ReturnList = ReturnList.GetRange(WantedTupleIndex + 1, ReturnList.Count - 1 - WantedTupleIndex); } else { ReturnList.Clear(); } } if (this._PreLoadFoldersInCache) { foreach (var FolderNode in ReturnList.Where(x => (x.Item2.FileInfo.FileAttributes & (UInt32)System.IO.FileAttributes.Directory) != 0)) { if (FolderNode.Item1 == "." || FolderNode.Item1 == "..") { continue; //Bypass special folders } if (!FileNodeCache[FolderNode.Item2.LocalPath].IsParsed) { FileNodeToRefreshList.Add(FolderNode.Item2); //Pre-loading of sub-folders of current folder } } } } foreach (var FileNodeToRefresh in FileNodeToRefreshList) { AddRefreshTask(FileNodeToRefresh); } return(true, ReturnList, null); }
/// <summary> /// Retrieve a file or folder from the remote repository /// Return either a RepositoryElement or a FileSystem Error Message /// </summary> public WebDAVClient.Model.Item GetRepositoryElement(String LocalFileName) { String RepositoryDocumentName = FileNode.ConvertLocalPathToRepositoryPath(LocalFileName); WebDAVClient.Model.Item RepositoryElement = null; if (RepositoryDocumentName.Contains(".")) { //We assume the FileName refers to a file try { RepositoryElement = this.GetFile(RepositoryDocumentName).GetAwaiter().GetResult(); return(RepositoryElement); } catch (WebDAVException ex) when(ex.GetHttpCode() == 404) { return(null); } catch (WebDAVException ex) { throw ex; } catch (Exception ex) { throw ex; } } else { //We assume it's a folder try { RepositoryElement = this.GetFolder(RepositoryDocumentName).GetAwaiter().GetResult(); if (FileNode.IsRepositoryRootPath(RepositoryDocumentName)) { RepositoryElement.DisplayName = ""; } return(RepositoryElement); } catch (WebDAVException ex) when(ex.GetHttpCode() == 404) { //Try as a file try { RepositoryElement = this.GetFile(RepositoryDocumentName).GetAwaiter().GetResult(); return(RepositoryElement); } catch (WebDAVException ex1) when(ex1.GetHttpCode() == 404) { return(null); } catch (WebDAVException ex1) { throw ex1; } catch (Exception ex1) { throw ex1; } } catch (WebDAVException ex) { throw ex; } catch (Exception ex) { throw ex; } } }