示例#1
0
文件: MultiTrie.cs 项目: hdxhan/netmq
        private bool AddHelper([CanBeNull] byte[] prefix, int start, int size, [NotNull] Pipe pipe)
        {
            // We are at the node corresponding to the prefix. We are done.
            if (size == 0)
            {
                bool result = m_pipes == null;

                if (m_pipes == null)
                    m_pipes = new HashSet<Pipe>();

                m_pipes.Add(pipe);
                return result;
            }

            Debug.Assert(prefix != null);

            byte currentCharacter = prefix[start];

            if (currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count)
            {
                // The character is out of range of currently handled
                // characters. We have to extend the table.
                if (m_count == 0)
                {
                    m_minCharacter = currentCharacter;
                    m_count = 1;
                    m_next = null;
                }
                else if (m_count == 1)
                {
                    int oldc = m_minCharacter;
                    MultiTrie oldp = m_next[0];
                    m_count = (m_minCharacter < currentCharacter ? currentCharacter - m_minCharacter : m_minCharacter - currentCharacter) + 1;
                    m_next = new MultiTrie[m_count];
                    m_minCharacter = Math.Min(m_minCharacter, currentCharacter);
                    m_next[oldc - m_minCharacter] = oldp;
                }
                else if (m_minCharacter < currentCharacter)
                {
                    // The new character is above the current character range.
                    m_count = currentCharacter - m_minCharacter + 1;
                    m_next = m_next.Resize(m_count, true);
                }
                else
                {
                    // The new character is below the current character range.
                    m_count = (m_minCharacter + m_count) - currentCharacter;
                    m_next = m_next.Resize(m_count, false);
                    m_minCharacter = currentCharacter;
                }
            }

            // If next node does not exist, create one.
            if (m_count == 1)
            {
                if (m_next == null)
                {
                    m_next = new MultiTrie[1];
                    m_next[0] = new MultiTrie();
                    ++m_liveNodes;
                }

                return m_next[0].AddHelper(prefix, start + 1, size - 1, pipe);
            }
            else
            {
                if (m_next[currentCharacter - m_minCharacter] == null)
                {
                    m_next[currentCharacter - m_minCharacter] = new MultiTrie();
                    ++m_liveNodes;
                }

                return m_next[currentCharacter - m_minCharacter].AddHelper(prefix, start + 1, size - 1, pipe);
            }
        }
示例#2
0
文件: XPub.cs 项目: b-cuts/netmq
        public XPub([NotNull] Ctx parent, int threadId, int socketId)
            : base(parent, threadId, socketId)
        {
            m_options.SocketType = ZmqSocketType.Xpub;

            m_welcomeMessage = new Msg();
            m_welcomeMessage.InitEmpty();

            m_subscriptions = new MultiTrie();
            m_distribution = new Distribution();
            m_pendingMessages = new Queue<KeyValuePair<Msg, Pipe>>();
        }
