DisjointSequence.h

Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1