Beispiel #1
0
        //  Signal all the matching pipes.
        public void Match(byte[] data, int size, MtrieDelegate func, Object arg)
        {
            Mtrie current = this;

            int idx = 0;

            while (true)
            {
                //  Signal the pipes attached to this node.
                if (current.m_pipes != null)
                {
                    foreach (Pipe it in current.m_pipes)
                    {
                        func(it, null, arg);
                    }
                }

                //  If we are at the end of the message, there's nothing more to match.
                if (size == 0)
                {
                    break;
                }

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

                byte c = data[idx];
                //  If there's one subnode (optimisation).
                if (current.m_count == 1)
                {
                    if (c != current.m_min)
                    {
                        break;
                    }
                    current = current.m_next[0];
                    idx++;
                    size--;
                    continue;
                }

                //  If there are multiple subnodes.
                if (c < current.m_min || c >=
                    current.m_min + current.m_count)
                {
                    break;
                }
                if (current.m_next [c - current.m_min] == null)
                {
                    break;
                }
                current = current.m_next [c - current.m_min];
                idx++;
                size--;
            }
        }
Beispiel #2
0
        private bool RemoveHelper(byte[] pipe, byte[] buff, int buffsize, int maxbuffsize,
                                  MtrieDelegate func, Object arg)
        {
            //  Remove the subscription from this node.
            if (m_pipes != null && m_pipes.Remove(pipe) && m_pipes.Count == 0)
            {
                func(null, buff, arg);
                m_pipes = null;
            }

            //  Adjust the buffer.
            if (buffsize >= maxbuffsize)
            {
                maxbuffsize = buffsize + 256;
                Array.Resize(ref buff, maxbuffsize);
            }

            //  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)
            {
                buff[buffsize] = (byte)m_min;
                buffsize++;
                m_next[0].RemoveHelper(pipe, buff, buffsize, maxbuffsize,
                                       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_min + m_count - 1;
            //  New max non-null character in the node table after the removal
            int newMax = m_min;

            for (int c = 0; c != m_count; c++)
            {
                buff[buffsize] = (byte)(m_min + c);
                if (m_next[c] != null)
                {
                    m_next[c].RemoveHelper(pipe, buff, buffsize + 1,
                                           maxbuffsize, func, arg);

                    //  Prune redundant nodes from the mtrie
                    if (m_next[c].IsRedundant)
                    {
                        m_next[c] = 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 (c + m_min < newMin)
                        {
                            newMin = c + m_min;
                        }
                        if (c + m_min > newMax)
                        {
                            newMax = c + m_min;
                        }
                    }
                }
            }

            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_min && newMin < m_min + m_count);
                Mtrie node = m_next[newMin - m_min];
                Debug.Assert(node != null);
                m_next  = null;
                m_next  = new Mtrie[] { node };
                m_count = 1;
                m_min   = newMin;
            }
            else if (m_liveNodes > 1 && (newMin > m_min || newMax < m_min + m_count - 1))
            {
                Debug.Assert(newMax - newMin + 1 > 1);

                Mtrie[] old_table = m_next;
                Debug.Assert(newMin > m_min || newMax < m_min + m_count - 1);
                Debug.Assert(newMin >= m_min);
                Debug.Assert(newMax <= m_min + m_count - 1);
                Debug.Assert(newMax - newMin + 1 < m_count);
                m_count = newMax - newMin + 1;
                m_next  = new Mtrie[m_count];

                Array.Copy(old_table, (newMin - m_min), m_next, 0, m_count);

                m_min = newMin;
            }
            return(true);
        }
Beispiel #3
0
 //  Remove all subscriptions for a specific peer from the trie.
 //  If there are no subscriptions left on some topics, invoke the
 //  supplied callback function.
 public bool RemoveHelper(byte[] pipe, MtrieDelegate func, Object arg)
 {
     return(RemoveHelper(pipe, new byte[0], 0, 0, func, arg));
 }
