internal ChildrenContainer Clone()
        {
            ChildrenContainer container = new ChildrenContainer(KeyLength);

            container._children = new Dictionary <string[], Node>(_children, new NodeComparer(KeyLength));

            return(container);
        }
예제 #2
0
 public Node(string[] prefix, string pathToHere, int initialKeySize)
 {
     Prefix    = prefix;
     _children = new ChildrenContainer(initialKeySize);
     Path      = pathToHere + "/" + string.Join("/", Prefix);
     if (Path == "/")
     {
         Path = "";
     }
 }
예제 #3
0
        public void Compress()
        {
            bool canCompress = true;

            var children = System.Threading.Volatile.Read(ref _children);

            if (children.Count == 0)
            {
                return;
            }

            foreach (var kv in children)
            {
                if (kv.Value.Services.Count > 0)
                {
                    canCompress = false;
                    break;
                }
            }

            if (canCompress)
            {
                var newMerged = new ChildrenContainer(children.KeyLength + 1);
                foreach (var kv in children)
                {
                    foreach (var childkv in kv.Value.Children)
                    {
                        //This will prune out orphaned trees
                        if (childkv.Value.Services.Count > 0 || childkv.Value.Children.Count > 0)
                        {
                            var mergedKey = Enumerable.Concat(kv.Key, childkv.Key).ToArray();
                            var newNode   = childkv.Value.CloneWithNewPrefix(mergedKey, Path);
                            newMerged[newNode.Prefix] = newNode;
                        }
                    }
                }
                System.Threading.Volatile.Write(ref _children, newMerged);
                Compress();
            }
            else
            {
                foreach (var kv in children)
                {
                    kv.Value.Compress();
                }
            }
        }
예제 #4
0
        internal bool RemoveServiceFromRoute(string[] route, Service service)
        {
            ChildrenContainer container = System.Threading.Volatile.Read(ref _children);

            if (route.Length == 0)
            {
                return(Services.RemoveService(service));
            }

            Node child;

            if (container.TryGetValue(route, out child))
            {
                return(child.RemoveServiceFromRoute(route.Skip(container.KeyLength).ToArray(), service));
            }
            return(false);
        }
        public ChildrenContainer SplitContainer(int newKeyLength, string currentPath)
        {
            ChildrenContainer newContainer = new ChildrenContainer(newKeyLength);

            foreach (var kv in _children)
            {
                var  newPrefix     = kv.Key.Take(newKeyLength).ToArray();
                var  newTailPrefix = kv.Key.Skip(newKeyLength).ToArray();
                Node newHeadNode;
                if (!newContainer._children.TryGetValue(newPrefix, out newHeadNode))
                {
                    newHeadNode = new Node(newPrefix, currentPath, KeyLength - newKeyLength);
                    newContainer.Add(newPrefix, newHeadNode);
                }
                var oldNode = kv.Value.CloneWithNewPrefix(newTailPrefix, newHeadNode.Path);
                newHeadNode.Children.Add(newTailPrefix, oldNode);
            }

            return(newContainer);
        }
예제 #6
0
        public Service GetService(string[] route, out string matchedPath)
        {
            ChildrenContainer container = System.Threading.Volatile.Read(ref _children);

            if (route.Length == 0)
            {
                matchedPath = Path;
                return(Services.GetService());
            }

            Node child;

            if (container.TryGetValue(route, out child))
            {
                var returnService = child.GetService(route.Skip(container.KeyLength).ToArray(), out matchedPath);
                if (returnService != null)
                {
                    return(returnService);
                }
            }
            matchedPath = Path;
            return(Services.GetService());
        }