Ejemplo n.º 1
0
        /// <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);
        }