Parcourir la source

[1958] Better documentation if multi_index_container, removed redundant index.

Marcin Siodelski il y a 12 ans
Parent
commit
3b17dac1ab
1 fichiers modifiés avec 98 ajouts et 41 suppressions
  1. 98 41
      tests/tools/perfdhcp/stats_mgr.h

+ 98 - 41
tests/tools/perfdhcp/stats_mgr.h

@@ -149,7 +149,70 @@ public:
         ///
         /// List of packets based on multi index container allows efficient
         /// search of packets based on their sequence (order in which they
-        /// were inserted) as well as based on packet transaction id.
+        /// were inserted) as well as based on their hashed transaction id.
+        /// The first index (sequenced) provides the way to use container
+        /// as a regular list (including iterators, removal of elements from
+        /// the middle of the collection etc.). This index is meant to be used
+        /// more frequently than the latter one and it is based on the
+        /// assumption that responses from the DHCP server are received in
+        /// order. In this case, when next packet is received it can be
+        /// matched with next packet on the list of sent packets. This
+        /// prevents intensive searches on the list of sent packets every
+        /// time new packet arrives. In many cases however packets can be
+        /// dropped by the server or may be sent out of order and we still
+        ///  want to have ability to search packets using transaction id.
+        /// The second index can be used for this purpose. This index is
+        /// hashing transaction ids using custom function \ref hashTransid.
+        /// Note that other possibility would be to simply specify index
+        /// that uses transaction id directly (instead of hashing with
+        /// \ref hashTransid). In this case however we have chosen to use
+        /// hashing function because it shortens the index size to just
+        /// 1023 values maximum. Search operation on this index generally
+        /// returns the range of packets that have the same transaction id
+        /// hash assigned but most often these ranges will be short so further
+        /// search within a range to find a packet with pacrticular transaction
+        /// id will not be intensive.
+        ///
+        /// Example 1: Add elements to the list
+        /// \code
+        /// PktList packets_collection();
+        /// boost::shared_ptr<Pkt4> pkt1(new Pkt4(...));
+        /// boost::shared_ptr<Pkt4> pkt2(new Pkt4(...));
+        /// // Add new packet to the container, it will be available through
+        /// // both indexes
+        /// packets_collection.push_back(pkt1);
+        /// // Here is another way to add packet to the container. The result
+        /// // is exactly the same as previously.
+        /// packets_collection.template get<0>().push_back(pkt2);
+        /// \endcode
+        ///
+        /// Example 2: Access elements through sequencial index
+        /// \code
+        /// PktList packets_collection();
+        /// ...  # Add elements to the container
+        /// for (PktListIterator it = packets_collection.begin();
+        ///      it != packets_collection.end();
+        ///      ++it) {
+        ///          boost::shared_ptr<Pkt4> pkt = *it;
+        ///          # Do something with packet;
+        ///      }
+        /// \endcode
+        ///
+        /// Example 3: Access elements through hashed index
+        /// \code
+        /// // Get the instance of the second search index.
+        /// PktListTransidHashIndex& idx = sent_packets_.template get<1>();
+        /// // Get the range (bucket) of packets sharing the same transaction
+        /// // id hash.
+        /// std::pair<PktListTransidHashIterator,PktListTransidHashIterator> p =
+        ///     idx.equal_range(hashTransid(rcvd_packet));
+        /// // Iterate through the returned bucket.
+        /// for (PktListTransidHashIterator it = p.first; it != p.second;
+        ///     ++it) {
+        ///    boost::shared_ptr pkt = *it;
+        ///    ... # Do something with the packet (e.g. check transaction id)
+        /// }
+        /// \endcode
         typedef boost::multi_index_container<
             boost::shared_ptr<const T>,
             boost::multi_index::indexed_by<
@@ -160,13 +223,6 @@ public:
                             uint32_t,
                             &ExchangeStats::hashTransid
                         >
-                >,
-                boost::multi_index::hashed_non_unique<
-                    boost::multi_index::const_mem_fun<
-                        T,
-                        uint32_t,
-                        &T::getTransid
-                    >
                 >
             >
         > PktList;
