00001 /* 00002 * 00003 * 00004 * Distributed under the OpenDDS License. 00005 * See: http://www.opendds.org/license.html 00006 */ 00007 00008 #ifndef DCPS_DISJOINTSEQUENCE_H 00009 #define DCPS_DISJOINTSEQUENCE_H 00010 00011 #include "dcps_export.h" 00012 #include "Definitions.h" 00013 #include "SequenceNumber.h" 00014 00015 #include "PoolAllocator.h" 00016 00017 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 00018 00019 namespace OpenDDS { 00020 namespace DCPS { 00021 00022 /// Data structure for a set of SequenceNumbers. 00023 /// Sequence numbers can be inserted as single numbers, ranges, 00024 /// or RTPS-style bitmaps. The DisjointSequence can then be queried for 00025 /// contiguous ranges and internal gaps. 00026 class OpenDDS_Dcps_Export DisjointSequence { 00027 public: 00028 00029 DisjointSequence(); 00030 void reset(); 00031 00032 bool empty() const; 00033 00034 /// Lowest SequenceNumber in the set. 00035 /// Precondition: !empty() 00036 SequenceNumber low() const; 00037 00038 /// Highest SequenceNumber in the set. 00039 /// Precondition: !empty() 00040 SequenceNumber high() const; 00041 00042 /// Gets the high end of the lowest contiguous range. 00043 /// Named after the use case of tracking received messages (which may be 00044 /// received out-of-order) and then determining the largest value that the 00045 /// receiver is allowed to acknowledge (under a cumulative-acking protocol). 00046 /// If empty(), returns SEQUENCENUMBER_UNKNOWN. 00047 SequenceNumber cumulative_ack() const; 00048 00049 /// Gets the low end of the highest contiguous range, may be thought of as 00050 /// the inverse of cumulative_ack(). 00051 /// If empty(), returns SEQUENCENUMBER_UNKNOWN. 00052 SequenceNumber last_ack() const; 00053 00054 /// Objects with the disjoint() property have an internal gap in the inserted 00055 /// SequenceNumbers. 00056 bool disjoint() const; 00057 00058 bool contains(SequenceNumber value) const; 00059 00060 /// All insert() methods return true upon modifying the set and false if 00061 /// the set already contained the SequenceNumber(s) that were to be inserted. 00062 /// This is the general form of insert() whereby the caller receives a list of 00063 /// sub-ranges of 'range' that were not already in the DisjointSequence. 00064 /// For example, given a DisjointSequence 'seq' containing (1, 2, 5, 9), 00065 /// calling seq.insert(SequenceRange(4, 12), v) returns true 00066 /// and yields v = [(4, 4), (6, 8), (10, 12)] and seq = (1, 2, 4, ..., 12). 00067 bool insert(const SequenceRange& range, OPENDDS_VECTOR(SequenceRange)& added); 00068 00069 /// Insert all numbers between range.first and range.second (both inclusive). 00070 bool insert(const SequenceRange& range); 00071 00072 /// Shorthand for "insert(SequenceRange(value, value))" 00073 bool insert(SequenceNumber value); 00074 00075 /// Insert using the RTPS compact representation of a set. The three 00076 /// parameters, taken together, describe a set with each 1 bit starting 00077 /// at the msb of bits[0] and extending through num_bits (which are located at 00078 /// the next least significant bits of bits[0] followed by the msb of bits[1], 00079 /// etc.) indicating presence of the number (value + bit_index) in the set. 00080 /// bit_index is 0-based. 00081 /// Precondition: the array 'bits' has at least ceil(num_bits / 32) entries. 00082 bool insert(SequenceNumber value, 00083 CORBA::ULong num_bits, 00084 const CORBA::Long bits[]); 00085 00086 /// Inverse of insert(value, num_bits, bits). Populates array of 00087 /// bitmap[length] with the bitmap of ranges above the cumulative_ack() value. 00088 /// Sets the number of significant (used) bits in num_bits. The 'base' of the 00089 /// bitmap is one larger than cumulative_ack(). Returns true if the entire 00090 /// DisjointSequence was able to fit in bitmap[]. Returning false is not an 00091 /// error, it's just that the higher-valued ranges didn't fit. If invert is 00092 /// true, the 1's in the bitmap represent the missing_sequence_ranges() 00093 /// instead of the present_sequence_ranges(). 00094 /// Precondition: the array 'bits' has 'length' entries allocated. 00095 bool to_bitmap(CORBA::Long bitmap[], 00096 CORBA::ULong length, 00097 CORBA::ULong& num_bits, 00098 bool invert = false) const; 00099 00100 /// Returns missing ranges of SequenceNumbers (internal gaps in the sequence) 00101 OPENDDS_VECTOR(SequenceRange) missing_sequence_ranges() const; 00102 00103 /// Returns a representation of the members of the sequence as a list of 00104 /// contiguous ranges (each Range is inclusive on both sides). 00105 OPENDDS_VECTOR(SequenceRange) present_sequence_ranges() const; 00106 00107 void dump() const; 00108 00109 private: 00110 static void validate(const SequenceRange& range); 00111 00112 static bool SequenceRange_LessThan(const SequenceRange& lhs, 00113 const SequenceRange& rhs) 00114 { 00115 return lhs.second < rhs.second; 00116 } 00117 00118 typedef bool (*SRCompare)(const SequenceRange&, const SequenceRange&); 00119 typedef OPENDDS_SET_CMP(SequenceRange, SRCompare) RangeSet; 00120 RangeSet sequences_; 00121 00122 00123 // helper methods: 00124 00125 bool insert_i(const SequenceRange& range, 00126 OPENDDS_VECTOR(SequenceRange)* gaps = 0); 00127 00128 bool insert_bitmap_range(RangeSet::iterator& iter, const SequenceRange& sr); 00129 00130 public: 00131 /// Set the bits in range [low, high] in the bitmap, updating num_bits. 00132 static bool fill_bitmap_range(CORBA::ULong low, CORBA::ULong high, 00133 CORBA::Long bitmap[], CORBA::ULong length, 00134 CORBA::ULong& num_bits); 00135 }; 00136 00137 00138 } // namespace DCPS 00139 } // namespace OpenDDS 00140 00141 OPENDDS_END_VERSIONED_NAMESPACE_DECL 00142 00143 #ifdef __ACE_INLINE__ 00144 # include "DisjointSequence.inl" 00145 #endif /* __ACE_INLINE__ */ 00146 00147 #endif /* DCPS_DISJOINTSEQUENCE_H */