• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

IpMap.h

Go to the documentation of this file.
00001 # if ! defined(TS_IP_MAP_HEADER)
00002 # define TS_IP_MAP_HEADER
00003 
00004 # include "ink_platform.h"
00005 # include "ink_defs.h"
00006 # include <ts/ink_inet.h>
00007 # include <ts/IntrusiveDList.h>
00008 # include <ts/ink_assert.h>
00009 
00010 /** @file
00011 
00012     Map of IP addresses to client data.
00013 
00014     @section license License
00015 
00016     Licensed to the Apache Software Foundation (ASF) under one
00017     or more contributor license agreements.  See the NOTICE file
00018     distributed with this work for additional information
00019     regarding copyright ownership.  The ASF licenses this file
00020     to you under the Apache License, Version 2.0 (the
00021     "License"); you may not use this file except in compliance
00022     with the License.  You may obtain a copy of the License at
00023 
00024       http://www.apache.org/licenses/LICENSE-2.0
00025 
00026     Unless required by applicable law or agreed to in writing, software
00027     distributed under the License is distributed on an "AS IS" BASIS,
00028     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00029     See the License for the specific language governing permissions and
00030     limitations under the License.
00031 */
00032 
00033 namespace ts { namespace detail {
00034 
00035   /** Interval class.
00036       This holds an interval based on a metric @a T along with
00037       client data.
00038   */
00039   template <
00040     typename T, ///< Metric for span.
00041     typename A  = T const& ///< Argument type.
00042   > struct Interval {
00043     typedef T Metric; ///< Metric (storage) type.
00044     typedef A ArgType; ///< Type used to pass instances of @c Metric.
00045 
00046     Interval() {} ///< Default constructor.
00047     /// Construct with values.
00048     Interval(
00049       ArgType min, ///< Minimum value in span.
00050       ArgType max ///< Maximum value in span.
00051     ) : _min(min), _max(max) {}
00052     Metric _min; ///< Minimum value in span.
00053     Metric _max; ///< Maximum value in span.
00054   };
00055 
00056   class Ip4Map; // Forward declare.
00057   class Ip6Map; // Forward declare.
00058 
00059   /** A node in a red/black tree.
00060 
00061       This class provides only the basic tree operations. The client
00062       must provide the search and decision logic. This enables this
00063       class to be a base class for templated nodes with much less code
00064       duplication.
00065   */
00066   struct RBNode {
00067     typedef RBNode self; ///< self reference type
00068 
00069     /// Node colors
00070     typedef enum { RED, BLACK } Color;
00071 
00072     /// Directional constants
00073     typedef enum { NONE, LEFT, RIGHT } Direction;
00074 
00075     /// Get a child by direction.
00076     /// @return The child in the direction @a d if it exists,
00077     /// @c NULL if not.
00078     self* getChild(
00079       Direction d //!< The direction of the desired child
00080     ) const;
00081 
00082     /** Determine which child a node is
00083         @return @c LEFT if @a n is the left child,
00084         @c RIGHT if @a n is the right child,
00085         @c NONE if @a n is not a child
00086     */
00087     Direction getChildDirection(
00088       self* const& n //!< The presumed child node
00089     ) const {
00090       return (n == _left) ? LEFT : (n == _right) ? RIGHT : NONE;
00091     }
00092 
00093     /** Get the parent node.
00094         @return A Node* to the parent node or a @c nil Node* if no parent.
00095     */
00096     self* getParent() const { return const_cast<self*>(_parent); }
00097 
00098     /// @return The color of the node.
00099     Color getColor() const { return _color; }
00100 
00101     /** Reverse a direction
00102         @return @c LEFT if @a d is @c RIGHT, @c RIGHT if @a d is @c LEFT,
00103         @c NONE otherwise.
00104     */
00105     Direction flip(Direction d) {
00106       return LEFT == d ? RIGHT : RIGHT == d ? LEFT : NONE;
00107     }
00108 
00109     /** Perform internal validation checks.
00110         @return 0 on failure, black height of the tree on success.
00111     */
00112     int validate();
00113 
00114     /// Default constructor.
00115     RBNode()
00116       : _color(RED)
00117       , _parent(0)
00118       , _left(0)
00119       , _right(0)
00120       , _next(0)
00121       , _prev(0) {
00122     }
00123 
00124     /// Destructor (force virtual).
00125     virtual ~RBNode() { }
00126 
00127     /** Rotate the subtree rooted at this node.
00128         The node is rotated in to the position of one of its children.
00129         Which child is determined by the direction parameter @a d. The
00130         child in the other direction becomes the new root of the subtree.
00131 
00132         If the parent pointer is set, then the child pointer of the original
00133         parent is updated so that the tree is left in a consistent state.
00134 
00135         @note If there is no child in the other direction, the rotation
00136         fails and the original node is returned. It is @b not required
00137         that a child exist in the direction specified by @a d.
00138 
00139         @return The new root node for the subtree.
00140     */
00141     self* rotate(
00142       Direction d //!< The direction to rotate
00143     );
00144 
00145     /** Set the child node in direction @a d to @a n.
00146         The @a d child is set to the node @a n. The pointers in this
00147         node and @a n are set correctly. This can only be called if
00148         there is no child node already present.
00149 
00150         @return @a n.
00151     */
00152     self* setChild(
00153       self* n, //!< The node to set as the child
00154       Direction d //!< The direction of the child
00155     );
00156 
00157     /** Remove this node from the tree.
00158         The tree is rebalanced after removal.
00159         @return The new root node.
00160     */
00161     self* remove();
00162 
00163     void clearChild(Direction dir) {
00164       if (LEFT == dir) _left = 0;
00165       else if (RIGHT == dir) _right = 0;
00166     }
00167 
00168     /** @name Subclass hook methods */
00169     //@{
00170     /** Structural change notification.
00171         This method is called if the structure of the subtree rooted at
00172         this node was changed.
00173                         
00174         This is intended a hook. The base method is empty so that subclasses
00175         are not required to override.
00176     */
00177     virtual void structureFixup() {}
00178 
00179     /** Called from @c validate to perform any additional validation checks.
00180         Clients should chain this if they wish to perform additional checks.
00181         @return @c true if the validation is successful, @c false otherwise.
00182         @note The base method simply returns @c true.
00183     */
00184     virtual bool structureValidate() { return true; }
00185     //@}
00186 
00187     /** Replace this node with another node.
00188         This is presumed to be non-order modifying so the next reference
00189         is @b not updated.
00190     */
00191     void replaceWith(
00192       self* n //!< Node to put in place of this node.
00193     );
00194 
00195     //! Rebalance the tree starting at this node
00196     /** The tree is rebalanced so that all of the invariants are
00197         true. The (potentially new) root of the tree is returned.
00198 
00199         @return The root node of the tree after the rebalance.
00200     */
00201     self* rebalanceAfterInsert();
00202                 
00203     /** Rebalance the tree after a deletion.
00204         Called on the lowest modified node.
00205         @return The new root of the tree.
00206     */
00207     self* rebalanceAfterRemove(
00208       Color c, //!< The color of the removed node.
00209       Direction d //!< Direction of removed node from parent
00210     );
00211 
00212     //! Invoke @c structure_fixup() on this node and all of its ancestors.
00213     self* rippleStructureFixup();
00214 
00215     Color _color;  ///< node color
00216     self* _parent; ///< parent node (needed for rotations)
00217     self* _left;   ///< left child
00218     self* _right;  ///< right child
00219     self* _next; ///< Next node.
00220     self* _prev; ///< Previous node.
00221   };
00222 
00223 }} // namespace ts::detail
00224 
00225 /** Map from IP addresses to client data.
00226 
00227     Conceptually this class maps the entire space of IP addresses to
00228     client data. Client data is stored as a @c (void*). Memory
00229     management of the data is left to the client. The interface
00230     supports marking ranges of addresses with a specific client
00231     data. Marking takes a painter's algorithm approach -- any marking
00232     overwrites any previous marking on an address. Details of marking
00233     calls are discarded and only the final results are kept. That is,
00234     a client cannot unmark expliticly any previous marking. Only a
00235     specific range of addresses can be unmarked.
00236 
00237     Both IPv4 and IPv6 are supported in the same map. Mixed ranges are
00238     not supported (any particular range of addresses must be a single
00239     protocol but ranges of both types can be in the map).
00240 
00241     Use @c mark to mark / set / add addresses to the map.
00242     Use @c unmark to unset addresses (setting the client data to 0 does
00243     @b not remove the address -- this is for the convenience of clients
00244     that do not need data, only membership). @c contains tests for
00245     membership and retrieves the client data.
00246 
00247     Ranges can be marked and unmarked arbitrarily. The internal
00248     representation keeps a minimal set of ranges to describe the
00249     current addresses. Search time is O(log n) where n is the number
00250     of disjoint ranges. Marking and unmarking can take O(log n) and
00251     may require memory allocation / deallocation although this is
00252     minimized.
00253 */
00254 
00255 class IpMap {
00256 public:
00257   typedef IpMap self; ///< Self reference type.
00258 
00259   class iterator; // forward declare.
00260   
00261   /** Public API for intervals in the map.
00262   */
00263   class Node : protected ts::detail::RBNode {
00264     friend class iterator;
00265     friend class IpMap;
00266   public:
00267     typedef Node self; ///< Self reference type.
00268     /// Default constructor.
00269     Node() : _data(0) {}
00270     /// Construct with @a data.
00271     Node(void* data) : _data(data) {}
00272     /// @return Client data for the node.
00273     virtual void* data() { return _data; }
00274     /// Set client data.
00275     virtual self& setData(
00276       void* data ///< Client data pointer to store.
00277     ) {
00278       _data = data;
00279       return *this;
00280     }
00281     /// @return Minimum value of the interval.
00282     virtual sockaddr const* min() const = 0;
00283     /// @return Maximum value of the interval.
00284     virtual sockaddr const* max() const = 0;
00285   protected:
00286     void* _data; ///< Client data.
00287   };
00288 
00289   /** Iterator over nodes / intervals.
00290 
00291       The iteration is over all nodes, regardless of which node is
00292       used to create the iterator. The node passed to the constructor
00293       just sets the current location.
00294   */
00295   class iterator {
00296     friend class IpMap;
00297   public:
00298     typedef iterator self; ///< Self reference type.
00299     typedef Node value_type; ///< Referenced type for iterator.
00300     typedef int difference_type; ///< Distance type.
00301     typedef Node* pointer; ///< Pointer to referent.
00302     typedef Node& reference; ///< Reference to referent.
00303     typedef std::bidirectional_iterator_tag iterator_category;
00304     /// Default constructor.
00305     iterator() : _tree(0), _node(0) {}
00306 
00307     reference operator* () const; //!< value operator
00308     pointer operator -> () const; //!< dereference operator
00309     self& operator++(); //!< next node (prefix)
00310     self operator++(int); //!< next node (postfix)
00311     self& operator--(); ///< previous node (prefix)
00312     self operator--(int); ///< next node (postfix)
00313 
00314     /** Equality.
00315         @return @c true if the iterators refer to the same node.
00316     */
00317     bool operator==(self const& that) const;
00318     /** Inequality.
00319         @return @c true if the iterators refer to different nodes.
00320     */
00321     bool operator!=(self const& that) const { return ! (*this == that); }
00322   private:
00323     /// Construct a valid iterator.
00324     iterator(IpMap const* tree, Node* node) : _tree(tree), _node(node) {}
00325       IpMap const* _tree; ///< Container.
00326       Node* _node; //!< Current node.
00327     };
00328 
00329   IpMap(); ///< Default constructor.
00330   ~IpMap(); ///< Destructor.
00331 
00332   /** Mark a range.
00333       All addresses in the range [ @a min , @a max ] are marked with @a data.
00334       @return This object.
00335   */
00336   self& mark(
00337     sockaddr const* min, ///< Minimum value in range.
00338     sockaddr const* max, ///< Maximum value in range.
00339     void* data = 0     ///< Client data payload.
00340   );
00341 
00342   /** Mark a range.
00343       All addresses in the range [ @a min , @a max ] are marked with @a data.
00344       @note Convenience overload for IPv4 addresses.
00345       @return This object.
00346   */
00347   self& mark(
00348     in_addr_t min, ///< Minimum address (network order).
00349     in_addr_t max, ///< Maximum address (network order).
00350     void* data = 0 ///< Client data.
00351   );
00352 
00353   /** Mark a range.
00354       All addresses in the range [ @a min , @a max ] are marked with @a data.
00355       @note Convenience overload for IPv4 addresses.
00356       @return This object.
00357   */
00358   self& mark(
00359     IpAddr const& min, ///< Minimum address (network order).
00360     IpAddr const& max, ///< Maximum address (network order).
00361     void* data = 0 ///< Client data.
00362   );
00363 
00364   /** Mark an IPv4 address @a addr with @a data.
00365       This is equivalent to calling @c mark(addr, addr, data).
00366       @note Convenience overload for IPv4 addresses.
00367       @return This object.
00368   */
00369   self& mark(
00370     in_addr_t addr, ///< Address (network order).
00371     void* data = 0 ///< Client data.
00372   );
00373 
00374   /** Mark a range.
00375       All addresses in the range [ @a min , @a max ] are marked with @a data.
00376       @note Convenience overload.
00377       @return This object.
00378   */
00379   self& mark(
00380     IpEndpoint const* min, ///< Minimum address (network order).
00381     IpEndpoint const* max, ///< Maximum address (network order).
00382     void* data = 0 ///< Client data.
00383   );
00384 
00385   /** Mark an address @a addr with @a data.
00386       This is equivalent to calling @c mark(addr, addr, data).
00387       @note Convenience overload.
00388       @return This object.
00389   */
00390   self& mark(
00391     IpEndpoint const* addr, ///< Address (network order).
00392     void* data = 0 ///< Client data.
00393   );
00394 
00395   /** Unmark addresses.
00396 
00397       All addresses in the range [ @a min , @a max ] are cleared
00398       (removed from the map), no longer marked.
00399 
00400       @return This object.
00401   */
00402   self& unmark(
00403     sockaddr const* min, ///< Minimum value.
00404     sockaddr const* max  ///< Maximum value.
00405   );
00406   /// Unmark addresses (overload).
00407   self& unmark(
00408     IpEndpoint const* min,
00409     IpEndpoint const* max
00410   );
00411   /// Unmark overload.
00412   self& unmark(
00413     in_addr_t min, ///< Minimum of range to unmark.
00414     in_addr_t max  ///< Maximum of range to unmark.
00415   );
00416 
00417   /** Fill addresses.
00418 
00419       This background fills using the range. All addresses in the
00420       range that are @b not present in the map are added. No
00421       previously present address is changed.
00422 
00423       @note This is useful for filling in first match tables because @a data for already present
00424       addresses is not changed.
00425 
00426       @return This object.
00427   */
00428   self& fill(
00429     sockaddr const* min,
00430     sockaddr const* max,
00431     void* data = 0
00432   );
00433   /// Fill addresses (overload).
00434   self& fill(
00435     IpEndpoint const* min,
00436     IpEndpoint const* max,
00437     void* data = 0
00438   );
00439   /// Fill addresses (overload).
00440   self& fill(
00441     in_addr_t min,
00442     in_addr_t max,
00443     void* data = 0
00444   );
00445 
00446   /** Test for membership.
00447 
00448       @return @c true if the address is in the map, @c false if not.
00449       If the address is in the map and @a ptr is not @c NULL, @c *ptr
00450       is set to the client data for the address.
00451   */
00452   bool contains(
00453     sockaddr const* target, ///< Search target (network order).
00454     void **ptr = 0 ///< Client data return.
00455   ) const;
00456 
00457   /** Test for membership.
00458 
00459       @note Covenience overload for IPv4.
00460 
00461       @return @c true if the address is in the map, @c false if not.
00462       If the address is in the map and @a ptr is not @c NULL, @c *ptr
00463       is set to the client data for the address.
00464   */
00465   bool contains(
00466     in_addr_t target, ///< Search target (network order).
00467     void **ptr = 0 ///< Client data return.
00468   ) const;
00469 
00470   /** Test for membership.
00471 
00472       @note Convenience overload for @c IpEndpoint.
00473 
00474       @return @c true if the address is in the map, @c false if not.
00475       If the address is in the map and @a ptr is not @c NULL, @c *ptr
00476       is set to the client data for the address.
00477   */
00478   bool contains(
00479     IpEndpoint const* target, ///< Search target (network order).
00480     void **ptr = 0 ///< Client data return.
00481   ) const;
00482 
00483   /** Test for membership.
00484 
00485       @note Convenience overload for @c IpAddr.
00486 
00487       @return @c true if the address is in the map, @c false if not.
00488       If the address is in the map and @a ptr is not @c NULL, @c *ptr
00489       is set to the client data for the address.
00490   */
00491   bool contains(
00492     IpAddr const& target, ///< Search target (network order).
00493     void **ptr = 0 ///< Client data return.
00494   ) const;
00495 
00496   /** Remove all addresses from the map.
00497 
00498       @note This is much faster than @c unmark.
00499       @return This object.
00500   */
00501   self& clear();
00502 
00503   /// Iterator for first element.
00504   iterator begin() const;
00505   /// Iterator past last element.
00506   iterator end() const;
00507   /// @return Number of distinct ranges in the map.
00508   size_t getCount() const;
00509 
00510   /** Validate internal data structures.
00511       @note Intended for debugging, not general client use.
00512   */
00513   void validate();
00514 
00515   /// Print all spans.
00516   /// @return This map.
00517   //  self& print();
00518 
00519 protected:
00520   /// Force the IPv4 map to exist.
00521   /// @return The IPv4 map.
00522   ts::detail::Ip4Map* force4();
00523   /// Force the IPv6 map to exist.
00524   /// @return The IPv6 map.
00525   ts::detail::Ip6Map* force6();
00526   
00527   ts::detail::Ip4Map* _m4; ///< Map of IPv4 addresses.
00528   ts::detail::Ip6Map* _m6; ///< Map of IPv6 addresses.
00529   
00530 };
00531 
00532 inline IpMap& IpMap::mark(in_addr_t addr, void* data) {
00533   return this->mark(addr, addr, data);
00534 }
00535 
00536 inline IpMap& IpMap::mark(IpAddr const& min, IpAddr const& max, void* data) {
00537   IpEndpoint x,y;
00538   x.assign(min);
00539   y.assign(max);
00540   return this->mark(&x.sa, &y.sa, data);
00541 }
00542 
00543 inline IpMap& IpMap::mark(IpEndpoint const* addr, void* data) {
00544   return this->mark(&addr->sa, &addr->sa, data);
00545 }
00546 
00547 inline IpMap& IpMap::mark(IpEndpoint const* min, IpEndpoint const* max, void* data) {
00548   return this->mark(&min->sa, &max->sa, data);
00549 }
00550 
00551 inline IpMap& IpMap::unmark(IpEndpoint const* min, IpEndpoint const* max) {
00552   return this->unmark(&min->sa, &max->sa);
00553 }
00554 
00555 inline IpMap& IpMap::fill(IpEndpoint const* min, IpEndpoint const* max, void* data) {
00556   return this->fill(&min->sa, &max->sa, data);
00557 }
00558 
00559 inline bool IpMap::contains(IpEndpoint const* target, void** ptr) const {
00560   return this->contains(&target->sa, ptr);
00561 }
00562 
00563 inline bool
00564 IpMap::contains(IpAddr const& addr, void** ptr) const {
00565   IpEndpoint ip;
00566   ip.assign(addr);
00567   return this->contains(&ip.sa, ptr);
00568 }
00569 
00570 inline IpMap::iterator
00571 IpMap::end() const {
00572   return iterator(this, 0);
00573 }
00574 
00575 inline IpMap::iterator
00576 IpMap::iterator::operator ++ (int) {
00577   iterator old(*this);
00578   ++*this;
00579   return old;
00580 }
00581 
00582 inline IpMap::iterator
00583 IpMap::iterator::operator--(int) {
00584   self tmp(*this);
00585   --*this;
00586   return tmp;
00587 }
00588 
00589 inline bool
00590 IpMap::iterator::operator == (iterator const& that) const {
00591   return _tree == that._tree && _node == that._node;
00592 }
00593 
00594 inline IpMap::iterator::reference
00595 IpMap::iterator::operator * () const {
00596   return *_node;
00597 }
00598 
00599 inline IpMap::iterator::pointer
00600 IpMap::iterator::operator -> () const {
00601   return _node;
00602 }
00603 
00604 inline IpMap::IpMap() : _m4(0), _m6(0) {}
00605 
00606 # endif // TS_IP_MAP_HEADER

Generated by  doxygen 1.7.1