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

IpMap.cc

Go to the documentation of this file.
00001 # include "IpMap.h"
00002 
00003 /** @file
00004     IP address map support.
00005 
00006     Provide the ability to create a range based mapping for the IP
00007     address space. Addresses can be added and removed and each address
00008     is associated with arbitrary client data.
00009 
00010     @internal Don't bother to look at this code if you don't know how
00011     a red/black tree works. There are so many good references on the
00012     subject it's a waste to have some inferior version here. The
00013     methods on @c Node follow the standard implementation except for
00014     being parameterized by direction (so that, for instance, right
00015     rotate and left rotate are both done by the @c rotate method with
00016     a direction argument).
00017 
00018     @section license License
00019 
00020     Licensed to the Apache Software Foundation (ASF) under one
00021     or more contributor license agreements.  See the NOTICE file
00022     distributed with this work for additional information
00023     regarding copyright ownership.  The ASF licenses this file
00024     to you under the Apache License, Version 2.0 (the
00025     "License"); you may not use this file except in compliance
00026     with the License.  You may obtain a copy of the License at
00027 
00028     http://www.apache.org/licenses/LICENSE-2.0
00029 
00030     Unless required by applicable law or agreed to in writing, software
00031     distributed under the License is distributed on an "AS IS" BASIS,
00032     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00033     See the License for the specific language governing permissions and
00034     limitations under the License.
00035  */
00036 
00037 // Validation / printing disabled until I figure out how to generalize so
00038 // as to not tie reporting into a particular project environment.
00039 
00040 /* @internal It is a bit ugly to store a @c sockaddr equivalent in the table
00041     as all that is actually needed is the raw address. Unfortunately some clients
00042     require a @c sockaddr* return via the iterator and that's expensive to
00043     compute all the time. I should, at some point, re-examine this and see if we
00044     can do better and have a more compact internal format. I suspect I did this
00045     before we had IpAddr as a type.
00046 */
00047 
00048 namespace ts { namespace detail {
00049 
00050 // Helper functions
00051 
00052 inline int cmp(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
00053   return memcmp(lhs.sin6_addr.s6_addr, rhs.sin6_addr.s6_addr, TS_IP6_SIZE);
00054 }
00055 
00056 /// Less than.
00057 inline bool operator<(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
00058   return ts::detail::cmp(lhs, rhs) < 0;
00059 }
00060 inline bool operator<(sockaddr_in6 const* lhs, sockaddr_in6 const& rhs) {
00061   return ts::detail::cmp(*lhs, rhs) < 0;
00062 }
00063 /// Less than.
00064 inline bool operator<(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
00065   return ts::detail::cmp(lhs, *rhs) < 0;
00066 }
00067 /// Equality.
00068 inline bool operator==(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
00069   return ts::detail::cmp(lhs, *rhs) == 0;
00070 }
00071 /// Equality.
00072 inline bool operator==(sockaddr_in6 const* lhs, sockaddr_in6 const& rhs) {
00073   return ts::detail::cmp(*lhs, rhs) == 0;
00074 }
00075 /// Equality.
00076 inline bool operator==(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
00077   return ts::detail::cmp(lhs, rhs) == 0;
00078 }
00079 /// Less than or equal.
00080 inline bool operator<=(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
00081   return ts::detail::cmp(lhs, *rhs) <= 0;
00082 }
00083 /// Less than or equal.
00084 inline bool operator<=(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
00085   return ts::detail::cmp(lhs, rhs) <= 0;
00086 }
00087 /// Greater than or equal.
00088 inline bool operator>=(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
00089   return ts::detail::cmp(lhs, rhs) >= 0;
00090 }
00091 /// Greater than or equal.
00092 inline bool operator>=(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
00093   return ts::detail::cmp(lhs, *rhs) >= 0;
00094 }
00095 /// Greater than.
00096 inline bool operator>(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
00097   return ts::detail::cmp(lhs, *rhs) > 0;
00098 }
00099 
00100 /// Equality.
00101 /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
00102 /// @return @c true if @a c and the color of @a n are the same.
00103 inline bool operator == ( RBNode* n, RBNode::Color c ) {
00104   return c == ( n ? n->getColor() : RBNode::BLACK);
00105 }
00106 /// Equality.
00107 /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
00108 /// @return @c true if @a c and the color of @a n are the same.
00109 inline bool operator == ( RBNode::Color c, RBNode* n ) {
00110   return n == c;
00111 }
00112 
00113 inline RBNode*
00114 RBNode::getChild(Direction d) const {
00115   return d == RIGHT ? _right
00116     : d == LEFT ? _left
00117     : 0
00118     ;
00119 }
00120 
00121 RBNode*
00122 RBNode::rotate(Direction d) {
00123   self* parent = _parent; // Cache because it can change before we use it.
00124   Direction child_dir = _parent ? _parent->getChildDirection(this) : NONE;
00125   Direction other_dir = this->flip(d);
00126   self* child = this;
00127 
00128   if (d != NONE && this->getChild(other_dir)) {
00129     child = this->getChild(other_dir);
00130     this->clearChild(other_dir);
00131     this->setChild(child->getChild(d), other_dir);
00132     child->clearChild(d);
00133     child->setChild(this, d);
00134     child->structureFixup();
00135     this->structureFixup();
00136     if (parent) {
00137       parent->clearChild(child_dir);
00138       parent->setChild(child, child_dir);
00139     } else {
00140       child->_parent = 0;
00141     }
00142   }
00143   return child;
00144 }
00145 
00146 RBNode*
00147 RBNode::setChild(self* n, Direction d) {
00148   if (n) n->_parent = this;
00149   if (d == RIGHT) _right = n;
00150   else if (d == LEFT) _left = n;
00151   return n;
00152 }
00153 
00154 // Returns the root node
00155 RBNode*
00156 RBNode::rippleStructureFixup() {
00157   self* root = this; // last node seen, root node at the end
00158   self* p = this;
00159   while (p) {
00160     p->structureFixup();
00161     root = p;
00162     p = root->_parent;
00163   }
00164   return root;
00165 }
00166 
00167 void
00168 RBNode::replaceWith(self* n) {
00169   n->_color = _color;
00170   if (_parent) {
00171     Direction d = _parent->getChildDirection(this);
00172     _parent->setChild(0, d);
00173     if (_parent != n) _parent->setChild(n, d);
00174   } else {
00175     n->_parent = 0;
00176   }
00177   n->_left = n->_right = 0;
00178   if (_left && _left != n) n->setChild(_left, LEFT);
00179   if (_right && _right != n) n->setChild(_right, RIGHT);
00180   _left = _right = 0;
00181 }
00182 
00183 /* Rebalance the tree. This node is the unbalanced node. */
00184 RBNode*
00185 RBNode::rebalanceAfterInsert() {
00186   self* x(this); // the node with the imbalance
00187 
00188   while (x && x->_parent == RED) {
00189     Direction child_dir = NONE;
00190         
00191     if (x->_parent->_parent)
00192       child_dir = x->_parent->_parent->getChildDirection(x->_parent);
00193     else
00194       break;
00195     Direction other_dir(flip(child_dir));
00196         
00197     self* y = x->_parent->_parent->getChild(other_dir);
00198     if (y == RED) {
00199       x->_parent->_color = BLACK;
00200       y->_color = BLACK;
00201       x = x->_parent->_parent;
00202       x->_color = RED;
00203     } else {
00204       if (x->_parent->getChild(other_dir) == x) {
00205         x = x->_parent;
00206         x->rotate(child_dir);
00207       }
00208       // Note setting the parent color to BLACK causes the loop to exit.
00209       x->_parent->_color = BLACK;
00210       x->_parent->_parent->_color = RED;
00211       x->_parent->_parent->rotate(other_dir);
00212     }
00213   }
00214     
00215   // every node above this one has a subtree structure change,
00216   // so notify it. serendipitously, this makes it easy to return
00217   // the new root node.
00218   self* root = this->rippleStructureFixup();
00219   root->_color = BLACK;
00220 
00221   return root;
00222 }
00223 
00224 
00225 // Returns new root node
00226 RBNode*
00227 RBNode::remove() {
00228   self* root = 0; // new root node, returned to caller
00229 
00230   /*  Handle two special cases first.
00231       - This is the only node in the tree, return a new root of NIL
00232       - This is the root node with only one child, return that child as new root
00233   */
00234   if (!_parent && !(_left && _right)) {
00235     if (_left) {
00236       _left->_parent = 0;
00237       root = _left;
00238       root->_color = BLACK;
00239     } else if (_right) {
00240       _right->_parent = 0;
00241       root = _right;
00242       root->_color = BLACK;
00243     } // else that was the only node, so leave @a root @c NULL.
00244     return root;
00245   }
00246 
00247   /*  The node to be removed from the tree.
00248       If @c this (the target node) has both children, we remove
00249       its successor, which cannot have a left child and
00250       put that node in place of the target node. Otherwise this
00251       node has at most one child, so we can remove it.
00252       Note that the successor of a node with a right child is always
00253       a right descendant of the node. Therefore, remove_node
00254       is an element of the tree rooted at this node.
00255       Because of the initial special case checks, we know
00256       that remove_node is @b not the root node.
00257   */
00258   self* remove_node(_left && _right ? _next : this);
00259 
00260   // This is the color of the node physically removed from the tree.
00261   // Normally this is the color of @a remove_node
00262   Color remove_color = remove_node->_color;
00263   // Need to remember the direction from @a remove_node to @a splice_node
00264   Direction d(NONE);
00265 
00266   // The child node that will be promoted to replace the removed node.
00267   // The choice of left or right is irrelevant, as remove_node has at
00268   // most one child (and splice_node may be NIL if remove_node has no
00269   // children).
00270   self* splice_node(remove_node->_left
00271     ? remove_node->_left
00272     : remove_node->_right
00273   );
00274 
00275   if (splice_node) {
00276     // @c replace_with copies color so in this case the actual color
00277     // lost is that of the splice_node.
00278     remove_color = splice_node->_color;
00279     remove_node->replaceWith(splice_node);
00280   } else {
00281     // No children on remove node so we can just clip it off the tree
00282     // We update splice_node to maintain the invariant that it is
00283     // the node where the physical removal occurred.
00284     splice_node = remove_node->_parent;
00285     // Keep @a d up to date.
00286     d = splice_node->getChildDirection(remove_node);
00287     splice_node->setChild(0, d);
00288   }
00289 
00290   // If the node to pull out of the tree isn't this one, 
00291   // then replace this node in the tree with that removed
00292   // node in liu of copying the data over.
00293   if (remove_node != this) {
00294     // Don't leave @a splice_node referring to a removed node
00295     if (splice_node == this) splice_node = remove_node;
00296     this->replaceWith(remove_node);
00297   }
00298 
00299   root = splice_node->rebalanceAfterRemove(remove_color, d);
00300   root->_color = BLACK;
00301   return root;
00302 }
00303 
00304 /**
00305  * Rebalance tree after a deletion
00306  * Called on the spliced in node or its parent, whichever is not NIL.
00307  * This modifies the tree structure only if @a c is @c BLACK.
00308  */
00309 RBNode*
00310 RBNode::rebalanceAfterRemove(
00311   Color c, //!< The color of the removed node
00312   Direction d //!< Direction of removed node from its parent
00313 ) {
00314   self* root;
00315 
00316   if (BLACK == c) { // only rebalance if too much black
00317     self* n = this;
00318     self* parent = n->_parent;
00319 
00320     // If @a direction is set, then we need to start at a leaf psuedo-node.
00321     // This is why we need @a parent, otherwise we could just use @a n.
00322     if (NONE != d) {
00323       parent = n;
00324       n = 0;
00325     }
00326 
00327     while (parent) { // @a n is not the root
00328       // If the current node is RED, we can just recolor and be done
00329       if (n == RED) {
00330         n->_color = BLACK;
00331         break;
00332       } else {
00333         // Parameterizing the rebalance logic on the directions. We
00334         // write for the left child case and flip directions for the
00335         // right child case
00336         Direction near(LEFT), far(RIGHT);
00337         if (
00338           (NONE == d && parent->getChildDirection(n) == RIGHT)
00339           || RIGHT == d
00340         ) {
00341           near = RIGHT;
00342           far = LEFT;
00343         }
00344 
00345         self* w = parent->getChild(far); // sibling(n)
00346 
00347         if (w->_color == RED) {
00348           w->_color = BLACK;
00349           parent->_color = RED;
00350           parent->rotate(near);
00351           w = parent->getChild(far);
00352         }
00353 
00354         self* wfc = w->getChild(far);
00355         if (w->getChild(near) == BLACK && wfc == BLACK) {
00356           w->_color = RED;
00357           n = parent;
00358           parent = n->_parent;
00359           d = NONE; // Cancel any leaf node logic
00360         } else {
00361           if (wfc->_color == BLACK) {
00362             w->getChild(near)->_color = BLACK;
00363             w->_color = RED;
00364             w->rotate(far);
00365             w = parent->getChild(far);
00366             wfc = w->getChild(far); // w changed, update far child cache.
00367           }
00368           w->_color = parent->_color;
00369           parent->_color = BLACK;
00370           wfc->_color = BLACK;
00371           parent->rotate(near);
00372           break;
00373         }
00374       }
00375     }
00376   }
00377   root = this->rippleStructureFixup();
00378   return root;
00379 }
00380 
00381 /** Ensure that the local information associated with each node is
00382     correct globally This should only be called on debug builds as it
00383     breaks any efficiencies we have gained from our tree structure.
00384     */
00385 int
00386 RBNode::validate() {
00387 # if 0
00388   int black_ht = 0;
00389   int black_ht1, black_ht2;
00390 
00391   if (_left) {
00392     black_ht1 = _left->validate();
00393   }
00394   else
00395     black_ht1 = 1;
00396 
00397   if (black_ht1 > 0 && _right)
00398     black_ht2 = _right->validate();
00399   else
00400     black_ht2 = 1;
00401 
00402   if (black_ht1 == black_ht2) {
00403     black_ht = black_ht1;
00404     if (this->_color == BLACK)
00405       ++black_ht;
00406     else {      // No red-red
00407       if (_left == RED)
00408         black_ht = 0;
00409       else if (_right == RED)
00410         black_ht = 0;
00411       if (black_ht == 0)
00412         std::cout << "Red-red child\n";
00413     }
00414   } else {
00415     std::cout << "Height mismatch " << black_ht1 << " " << black_ht2 << "\n";
00416   }
00417   if (black_ht > 0 && !this->structureValidate())
00418     black_ht = 0;
00419 
00420   return black_ht;
00421 # else
00422   return 0;
00423 # endif
00424 }
00425 
00426 /** Base template class for IP maps.
00427     This class is templated by the @a N type which must be a subclass
00428     of @c RBNode. This class carries information about the addresses stored
00429     in the map. This includes the type, the common argument type, and
00430     some utility methods to operate on the address.
00431 */
00432 template <
00433   typename N ///< Node type.
00434 > struct IpMapBase {
00435   friend class ::IpMap;
00436   
00437   typedef IpMapBase self; ///< Self reference type.
00438   typedef typename N::ArgType ArgType; ///< Import type.
00439   typedef typename N::Metric Metric;   ///< Import type.g482
00440 
00441   IpMapBase() : _root(0) {}
00442   ~IpMapBase() { this->clear(); }
00443 
00444   /** Mark a range.
00445       All addresses in the range [ @a min , @a max ] are marked with @a data.
00446       @return This object.
00447   */
00448   self& mark(
00449     ArgType min, ///< Minimum value in range.
00450     ArgType max, ///< Maximum value in range.
00451     void* data = 0     ///< Client data payload.
00452   );
00453   /** Unmark addresses.
00454 
00455       All addresses in the range [ @a min , @a max ] are cleared
00456       (removed from the map), no longer marked.
00457 
00458       @return This object.
00459   */
00460   self& unmark(
00461     ArgType min,
00462     ArgType max
00463   );
00464 
00465   /** Fill addresses.
00466 
00467       This background fills using the range. All addresses in the
00468       range that are @b not present in the map are added. No
00469       previously present address is changed.
00470 
00471       @note This is useful for filling in first match tables.
00472 
00473       @return This object.
00474   */
00475   self& fill(
00476     ArgType min,
00477     ArgType max,
00478     void* data = 0
00479   );
00480 
00481   /** Test for membership.
00482 
00483       @return @c true if the address is in the map, @c false if not.
00484       If the address is in the map and @a ptr is not @c NULL, @c *ptr
00485       is set to the client data for the address.
00486   */
00487   bool contains(
00488     ArgType target, ///< Search target value.
00489     void **ptr = 0 ///< Client data return.
00490   ) const;
00491 
00492   /** Remove all addresses in the map.
00493 
00494       @note This is much faster than using @c unmark with a range of
00495       all addresses.
00496 
00497       @return This object.
00498   */
00499   self& clear();
00500 
00501   /** Lower bound for @a target.  @return The node whose minimum value
00502       is the largest that is not greater than @a target, or @c NULL if
00503       all minimum values are larger than @a target.
00504   */
00505   N* lowerBound(ArgType target);
00506 
00507   /** Insert @a n after @a spot.
00508       Caller is responsible for ensuring that @a spot is in this container
00509       and the proper location for @a n.
00510   */
00511   void insertAfter(
00512     N* spot, ///< Node in list.
00513     N* n ///< Node to insert.
00514   );
00515   /** Insert @a n before @a spot.
00516       Caller is responsible for ensuring that @a spot is in this container
00517       and the proper location for @a n.
00518   */
00519   void insertBefore(
00520     N* spot, ///< Node in list.
00521     N* n ///< Node to insert.
00522   );
00523   /// Add node @a n as the first node.
00524   void prepend(
00525     N* n
00526   );
00527   /// Add node @a n as the last node.
00528   void append(
00529     N* n
00530   );
00531   /// Remove a node.
00532   void remove(
00533     N* n ///< Node to remove.
00534   );
00535 
00536   /** Validate internal data structures.
00537       @note Intended for debugging, not general client use.
00538   */
00539   void validate();
00540 
00541   /// @return The number of distinct ranges.
00542   size_t getCount() const;
00543 
00544   /// Print all spans.
00545   /// @return This map.
00546   self& print();
00547   
00548   // Helper methods.
00549   N* prev(RBNode* n) const { return static_cast<N*>(n->_prev); }
00550   N* next(RBNode* n) const { return static_cast<N*>(n->_next); }
00551   N* parent(RBNode* n) const { return static_cast<N*>(n->_parent); }
00552   N* left(RBNode* n) const { return static_cast<N*>(n->_left); }
00553   N* right(RBNode* n) const { return static_cast<N*>(n->_right); }
00554   N* getHead() { return static_cast<N*>(_list.getHead()); }
00555   N* getTail() { return static_cast<N*>(_list.getTail()); }
00556 
00557   N* _root; ///< Root node.
00558   /// In order list of nodes.
00559   /// For ugly compiler reasons, this is a list of base class pointers
00560   /// even though we really store @a N instances on it.
00561   typedef IntrusiveDList<RBNode, &RBNode::_next, &RBNode::_prev> NodeList;
00562   /// This keeps track of all allocated nodes in order.
00563   /// Iteration depends on this list being maintained.
00564   NodeList _list;
00565 };
00566 
00567 template < typename N > N*
00568 IpMapBase<N>::lowerBound(ArgType target) {
00569   N* n = _root; // current node to test.
00570   N* zret = 0; // best node so far.
00571   while (n) {
00572     if (target < n->_min) n = left(n);
00573     else {
00574       zret = n; // this is a better candidate.
00575       if (n->_max < target) n = right(n);
00576       else break;
00577     }
00578   }
00579   return zret;
00580 }
00581 
00582 template < typename N > IpMapBase<N>&
00583 IpMapBase<N>::clear() {
00584   // Delete everything.
00585   N* n = static_cast<N*>(_list.getHead());
00586   while (n) {
00587     N* x = n;
00588     n = next(n);
00589     delete x;
00590   }
00591   _list.clear();
00592   _root = 0;
00593   return *this;
00594 }
00595 
00596 template < typename N > IpMapBase<N>&
00597 IpMapBase<N>::fill(ArgType rmin, ArgType rmax, void* payload) {
00598   // Rightmost node of interest with n->_min <= min.
00599   N* n = this->lowerBound(rmin);
00600   N* x = 0; // New node (if any).
00601   // Need copies because we will modify these.
00602   Metric min = N::deref(rmin);
00603   Metric max = N::deref(rmax);
00604 
00605   // Handle cases involving a node of interest to the left of the
00606   // range.
00607   if (n) {
00608     if (n->_min < min) {
00609       Metric min_1 = min;
00610       N::dec(min_1);  // dec is OK because min isn't zero.
00611       if (n->_max < min_1) { // no overlap or adj.
00612         n = next(n);
00613       } else if (n->_max >= max) { // incoming range is covered, just discard.
00614         return *this;
00615       } else if (n->_data != payload) { // different payload, clip range on left.
00616         min = n->_max;
00617         N::inc(min);
00618         n = next(n);
00619       } else { // skew overlap with same payload, use node and continue.
00620         x = n;
00621         n = next(n);
00622       }
00623     }
00624   } else {
00625     n = this->getHead();
00626   }
00627 
00628   // Work through the rest of the nodes of interest.
00629   // Invariant: n->_min >= min
00630 
00631   // Careful here -- because max_plus1 might wrap we need to use it only
00632   // if we can certain it didn't. This is done by ordering the range
00633   // tests so that when max_plus1 is used when we know there exists a
00634   // larger value than max.
00635   Metric max_plus1 = max;
00636   N::inc(max_plus1);
00637   /* Notes:
00638      - max (and thence max_plus1) never change during the loop.
00639      - we must have either x != 0 or adjust min but not both.
00640   */
00641   while (n) {
00642     if (n->_data == payload) {
00643       if (x) {
00644         if (n->_max <= max) {
00645           // next range is covered, so we can remove and continue.
00646           this->remove(n);
00647           n = next(x);
00648         } else if (n->_min <= max_plus1) {
00649           // Overlap or adjacent with larger max - absorb and finish.
00650           x->setMax(n->_max);
00651           this->remove(n);
00652           return *this;
00653         } else {
00654           // have the space to finish off the range.
00655           x->setMax(max);
00656           return *this;
00657         }
00658       } else { // not carrying a span.
00659         if (n->_max <= max) { // next range is covered - use it.
00660           x = n;
00661           x->setMin(min);
00662           n = next(n);
00663         } else if (n->_min <= max_plus1) {
00664           n->setMin(min);
00665           return *this;
00666         } else { // no overlap, space to complete range.
00667           this->insertBefore(n, new N(min, max, payload));
00668           return *this;
00669         }
00670       }
00671     } else { // different payload
00672       if (x) {
00673         if (max < n->_min) { // range ends before n starts, done.
00674           x->setMax(max);
00675           return *this;
00676         } else if (max <= n->_max) { // range ends before n, done.
00677           x->setMaxMinusOne(n->_min);
00678           return *this;
00679         } else { // n is contained in range, skip over it.
00680           x->setMaxMinusOne(n->_min);
00681           x = 0;
00682           min = n->_max;
00683           N::inc(min); // OK because n->_max maximal => next is null.
00684           n = next(n);
00685         }
00686       } else { // no carry node.
00687         if (max < n->_min) { // entirely before next span.
00688           this->insertBefore(n, new N(min, max, payload));
00689           return *this;
00690         } else {
00691           if (min < n->_min) { // leading section, need node.
00692             N* y = new N(min, n->_min, payload);
00693             y->decrementMax();
00694             this->insertBefore(n, y);
00695           }
00696           if (max <= n->_max) // nothing past node
00697             return *this;
00698           min = n->_max;
00699           N::inc(min);
00700           n = next(n);
00701         }
00702       }
00703     }
00704   }
00705   // Invariant: min is larger than any existing range maximum.
00706   if (x) {
00707     x->setMax(max);
00708   } else {
00709     this->append(new N(min, max, payload));
00710   }
00711   return *this;
00712 }
00713 
00714 template < typename N > IpMapBase<N>&
00715 IpMapBase<N>::mark(ArgType min, ArgType max, void* payload) {
00716   N* n = this->lowerBound(min); // current node.
00717   N* x = 0; // New node, gets set if we re-use an existing one.
00718   N* y = 0; // Temporary for removing and advancing.
00719 
00720   // Several places it is handy to have max+1. Must be careful
00721   // about wrapping.
00722   Metric max_plus = N::deref(max);
00723   N::inc(max_plus);
00724 
00725   /* Some subtlety - for IPv6 we overload the compare operators to do
00726      the right thing, but we can't overload pointer
00727      comparisons. Therefore we carefully never compare pointers in
00728      this logic. Only @a min and @a max can be pointers, everything
00729      else is an instance or a reference. Since there's no good reason
00730      to compare @a min and @a max this isn't particularly tricky, but
00731      it's good to keep in mind. If we were somewhat more clever, we
00732      would provide static less than and equal operators in the
00733      template class @a N and convert all the comparisons to use only
00734      those two via static function call.
00735   */
00736 
00737   /*  We have lots of special cases here primarily to minimize memory
00738       allocation by re-using an existing node as often as possible.
00739   */
00740   if (n) {
00741     // Watch for wrap.
00742     Metric min_1 = N::deref(min);
00743     N::dec(min_1);
00744     if (n->_min == min) {
00745       // Could be another span further left which is adjacent.
00746       // Coalesce if the data is the same. min_1 is OK because
00747       // if there is a previous range, min is not zero.
00748       N* p = prev(n);
00749       if (p && p->_data == payload && p->_max == min_1) {
00750         x = p;
00751         n = x; // need to back up n because frame of reference moved.
00752         x->setMax(max);
00753       } else if (n->_max <= max) {
00754         // Span will be subsumed by request span so it's available for use.
00755         x = n;
00756         x->setMax(max).setData(payload);
00757       } else if (n->_data == payload) {
00758         return *this; // request is covered by existing span with the same data
00759       } else {
00760         // request span is covered by existing span.
00761         x = new N(min, max, payload); //
00762         n->setMin(max_plus); // clip existing.
00763         this->insertBefore(n, x);
00764         return *this;
00765       }
00766     } else if (n->_data == payload && n->_max >= min_1) {
00767       // min_1 is safe here because n->_min < min so min is not zero.
00768       x = n;
00769       // If the existing span covers the requested span, we're done.
00770       if (x->_max >= max) return *this;
00771       x->setMax(max);
00772     } else if (n->_max <= max) {
00773       // Can only have left skew overlap, otherwise disjoint.
00774       // Clip if overlap.
00775       if (n->_max >= min) n->setMax(min_1);
00776       else if (next(n) && n->_max <= max) {
00777         // request region covers next span so we can re-use that node.
00778         x = next(n);
00779         x->setMin(min).setMax(max).setData(payload);
00780         n = x; // this gets bumped again, which is correct.
00781       }
00782     } else {
00783       // Existing span covers new span but with a different payload.
00784       // We split it, put the new span in between and we're done.
00785       // max_plus is valid because n->_max > max.
00786       N* r;
00787       x = new N(min, max, payload);
00788       r = new N(max_plus, n->_max, n->_data);
00789       n->setMax(min_1);
00790       this->insertAfter(n, x);
00791       this->insertAfter(x, r);
00792       return *this; // done.
00793     }
00794     n = next(n); // lower bound span handled, move on.
00795     if (!x) {
00796       x = new N(min, max, payload);
00797       if (n) this->insertBefore(n, x);
00798       else this->append(x); // note that since n == 0 we'll just return.
00799     }
00800   } else if (0 != (n = this->getHead()) && // at least one node in tree.
00801              n->_data == payload && // payload matches
00802              (n->_max <= max || n->_min <= max_plus) // overlap or adj.
00803   ) {
00804     // Same payload with overlap, re-use.
00805     x = n;
00806     n = next(n);
00807     x->setMin(min);
00808     if (x->_max < max) x->setMax(max);
00809   } else {
00810     x = new N(min, max, payload);
00811     this->prepend(x);
00812   }
00813 
00814   // At this point, @a x has the node for this span and all existing spans of
00815   // interest start at or past this span.
00816   while (n) {
00817     if (n->_max <= max) { // completely covered, drop span, continue
00818       y = n;
00819       n = next(n);
00820       this->remove(y);
00821     } else if (max_plus < n->_min) { // no overlap, done.
00822       break;
00823     } else if (n->_data == payload) { // skew overlap or adj., same payload
00824       x->setMax(n->_max);
00825       y = n;
00826       n = next(n);
00827       this->remove(y);
00828     } else if (n->_min <= max) { // skew overlap different payload
00829       n->setMin(max_plus);
00830       break;
00831     }
00832   }
00833 
00834   return *this;
00835 }
00836 
00837 template <typename N> IpMapBase<N>&
00838 IpMapBase<N>::unmark(ArgType min, ArgType max) {
00839   N* n = this->lowerBound(min);
00840   N* x; // temp for deletes.
00841 
00842   // Need to handle special case where first span starts to the left.
00843   if (n && n->_min < min) {
00844     if (n->_max >= min) { // some overlap
00845       if (n->_max > max) {
00846         // request span is covered by existing span - split existing span.
00847         x = new N(max, N::argue(n->_max), n->_data);
00848         x->incrementMin();
00849         n->setMaxMinusOne(N::deref(min));
00850         this->insertAfter(n, x);
00851         return *this; // done.
00852       } else {
00853         n->setMaxMinusOne(N::deref(min)); // just clip overlap.
00854       }
00855     } // else disjoint so just skip it.
00856     n = next(n);
00857   }
00858   // n and all subsequent spans start at >= min.
00859   while (n) {
00860     x = n;
00861     n = next(n);
00862     if (x->_max <= max) {
00863       this->remove(x);
00864     } else {
00865       if (x->_min <= max) { // clip overlap
00866         x->setMinPlusOne(N::deref(max));
00867       }
00868       break;
00869     }
00870   }
00871   return *this;
00872 }
00873 
00874 template <typename N> void
00875 IpMapBase<N>::insertAfter(N* spot, N* n) {
00876   N* c = right(spot);
00877   if (!c) spot->setChild(n, N::RIGHT);
00878   else spot->_next->setChild(n, N::LEFT);
00879 
00880   _list.insertAfter(spot, n);
00881   _root = static_cast<N*>(n->rebalanceAfterInsert());
00882 }
00883 
00884 template <typename N> void
00885 IpMapBase<N>::insertBefore(N* spot, N* n) {
00886   N* c = left(spot);
00887   if (!c) spot->setChild(n, N::LEFT);
00888   else spot->_prev->setChild(n, N::RIGHT);
00889 
00890   _list.insertBefore(spot, n);
00891   _root = static_cast<N*>(n->rebalanceAfterInsert());
00892 }
00893 
00894 template <typename N> void
00895 IpMapBase<N>::prepend(N* n) {
00896   if (!_root) _root = n;
00897   else _root = static_cast<N*>(_list.getHead()->setChild(n, N::LEFT)->rebalanceAfterInsert());
00898   _list.prepend(n);
00899 }
00900 
00901 template <typename N> void
00902 IpMapBase<N>::append(N* n) {
00903   if (!_root) _root = n;
00904   else _root = static_cast<N*>(_list.getTail()->setChild(n, N::RIGHT)->rebalanceAfterInsert());
00905   _list.append(n);
00906 }
00907 
00908 template <typename N> void
00909 IpMapBase<N>::remove(N* n) {
00910   _root = static_cast<N*>(n->remove());
00911   _list.take(n);
00912   delete n;
00913 }
00914 
00915 template <typename N> bool
00916 IpMapBase<N>::contains(ArgType x, void** ptr) const {
00917   bool zret = false;
00918   N* n = _root; // current node to test.
00919   while (n) {
00920     if (x < n->_min) n = left(n);
00921     else if (n->_max < x) n = right(n);
00922     else {
00923       if (ptr) *ptr = n->_data;
00924       zret = true;
00925       break;
00926     }
00927   }
00928   return zret;
00929 }
00930 
00931 template < typename N > size_t IpMapBase<N>::getCount() const { return _list.getCount(); }
00932 //----------------------------------------------------------------------------
00933 template <typename N> void
00934 IpMapBase<N>::validate() {
00935 # if 0
00936   if (_root) _root->validate();
00937   for ( Node* n = _list.getHead() ; n ; n = n->_next ) {
00938     Node* x;
00939     if (0 != (x = n->_next)) {
00940       if (x->_prev != n)
00941         std::cout << "Broken list" << std::endl;
00942       if (n->_max >= x->_min)
00943         std::cout << "Out of order - " << n->_max << " > " << x->_min << std::endl;
00944       if (n->_parent == n || n->_left == n || n->_right == n)
00945         std::cout << "Looped node" << std::endl;
00946     }
00947   }
00948 # endif
00949 }
00950 
00951 template <typename N> IpMapBase<N>&
00952 IpMapBase<N>::print() {
00953 # if 0
00954   for ( Node* n = _list.getHead() ; n ; n = n->_next ) {
00955     std::cout
00956       << n << ": " << n->_min << '-' << n->_max << " [" << n->_data << "] "
00957       << (n->_color == Node::BLACK ? "Black " : "Red   ") << "P=" << n->_parent << " L=" << n->_left << " R=" << n->_right
00958       << std::endl;
00959   }
00960 # endif
00961   return *this;
00962 }
00963 
00964 //----------------------------------------------------------------------------
00965 typedef Interval<in_addr_t, in_addr_t> Ip4Span;
00966 
00967 /** Node for IPv4 map.
00968     We store the address in host order in the @a _min and @a _max
00969     members for performance. We store copies in the @a _sa member
00970     for API compliance (which requires @c sockaddr* access).
00971 */
00972 class Ip4Node : public IpMap::Node, protected Ip4Span {
00973   friend struct IpMapBase<Ip4Node>;
00974 public:
00975   typedef Ip4Node self; ///< Self reference type.
00976 
00977   /// Construct with values.
00978   Ip4Node(
00979     ArgType min, ///< Minimum address (host order).
00980     ArgType max, ///< Maximum address (host order).
00981     void* data ///< Client data.
00982   ) : Node(data), Ip4Span(min, max) {
00983     ats_ip4_set(ats_ip_sa_cast(&_sa._min), htonl(min));
00984     ats_ip4_set(ats_ip_sa_cast(&_sa._max), htonl(max));
00985   }
00986   /// @return The minimum value of the interval.
00987   virtual sockaddr const* min() const {
00988     return ats_ip_sa_cast(&_sa._min);
00989   }
00990   /// @return The maximum value of the interval.
00991   virtual sockaddr const* max() const {
00992     return ats_ip_sa_cast(&_sa._max);
00993   }
00994   /// Set the client data.
00995   self& setData(
00996     void* data ///< Client data.
00997   ) {
00998     _data = data;
00999     return *this;
01000   }
01001 protected:
01002   
01003   /// Set the minimum value of the interval.
01004   /// @return This interval.
01005   self& setMin(
01006     ArgType min ///< Minimum value (host order).
01007   ) {
01008     _min = min;
01009     _sa._min.sin_addr.s_addr = htonl(min);
01010     return *this;
01011   }
01012   
01013   /// Set the maximum value of the interval.
01014   /// @return This interval.
01015   self& setMax(
01016     ArgType max ///< Maximum value (host order).
01017   ) {
01018     _max = max;
01019     _sa._max.sin_addr.s_addr = htonl(max);
01020     return *this;
01021   }
01022   
01023   /** Set the maximum value to one less than @a max.
01024       @return This object.
01025   */
01026   self& setMaxMinusOne(
01027     ArgType max ///< One more than maximum value.
01028   ) {
01029     return this->setMax(max-1);
01030   }
01031   /** Set the minimum value to one more than @a min.
01032       @return This object.
01033   */
01034   self& setMinPlusOne(
01035     ArgType min ///< One less than minimum value.
01036   ) {
01037     return this->setMin(min+1);
01038   }
01039   /** Decremement the maximum value in place.
01040       @return This object.
01041   */
01042   self& decrementMax() {
01043     this->setMax(_max-1);
01044     return *this;
01045   }
01046   /** Increment the minimum value in place.
01047       @return This object.
01048   */
01049   self& incrementMin() {
01050     this->setMin(_min+1);
01051     return *this;
01052   }
01053 
01054   /// Increment a metric.
01055   static void inc(
01056     Metric& m ///< Incremented in place.
01057   ) {
01058     ++m;
01059   }
01060   
01061   /// Decrement a metric.
01062   static void dec(
01063     Metric& m ///< Decremented in place.
01064   ) {
01065     --m;
01066   }
01067   
01068   /// @return Dereferenced @a addr.
01069   static Metric deref(
01070     ArgType addr ///< Argument to dereference.
01071   ) {
01072     return addr;
01073   }
01074 
01075   /// @return The argument type for the @a metric.
01076   static ArgType argue(
01077     Metric const& metric
01078   ) {
01079     return metric;
01080   }
01081   
01082   struct {
01083     sockaddr_in _min;
01084     sockaddr_in _max;
01085   } _sa; ///< Addresses in API compliant form.
01086 
01087 };
01088 
01089 class Ip4Map : public IpMapBase<Ip4Node> {
01090   friend class ::IpMap;
01091 };
01092 
01093 //----------------------------------------------------------------------------
01094 typedef Interval<sockaddr_in6> Ip6Span;
01095 
01096 /** Node for IPv6 map.
01097 */
01098 class Ip6Node : public IpMap::Node, protected Ip6Span {
01099   friend struct IpMapBase<Ip6Node>;
01100 public:
01101   typedef Ip6Node self; ///< Self reference type.
01102   /// Override @c ArgType from @c Interval because the convention
01103   /// is to use a pointer, not a reference.
01104   typedef Metric const* ArgType;
01105 
01106   /// Construct from pointers.
01107   Ip6Node(
01108     ArgType min, ///< Minimum address (network order).
01109     ArgType max, ///< Maximum address (network order).
01110     void* data ///< Client data.
01111   ) : Node(data), Ip6Span(*min, *max) {
01112   }
01113   /// Construct with values.
01114   Ip6Node(
01115     Metric const& min, ///< Minimum address (network order).
01116     Metric const& max, ///< Maximum address (network order).
01117     void* data ///< Client data.
01118   ) : Node(data), Ip6Span(min, max) {
01119   }
01120   /// @return The minimum value of the interval.
01121   virtual sockaddr const* min() const {
01122     return ats_ip_sa_cast(&_min);
01123   }
01124   /// @return The maximum value of the interval.
01125   virtual sockaddr const* max() const {
01126     return ats_ip_sa_cast(&_max);
01127   }
01128   /// Set the client data.
01129   self& setData(
01130     void* data ///< Client data.
01131   ) {
01132     _data = data;
01133     return *this;
01134   }
01135 protected:
01136   
01137   /// Set the minimum value of the interval.
01138   /// @return This interval.
01139   self& setMin(
01140     ArgType min ///< Minimum value (host order).
01141   ) {
01142     ats_ip_copy(ats_ip_sa_cast(&_min), ats_ip_sa_cast(min));
01143     return *this;
01144   }
01145   
01146   /// Set the minimum value of the interval.
01147   /// @note Convenience overload.
01148   /// @return This interval.
01149   self& setMin(
01150     Metric const& min ///< Minimum value (host order).
01151   ) {
01152     return this->setMin(&min);
01153   }
01154   
01155   /// Set the maximum value of the interval.
01156   /// @return This interval.
01157   self& setMax(
01158     ArgType max ///< Maximum value (host order).
01159   ) {
01160     ats_ip_copy(ats_ip_sa_cast(&_max), ats_ip_sa_cast(max));
01161     return *this;
01162   }
01163   /// Set the maximum value of the interval.
01164   /// @note Convenience overload.
01165   /// @return This interval.
01166   self& setMax(
01167     Metric const& max ///< Maximum value (host order).
01168   ) {
01169     return this->setMax(&max);
01170   }
01171   /** Set the maximum value to one less than @a max.
01172       @return This object.
01173   */
01174   self& setMaxMinusOne(
01175     Metric const& max ///< One more than maximum value.
01176   ) {
01177     this->setMax(max);
01178     dec(_max);
01179     return *this;
01180   }
01181   /** Set the minimum value to one more than @a min.
01182       @return This object.
01183   */
01184   self& setMinPlusOne(
01185     Metric const& min ///< One less than minimum value.
01186   ) {
01187     this->setMin(min);
01188     inc(_min);
01189     return *this;
01190   }
01191   /** Decremement the maximum value in place.
01192       @return This object.
01193   */
01194   self& decrementMax() { dec(_max); return *this; }
01195   /** Increment the mininimum value in place.
01196       @return This object.
01197   */
01198   self& incrementMin() { inc(_min); return *this; }
01199   
01200   /// Increment a metric.
01201   static void inc(
01202     Metric& m ///< Incremented in place.
01203   ) {
01204     uint8_t* addr = m.sin6_addr.s6_addr;
01205     uint8_t* b = addr + TS_IP6_SIZE;
01206     // Ripple carry. Walk up the address incrementing until we don't
01207     // have a carry.
01208     do {
01209       ++*--b;
01210     } while (b > addr && 0 == *b);
01211   }
01212   
01213   /// Decrement a metric.
01214   static void dec(
01215     Metric& m ///< Decremented in place.
01216   ) {
01217     uint8_t* addr = m.sin6_addr.s6_addr;
01218     uint8_t* b = addr + TS_IP6_SIZE;
01219     // Ripple borrow. Walk up the address decrementing until we don't
01220     // have a borrow.
01221     do {
01222       --*--b;
01223     } while (b > addr && static_cast<uint8_t>(0xFF) == *b);
01224   }
01225   /// @return Dereferenced @a addr.
01226   static Metric const& deref(
01227     ArgType addr ///< Argument to dereference.
01228   ) {
01229     return *addr;
01230   }
01231   
01232   /// @return The argument type for the @a metric.
01233   static ArgType argue(
01234     Metric const& metric
01235   ) {
01236     return &metric;
01237   }
01238   
01239 };
01240 
01241 // We declare this after the helper operators and inside this namespace
01242 // so that the template uses these for comparisons.
01243 
01244 class Ip6Map : public IpMapBase<Ip6Node> {
01245   friend class ::IpMap;
01246 };
01247 
01248 }} // end ts::detail
01249 //----------------------------------------------------------------------------
01250 IpMap::~IpMap() {
01251   delete _m4;
01252   delete _m6;
01253 }
01254 
01255 inline ts::detail::Ip4Map*
01256 IpMap::force4() {
01257   if (!_m4) _m4 = new ts::detail::Ip4Map;
01258   return _m4;
01259 }
01260 
01261 inline ts::detail::Ip6Map*
01262 IpMap::force6() {
01263   if (!_m6) _m6 = new ts::detail::Ip6Map;
01264   return _m6;
01265 }
01266 
01267 bool
01268 IpMap::contains(sockaddr const* target, void** ptr) const {
01269   bool zret = false;
01270   if (AF_INET == target->sa_family) {
01271     zret = _m4 && _m4->contains(ntohl(ats_ip4_addr_cast(target)), ptr);
01272   } else if (AF_INET6 == target->sa_family) {
01273     zret = _m6 && _m6->contains(ats_ip6_cast(target), ptr);
01274   }
01275   return zret;
01276 }
01277 
01278 bool
01279 IpMap::contains(in_addr_t target, void** ptr) const {
01280   return _m4 && _m4->contains(ntohl(target), ptr);
01281 }
01282 
01283 IpMap&
01284 IpMap::mark(
01285   sockaddr const* min,
01286   sockaddr const* max,
01287   void* data
01288 ) {
01289   ink_assert(min->sa_family == max->sa_family);
01290   if (AF_INET == min->sa_family) {
01291     this->force4()->mark(
01292       ntohl(ats_ip4_addr_cast(min)),
01293       ntohl(ats_ip4_addr_cast(max)),
01294       data
01295     );
01296   } else if (AF_INET6 == min->sa_family) {
01297     this->force6()->mark(ats_ip6_cast(min), ats_ip6_cast(max), data);
01298   }
01299   return *this;
01300 }
01301 
01302 IpMap&
01303 IpMap::mark(in_addr_t min, in_addr_t max, void* data) {
01304   this->force4()->mark(ntohl(min), ntohl(max), data);
01305   return *this;
01306 }
01307 
01308 IpMap&
01309 IpMap::unmark(
01310   sockaddr const* min,
01311   sockaddr const* max
01312 ) {
01313   ink_assert(min->sa_family == max->sa_family);
01314   if (AF_INET == min->sa_family) {
01315     if (_m4)
01316       _m4->unmark(
01317         ntohl(ats_ip4_addr_cast(min)),
01318         ntohl(ats_ip4_addr_cast(max))
01319       );
01320   } else if (AF_INET6 == min->sa_family) {
01321     if (_m6) _m6->unmark(ats_ip6_cast(min), ats_ip6_cast(max));
01322   }
01323   return *this;
01324 }
01325 
01326 IpMap&
01327 IpMap::unmark(in_addr_t min, in_addr_t max) {
01328   if (_m4) _m4->unmark(ntohl(min), ntohl(max));
01329   return *this;
01330 }
01331 
01332 IpMap&
01333 IpMap::fill(
01334   sockaddr const* min,
01335   sockaddr const* max,
01336   void* data
01337 ) {
01338   ink_assert(min->sa_family == max->sa_family);
01339   if (AF_INET == min->sa_family) {
01340     this->force4()->fill(
01341       ntohl(ats_ip4_addr_cast(min)),
01342       ntohl(ats_ip4_addr_cast(max)),
01343       data
01344     );
01345   } else if (AF_INET6 == min->sa_family) {
01346     this->force6()->fill(ats_ip6_cast(min), ats_ip6_cast(max), data);
01347   }
01348   return *this;
01349 }
01350 
01351 IpMap&
01352 IpMap::fill(in_addr_t min, in_addr_t max, void* data) {
01353   this->force4()->fill(ntohl(min), ntohl(max), data);
01354   return *this;
01355 }
01356 
01357 size_t
01358 IpMap::getCount() const {
01359   size_t zret = 0;
01360   if (_m4) zret += _m4->getCount();
01361   if (_m6) zret += _m6->getCount();
01362   return zret;
01363 }
01364 
01365 IpMap&
01366 IpMap::clear() {
01367   if (_m4) _m4->clear();
01368   if (_m6) _m6->clear();
01369   return *this;
01370 }
01371 
01372 IpMap::iterator
01373 IpMap::begin() const {
01374   Node* x = 0;
01375   if (_m4) x = _m4->getHead();
01376   if (!x && _m6) x = _m6->getHead();
01377   return iterator(this, x);
01378 }
01379 
01380 IpMap::iterator&
01381 IpMap::iterator::operator ++ () {
01382   if (_node) {
01383     // If we go past the end of the list see if it was the v4 list
01384     // and if so, move to the v6 list (if it's there).
01385     Node* x = static_cast<Node*>(_node->_next);
01386     if (!x && _tree->_m4 && _tree->_m6 && _node == _tree->_m4->getTail())
01387       x = _tree->_m6->getHead();
01388     _node = x;
01389   }
01390   return *this;
01391 }
01392 
01393 inline IpMap::iterator&
01394 IpMap::iterator::operator--() {
01395   if (_node) {
01396     // At a node, try to back up. Handle the case where we back over the
01397     // start of the v6 addresses and switch to the v4, if there are any.
01398     Node* x = static_cast<Node*>(_node->_prev);
01399     if (!x && _tree->_m4 && _tree->_m6 && _node == _tree->_m6->getHead())
01400       x = _tree->_m4->getTail();
01401     _node = x;
01402   } else if (_tree) {
01403     // We were at the end. Back up to v6 if possible, v4 if not.
01404     if (_tree->_m6) _node = _tree->_m6->getTail();
01405     if (!_node && _tree->_m4) _node = _tree->_m4->getTail();
01406   }
01407   return *this;
01408 }
01409 
01410 
01411 //----------------------------------------------------------------------------
01412 //----------------------------------------------------------------------------
01413 

Generated by  doxygen 1.7.1