#include <DisjointSequence.h>
Public Member Functions | |
DisjointSequence () | |
void | reset () |
bool | empty () const |
SequenceNumber | low () const |
SequenceNumber | high () const |
SequenceNumber | cumulative_ack () const |
SequenceNumber | last_ack () const |
bool | disjoint () const |
bool | contains (SequenceNumber value) const |
bool | insert (const SequenceRange &range, OPENDDS_VECTOR(SequenceRange)&added) |
bool | insert (const SequenceRange &range) |
Insert all numbers between range.first and range.second (both inclusive). | |
bool | insert (SequenceNumber value) |
Shorthand for "insert(SequenceRange(value, value))". | |
bool | insert (SequenceNumber value, CORBA::ULong num_bits, const CORBA::Long bits[]) |
bool | to_bitmap (CORBA::Long bitmap[], CORBA::ULong length, CORBA::ULong &num_bits, bool invert=false) const |
OPENDDS_VECTOR (SequenceRange) missing_sequence_ranges() const | |
Returns missing ranges of SequenceNumbers (internal gaps in the sequence). | |
OPENDDS_VECTOR (SequenceRange) present_sequence_ranges() const | |
void | dump () const |
Static Public Member Functions | |
static bool | fill_bitmap_range (CORBA::ULong low, CORBA::ULong high, CORBA::Long bitmap[], CORBA::ULong length, CORBA::ULong &num_bits) |
Set the bits in range [low, high] in the bitmap, updating num_bits. | |
Private Types | |
typedef bool(* | SRCompare )(const SequenceRange &, const SequenceRange &) |
Private Member Functions | |
typedef | OPENDDS_SET_CMP (SequenceRange, SRCompare) RangeSet |
bool | insert_i (const SequenceRange &range, OPENDDS_VECTOR(SequenceRange)*gaps=0) |
bool | insert_bitmap_range (RangeSet::iterator &iter, const SequenceRange &sr) |
Static Private Member Functions | |
static void | validate (const SequenceRange &range) |
static bool | SequenceRange_LessThan (const SequenceRange &lhs, const SequenceRange &rhs) |
Private Attributes | |
RangeSet | sequences_ |
Data structure for a set of SequenceNumbers. Sequence numbers can be inserted as single numbers, ranges, or RTPS-style bitmaps. The DisjointSequence can then be queried for contiguous ranges and internal gaps.
Definition at line 26 of file DisjointSequence.h.
typedef bool(* OpenDDS::DCPS::DisjointSequence::SRCompare)(const SequenceRange &, const SequenceRange &) [private] |
Definition at line 118 of file DisjointSequence.h.
ACE_INLINE OpenDDS::DCPS::DisjointSequence::DisjointSequence | ( | ) |
Definition at line 54 of file DisjointSequence.inl.
00055 : sequences_(SequenceRange_LessThan) 00056 { 00057 }
bool OpenDDS::DCPS::DisjointSequence::contains | ( | SequenceNumber | value | ) | const |
Definition at line 328 of file DisjointSequence.cpp.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::process_data_i().
00329 { 00330 RangeSet::const_iterator iter = 00331 sequences_.lower_bound(SequenceRange(0 /*ignored*/, value)); 00332 return iter != sequences_.end() && iter->first <= value; 00333 }
ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::cumulative_ack | ( | ) | const |
Gets the high end of the lowest contiguous range. Named after the use case of tracking received messages (which may be received out-of-order) and then determining the largest value that the receiver is allowed to acknowledge (under a cumulative-acking protocol). If empty(), returns SEQUENCENUMBER_UNKNOWN.
Definition at line 26 of file DisjointSequence.inl.
References OpenDDS::RTPS::SEQUENCENUMBER_UNKNOWN, and sequences_.
Referenced by OpenDDS::DCPS::WriteDataContainer::data_delivered(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::HeldDataDeliveryHandler::notify_delivery(), OpenDDS::DCPS::RtpsUdpDataLink::process_data_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::ReliableSession::send_naks(), OpenDDS::DCPS::WriteDataContainer::sequence_acknowledged(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().
00027 { 00028 return sequences_.empty() 00029 ? SequenceNumber::SEQUENCENUMBER_UNKNOWN() 00030 : sequences_.begin()->second; 00031 }
ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::disjoint | ( | ) | const |
Objects with the disjoint() property have an internal gap in the inserted SequenceNumbers.
Definition at line 48 of file DisjointSequence.inl.
References sequences_.
Referenced by OpenDDS::DCPS::WriterInfo::coherent_change_received(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::process_data_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::ReliableSession::send_naks(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().
00049 { 00050 return sequences_.size() > 1; 00051 }
void OpenDDS::DCPS::DisjointSequence::dump | ( | void | ) | const |
Definition at line 345 of file DisjointSequence.cpp.
References LM_DEBUG, and sequences_.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::RtpsUdpDataLink::send_directed_nack_replies(), OpenDDS::DCPS::RtpsUdpDataLink::send_nack_replies(), and OpenDDS::DCPS::ReliableSession::send_naks().
00346 { 00347 ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump included ranges of " 00348 "SequenceNumbers:\n", this)); 00349 for (RangeSet::const_iterator iter = sequences_.begin(); 00350 iter != sequences_.end(); ++iter) { 00351 ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump\t%q-%q\n", 00352 this, iter->first.getValue(), iter->second.getValue())); 00353 } 00354 }
ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::empty | ( | void | ) | const |
Definition at line 42 of file DisjointSequence.inl.
References sequences_.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::deliver_held_data(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::nack_durable(), OpenDDS::DCPS::RtpsUdpDataLink::process_data_i(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::SingleSendBuffer::resend_fragments_i(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::RtpsUdpDataLink::send_directed_nack_replies(), OpenDDS::DCPS::RtpsUdpDataLink::send_nack_replies(), and OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack().
00043 { 00044 return sequences_.empty(); 00045 }
bool OpenDDS::DCPS::DisjointSequence::fill_bitmap_range | ( | CORBA::ULong | low, | |
CORBA::ULong | high, | |||
CORBA::Long | bitmap[], | |||
CORBA::ULong | length, | |||
CORBA::ULong & | num_bits | |||
) | [static] |
Set the bits in range [low, high] in the bitmap, updating num_bits.
Definition at line 234 of file DisjointSequence.cpp.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::extend_bitmap_range(), OpenDDS::DCPS::TransportReassembly::get_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), and to_bitmap().
00237 { 00238 bool clamped = false; 00239 CORBA::ULong idx_low = low / 32, bit_low = low % 32, 00240 idx_high = high / 32, bit_high = high % 32; 00241 00242 if (idx_low >= length) { 00243 return false; 00244 } 00245 if (idx_high >= length) { 00246 // clamp to largest number we can represent 00247 high = length * 32 - 1; 00248 idx_high = length - 1; 00249 bit_high = high % 32; 00250 clamped = true; 00251 } 00252 00253 // clear any full Longs between the last bit we wrote and idx_low 00254 for (CORBA::ULong i = (num_bits + 31) / 32; i < idx_low; ++i) { 00255 bitmap[i] = 0; 00256 } 00257 00258 // write the Long at idx_low, preserving bits that may already be there 00259 CORBA::ULong x = bitmap[idx_low]; // use unsigned for bitwise operators 00260 // clear the bits in x in the range [bit_last, bit_low) 00261 if (num_bits > 0) { 00262 const size_t bit_last = ((num_bits - 1) / 32 == idx_low) 00263 ? ((num_bits - 1) % 32 + 1) : 0; 00264 for (size_t m = bit_last; m < bit_low; ++m) { 00265 x &= ~(1 << (31 - m)); 00266 } 00267 } else { 00268 x = 0; 00269 } 00270 // set the bits in x in the range [bit_low, limit) 00271 const size_t limit = (idx_high == idx_low) ? bit_high : 31; 00272 for (size_t b = bit_low; b <= limit; ++b) { 00273 x |= (1 << (31 - b)); 00274 } 00275 bitmap[idx_low] = x; 00276 00277 // any full Longs inside the current range are set to all 1's 00278 for (CORBA::ULong elt = idx_low + 1; elt < idx_high; ++elt) { 00279 bitmap[elt] = 0xFFFFFFFF; 00280 } 00281 00282 if (idx_high > idx_low) { 00283 // write the Long at idx_high, no need to preserve bits since this is 00284 // the first iteration that's writing it 00285 x = 0; 00286 for (size_t b = 0; b <= bit_high; ++b) { 00287 x |= (1 << (31 - b)); 00288 } 00289 bitmap[idx_high] = x; 00290 } 00291 00292 num_bits = high + 1; 00293 return !clamped; 00294 }
ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::high | ( | ) | const |
Highest SequenceNumber in the set. Precondition: !empty()
Definition at line 20 of file DisjointSequence.inl.
References sequences_.
Referenced by OpenDDS::DCPS::WriterInfo::coherent_change_received(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), insert_bitmap_range(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().
00021 { 00022 return sequences_.rbegin()->second; 00023 }
bool OpenDDS::DCPS::DisjointSequence::insert | ( | SequenceNumber | value, | |
CORBA::ULong | num_bits, | |||
const CORBA::Long | bits[] | |||
) |
Insert using the RTPS compact representation of a set. The three parameters, taken together, describe a set with each 1 bit starting at the msb of bits[0] and extending through num_bits (which are located at the next least significant bits of bits[0] followed by the msb of bits[1], etc.) indicating presence of the number (value + bit_index) in the set. bit_index is 0-based. Precondition: the array 'bits' has at least ceil(num_bits / 32) entries.
Definition at line 89 of file DisjointSequence.cpp.
References OpenDDS::DCPS::SequenceNumber::getValue(), insert_bitmap_range(), and sequences_.
00091 { 00092 bool inserted = false; 00093 RangeSet::iterator iter = sequences_.end(); 00094 SequenceNumber::Value range_start = 0; 00095 const SequenceNumber::Value val = value.getValue(); 00096 00097 // See RTPS v2.1 section 9.4.2.6 SequenceNumberSet 00098 for (CORBA::ULong i = 0, x = 0, bit = 0; i < num_bits; ++i, ++bit) { 00099 00100 if (bit == 32) bit = 0; 00101 00102 if (bit == 0) { 00103 x = static_cast<CORBA::ULong>(bits[i / 32]); 00104 if (x == 0) { 00105 // skip an entire Long if it's all 0's (adds 32 due to ++i) 00106 i += 31; 00107 bit = 31; 00108 //FUTURE: this could be generalized with something like the x86 "bsr" 00109 // instruction using compiler intrinsics, VC++ _BitScanReverse() 00110 // and GCC __builtin_clz() 00111 continue; 00112 } 00113 } 00114 00115 if (x & (1 << (31 - bit))) { 00116 if (range_start == 0) { 00117 range_start = val + i; 00118 } 00119 00120 } else if (range_start != 0) { 00121 // this is a "0" bit and we've previously seen a "1": insert a range 00122 const SequenceNumber::Value to_insert = val + i - 1; 00123 if (insert_bitmap_range(iter, SequenceRange(range_start, to_insert))) { 00124 inserted = true; 00125 } 00126 range_start = 0; 00127 00128 if (iter != sequences_.end() && iter->second.getValue() != to_insert) { 00129 // skip ahead: next gap in sequence must be past iter->second 00130 CORBA::ULong next_i = CORBA::ULong(iter->second.getValue() - val); 00131 bit = next_i % 32; 00132 if (next_i / 32 != i / 32) { 00133 x = static_cast<CORBA::ULong>(bits[next_i / 32]); 00134 } 00135 i = next_i; 00136 } 00137 } 00138 } 00139 00140 if (range_start != 0) { 00141 // iteration finished before we saw a "0" (inside a range) 00142 SequenceNumber range_end = (value + num_bits).previous(); 00143 if (insert_bitmap_range(iter, SequenceRange(range_start, range_end))) { 00144 return true; 00145 } 00146 } 00147 return inserted; 00148 }
ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert | ( | SequenceNumber | value | ) |
Shorthand for "insert(SequenceRange(value, value))".
Definition at line 66 of file DisjointSequence.inl.
References insert_i().
00067 { 00068 return insert_i(SequenceRange(value, value)); 00069 }
ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert | ( | const SequenceRange & | range | ) |
Insert all numbers between range.first and range.second (both inclusive).
Definition at line 72 of file DisjointSequence.inl.
References insert_i().
00073 { 00074 return insert_i(range); 00075 }
ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert | ( | const SequenceRange & | range, | |
OPENDDS_VECTOR(SequenceRange)& | added | |||
) |
All insert() methods return true upon modifying the set and false if the set already contained the SequenceNumber(s) that were to be inserted. This is the general form of insert() whereby the caller receives a list of sub-ranges of 'range' that were not already in the DisjointSequence. For example, given a DisjointSequence 'seq' containing (1, 2, 5, 9), calling seq.insert(SequenceRange(4, 12), v) returns true and yields v = [(4, 4), (6, 8), (10, 12)] and seq = (1, 2, 4, ..., 12).
Definition at line 78 of file DisjointSequence.inl.
References insert_i().
Referenced by OpenDDS::DCPS::ReliableSession::check_header(), OpenDDS::DCPS::WriteDataContainer::data_delivered(), OpenDDS::DCPS::ReliableSession::expire_naks(), OpenDDS::DCPS::ReliableSession::nakack_received(), OpenDDS::DCPS::RtpsUdpDataLink::process_data_i(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::RtpsUdpDataLink::process_requested_changes(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::ReliableSession::record_header_received(), OpenDDS::DCPS::SingleSendBuffer::resend_i(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::RtpsUdpDataLink::send_nackfrag_replies(), OpenDDS::DCPS::ReliableSession::send_naks(), and OpenDDS::DCPS::ReliableSession::syn_hook().
00080 { 00081 return insert_i(range, &gaps); 00082 }
bool OpenDDS::DCPS::DisjointSequence::insert_bitmap_range | ( | RangeSet::iterator & | iter, | |
const SequenceRange & | sr | |||
) | [private] |
Definition at line 151 of file DisjointSequence.cpp.
References high(), low(), and sequences_.
Referenced by insert().
00153 { 00154 // This is similar to insert_i(), except it doesn't need an O(log(n)) search 00155 // of sequences_ every time to find the starting point, and it doesn't 00156 // compute the 'gaps'. 00157 00158 const SequenceNumber::Value previous = range.first.getValue() - 1, 00159 next = range.second.getValue() + 1; 00160 00161 if (!sequences_.empty()) { 00162 if (iter == sequences_.end()) { 00163 iter = sequences_.lower_bound(SequenceRange(1 /*ignored*/, previous)); 00164 } else { 00165 // start where we left off last time and get the lower_bound(previous) 00166 for (; iter != sequences_.end() && iter->second < previous; ++iter) ; 00167 } 00168 } 00169 00170 if (iter == sequences_.end() || iter->first > next) { 00171 // can't combine on either side, insert a new range 00172 iter = sequences_.insert(iter, range); 00173 return true; 00174 } 00175 00176 if (iter->first <= range.first && iter->second >= range.second) { 00177 // range is already covered by this DisjointSet 00178 return false; 00179 } 00180 00181 // find the right-most (highest) range we can use 00182 RangeSet::iterator right = iter; 00183 for (; right != sequences_.end() && right->second < next; ++right) ; 00184 00185 SequenceNumber high = range.second; 00186 if (right != sequences_.end() 00187 && right->first <= next && right->first > range.first) { 00188 high = right->second; 00189 ++right; 00190 } 00191 00192 const SequenceNumber low = std::min(iter->first, range.first); 00193 sequences_.erase(iter, right); 00194 00195 iter = sequences_.insert(SequenceRange(low, high)).first; 00196 return true; 00197 }
bool OpenDDS::DCPS::DisjointSequence::insert_i | ( | const SequenceRange & | range, | |
OPENDDS_VECTOR(SequenceRange)* | gaps = 0 | |||
) | [private] |
Definition at line 28 of file DisjointSequence.cpp.
References sequences_, validate(), and OpenDDS::DCPS::SequenceNumber::ZERO().
Referenced by insert().
00030 { 00031 validate(range); 00032 00033 RangeSet::iterator range_above = sequences_.lower_bound(range); 00034 if (range_above != sequences_.end() 00035 && range_above->first <= range.first) { 00036 return false; // already have this range, nothing to insert 00037 } 00038 00039 SequenceRange newRange = range; 00040 if (range_above != sequences_.end() 00041 && ++SequenceNumber(newRange.second) >= range_above->first) { 00042 // newRange overlaps range_above, replace range_above with modified newRange 00043 newRange.second = range_above->second; 00044 // move to just past this iterator for the erase 00045 ++range_above; 00046 } 00047 00048 const SequenceNumber::Value previous = range.first.getValue() - 1; 00049 // find the lower_bound for the SequenceNumber just before this range 00050 // to see if any ranges need to combine 00051 const RangeSet::iterator range_below = 00052 sequences_.lower_bound(SequenceRange(1 /*ignored*/, 00053 (previous > 0) ? previous 00054 : SequenceNumber::ZERO())); 00055 if (range_below != sequences_.end()) { 00056 // if low end falls inside of the range_below range 00057 // then combine 00058 if (newRange.first > range_below->first) { 00059 newRange.first = range_below->first; 00060 } 00061 00062 if (gaps) { 00063 RangeSet::iterator gap_iter = range_below; 00064 if (range.first < gap_iter->second) { 00065 gaps->push_back(SequenceRange(range.first, 00066 gap_iter->second.previous())); 00067 } 00068 SequenceNumber last_gap = gap_iter++->second; 00069 for (; gap_iter != range_above; ++gap_iter) { 00070 const SequenceNumber in_range = 00071 std::min(gap_iter->first.previous().getValue(), 00072 range.second.getValue()); 00073 gaps->push_back(SequenceRange(++last_gap, in_range)); 00074 last_gap = gap_iter->second; 00075 } 00076 if (last_gap < range.second) { 00077 gaps->push_back(SequenceRange(++last_gap, range.second)); 00078 } 00079 } 00080 00081 sequences_.erase(range_below, range_above); 00082 } 00083 00084 sequences_.insert(newRange); 00085 return true; 00086 }
ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::last_ack | ( | ) | const |
Gets the low end of the highest contiguous range, may be thought of as the inverse of cumulative_ack(). If empty(), returns SEQUENCENUMBER_UNKNOWN.
Definition at line 34 of file DisjointSequence.inl.
References OpenDDS::RTPS::SEQUENCENUMBER_UNKNOWN, and sequences_.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), and OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks().
00035 { 00036 return sequences_.empty() 00037 ? SequenceNumber::SEQUENCENUMBER_UNKNOWN() 00038 : sequences_.rbegin()->first; 00039 }
ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::low | ( | ) | const |
Lowest SequenceNumber in the set. Precondition: !empty()
Definition at line 14 of file DisjointSequence.inl.
References sequences_.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::deliver_held_data(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::ReliableSession::expire_naks(), insert_bitmap_range(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::nack_durable(), OpenDDS::DCPS::RtpsUdpDataLink::process_data_i(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks(), OpenDDS::DCPS::ReliableSession::send_naks(), and to_bitmap().
00015 { 00016 return sequences_.begin()->first; 00017 }
typedef OpenDDS::DCPS::DisjointSequence::OPENDDS_SET_CMP | ( | SequenceRange | , | |
SRCompare | ||||
) | [private] |
OpenDDS::DCPS::DisjointSequence::OPENDDS_VECTOR | ( | SequenceRange | ) | const |
Returns a representation of the members of the sequence as a list of contiguous ranges (each Range is inclusive on both sides).
OpenDDS::DCPS::DisjointSequence::OPENDDS_VECTOR | ( | SequenceRange | ) | const |
Returns missing ranges of SequenceNumbers (internal gaps in the sequence).
ACE_INLINE void OpenDDS::DCPS::DisjointSequence::reset | ( | void | ) |
Definition at line 60 of file DisjointSequence.inl.
References sequences_.
Referenced by OpenDDS::DCPS::WriterInfo::reset_coherent_info(), and OpenDDS::DCPS::ReliableSession::syn_hook().
00061 { 00062 sequences_.clear(); 00063 }
static bool OpenDDS::DCPS::DisjointSequence::SequenceRange_LessThan | ( | const SequenceRange & | lhs, | |
const SequenceRange & | rhs | |||
) | [inline, static, private] |
Definition at line 112 of file DisjointSequence.h.
bool OpenDDS::DCPS::DisjointSequence::to_bitmap | ( | CORBA::Long | bitmap[], | |
CORBA::ULong | length, | |||
CORBA::ULong & | num_bits, | |||
bool | invert = false | |||
) | const |
Inverse of insert(value, num_bits, bits). Populates array of bitmap[length] with the bitmap of ranges above the cumulative_ack() value. Sets the number of significant (used) bits in num_bits. The 'base' of the bitmap is one larger than cumulative_ack(). Returns true if the entire DisjointSequence was able to fit in bitmap[]. Returning false is not an error, it's just that the higher-valued ranges didn't fit. If invert is true, the 1's in the bitmap represent the missing_sequence_ranges() instead of the present_sequence_ranges(). Precondition: the array 'bits' has 'length' entries allocated.
Definition at line 200 of file DisjointSequence.cpp.
References cumulative_ack(), disjoint(), fill_bitmap_range(), OpenDDS::DCPS::SequenceNumber::getValue(), high(), low(), and sequences_.
Referenced by OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), and OpenDDS::DCPS::RtpsUdpDataLink::send_ack_nacks().
00202 { 00203 // num_bits will be 1 more than the index of the last bit we wrote 00204 num_bits = 0; 00205 if (!disjoint()) { 00206 return true; 00207 } 00208 00209 const SequenceNumber base = ++SequenceNumber(cumulative_ack()); 00210 00211 for (RangeSet::const_iterator iter = sequences_.begin(), prev = iter++; 00212 iter != sequences_.end(); ++iter, ++prev) { 00213 00214 CORBA::ULong low = 0, high = 0; 00215 00216 if (invert) { 00217 low = CORBA::ULong(prev->second.getValue() + 1 - base.getValue()); 00218 high = CORBA::ULong(iter->first.getValue() - 1 - base.getValue()); 00219 00220 } else { 00221 low = CORBA::ULong(iter->first.getValue() - base.getValue()); 00222 high = CORBA::ULong(iter->second.getValue() - base.getValue()); 00223 } 00224 00225 if (!fill_bitmap_range(low, high, bitmap, length, num_bits)) { 00226 return false; 00227 } 00228 } 00229 00230 return true; 00231 }
void OpenDDS::DCPS::DisjointSequence::validate | ( | const SequenceRange & | range | ) | [static, private] |
Definition at line 336 of file DisjointSequence.cpp.
Referenced by insert_i().
00337 { 00338 if (range.first > range.second) { 00339 throw std::runtime_error("SequenceNumber range invalid, range must " 00340 "be ascending."); 00341 } 00342 }
RangeSet OpenDDS::DCPS::DisjointSequence::sequences_ [private] |
Definition at line 120 of file DisjointSequence.h.
Referenced by cumulative_ack(), disjoint(), dump(), empty(), high(), insert(), insert_bitmap_range(), insert_i(), last_ack(), low(), reset(), and to_bitmap().