Beispiel #4
0
        //  Signal all the matching pipes.
        public void Match(byte[] data, int size, MtrieDelegate func, Object arg)
        {
            Mtrie current = this;

            int idx = 0;

            while (true)
            {


                //  Signal the pipes attached to this node.
                if (current.m_pipes != null)
                {
                    foreach (byte[] it in current.m_pipes)
                        func(it, null, arg);
                }

                //  If we are at the end of the message, there's nothing more to match.
                if (size == 0)
                    break;

                //  If there are no subnodes in the trie, return.
                if (current.m_count == 0)
                    break;

                byte c = data[idx];
                //  If there's one subnode (optimisation).
                if (current.m_count == 1)
                {
                    if (c != current.m_min)
                        break;
                    current = current.m_next[0];
                    idx++;
                    size--;
                    continue;
                }

                //  If there are multiple subnodes.
                if (c < current.m_min || c >=
                    current.m_min + current.m_count)
                    break;
                if (current.m_next[c - current.m_min] == null)
                    break;
                current = current.m_next[c - current.m_min];
                idx++;
                size--;
            }
        }
Beispiel #5
0
        private bool RemoveHelper(byte[] pipe, byte[] buff, int buffsize, int maxbuffsize,
                               MtrieDelegate func, Object arg)
        {

            //  Remove the subscription from this node.
            if (m_pipes != null && m_pipes.Remove(pipe) && m_pipes.Count == 0)
            {
                func(null, buff, arg);
                m_pipes = null;
            }

            //  Adjust the buffer.
            if (buffsize >= maxbuffsize)
            {
                maxbuffsize = buffsize + 256;
                buff = Utils.Realloc(buff, maxbuffsize);
            }

            //  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)
            {
                buff[buffsize] = (byte)m_min;
                buffsize++;
                m_next[0].RemoveHelper(pipe, buff, buffsize, maxbuffsize,
                                   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_min + m_count - 1;
            //  New max non-null character in the node table after the removal
            int newMax = m_min;
            for (int c = 0; c != m_count; c++)
            {
                buff[buffsize] = (byte)(m_min + c);
                if (m_next[c] != null)
                {
                    m_next[c].RemoveHelper(pipe, buff, buffsize + 1,
                                       maxbuffsize, func, arg);

                    //  Prune redundant nodes from the mtrie
                    if (m_next[c].IsRedundant)
                    {
                        m_next[c] = 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 (c + m_min < newMin)
                            newMin = c + m_min;
                        if (c + m_min > newMax)
                            newMax = c + m_min;
                    }
                }
            }

            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_min && newMin < m_min + m_count);
                Mtrie node = m_next[newMin - m_min];
                Debug.Assert(node != null);
                m_next = null;
                m_next = new Mtrie[] { node };
                m_count = 1;
                m_min = newMin;
            }
            else if (m_liveNodes > 1 && (newMin > m_min || newMax < m_min + m_count - 1))
            {
                Debug.Assert(newMax - newMin + 1 > 1);

                Mtrie[] old_table = m_next;
                Debug.Assert(newMin > m_min || newMax < m_min + m_count - 1);
                Debug.Assert(newMin >= m_min);
                Debug.Assert(newMax <= m_min + m_count - 1);
                Debug.Assert(newMax - newMin + 1 < m_count);
                m_count = newMax - newMin + 1;
                m_next = new Mtrie[m_count];

                Array.Copy(old_table, (newMin - m_min), m_next, 0, m_count);

                m_min = newMin;
            }
            return true;
        }
Beispiel #6
0
 //  Remove all subscriptions for a specific peer from the trie.
 //  If there are no subscriptions left on some topics, invoke the
 //  supplied callback function.
 public bool RemoveHelper(byte[] pipe, MtrieDelegate func, Object arg)
 {
     return RemoveHelper(pipe, new byte[0], 0, 0, func, arg);
 }