예제 #1
0
        /// <remarks>
        /// Variables <code>head</code> and <code>tail</code> mark the start and
        /// end of the messages received, but not delivered yet. When a message is
        /// received, if its seqno is smaller than <code>head</code>, it is
        /// discarded (already received). If it is bigger than <code>tail</code>,
        /// we advance <code>tail</code> and add empty elements. If it is between
        /// <code>head</code> and <code>tail</code>, we set the corresponding
        /// missing (or already present) element. If it is equal to
        /// <code>tail</code>, we advance the latter by 1 and add the message
        /// (default case).
        /// </remarks>
        /// <summary>
        /// Adds a message according to its sequence number.
        /// </summary>
        /// <param name="seqno">Sequence number of the message.</param>
        /// <param name="msg">Message to add.</param>
        public void add(long seqno, Message msg)
        {
            Entry current = null;
            long  old_tail;

            rwlock.writeLock();
            try
            {
                old_tail = tail;
                if (seqno < head)
                {
                    if (Trace.trace)
                    {
                        Trace.info("NakReceiverWindow.add()", "seqno " + seqno +
                                   " is smaller than " + head + "); discarding message");
                    }
                    return;
                }

                // add at end (regular expected msg)
                if (seqno == tail)
                {
                    msgs.Add(new Entry(seqno, msg));
                    tail++;
                }
                // gap detected
                // i. add placeholders, creating gaps
                // ii. add real msg
                // iii. tell retransmitter to retrieve missing msgs
                else if (seqno > tail)
                {
                    for (long i = tail; i < seqno; i++)
                    {
                        msgs.Add(new Entry(i, null));
                        tail++;
                    }
                    msgs.Add(new Entry(seqno, msg));
                    tail = seqno + 1;
                    if (retransmitter != null)
                    {
                        retransmitter.add(old_tail, seqno - 1);
                    }
                    // finally received missing message
                }
                else if (seqno < tail)
                {
                    if (Trace.trace)
                    {
                        Trace.info("NakReceiverWindow.add()", "added missing msg " + msg.Source + "#" + seqno);
                    }

                    for (int i = 0; i < msgs.Count; i++)
                    {
                        current = (Entry)msgs[i];
                        // overwrite any previous message (e.g. added by down()) and
                        // remove seqno from retransmitter
                        if (seqno == current.seqno)
                        {
                            current.msg = msg;
                            if (retransmitter != null)
                            {
                                retransmitter.remove(seqno);
                            }
                            break;
                        }
                    }
                }
                _updateLowestSeen();
                _updateHighestSeen();
            }
            finally
            {
                rwlock.writeUnlock();
            }
        }