示例#3
0
        private bool AddHelper(byte[] prefix, int start, int size, Pipe pipe)
        {
            // We are at the node corresponding to the prefix. We are done.
            if (size == 0)
            {
                bool result = m_pipes == null;

                if (m_pipes == null)
                {
                    m_pipes = new HashSet <Pipe>();
                }

                m_pipes.Add(pipe);
                return(result);
            }

            Debug.Assert(prefix != null);

            byte currentCharacter = prefix[start];

            if (currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count)
            {
                // The character is out of range of currently handled
                // characters. We have to extend the table.
                if (m_count == 0)
                {
                    m_minCharacter = currentCharacter;
                    m_count        = 1;
                    m_next         = null;
                }
                else if (m_count == 1)
                {
                    int       oldc = m_minCharacter;
                    MultiTrie oldp = m_next[0];
                    m_count        = (m_minCharacter < currentCharacter ? currentCharacter - m_minCharacter : m_minCharacter - currentCharacter) + 1;
                    m_next         = new MultiTrie[m_count];
                    m_minCharacter = Math.Min(m_minCharacter, currentCharacter);
                    m_next[oldc - m_minCharacter] = oldp;
                }
                else if (m_minCharacter < currentCharacter)
                {
                    // The new character is above the current character range.
                    m_count = currentCharacter - m_minCharacter + 1;
                    m_next  = m_next.Resize(m_count, true);
                }
                else
                {
                    // The new character is below the current character range.
                    m_count        = (m_minCharacter + m_count) - currentCharacter;
                    m_next         = m_next.Resize(m_count, false);
                    m_minCharacter = currentCharacter;
                }
            }

            // If next node does not exist, create one.
            if (m_count == 1)
            {
                if (m_next == null)
                {
                    m_next    = new MultiTrie[1];
                    m_next[0] = new MultiTrie();
                    ++m_liveNodes;
                }

                return(m_next[0].AddHelper(prefix, start + 1, size - 1, pipe));
            }
            else
            {
                if (m_next[currentCharacter - m_minCharacter] == null)
                {
                    m_next[currentCharacter - m_minCharacter] = new MultiTrie();
                    ++m_liveNodes;
                }

                return(m_next[currentCharacter - m_minCharacter].AddHelper(prefix, start + 1, size - 1, pipe));
            }
        }
示例#4
0
        private bool RemoveHelper([NotNull] Pipe pipe, [NotNull] byte[] buffer, int bufferSize, int maxBufferSize, [NotNull] MultiTrieDelegate func, [CanBeNull] object arg)
        {
            // Remove the subscription from this node.
            if (m_pipes != null && m_pipes.Remove(pipe) && m_pipes.Count == 0)
            {
                func(pipe, buffer, bufferSize, arg);
                m_pipes = null;
            }

            // Adjust the buffer.
            if (bufferSize >= maxBufferSize)
            {
                maxBufferSize = bufferSize + 256;
                Array.Resize(ref buffer, maxBufferSize);
            }

            // If there are no subnodes in the trie, return.
            if (m_count == 0)
            {
                return(true);
            }

            // If there's one subnode (optimisation).
            if (m_count == 1)
            {
                buffer[bufferSize] = (byte)m_minCharacter;
                bufferSize++;
                m_next[0].RemoveHelper(pipe, buffer, bufferSize, maxBufferSize, func, arg);

                // Prune the node if it was made redundant by the removal
                if (m_next[0].IsRedundant)
                {
                    m_next  = null;
                    m_count = 0;
                    --m_liveNodes;
                    Debug.Assert(m_liveNodes == 0);
                }
                return(true);
            }

            // If there are multiple subnodes.

            // New min non-null character in the node table after the removal
            int newMin = m_minCharacter + m_count - 1;

            // New max non-null character in the node table after the removal
            int newMax = m_minCharacter;

            for (int currentCharacter = 0; currentCharacter != m_count; currentCharacter++)
            {
                buffer[bufferSize] = (byte)(m_minCharacter + currentCharacter);
                if (m_next[currentCharacter] != null)
                {
                    m_next[currentCharacter].RemoveHelper(pipe, buffer, bufferSize + 1,
                                                          maxBufferSize, func, arg);

                    // Prune redundant nodes from the mtrie
                    if (m_next[currentCharacter].IsRedundant)
                    {
                        m_next[currentCharacter] = null;

                        Debug.Assert(m_liveNodes > 0);
                        --m_liveNodes;
                    }
                    else
                    {
                        // The node is not redundant, so it's a candidate for being
                        // the new min/max node.
                        //
                        // We loop through the node array from left to right, so the
                        // first non-null, non-redundant node encountered is the new
                        // minimum index. Conversely, the last non-redundant, non-null
                        // node encountered is the new maximum index.
                        if (currentCharacter + m_minCharacter < newMin)
                        {
                            newMin = currentCharacter + m_minCharacter;
                        }

                        if (currentCharacter + m_minCharacter > newMax)
                        {
                            newMax = currentCharacter + m_minCharacter;
                        }
                    }
                }
            }

            Debug.Assert(m_count > 1);

            // Free the node table if it's no longer used.
            if (m_liveNodes == 0)
            {
                m_next  = null;
                m_count = 0;
            }
            // Compact the node table if possible
            else if (m_liveNodes == 1)
            {
                // If there's only one live node in the table we can
                // switch to using the more compact single-node
                // representation
                Debug.Assert(newMin == newMax);
                Debug.Assert(newMin >= m_minCharacter && newMin < m_minCharacter + m_count);

                MultiTrie node = m_next[newMin - m_minCharacter];

                Debug.Assert(node != null);

                m_next         = null;
                m_next         = new[] { node };
                m_count        = 1;
                m_minCharacter = newMin;
            }
            else if (m_liveNodes > 1 && (newMin > m_minCharacter || newMax < m_minCharacter + m_count - 1))
            {
                Debug.Assert(newMax - newMin + 1 > 1);

                MultiTrie[] oldTable = m_next;
                Debug.Assert(newMin > m_minCharacter || newMax < m_minCharacter + m_count - 1);
                Debug.Assert(newMin >= m_minCharacter);
                Debug.Assert(newMax <= m_minCharacter + m_count - 1);
                Debug.Assert(newMax - newMin + 1 < m_count);
                m_count = newMax - newMin + 1;
                m_next  = new MultiTrie[m_count];

                Array.Copy(oldTable, (newMin - m_minCharacter), m_next, 0, m_count);

                m_minCharacter = newMin;
            }
            return(true);
        }