@@ -179,12 +235,6 @@ public:
         /// Packet list iterator to access packets using transaction id hash.
         typedef typename PktListTransidHashIndex::const_iterator
             PktListTransidHashIterator;
-        /// Packet list index to search packets using transaction id.
-        typedef typename PktList::template nth_index<2>::type
-            PktListTransidIndex;
-        /// Packet list iterator to access packets using transaction id.
-        typedef typename PktListTransidIndex::const_iterator
-            PktListTransidIterator;
 
         /// \brief Constructor
         ///
@@ -536,34 +586,39 @@ public:
                  it != rcvd_packets_.end();
                  ++it) {
                 boost::shared_ptr<const T> rcvd_packet = *it;
-                // Search for corresponding sent packet using transaction id
-                // of received packet.
-                PktListTransidIndex& idx = archived_packets_.template get<2>();
-                PktListTransidIterator it_archived =
-                    idx.find(rcvd_packet->getTransid());
-                // This should not happen that there is no corresponding
-                // sent packet. If it does however, we just drop the packet.
-                if (it_archived != idx.end()) {
-                    boost::shared_ptr<const T> sent_packet = *it_archived;
-                    // Get sent and received packet times.
-                    ptime sent_time = sent_packet->getTimestamp();
-                    ptime rcvd_time = rcvd_packet->getTimestamp();
-                    // All sent and received packets should have timestamps
-                    // set but if there is a bug somewhere and packet does
-                    // not have timestamp we want to catch this here.
-                    if (sent_time.is_not_a_date_time() ||
-                        rcvd_time.is_not_a_date_time()) {
-                        isc_throw(InvalidOperation, "packet time is not set");
+                PktListTransidHashIndex& idx =
+                    archived_packets_.template get<1>();
+                std::pair<PktListTransidHashIterator,
+                          PktListTransidHashIterator> p =
+                    idx.equal_range(hashTransid(rcvd_packet));
+                for (PktListTransidHashIterator it_archived = p.first;
+                     it_archived != p.second;
+                     ++it) {
+                    if ((*it_archived)->getTransid() ==
+                        rcvd_packet->getTransid()) {
+                        boost::shared_ptr<const T> sent_packet = *it_archived;
+                        // Get sent and received packet times.
+                        ptime sent_time = sent_packet->getTimestamp();
+                        ptime rcvd_time = rcvd_packet->getTimestamp();
+                        // All sent and received packets should have timestamps
+                        // set but if there is a bug somewhere and packet does
+                        // not have timestamp we want to catch this here.
+                        if (sent_time.is_not_a_date_time() ||
+                            rcvd_time.is_not_a_date_time()) {
+                            isc_throw(InvalidOperation, "packet time is not set");
+                        }
+                        // Calculate durations of packets from beginning of epoch.
+                        ptime epoch_time(min_date_time);
+                        time_period sent_period(epoch_time, sent_time);
+                        time_period rcvd_period(epoch_time, rcvd_time);
+                        // Print timestamps for sent and received packet.
+                        std::cout << "sent / received: "
+                                  << to_iso_string(sent_period.length())
+                                  << " / "
+                                  << to_iso_string(rcvd_period.length())
+                                  << std::endl;
+                        break;
                     }
-                    // Calculate durations of packets from beginning of epoch.
-                    ptime epoch_time(min_date_time);
-                    time_period sent_period(epoch_time, sent_time);
-                    time_period rcvd_period(epoch_time, rcvd_time);
-                    // Print timestamps for sent and received packet.
-                    std::cout << "sent / received: "
-                              << to_iso_string(sent_period.length())
-                              << " / " << to_iso_string(rcvd_period.length())
-                              << std::endl;
                 }
             }
         }
@@ -591,6 +646,8 @@ public:
              // archived packets may be used for diagnostics
              // when test is completed.
              archived_packets_.push_back(*it);
+             // get<0>() template returns sequencial index to
+             // container.
              return(sent_packets_.template get<0>().erase(it));
         }