public void insert(int seqno1, int seqno2) { // Data to be inserted must be larger than all those in the list // guaranteed by the UDT receiver if (0 == m_iLength) { // insert data into an empty list m_iHead = 0; m_iTail = 0; m_piData1[m_iHead] = seqno1; if (seqno2 != seqno1) { m_piData2[m_iHead] = seqno2; } m_piNext[m_iHead] = -1; m_piPrior[m_iHead] = -1; m_iLength += SequenceNumber.seqlen(seqno1, seqno2); return; } // otherwise searching for the position where the node should be int offset = SequenceNumber.seqoff(m_piData1[m_iHead], seqno1); int loc = (m_iHead + offset) % m_iSize; if ((-1 != m_piData2[m_iTail]) && (SequenceNumber.incseq(m_piData2[m_iTail]) == seqno1)) { // coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7] loc = m_iTail; m_piData2[loc] = seqno2; } else { // create new node m_piData1[loc] = seqno1; if (seqno2 != seqno1) { m_piData2[loc] = seqno2; } m_piNext[m_iTail] = loc; m_piPrior[loc] = m_iTail; m_piNext[loc] = -1; m_iTail = loc; } m_iLength += SequenceNumber.seqlen(seqno1, seqno2); }
int insert_unsafe(int seqno1, int seqno2) { if (0 == m_iLength) { // insert data into an empty list m_iHead = 0; m_piData1[m_iHead] = seqno1; if (seqno2 != seqno1) { m_piData2[m_iHead] = seqno2; } m_piNext[m_iHead] = -1; m_iLastInsertPos = m_iHead; m_iLength += SequenceNumber.seqlen(seqno1, seqno2); return(m_iLength); } // otherwise find the position where the data can be inserted int origlen = m_iLength; int offset = SequenceNumber.seqoff(m_piData1[m_iHead], seqno1); int loc = (m_iHead + offset + m_iSize) % m_iSize; if (offset < 0) { // Insert data prior to the head pointer m_piData1[loc] = seqno1; if (seqno2 != seqno1) { m_piData2[loc] = seqno2; } // new node becomes head m_piNext[loc] = m_iHead; m_iHead = loc; m_iLastInsertPos = loc; m_iLength += SequenceNumber.seqlen(seqno1, seqno2); } else if (offset > 0) { if (seqno1 == m_piData1[loc]) { m_iLastInsertPos = loc; // first seqno is equivlent, compare the second if (-1 == m_piData2[loc]) { if (seqno2 != seqno1) { m_iLength += SequenceNumber.seqlen(seqno1, seqno2) - 1; m_piData2[loc] = seqno2; } } else if (SequenceNumber.seqcmp(seqno2, m_piData2[loc]) > 0) { // new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7] m_iLength += SequenceNumber.seqlen(m_piData2[loc], seqno2) - 1; m_piData2[loc] = seqno2; } else { // Do nothing if it is already there return(0); } } else { // searching the prior node int i; if ((-1 != m_iLastInsertPos) && (SequenceNumber.seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0)) { i = m_iLastInsertPos; } else { i = m_iHead; } while ((-1 != m_piNext[i]) && (SequenceNumber.seqcmp(m_piData1[m_piNext[i]], seqno1) < 0)) { i = m_piNext[i]; } if ((-1 == m_piData2[i]) || (SequenceNumber.seqcmp(m_piData2[i], seqno1) < 0)) { m_iLastInsertPos = loc; // no overlap, create new node m_piData1[loc] = seqno1; if (seqno2 != seqno1) { m_piData2[loc] = seqno2; } m_piNext[loc] = m_piNext[i]; m_piNext[i] = loc; m_iLength += SequenceNumber.seqlen(seqno1, seqno2); } else { m_iLastInsertPos = i; // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7] if (SequenceNumber.seqcmp(m_piData2[i], seqno2) < 0) { m_iLength += SequenceNumber.seqlen(m_piData2[i], seqno2) - 1; m_piData2[i] = seqno2; loc = i; } else { return(0); } } } } else { m_iLastInsertPos = m_iHead; // insert to head node if (seqno2 != seqno1) { if (-1 == m_piData2[loc]) { m_iLength += SequenceNumber.seqlen(seqno1, seqno2) - 1; m_piData2[loc] = seqno2; } else if (SequenceNumber.seqcmp(seqno2, m_piData2[loc]) > 0) { m_iLength += SequenceNumber.seqlen(m_piData2[loc], seqno2) - 1; m_piData2[loc] = seqno2; } else { return(0); } } else { return(0); } } // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9] while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc])) { int i = m_piNext[loc]; if (SequenceNumber.seqcmp(m_piData1[i], SequenceNumber.incseq(m_piData2[loc])) <= 0) { // coalesce if there is overlap if (-1 != m_piData2[i]) { if (SequenceNumber.seqcmp(m_piData2[i], m_piData2[loc]) > 0) { if (SequenceNumber.seqcmp(m_piData2[loc], m_piData1[i]) >= 0) { m_iLength -= SequenceNumber.seqlen(m_piData1[i], m_piData2[loc]); } m_piData2[loc] = m_piData2[i]; } else { m_iLength -= SequenceNumber.seqlen(m_piData1[i], m_piData2[i]); } } else { if (m_piData1[i] == SequenceNumber.incseq(m_piData2[loc])) { m_piData2[loc] = m_piData1[i]; } else { m_iLength--; } } m_piData1[i] = -1; m_piData2[i] = -1; m_piNext[loc] = m_piNext[i]; } else { break; } } return(m_iLength - origlen); }
void remove_unsafe(int seqno) { if (0 == m_iLength) { return; } // Remove all from the head pointer to a node with a larger seq. no. or the list is empty int offset = SequenceNumber.seqoff(m_piData1[m_iHead], seqno); int loc = (m_iHead + offset + m_iSize) % m_iSize; if (0 == offset) { // It is the head. Remove the head and point to the next node loc = (loc + 1) % m_iSize; if (-1 == m_piData2[m_iHead]) { loc = m_piNext[m_iHead]; } else { m_piData1[loc] = SequenceNumber.incseq(seqno); if (SequenceNumber.seqcmp(m_piData2[m_iHead], SequenceNumber.incseq(seqno)) > 0) { m_piData2[loc] = m_piData2[m_iHead]; } m_piData2[m_iHead] = -1; m_piNext[loc] = m_piNext[m_iHead]; } m_piData1[m_iHead] = -1; if (m_iLastInsertPos == m_iHead) { m_iLastInsertPos = -1; } m_iHead = loc; m_iLength--; } else if (offset > 0) { int h = m_iHead; if (seqno == m_piData1[loc]) { // target node is not empty, remove part/all of the seqno in the node. int temp = loc; loc = (loc + 1) % m_iSize; if (-1 == m_piData2[temp]) { m_iHead = m_piNext[temp]; } else { // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3) m_piData1[loc] = SequenceNumber.incseq(seqno); if (SequenceNumber.seqcmp(m_piData2[temp], m_piData1[loc]) > 0) { m_piData2[loc] = m_piData2[temp]; } m_iHead = loc; m_piNext[loc] = m_piNext[temp]; m_piNext[temp] = loc; m_piData2[temp] = -1; } } else { // target node is empty, check prior node int i = m_iHead; while ((-1 != m_piNext[i]) && (SequenceNumber.seqcmp(m_piData1[m_piNext[i]], seqno) < 0)) { i = m_piNext[i]; } loc = (loc + 1) % m_iSize; if (-1 == m_piData2[i]) { m_iHead = m_piNext[i]; } else if (SequenceNumber.seqcmp(m_piData2[i], seqno) > 0) { // remove part/all seqno in the prior node m_piData1[loc] = SequenceNumber.incseq(seqno); if (SequenceNumber.seqcmp(m_piData2[i], m_piData1[loc]) > 0) { m_piData2[loc] = m_piData2[i]; } m_piData2[i] = seqno; m_piNext[loc] = m_piNext[i]; m_piNext[i] = loc; m_iHead = loc; } else { m_iHead = m_piNext[i]; } } // Remove all nodes prior to the new head while (h != m_iHead) { if (m_piData2[h] != -1) { m_iLength -= SequenceNumber.seqlen(m_piData1[h], m_piData2[h]); m_piData2[h] = -1; } else { m_iLength--; } m_piData1[h] = -1; if (m_iLastInsertPos == h) { m_iLastInsertPos = -1; } h = m_piNext[h]; } } }