123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #ifndef PACKET_STORAGE_H
- #define PACKET_STORAGE_H
- #include <boost/noncopyable.hpp>
- #include <boost/shared_ptr.hpp>
- #include <list>
- #include <stdint.h>
- namespace isc {
- namespace perfdhcp {
- /// \brief Represents a list of packets with a sequential and random access to
- /// list elements.
- ///
- /// The main purpose of this class is to support sending Renew and Release
- /// messages from perfdhcp. The Renew and Release messages are sent for existing
- /// leases only. Therefore, the typical use case for this class is that it holds
- /// a list of Rely messages sent by the server in response to Request messages.
- /// The Request messages hold addresses and/or IPv6 prefixes acquired so they
- /// can be used to identify existing leases. When perfdhcp needs to send Renew
- /// or Release message, it will access one of the elements on this list and
- /// will create the Renew or Release message based on its content. Once the
- /// element (packet) is returned it is also deleted from the list, so as it is
- /// not used again. This class provide either sequential access to the packets
- /// or random access. The random access algorithm is much slower but at least
- /// it allows to simulate more real scenario when the renewing or releasing
- /// client is random.
- ///
- /// \tparam Pkt4 or Pkt6 class, which represents DHCPv4 or DHCPv6 message
- /// respectively.
- ///
- /// \note Although the class is intended to hold Pkt4 and Pkt6 objects, the
- /// current implementation is generic enough to holds any object wrapped in the
- /// boost::shared_ptr.
- template<typename T>
- class PacketStorage : public boost::noncopyable {
- public:
- /// A type which represents the pointer to a packet.
- typedef boost::shared_ptr<T> PacketPtr;
- private:
- /// An internal container actually holding packets.
- typedef typename std::list<PacketPtr> PacketContainer;
- /// An iterator to the element in the internal container.
- typedef typename PacketContainer::iterator PacketContainerIterator;
- public:
- /// \brief Constructor.
- PacketStorage() { }
- /// \brief Appends the new packet object to the collection.
- ///
- /// \param packet A pointer to an object representing a packet.
- void append(const PacketPtr& packet) {
- storage_.push_back(packet);
- if (storage_.size() == 1) {
- current_pointer_ = storage_.begin();
- }
- }
- /// \brief Removes all packets from the storage.
- void clear() {
- storage_.clear();
- }
- /// \brief Checks if the storage has no packets.
- ///
- /// \return true if storage is empty, false otherwise.
- bool empty() const {
- return (storage_.empty());
- }
- /// \brief Returns next packet from the storage..
- ///
- /// This function returns packets sequentially (in the same order
- /// in which they have been appended). The returned packet is
- /// instantly removed from the storage.
- ///
- /// \return next packet from the storage.
- PacketPtr getNext() {
- if (storage_.empty()) {
- return (PacketPtr());
- } else if (current_pointer_ == storage_.end()) {
- current_pointer_ = storage_.begin();
- }
- PacketPtr packet = *current_pointer_;
- current_pointer_ = storage_.erase(current_pointer_);
- return (packet);
- }
- /// \brief Returns random packet from the storage.
- ///
- /// This function picks random packet from the storage and returns
- /// it. It is way slower than the @c getNext function because it has to
- /// iterate over all existing entries from the beginning of the storage
- /// to the random packet's position. Therefore, care should be taken
- /// when using this function to access elements when storage is large.
- ///
- /// \return random packet from the storage.
- PacketPtr getRandom() {
- if (empty()) {
- return (PacketPtr());
- }
- current_pointer_ = storage_.begin();
- if (size() > 1) {
- std::advance(current_pointer_, rand() % (size() - 1));
- }
- PacketPtr packet = *current_pointer_;
- current_pointer_ = storage_.erase(current_pointer_);
- return (packet);
- }
- /// \brief Returns number of packets in the storage.
- ///
- /// \return number of packets in the storage.
- uint32_t size() const {
- return (storage_.size());
- }
- private:
- std::list<PacketPtr> storage_; ///< Holds all appended packets.
- PacketContainerIterator current_pointer_; ///< Holds the iterator to the
- ///< next element returned.
- };
- } // namespace perfdhcp
- } // namespace isc
- #endif // PACKET_STORAGE_H
|