Beispiel #1
0
        public override void Process(Command command)
        {
            var count   = 0;
            var options = this.LoadOptions <CommandOptions>((TextCommand)command);
            var dir     = this.Connection.FileSystemManager.ResolveDirectory(options.Uri);

            dir.Refresh();

            if (options.Regex != null)
            {
                options.Regex = TextConversion.FromEscapedHexString(options.Regex);
            }

            if (!dir.Exists)
            {
                throw new DirectoryNodeNotFoundException(dir.Address);
            }

            Connection.WriteOk();

            if (options.IncludeAttributes)
            {
                Exception       exception = null;
                InvocationQueue queue;

                if (t_InvocationQueue == null)
                {
                    t_InvocationQueue = new InvocationQueue();
                }

                queue = t_InvocationQueue;

                queue.TaskAsynchronisity = TaskAsynchronisity.AsyncWithSystemPoolThread;

                queue.Start();

                try
                {
                    IEnumerable <INode> children = null;

                    if (String.IsNullOrEmpty(options.Regex))
                    {
                        children = dir.GetChildren();
                    }
                    else
                    {
                        children = dir.GetChildren(RegexBasedNodePredicateHelper.New(options.Regex));
                    }

                    foreach (var node in children)
                    {
                        var enclosedNode = node;

                        if (queue.TaskState == TaskState.Stopped)
                        {
                            break;
                        }

                        queue.Enqueue
                        (
                            delegate
                        {
                            try
                            {
                                if (enclosedNode.NodeType == NodeType.Directory)
                                {
                                    Connection.WriteTextPartialBlock("d:");
                                }
                                else
                                {
                                    Connection.WriteTextPartialBlock("f:");
                                }

                                Connection.WriteTextBlock(TextConversion.ToEscapedHexString(enclosedNode.Name, TextConversion.IsStandardUrlEscapedChar));

                                AttributesCommands.PrintAttributes(this.Connection, enclosedNode);

                                count++;

                                if (count % 15 == 0)
                                {
                                    Connection.Flush();
                                }
                            }
                            catch (Exception e)
                            {
                                queue.Stop();

                                exception = e;
                            }
                        }
                        );
                    }

                    if (queue.TaskState == TaskState.Stopped)
                    {
                        throw exception;
                    }
                }
                finally
                {
                    queue.Enqueue(queue.Stop);

                    queue.WaitForAnyTaskState(value => value != TaskState.Running);

                    queue.Reset();

                    Connection.Flush();
                }
            }
            else
            {
                IEnumerable <string> children;

                if (string.IsNullOrEmpty(options.Regex))
                {
                    children = dir.GetChildNames(NodeType.Directory);
                }
                else
                {
                    children = dir.GetChildNames(NodeType.Directory, PredicateUtils.NewRegex(options.Regex));
                }

                foreach (var name in children)
                {
                    Connection.WriteTextPartialBlock("d:");
                    Connection.WriteTextBlock(TextConversion.ToEscapedHexString(name, TextConversion.IsStandardUrlEscapedChar));

                    count++;

                    if (count % 15 == 0)
                    {
                        Connection.Flush();
                    }
                }

                count = 0;

                if (string.IsNullOrEmpty(options.Regex))
                {
                    children = dir.GetChildNames(NodeType.File);
                }
                else
                {
                    children = dir.GetChildNames(NodeType.File, PredicateUtils.NewRegex(options.Regex));
                }

                foreach (var name in children)
                {
                    Connection.WriteTextPartialBlock("f:");
                    Connection.WriteTextBlock(TextConversion.ToEscapedHexString(name));

                    count++;

                    if (count % 15 == 0)
                    {
                        Connection.Flush();
                    }
                }
            }

            Connection.Flush();
        }
        public override IEnumerable <INode> DoGetChildren(NodeType nodeType, Predicate <INode> acceptNode)
        {
            var listedAllChildren = false;
            IDictionary <string, INode>      newChildren;
            Pair <DirectoryRefreshMask, int> refreshInfo;

            foreach (INode node in this.GetJumpPoints(nodeType, acceptNode))
            {
                yield return(node);
            }

            var shouldLoadFromNetwork = false;

            lock (this.SyncLock)
            {
                refreshInfo = this.directoryRefreshInfo;

                if ((refreshInfo.Left & DirectoryRefreshMask.Children) != 0)
                {
                    shouldLoadFromNetwork = true;
                }

                if (this.children == null)
                {
                    this.children = new SortedDictionary <string, INode>(StringComparer.CurrentCultureIgnoreCase);
                }
            }

            if (shouldLoadFromNetwork)
            {
                string regex          = null;
                var    skipAcceptNode = false;;
                var    toRemove       = new List <string>();

                var newAttributes = new Dictionary <string, object>(StringComparer.CurrentCultureIgnoreCase);

                if (NetworkDirectory.threadLocalNewChildren == null)
                {
                    NetworkDirectory.threadLocalNewChildren = new SortedDictionary <string, INode>(StringComparer.CurrentCultureIgnoreCase);
                }
                else
                {
                    NetworkDirectory.threadLocalNewChildren.Clear();
                }

                newChildren = NetworkDirectory.threadLocalNewChildren;

                try
                {
                    if (RegexBasedNodePredicateHelper.IsRegexBasedNodePredicate(acceptNode)
                        /* Only load based on REGEX if not refreshing AllChildren */
                        && refreshInfo.Left != DirectoryRefreshMask.AllChildren)
                    {
                        regex = RegexBasedNodePredicateHelper.GetRegexFromRegexBasedNodePredicate(acceptNode).ToString();

                        if (RegexBasedNodePredicateHelper.PredicateNameBasedOnly(acceptNode))
                        {
                            skipAcceptNode = true;
                        }
                    }

                    using (var freeClientContext = ((NetworkFileSystem)this.FileSystem).GetFreeClientContext())
                    {
                        var networkclient = freeClientContext.NetworkFileSystemClient;

                        IEnumerator <NetworkFileSystemEntry> enumerator;

                        var enumerable = networkclient.ListAttributes(this.Address.RemoteUri, regex);

                        using (enumerator = enumerable.GetEnumerator())
                        {
                            while (true)
                            {
                                try
                                {
                                    if (!enumerator.MoveNext())
                                    {
                                        break;
                                    }
                                }
                                catch (DirectoryNodeNotFoundException)
                                {
                                    lock (this.SyncLock)
                                    {
                                        foreach (var node in this.children.Values)
                                        {
                                            ((NetworkNodeAndFileAttributes)node.Attributes).Clear();
                                            ((NetworkNodeAndFileAttributes)node.Attributes).SetValue <bool>("exists", false);
                                        }

                                        this.children.Clear();
                                    }

                                    throw;
                                }

                                var entry = enumerator.Current;

                                INode child = null;

                                if (entry.NodeType == NodeType.Directory)
                                {
                                    child = this.ResolveDirectory(entry.Name);
                                }
                                else
                                {
                                    child = this.ResolveFile(entry.Name);
                                }

                                var attributes = (NetworkNodeAndFileAttributes)child.Attributes;

                                newAttributes.Clear();

                                foreach (var attribute in entry.ReadAttributes())
                                {
                                    newAttributes[attribute.Key] = attribute.Value;
                                }

                                try
                                {
                                    lock (attributes.SyncLock)
                                    {
                                        toRemove.Clear();

                                        foreach (var attribute in newAttributes)
                                        {
                                            attributes.SetValue <object>(attribute.Key, attribute.Value);
                                        }

                                        foreach (var name in attributes.Names)
                                        {
                                            if (!newAttributes.ContainsKey(name))
                                            {
                                                toRemove.Add(name);
                                            }
                                        }

                                        foreach (var name in toRemove)
                                        {
                                            attributes.SetValue <object>(name, null);
                                        }

                                        attributes.SetValue <bool>("exists", true);
                                    }

                                    newChildren.Add(child.Name, child);
                                }
                                catch (Exception)
                                {
                                    Debugger.Break();
                                }

                                if ((nodeType.Equals(NodeType.Any) || child.NodeType.Equals(nodeType)) &&
                                    (skipAcceptNode || acceptNode(child)))
                                {
                                    yield return(child);
                                }
                            }
                        }

                        if (regex == null)
                        {
                            listedAllChildren = true;
                        }
                    }
                }
                finally
                {
                    lock (this.SyncLock)
                    {
                        if (listedAllChildren)
                        {
                            toRemove.Clear();

                            foreach (var node in this.children.Values)
                            {
                                if (!newChildren.ContainsKey(node.Name))
                                {
                                    ((NetworkNodeAndFileAttributes)node.Attributes).Clear();
                                    ((NetworkNodeAndFileAttributes)node.Attributes).SetValue <bool>("exists", false);

                                    toRemove.Add(node.Name);
                                }
                            }

                            foreach (var name in toRemove)
                            {
                                this.children.Remove(name);
                            }

                            if (this.directoryRefreshInfo.Right == refreshInfo.Right)
                            {
                                this.directoryRefreshInfo.Left = DirectoryRefreshMask.None;
                            }
                        }

                        foreach (var node in newChildren.Values)
                        {
                            this.children[node.Name] = node;
                        }
                    }

                    toRemove.Clear();
                }

                yield break;
            }
            else
            {
                var retvals = new List <INode>();

                // Copy the children because we want to yield outside the lock

                lock (this.SyncLock)
                {
                    foreach (var pair in this.children)
                    {
                        if ((nodeType.Equals(NodeType.Any) || pair.Value.NodeType.Equals(nodeType)) && acceptNode(pair.Value))
                        {
                            retvals.Add(pair.Value);
                        }
                    }
                }

                foreach (var node in retvals)
                {
                    yield return(node);
                }
            }
        }