示例#5
0
        private bool RemoveHelper(byte[] prefix, int start, int size, Pipe pipe)
        {
            if (size == 0)
            {
                if (m_pipes != null)
                {
                    bool erased = m_pipes.Remove(pipe);
                    Debug.Assert(erased);
                    if (m_pipes.Count == 0)
                    {
                        m_pipes = null;
                    }
                }
                return(m_pipes == null);
            }

            byte currentCharacter = prefix[start];

            if (m_count == 0 || currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count)
            {
                return(false);
            }

            MultiTrie nextNode = m_count == 1 ? m_next[0] : m_next[currentCharacter - m_minCharacter];

            if (nextNode == null)
            {
                return(false);
            }

            bool ret = nextNode.RemoveHelper(prefix, start + 1, size - 1, pipe);

            if (nextNode.IsRedundant)
            {
                Debug.Assert(m_count > 0);

                if (m_count == 1)
                {
                    m_next  = null;
                    m_count = 0;
                    --m_liveNodes;
                    Debug.Assert(m_liveNodes == 0);
                }
                else
                {
                    m_next[currentCharacter - m_minCharacter] = null;
                    Debug.Assert(m_liveNodes > 1);
                    --m_liveNodes;

                    // Compact the table if possible
                    if (m_liveNodes == 1)
                    {
                        // If there's only one live node in the table we can
                        // switch to using the more compact single-node
                        // representation
                        int i;
                        for (i = 0; i < m_count; ++i)
                        {
                            if (m_next[i] != null)
                            {
                                break;
                            }
                        }

                        Debug.Assert(i < m_count);
                        m_minCharacter += i;
                        m_count         = 1;
                        MultiTrie old = m_next[i];
                        m_next = new[] { old };
                    }
                    else if (currentCharacter == m_minCharacter)
                    {
                        // We can compact the table "from the left"
                        int i;
                        for (i = 1; i < m_count; ++i)
                        {
                            if (m_next[i] != null)
                            {
                                break;
                            }
                        }

                        Debug.Assert(i < m_count);
                        m_minCharacter += i;
                        m_count        -= i;
                        m_next          = m_next.Resize(m_count, false);
                    }
                    else if (currentCharacter == m_minCharacter + m_count - 1)
                    {
                        // We can compact the table "from the right"
                        int i;
                        for (i = 1; i < m_count; ++i)
                        {
                            if (m_next[m_count - 1 - i] != null)
                            {
                                break;
                            }
                        }
                        Debug.Assert(i < m_count);
                        m_count -= i;
                        m_next   = m_next.Resize(m_count, true);
                    }
                }
            }

            return(ret);
        }