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