~ubuntu-branches/ubuntu/wily/trafficserver/wily

« back to all changes in this revision

Viewing changes to lib/ts/IpMap.cc

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2012-12-17 22:28:16 UTC
  • mfrom: (5.1.8 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20121217222816-7xwjsx5k76zkb63d
Tags: 3.2.0-1ubuntu1
* Revert FreeBSD strerror_r() fixes that give errors with glibc 2.16.
* Apply patch from Konstantinos Margaritis to define barriers on ARM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# include "IpMap.h"
 
2
 
 
3
/** @file
 
4
    IP address map support.
 
5
 
 
6
    Provide the ability to create a range based mapping for the IP
 
7
    address space. Addresses can be added and removed and each address
 
8
    is associated with arbitrary client data.
 
9
 
 
10
    @internal Don't bother to look at this code if you don't know how
 
11
    a red/black tree works. There are so many good references on the
 
12
    subject it's a waste to have some inferior version here. The
 
13
    methods on @c Node follow the standard implementation except for
 
14
    being parameterized by direction (so that, for instance, right
 
15
    rotate and left rotate are both done by the @c rotate method with
 
16
    a direction argument).
 
17
 
 
18
    @section license License
 
19
 
 
20
    Licensed to the Apache Software Foundation (ASF) under one
 
21
    or more contributor license agreements.  See the NOTICE file
 
22
    distributed with this work for additional information
 
23
    regarding copyright ownership.  The ASF licenses this file
 
24
    to you under the Apache License, Version 2.0 (the
 
25
    "License"); you may not use this file except in compliance
 
26
    with the License.  You may obtain a copy of the License at
 
27
 
 
28
    http://www.apache.org/licenses/LICENSE-2.0
 
29
 
 
30
    Unless required by applicable law or agreed to in writing, software
 
31
    distributed under the License is distributed on an "AS IS" BASIS,
 
32
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
33
    See the License for the specific language governing permissions and
 
34
    limitations under the License.
 
35
 */
 
36
 
 
37
// Validation / printing disabled until I figure out how to generalize so
 
38
// as to not tie reporting into a particular project environment.
 
39
 
 
40
namespace ts { namespace detail {
 
41
 
 
42
// Helper functions
 
43
 
 
44
inline int cmp(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
 
45
  return memcmp(lhs.sin6_addr.s6_addr, rhs.sin6_addr.s6_addr, TS_IP6_SIZE);
 
46
}
 
47
 
 
48
/// Less than.
 
49
inline bool operator<(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
 
50
  return ts::detail::cmp(lhs, rhs) < 0;
 
51
}
 
52
inline bool operator<(sockaddr_in6 const* lhs, sockaddr_in6 const& rhs) {
 
53
  return ts::detail::cmp(*lhs, rhs) < 0;
 
54
}
 
55
/// Less than.
 
56
inline bool operator<(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
 
57
  return ts::detail::cmp(lhs, *rhs) < 0;
 
58
}
 
59
/// Equality.
 
60
inline bool operator==(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
 
61
  return ts::detail::cmp(lhs, *rhs) == 0;
 
62
}
 
63
/// Equality.
 
64
inline bool operator==(sockaddr_in6 const* lhs, sockaddr_in6 const& rhs) {
 
65
  return ts::detail::cmp(*lhs, rhs) == 0;
 
66
}
 
67
/// Equality.
 
68
inline bool operator==(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
 
69
  return ts::detail::cmp(lhs, rhs) == 0;
 
70
}
 
71
/// Less than or equal.
 
72
inline bool operator<=(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
 
73
  return ts::detail::cmp(lhs, *rhs) <= 0;
 
74
}
 
75
/// Less than or equal.
 
76
inline bool operator<=(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
 
77
  return ts::detail::cmp(lhs, rhs) <= 0;
 
78
}
 
79
/// Greater than or equal.
 
80
inline bool operator>=(sockaddr_in6 const& lhs, sockaddr_in6 const& rhs) {
 
81
  return ts::detail::cmp(lhs, rhs) >= 0;
 
82
}
 
83
/// Greater than or equal.
 
84
inline bool operator>=(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
 
85
  return ts::detail::cmp(lhs, *rhs) >= 0;
 
86
}
 
87
/// Greater than.
 
88
inline bool operator>(sockaddr_in6 const& lhs, sockaddr_in6 const* rhs) {
 
89
  return ts::detail::cmp(lhs, *rhs) > 0;
 
90
}
 
91
 
 
92
/// Equality.
 
93
/// @note If @a n is @c NULL it is treated as having the color @c BLACK.
 
94
/// @return @c true if @a c and the color of @a n are the same.
 
95
inline bool operator == ( RBNode* n, RBNode::Color c ) {
 
96
  return c == ( n ? n->getColor() : RBNode::BLACK);
 
97
}
 
98
/// Equality.
 
99
/// @note If @a n is @c NULL it is treated as having the color @c BLACK.
 
100
/// @return @c true if @a c and the color of @a n are the same.
 
101
inline bool operator == ( RBNode::Color c, RBNode* n ) {
 
102
  return n == c;
 
103
}
 
104
 
 
105
inline RBNode*
 
106
RBNode::getChild(Direction d) const {
 
107
  return d == RIGHT ? _right
 
108
    : d == LEFT ? _left
 
109
    : 0
 
110
    ;
 
111
}
 
112
 
 
113
RBNode*
 
114
RBNode::rotate(Direction d) {
 
115
  self* parent = _parent; // Cache because it can change before we use it.
 
116
  Direction child_dir = _parent ? _parent->getChildDirection(this) : NONE;
 
117
  Direction other_dir = this->flip(d);
 
118
  self* child = this;
 
119
 
 
120
  if (d != NONE && this->getChild(other_dir)) {
 
121
    child = this->getChild(other_dir);
 
122
    this->clearChild(other_dir);
 
123
    this->setChild(child->getChild(d), other_dir);
 
124
    child->clearChild(d);
 
125
    child->setChild(this, d);
 
126
    child->structureFixup();
 
127
    this->structureFixup();
 
128
    if (parent) {
 
129
      parent->clearChild(child_dir);
 
130
      parent->setChild(child, child_dir);
 
131
    } else {
 
132
      child->_parent = 0;
 
133
    }
 
134
  }
 
135
  return child;
 
136
}
 
137
 
 
138
RBNode*
 
139
RBNode::setChild(self* n, Direction d) {
 
140
  if (n) n->_parent = this;
 
141
  if (d == RIGHT) _right = n;
 
142
  else if (d == LEFT) _left = n;
 
143
  return n;
 
144
}
 
145
 
 
146
// Returns the root node
 
147
RBNode*
 
148
RBNode::rippleStructureFixup() {
 
149
  self* root = this; // last node seen, root node at the end
 
150
  self* p = this;
 
151
  while (p) {
 
152
    p->structureFixup();
 
153
    root = p;
 
154
    p = root->_parent;
 
155
  }
 
156
  return root;
 
157
}
 
158
 
 
159
void
 
160
RBNode::replaceWith(self* n) {
 
161
  n->_color = _color;
 
162
  if (_parent) {
 
163
    Direction d = _parent->getChildDirection(this);
 
164
    _parent->setChild(0, d);
 
165
    if (_parent != n) _parent->setChild(n, d);
 
166
  } else {
 
167
    n->_parent = 0;
 
168
  }
 
169
  n->_left = n->_right = 0;
 
170
  if (_left && _left != n) n->setChild(_left, LEFT);
 
171
  if (_right && _right != n) n->setChild(_right, RIGHT);
 
172
  _left = _right = 0;
 
173
}
 
174
 
 
175
/* Rebalance the tree. This node is the unbalanced node. */
 
176
RBNode*
 
177
RBNode::rebalanceAfterInsert() {
 
178
  self* x(this); // the node with the imbalance
 
179
 
 
180
  while (x && x->_parent == RED) {
 
181
    Direction child_dir = NONE;
 
182
        
 
183
    if (x->_parent->_parent)
 
184
      child_dir = x->_parent->_parent->getChildDirection(x->_parent);
 
185
    else
 
186
      break;
 
187
    Direction other_dir(flip(child_dir));
 
188
        
 
189
    self* y = x->_parent->_parent->getChild(other_dir);
 
190
    if (y == RED) {
 
191
      x->_parent->_color = BLACK;
 
192
      y->_color = BLACK;
 
193
      x = x->_parent->_parent;
 
194
      x->_color = RED;
 
195
    } else {
 
196
      if (x->_parent->getChild(other_dir) == x) {
 
197
        x = x->_parent;
 
198
        x->rotate(child_dir);
 
199
      }
 
200
      // Note setting the parent color to BLACK causes the loop to exit.
 
201
      x->_parent->_color = BLACK;
 
202
      x->_parent->_parent->_color = RED;
 
203
      x->_parent->_parent->rotate(other_dir);
 
204
    }
 
205
  }
 
206
    
 
207
  // every node above this one has a subtree structure change,
 
208
  // so notify it. serendipitously, this makes it easy to return
 
209
  // the new root node.
 
210
  self* root = this->rippleStructureFixup();
 
211
  root->_color = BLACK;
 
212
 
 
213
  return root;
 
214
}
 
215
 
 
216
 
 
217
// Returns new root node
 
218
RBNode*
 
219
RBNode::remove() {
 
220
  self* root = 0; // new root node, returned to caller
 
221
 
 
222
  /*  Handle two special cases first.
 
223
      - This is the only node in the tree, return a new root of NIL
 
224
      - This is the root node with only one child, return that child as new root
 
225
  */
 
226
  if (!_parent && !(_left && _right)) {
 
227
    if (_left) {
 
228
      _left->_parent = 0;
 
229
      root = _left;
 
230
      root->_color = BLACK;
 
231
    } else if (_right) {
 
232
      _right->_parent = 0;
 
233
      root = _right;
 
234
      root->_color = BLACK;
 
235
    } // else that was the only node, so leave @a root @c NULL.
 
236
    return root;
 
237
  }
 
238
 
 
239
  /*  The node to be removed from the tree.
 
240
      If @c this (the target node) has both children, we remove
 
241
      its successor, which cannot have a left child and
 
242
      put that node in place of the target node. Otherwise this
 
243
      node has at most one child, so we can remove it.
 
244
      Note that the successor of a node with a right child is always
 
245
      a right descendant of the node. Therefore, remove_node
 
246
      is an element of the tree rooted at this node.
 
247
      Because of the initial special case checks, we know
 
248
      that remove_node is @b not the root node.
 
249
  */
 
250
  self* remove_node(_left && _right ? _next : this);
 
251
 
 
252
  // This is the color of the node physically removed from the tree.
 
253
  // Normally this is the color of @a remove_node
 
254
  Color remove_color = remove_node->_color;
 
255
  // Need to remember the direction from @a remove_node to @a splice_node
 
256
  Direction d(NONE);
 
257
 
 
258
  // The child node that will be promoted to replace the removed node.
 
259
  // The choice of left or right is irrelevant, as remove_node has at
 
260
  // most one child (and splice_node may be NIL if remove_node has no
 
261
  // children).
 
262
  self* splice_node(remove_node->_left
 
263
    ? remove_node->_left
 
264
    : remove_node->_right
 
265
  );
 
266
 
 
267
  if (splice_node) {
 
268
    // @c replace_with copies color so in this case the actual color
 
269
    // lost is that of the splice_node.
 
270
    remove_color = splice_node->_color;
 
271
    remove_node->replaceWith(splice_node);
 
272
  } else {
 
273
    // No children on remove node so we can just clip it off the tree
 
274
    // We update splice_node to maintain the invariant that it is
 
275
    // the node where the physical removal occurred.
 
276
    splice_node = remove_node->_parent;
 
277
    // Keep @a d up to date.
 
278
    d = splice_node->getChildDirection(remove_node);
 
279
    splice_node->setChild(0, d);
 
280
  }
 
281
 
 
282
  // If the node to pull out of the tree isn't this one, 
 
283
  // then replace this node in the tree with that removed
 
284
  // node in liu of copying the data over.
 
285
  if (remove_node != this) {
 
286
    // Don't leave @a splice_node referring to a removed node
 
287
    if (splice_node == this) splice_node = remove_node;
 
288
    this->replaceWith(remove_node);
 
289
  }
 
290
 
 
291
  root = splice_node->rebalanceAfterRemove(remove_color, d);
 
292
  root->_color = BLACK;
 
293
  return root;
 
294
}
 
295
 
 
296
/**
 
297
 * Rebalance tree after a deletion
 
298
 * Called on the spliced in node or its parent, whichever is not NIL.
 
299
 * This modifies the tree structure only if @a c is @c BLACK.
 
300
 */
 
301
RBNode*
 
302
RBNode::rebalanceAfterRemove(
 
303
  Color c, //!< The color of the removed node
 
304
  Direction d //!< Direction of removed node from its parent
 
305
) {
 
306
  self* root;
 
307
 
 
308
  if (BLACK == c) { // only rebalance if too much black
 
309
    self* n = this;
 
310
    self* parent = n->_parent;
 
311
 
 
312
    // If @a direction is set, then we need to start at a leaf psuedo-node.
 
313
    // This is why we need @a parent, otherwise we could just use @a n.
 
314
    if (NONE != d) {
 
315
      parent = n;
 
316
      n = 0;
 
317
    }
 
318
 
 
319
    while (parent) { // @a n is not the root
 
320
      // If the current node is RED, we can just recolor and be done
 
321
      if (n == RED) {
 
322
        n->_color = BLACK;
 
323
        break;
 
324
      } else {
 
325
        // Parameterizing the rebalance logic on the directions. We
 
326
        // write for the left child case and flip directions for the
 
327
        // right child case
 
328
        Direction near(LEFT), far(RIGHT);
 
329
        if (
 
330
          (NONE == d && parent->getChildDirection(n) == RIGHT)
 
331
          || RIGHT == d
 
332
        ) {
 
333
          near = RIGHT;
 
334
          far = LEFT;
 
335
        }
 
336
 
 
337
        self* w = parent->getChild(far); // sibling(n)
 
338
 
 
339
        if (w->_color == RED) {
 
340
          w->_color = BLACK;
 
341
          parent->_color = RED;
 
342
          parent->rotate(near);
 
343
          w = parent->getChild(far);
 
344
        }
 
345
 
 
346
        self* wfc = w->getChild(far);
 
347
        if (w->getChild(near) == BLACK && wfc == BLACK) {
 
348
          w->_color = RED;
 
349
          n = parent;
 
350
          parent = n->_parent;
 
351
          d = NONE; // Cancel any leaf node logic
 
352
        } else {
 
353
          if (wfc->_color == BLACK) {
 
354
            w->getChild(near)->_color = BLACK;
 
355
            w->_color = RED;
 
356
            w->rotate(far);
 
357
            w = parent->getChild(far);
 
358
            wfc = w->getChild(far); // w changed, update far child cache.
 
359
          }
 
360
          w->_color = parent->_color;
 
361
          parent->_color = BLACK;
 
362
          wfc->_color = BLACK;
 
363
          parent->rotate(near);
 
364
          break;
 
365
        }
 
366
      }
 
367
    }
 
368
  }
 
369
  root = this->rippleStructureFixup();
 
370
  return root;
 
371
}
 
372
 
 
373
/** Ensure that the local information associated with each node is
 
374
    correct globally This should only be called on debug builds as it
 
375
    breaks any efficiencies we have gained from our tree structure.
 
376
    */
 
377
int
 
378
RBNode::validate() {
 
379
# if 0
 
380
  int black_ht = 0;
 
381
  int black_ht1, black_ht2;
 
382
 
 
383
  if (_left) {
 
384
    black_ht1 = _left->validate();
 
385
  }
 
386
  else
 
387
    black_ht1 = 1;
 
388
 
 
389
  if (black_ht1 > 0 && _right)
 
390
    black_ht2 = _right->validate();
 
391
  else
 
392
    black_ht2 = 1;
 
393
 
 
394
  if (black_ht1 == black_ht2) {
 
395
    black_ht = black_ht1;
 
396
    if (this->_color == BLACK)
 
397
      ++black_ht;
 
398
    else {      // No red-red
 
399
      if (_left == RED)
 
400
        black_ht = 0;
 
401
      else if (_right == RED)
 
402
        black_ht = 0;
 
403
      if (black_ht == 0)
 
404
        std::cout << "Red-red child\n";
 
405
    }
 
406
  } else {
 
407
    std::cout << "Height mismatch " << black_ht1 << " " << black_ht2 << "\n";
 
408
  }
 
409
  if (black_ht > 0 && !this->structureValidate())
 
410
    black_ht = 0;
 
411
 
 
412
  return black_ht;
 
413
# else
 
414
  return 0;
 
415
# endif
 
416
}
 
417
 
 
418
/** Base template class for IP maps.
 
419
    This class is templated by the @a N type which must be a subclass
 
420
    of @c RBNode. This class carries information about the addresses stored
 
421
    in the map. This includes the type, the common argument type, and
 
422
    some utility methods to operate on the address.
 
423
*/
 
424
template <
 
425
  typename N ///< Node type.
 
426
> struct IpMapBase {
 
427
  friend class ::IpMap;
 
428
  
 
429
  typedef IpMapBase self; ///< Self reference type.
 
430
  typedef typename N::ArgType ArgType; ///< Import type.
 
431
  typedef typename N::Metric Metric;   ///< Import type.g482
 
432
 
 
433
  IpMapBase() : _root(0) {}
 
434
  ~IpMapBase() { this->clear(); }
 
435
 
 
436
  /** Mark a range.
 
437
      All addresses in the range [ @a min , @a max ] are marked with @a data.
 
438
      @return This object.
 
439
  */
 
440
  self& mark(
 
441
    ArgType min, ///< Minimum value in range.
 
442
    ArgType max, ///< Maximum value in range.
 
443
    void* data = 0     ///< Client data payload.
 
444
  );
 
445
  /** Unmark addresses.
 
446
 
 
447
      All addresses in the range [ @a min , @a max ] are cleared
 
448
      (removed from the map), no longer marked.
 
449
 
 
450
      @return This object.
 
451
  */
 
452
  self& unmark(
 
453
    ArgType min,
 
454
    ArgType max
 
455
  );
 
456
 
 
457
  /** Fill addresses.
 
458
 
 
459
      This background fills using the range. All addresses in the
 
460
      range that are @b not present in the map are added. No
 
461
      previously present address is changed.
 
462
 
 
463
      @note This is useful for filling in first match tables.
 
464
 
 
465
      @return This object.
 
466
  */
 
467
  self& fill(
 
468
    ArgType min,
 
469
    ArgType max,
 
470
    void* data = 0
 
471
  );
 
472
 
 
473
  /** Test for membership.
 
474
 
 
475
      @return @c true if the address is in the map, @c false if not.
 
476
      If the address is in the map and @a ptr is not @c NULL, @c *ptr
 
477
      is set to the client data for the address.
 
478
  */
 
479
  bool contains(
 
480
    ArgType target, ///< Search target value.
 
481
    void **ptr = 0 ///< Client data return.
 
482
  ) const;
 
483
 
 
484
  /** Remove all addresses in the map.
 
485
 
 
486
      @note This is much faster than using @c unmark with a range of
 
487
      all addresses.
 
488
 
 
489
      @return This object.
 
490
  */
 
491
  self& clear();
 
492
 
 
493
  /** Lower bound for @a target.  @return The node whose minimum value
 
494
      is the largest that is not greater than @a target, or @c NULL if
 
495
      all minimum values are larger than @a target.
 
496
  */
 
497
  N* lowerBound(ArgType target);
 
498
 
 
499
  /** Insert @a n after @a spot.
 
500
      Caller is responsible for ensuring that @a spot is in this container
 
501
      and the proper location for @a n.
 
502
  */
 
503
  void insertAfter(
 
504
    N* spot, ///< Node in list.
 
505
    N* n ///< Node to insert.
 
506
  );
 
507
  /** Insert @a n before @a spot.
 
508
      Caller is responsible for ensuring that @a spot is in this container
 
509
      and the proper location for @a n.
 
510
  */
 
511
  void insertBefore(
 
512
    N* spot, ///< Node in list.
 
513
    N* n ///< Node to insert.
 
514
  );
 
515
  /// Add node @a n as the first node.
 
516
  void prepend(
 
517
    N* n
 
518
  );
 
519
  /// Add node @a n as the last node.
 
520
  void append(
 
521
    N* n
 
522
  );
 
523
  /// Remove a node.
 
524
  void remove(
 
525
    N* n ///< Node to remove.
 
526
  );
 
527
 
 
528
  /** Validate internal data structures.
 
529
      @note Intended for debugging, not general client use.
 
530
  */
 
531
  void validate();
 
532
 
 
533
  /// @return The number of distinct ranges.
 
534
  size_t getCount() const;
 
535
 
 
536
  /// Print all spans.
 
537
  /// @return This map.
 
538
  self& print();
 
539
  
 
540
  // Helper methods.
 
541
  N* prev(RBNode* n) const { return static_cast<N*>(n->_prev); }
 
542
  N* next(RBNode* n) const { return static_cast<N*>(n->_next); }
 
543
  N* parent(RBNode* n) const { return static_cast<N*>(n->_parent); }
 
544
  N* left(RBNode* n) const { return static_cast<N*>(n->_left); }
 
545
  N* right(RBNode* n) const { return static_cast<N*>(n->_right); }
 
546
  N* getHead() { return static_cast<N*>(_list.getHead()); }
 
547
  N* getTail() { return static_cast<N*>(_list.getTail()); }
 
548
 
 
549
  N* _root; ///< Root node.
 
550
  /// In order list of nodes.
 
551
  /// For ugly compiler reasons, this is a list of base class pointers
 
552
  /// even though we really store @a N instances on it.
 
553
  typedef IntrusiveDList<RBNode, &RBNode::_next, &RBNode::_prev> NodeList;
 
554
  /// This keeps track of all allocated nodes in order.
 
555
  /// Iteration depends on this list being maintained.
 
556
  NodeList _list;
 
557
};
 
558
 
 
559
template < typename N > N*
 
560
IpMapBase<N>::lowerBound(ArgType target) {
 
561
  N* n = _root; // current node to test.
 
562
  N* zret = 0; // best node so far.
 
563
  while (n) {
 
564
    if (target < n->_min) n = left(n);
 
565
    else {
 
566
      zret = n; // this is a better candidate.
 
567
      if (n->_max < target) n = right(n);
 
568
      else break;
 
569
    }
 
570
  }
 
571
  return zret;
 
572
}
 
573
 
 
574
template < typename N > IpMapBase<N>&
 
575
IpMapBase<N>::clear() {
 
576
  // Delete everything.
 
577
  N* n = static_cast<N*>(_list.getHead());
 
578
  while (n) {
 
579
    N* x = n;
 
580
    n = next(n);
 
581
    delete x;
 
582
  }
 
583
  _list.clear();
 
584
  _root = 0;
 
585
  return *this;
 
586
}
 
587
 
 
588
template < typename N > IpMapBase<N>&
 
589
IpMapBase<N>::fill(ArgType rmin, ArgType rmax, void* payload) {
 
590
  // Rightmost node of interest with n->_min <= min.
 
591
  N* n = this->lowerBound(rmin);
 
592
  N* x = 0; // New node (if any).
 
593
  // Need copies because we will modify these.
 
594
  Metric min = N::deref(rmin);
 
595
  Metric max = N::deref(rmax);
 
596
 
 
597
  // Handle cases involving a node of interest to the left of the
 
598
  // range.
 
599
  if (n) {
 
600
    if (n->_min < min) {
 
601
      Metric min_1 = min;
 
602
      N::dec(min_1);  // dec is OK because min isn't zero.
 
603
      if (n->_max < min_1) { // no overlap or adj.
 
604
        n = next(n);
 
605
      } else if (n->_max >= max) { // incoming range is covered, just discard.
 
606
        return *this;
 
607
      } else if (n->_data != payload) { // different payload, clip range on left.
 
608
        min = n->_max;
 
609
        N::inc(min);
 
610
        n = next(n);
 
611
      } else { // skew overlap with same payload, use node and continue.
 
612
        x = n;
 
613
        n = next(n);
 
614
      }
 
615
    }
 
616
  } else {
 
617
    n = this->getHead();
 
618
  }
 
619
 
 
620
  // Work through the rest of the nodes of interest.
 
621
  // Invariant: n->_min >= min
 
622
 
 
623
  // Careful here -- because max_plus1 might wrap we need to use it only
 
624
  // if we can certain it didn't. This is done by ordering the range
 
625
  // tests so that when max_plus1 is used when we know there exists a
 
626
  // larger value than max.
 
627
  Metric max_plus1 = max;
 
628
  N::inc(max_plus1);
 
629
  /* Notes:
 
630
     - max (and thence max_plus1) never change during the loop.
 
631
     - we must have either x != 0 or adjust min but not both.
 
632
  */
 
633
  while (n) {
 
634
    if (n->_data == payload) {
 
635
      if (x) {
 
636
        if (n->_max <= max) {
 
637
          // next range is covered, so we can remove and continue.
 
638
          this->remove(n);
 
639
          n = next(x);
 
640
        } else if (n->_min <= max_plus1) {
 
641
          // Overlap or adjacent with larger max - absorb and finish.
 
642
          x->setMax(n->_max);
 
643
          this->remove(n);
 
644
          return *this;
 
645
        } else {
 
646
          // have the space to finish off the range.
 
647
          x->setMax(max);
 
648
          return *this;
 
649
        }
 
650
      } else { // not carrying a span.
 
651
        if (n->_max <= max) { // next range is covered - use it.
 
652
          x = n;
 
653
          x->setMin(min);
 
654
          n = next(n);
 
655
        } else if (n->_min <= max_plus1) {
 
656
          n->setMin(min);
 
657
          return *this;
 
658
        } else { // no overlap, space to complete range.
 
659
          this->insertBefore(n, new N(min, max, payload));
 
660
          return *this;
 
661
        }
 
662
      }
 
663
    } else { // different payload
 
664
      if (x) {
 
665
        if (max < n->_min) { // range ends before n starts, done.
 
666
          x->setMax(max);
 
667
          return *this;
 
668
        } else if (max <= n->_max) { // range ends before n, done.
 
669
          x->setMaxMinusOne(n->_min);
 
670
          return *this;
 
671
        } else { // n is contained in range, skip over it.
 
672
          x->setMaxMinusOne(n->_min);
 
673
          x = 0;
 
674
          min = n->_max;
 
675
          N::inc(min); // OK because n->_max maximal => next is null.
 
676
          n = next(n);
 
677
        }
 
678
      } else { // no carry node.
 
679
        if (max < n->_min) { // entirely before next span.
 
680
          this->insertBefore(n, new N(min, max, payload));
 
681
          return *this;
 
682
        } else {
 
683
          if (min < n->_min) { // leading section, need node.
 
684
            N* y = new N(min, n->_min, payload);
 
685
            y->decrementMax();
 
686
            this->insertBefore(n, y);
 
687
          }
 
688
          if (max <= n->_max) // nothing past node
 
689
            return *this;
 
690
          min = n->_max;
 
691
          N::inc(min);
 
692
          n = next(n);
 
693
        }
 
694
      }
 
695
    }
 
696
  }
 
697
  // Invariant: min is larger than any existing range maximum.
 
698
  if (x) {
 
699
    x->setMax(max);
 
700
  } else {
 
701
    this->append(new N(min, max, payload));
 
702
  }
 
703
  return *this;
 
704
}
 
705
 
 
706
template < typename N > IpMapBase<N>&
 
707
IpMapBase<N>::mark(ArgType min, ArgType max, void* payload) {
 
708
  N* n = this->lowerBound(min); // current node.
 
709
  N* x = 0; // New node, gets set if we re-use an existing one.
 
710
  N* y = 0; // Temporary for removing and advancing.
 
711
 
 
712
  // Several places it is handy to have max+1. Must be careful
 
713
  // about wrapping.
 
714
  Metric max_plus = N::deref(max);
 
715
  N::inc(max_plus);
 
716
 
 
717
  /* Some subtlety - for IPv6 we overload the compare operators to do
 
718
     the right thing, but we can't overload pointer
 
719
     comparisons. Therefore we carefully never compare pointers in
 
720
     this logic. Only @a min and @a max can be pointers, everything
 
721
     else is an instance or a reference. Since there's no good reason
 
722
     to compare @a min and @a max this isn't particularly tricky, but
 
723
     it's good to keep in mind. If we were somewhat more clever, we
 
724
     would provide static less than and equal operators in the
 
725
     template class @a N and convert all the comparisons to use only
 
726
     those two via static function call.
 
727
  */
 
728
 
 
729
  /*  We have lots of special cases here primarily to minimize memory
 
730
      allocation by re-using an existing node as often as possible.
 
731
  */
 
732
  if (n) {
 
733
    // Watch for wrap.
 
734
    Metric min_1 = N::deref(min);
 
735
    N::dec(min_1);
 
736
    if (n->_min == min) {
 
737
      // Could be another span further left which is adjacent.
 
738
      // Coalesce if the data is the same. min_1 is OK because
 
739
      // if there is a previous range, min is not zero.
 
740
      N* p = prev(n);
 
741
      if (p && p->_data == payload && p->_max == min_1) {
 
742
        x = p;
 
743
        n = x; // need to back up n because frame of reference moved.
 
744
        x->setMax(max);
 
745
      } else if (n->_max <= max) {
 
746
        // Span will be subsumed by request span so it's available for use.
 
747
        x = n;
 
748
        x->setMax(max).setData(payload);
 
749
      } else if (n->_data == payload) {
 
750
        return *this; // request is covered by existing span with the same data
 
751
      } else {
 
752
        // request span is covered by existing span.
 
753
        x = new N(min, max, payload); //
 
754
        n->setMin(max_plus); // clip existing.
 
755
        this->insertBefore(n, x);
 
756
        return *this;
 
757
      }
 
758
    } else if (n->_data == payload && n->_max >= min_1) {
 
759
      // min_1 is safe here because n->_min < min so min is not zero.
 
760
      x = n;
 
761
      // If the existing span covers the requested span, we're done.
 
762
      if (x->_max >= max) return *this;
 
763
      x->setMax(max);
 
764
    } else if (n->_max <= max) {
 
765
      // Can only have left skew overlap, otherwise disjoint.
 
766
      // Clip if overlap.
 
767
      if (n->_max >= min) n->setMax(min_1);
 
768
      else if (next(n) && n->_max <= max) {
 
769
        // request region covers next span so we can re-use that node.
 
770
        x = next(n);
 
771
        x->setMin(min).setMax(max).setData(payload);
 
772
        n = x; // this gets bumped again, which is correct.
 
773
      }
 
774
    } else {
 
775
      // Existing span covers new span but with a different payload.
 
776
      // We split it, put the new span in between and we're done.
 
777
      // max_plus is valid because n->_max > max.
 
778
      N* r;
 
779
      x = new N(min, max, payload);
 
780
      r = new N(max_plus, n->_max, n->_data);
 
781
      n->setMax(min_1);
 
782
      this->insertAfter(n, x);
 
783
      this->insertAfter(x, r);
 
784
      return *this; // done.
 
785
    }
 
786
    n = next(n); // lower bound span handled, move on.
 
787
    if (!x) {
 
788
      x = new N(min, max, payload);
 
789
      if (n) this->insertBefore(n, x);
 
790
      else this->append(x); // note that since n == 0 we'll just return.
 
791
    }
 
792
  } else if (0 != (n = this->getHead()) && // at least one node in tree.
 
793
             n->_data == payload && // payload matches
 
794
             (n->_max <= max || n->_min <= max_plus) // overlap or adj.
 
795
  ) {
 
796
    // Same payload with overlap, re-use.
 
797
    x = n;
 
798
    n = next(n);
 
799
    x->setMin(min);
 
800
    if (x->_max < max) x->setMax(max);
 
801
  } else {
 
802
    x = new N(min, max, payload);
 
803
    this->prepend(x);
 
804
  }
 
805
 
 
806
  // At this point, @a x has the node for this span and all existing spans of
 
807
  // interest start at or past this span.
 
808
  while (n) {
 
809
    if (n->_max <= max) { // completely covered, drop span, continue
 
810
      y = n;
 
811
      n = next(n);
 
812
      this->remove(y);
 
813
    } else if (max_plus < n->_min) { // no overlap, done.
 
814
      break;
 
815
    } else if (n->_data == payload) { // skew overlap or adj., same payload
 
816
      x->setMax(n->_max);
 
817
      y = n;
 
818
      n = next(n);
 
819
      this->remove(y);
 
820
    } else if (n->_min <= max) { // skew overlap different payload
 
821
      n->setMin(max_plus);
 
822
      break;
 
823
    }
 
824
  }
 
825
 
 
826
  return *this;
 
827
}
 
828
 
 
829
template <typename N> IpMapBase<N>&
 
830
IpMapBase<N>::unmark(ArgType min, ArgType max) {
 
831
  N* n = this->lowerBound(min);
 
832
  N* x; // temp for deletes.
 
833
 
 
834
  // Need to handle special case where first span starts to the left.
 
835
  if (n && n->_min < min) {
 
836
    if (n->_max >= min) { // some overlap
 
837
      if (n->_max > max) {
 
838
        // request span is covered by existing span - split existing span.
 
839
        x = new N(max, N::argue(n->_max), n->_data);
 
840
        x->incrementMin();
 
841
        n->setMaxMinusOne(N::deref(min));
 
842
        this->insertAfter(n, x);
 
843
        return *this; // done.
 
844
      } else {
 
845
        n->setMaxMinusOne(N::deref(min)); // just clip overlap.
 
846
      }
 
847
    } // else disjoint so just skip it.
 
848
    n = next(n);
 
849
  }
 
850
  // n and all subsequent spans start at >= min.
 
851
  while (n) {
 
852
    x = n;
 
853
    n = next(n);
 
854
    if (x->_max <= max) {
 
855
      this->remove(x);
 
856
    } else {
 
857
      if (x->_min <= max) { // clip overlap
 
858
        x->setMinPlusOne(N::deref(max));
 
859
      }
 
860
      break;
 
861
    }
 
862
  }
 
863
  return *this;
 
864
}
 
865
 
 
866
template <typename N> void
 
867
IpMapBase<N>::insertAfter(N* spot, N* n) {
 
868
  N* c = right(spot);
 
869
  if (!c) spot->setChild(n, N::RIGHT);
 
870
  else spot->_next->setChild(n, N::LEFT);
 
871
 
 
872
  _list.insertAfter(spot, n);
 
873
  _root = static_cast<N*>(n->rebalanceAfterInsert());
 
874
}
 
875
 
 
876
template <typename N> void
 
877
IpMapBase<N>::insertBefore(N* spot, N* n) {
 
878
  N* c = left(spot);
 
879
  if (!c) spot->setChild(n, N::LEFT);
 
880
  else spot->_prev->setChild(n, N::RIGHT);
 
881
 
 
882
  _list.insertBefore(spot, n);
 
883
  _root = static_cast<N*>(n->rebalanceAfterInsert());
 
884
}
 
885
 
 
886
template <typename N> void
 
887
IpMapBase<N>::prepend(N* n) {
 
888
  if (!_root) _root = n;
 
889
  else _root = static_cast<N*>(_list.getHead()->setChild(n, N::LEFT)->rebalanceAfterInsert());
 
890
  _list.prepend(n);
 
891
}
 
892
 
 
893
template <typename N> void
 
894
IpMapBase<N>::append(N* n) {
 
895
  if (!_root) _root = n;
 
896
  else _root = static_cast<N*>(_list.getTail()->setChild(n, N::RIGHT)->rebalanceAfterInsert());
 
897
  _list.append(n);
 
898
}
 
899
 
 
900
template <typename N> void
 
901
IpMapBase<N>::remove(N* n) {
 
902
  _root = static_cast<N*>(n->remove());
 
903
  _list.take(n);
 
904
  delete n;
 
905
}
 
906
 
 
907
template <typename N> bool
 
908
IpMapBase<N>::contains(ArgType x, void** ptr) const {
 
909
  bool zret = false;
 
910
  N* n = _root; // current node to test.
 
911
  while (n) {
 
912
    if (x < n->_min) n = left(n);
 
913
    else if (n->_max < x) n = right(n);
 
914
    else {
 
915
      if (ptr) *ptr = n->_data;
 
916
      zret = true;
 
917
      break;
 
918
    }
 
919
  }
 
920
  return zret;
 
921
}
 
922
 
 
923
template < typename N > size_t IpMapBase<N>::getCount() const { return _list.getCount(); }
 
924
//----------------------------------------------------------------------------
 
925
template <typename N> void
 
926
IpMapBase<N>::validate() {
 
927
# if 0
 
928
  if (_root) _root->validate();
 
929
  for ( Node* n = _list.getHead() ; n ; n = n->_next ) {
 
930
    Node* x;
 
931
    if (0 != (x = n->_next)) {
 
932
      if (x->_prev != n)
 
933
        std::cout << "Broken list" << std::endl;
 
934
      if (n->_max >= x->_min)
 
935
        std::cout << "Out of order - " << n->_max << " > " << x->_min << std::endl;
 
936
      if (n->_parent == n || n->_left == n || n->_right == n)
 
937
        std::cout << "Looped node" << std::endl;
 
938
    }
 
939
  }
 
940
# endif
 
941
}
 
942
 
 
943
template <typename N> IpMapBase<N>&
 
944
IpMapBase<N>::print() {
 
945
# if 0
 
946
  for ( Node* n = _list.getHead() ; n ; n = n->_next ) {
 
947
    std::cout
 
948
      << n << ": " << n->_min << '-' << n->_max << " [" << n->_data << "] "
 
949
      << (n->_color == Node::BLACK ? "Black " : "Red   ") << "P=" << n->_parent << " L=" << n->_left << " R=" << n->_right
 
950
      << std::endl;
 
951
  }
 
952
# endif
 
953
  return *this;
 
954
}
 
955
 
 
956
//----------------------------------------------------------------------------
 
957
typedef Interval<in_addr_t, in_addr_t> Ip4Span;
 
958
 
 
959
/** Node for IPv4 map.
 
960
    We store the address in host order in the @a _min and @a _max
 
961
    members for performance. We store copies in the @a _sa member
 
962
    for API compliance (which requires @c sockaddr* access).
 
963
*/
 
964
class Ip4Node : public IpMap::Node, protected Ip4Span {
 
965
  friend struct IpMapBase<Ip4Node>;
 
966
public:
 
967
  typedef Ip4Node self; ///< Self reference type.
 
968
 
 
969
  /// Construct with values.
 
970
  Ip4Node(
 
971
    ArgType min, ///< Minimum address (host order).
 
972
    ArgType max, ///< Maximum address (host order).
 
973
    void* data ///< Client data.
 
974
  ) : Node(data), Ip4Span(min, max) {
 
975
    ats_ip4_set(ats_ip_sa_cast(&_sa._min), htonl(min));
 
976
    ats_ip4_set(ats_ip_sa_cast(&_sa._max), htonl(max));
 
977
  }
 
978
  /// @return The minimum value of the interval.
 
979
  virtual sockaddr const* min() const {
 
980
    return ats_ip_sa_cast(&_sa._min);
 
981
  }
 
982
  /// @return The maximum value of the interval.
 
983
  virtual sockaddr const* max() const {
 
984
    return ats_ip_sa_cast(&_sa._max);
 
985
  }
 
986
  /// Set the client data.
 
987
  self& setData(
 
988
    void* data ///< Client data.
 
989
  ) {
 
990
    _data = data;
 
991
    return *this;
 
992
  }
 
993
protected:
 
994
  
 
995
  /// Set the minimum value of the interval.
 
996
  /// @return This interval.
 
997
  self& setMin(
 
998
    ArgType min ///< Minimum value (host order).
 
999
  ) {
 
1000
    _min = min;
 
1001
    _sa._min.sin_addr.s_addr = htonl(min);
 
1002
    return *this;
 
1003
  }
 
1004
  
 
1005
  /// Set the maximum value of the interval.
 
1006
  /// @return This interval.
 
1007
  self& setMax(
 
1008
    ArgType max ///< Maximum value (host order).
 
1009
  ) {
 
1010
    _max = max;
 
1011
    _sa._max.sin_addr.s_addr = htonl(max);
 
1012
    return *this;
 
1013
  }
 
1014
  
 
1015
  /** Set the maximum value to one less than @a max.
 
1016
      @return This object.
 
1017
  */
 
1018
  self& setMaxMinusOne(
 
1019
    ArgType max ///< One more than maximum value.
 
1020
  ) {
 
1021
    return this->setMax(max-1);
 
1022
  }
 
1023
  /** Set the minimum value to one more than @a min.
 
1024
      @return This object.
 
1025
  */
 
1026
  self& setMinPlusOne(
 
1027
    ArgType min ///< One less than minimum value.
 
1028
  ) {
 
1029
    return this->setMin(min+1);
 
1030
  }
 
1031
  /** Decremement the maximum value in place.
 
1032
      @return This object.
 
1033
  */
 
1034
  self& decrementMax() {
 
1035
    this->setMax(_max-1);
 
1036
    return *this;
 
1037
  }
 
1038
  /** Increment the minimum value in place.
 
1039
      @return This object.
 
1040
  */
 
1041
  self& incrementMin() {
 
1042
    this->setMin(_min+1);
 
1043
    return *this;
 
1044
  }
 
1045
 
 
1046
  /// Increment a metric.
 
1047
  static void inc(
 
1048
    Metric& m ///< Incremented in place.
 
1049
  ) {
 
1050
    ++m;
 
1051
  }
 
1052
  
 
1053
  /// Decrement a metric.
 
1054
  static void dec(
 
1055
    Metric& m ///< Decremented in place.
 
1056
  ) {
 
1057
    --m;
 
1058
  }
 
1059
  
 
1060
  /// @return Dereferenced @a addr.
 
1061
  static Metric deref(
 
1062
    ArgType addr ///< Argument to dereference.
 
1063
  ) {
 
1064
    return addr;
 
1065
  }
 
1066
 
 
1067
  /// @return The argument type for the @a metric.
 
1068
  static ArgType argue(
 
1069
    Metric const& metric
 
1070
  ) {
 
1071
    return metric;
 
1072
  }
 
1073
  
 
1074
  struct {
 
1075
    sockaddr_in _min;
 
1076
    sockaddr_in _max;
 
1077
  } _sa; ///< Addresses in API compliant form.
 
1078
 
 
1079
};
 
1080
 
 
1081
class Ip4Map : public IpMapBase<Ip4Node> {
 
1082
  friend class ::IpMap;
 
1083
};
 
1084
 
 
1085
//----------------------------------------------------------------------------
 
1086
typedef Interval<sockaddr_in6> Ip6Span;
 
1087
 
 
1088
/** Node for IPv6 map.
 
1089
*/
 
1090
class Ip6Node : public IpMap::Node, protected Ip6Span {
 
1091
  friend struct IpMapBase<Ip6Node>;
 
1092
public:
 
1093
  typedef Ip6Node self; ///< Self reference type.
 
1094
  /// Override @c ArgType from @c Interval because the convention
 
1095
  /// is to use a pointer, not a reference.
 
1096
  typedef Metric const* ArgType;
 
1097
 
 
1098
  /// Construct from pointers.
 
1099
  Ip6Node(
 
1100
    ArgType min, ///< Minimum address (network order).
 
1101
    ArgType max, ///< Maximum address (network order).
 
1102
    void* data ///< Client data.
 
1103
  ) : Node(data), Ip6Span(*min, *max) {
 
1104
  }
 
1105
  /// Construct with values.
 
1106
  Ip6Node(
 
1107
    Metric const& min, ///< Minimum address (network order).
 
1108
    Metric const& max, ///< Maximum address (network order).
 
1109
    void* data ///< Client data.
 
1110
  ) : Node(data), Ip6Span(min, max) {
 
1111
  }
 
1112
  /// @return The minimum value of the interval.
 
1113
  virtual sockaddr const* min() const {
 
1114
    return ats_ip_sa_cast(&_min);
 
1115
  }
 
1116
  /// @return The maximum value of the interval.
 
1117
  virtual sockaddr const* max() const {
 
1118
    return ats_ip_sa_cast(&_max);
 
1119
  }
 
1120
  /// Set the client data.
 
1121
  self& setData(
 
1122
    void* data ///< Client data.
 
1123
  ) {
 
1124
    _data = data;
 
1125
    return *this;
 
1126
  }
 
1127
protected:
 
1128
  
 
1129
  /// Set the minimum value of the interval.
 
1130
  /// @return This interval.
 
1131
  self& setMin(
 
1132
    ArgType min ///< Minimum value (host order).
 
1133
  ) {
 
1134
    ats_ip_copy(ats_ip_sa_cast(&_min), ats_ip_sa_cast(min));
 
1135
    return *this;
 
1136
  }
 
1137
  
 
1138
  /// Set the minimum value of the interval.
 
1139
  /// @note Convenience overload.
 
1140
  /// @return This interval.
 
1141
  self& setMin(
 
1142
    Metric const& min ///< Minimum value (host order).
 
1143
  ) {
 
1144
    return this->setMin(&min);
 
1145
  }
 
1146
  
 
1147
  /// Set the maximum value of the interval.
 
1148
  /// @return This interval.
 
1149
  self& setMax(
 
1150
    ArgType max ///< Maximum value (host order).
 
1151
  ) {
 
1152
    ats_ip_copy(ats_ip_sa_cast(&_max), ats_ip_sa_cast(max));
 
1153
    return *this;
 
1154
  }
 
1155
  /// Set the maximum value of the interval.
 
1156
  /// @note Convenience overload.
 
1157
  /// @return This interval.
 
1158
  self& setMax(
 
1159
    Metric const& max ///< Maximum value (host order).
 
1160
  ) {
 
1161
    return this->setMax(&max);
 
1162
  }
 
1163
  /** Set the maximum value to one less than @a max.
 
1164
      @return This object.
 
1165
  */
 
1166
  self& setMaxMinusOne(
 
1167
    Metric const& max ///< One more than maximum value.
 
1168
  ) {
 
1169
    this->setMax(max);
 
1170
    dec(_max);
 
1171
    return *this;
 
1172
  }
 
1173
  /** Set the minimum value to one more than @a min.
 
1174
      @return This object.
 
1175
  */
 
1176
  self& setMinPlusOne(
 
1177
    Metric const& min ///< One less than minimum value.
 
1178
  ) {
 
1179
    this->setMin(min);
 
1180
    inc(_min);
 
1181
    return *this;
 
1182
  }
 
1183
  /** Decremement the maximum value in place.
 
1184
      @return This object.
 
1185
  */
 
1186
  self& decrementMax() { dec(_max); return *this; }
 
1187
  /** Increment the mininimum value in place.
 
1188
      @return This object.
 
1189
  */
 
1190
  self& incrementMin() { inc(_min); return *this; }
 
1191
  
 
1192
  /// Increment a metric.
 
1193
  static void inc(
 
1194
    Metric& m ///< Incremented in place.
 
1195
  ) {
 
1196
    uint8_t* addr = m.sin6_addr.s6_addr;
 
1197
    uint8_t* b = addr + TS_IP6_SIZE;
 
1198
    // Ripple carry. Walk up the address incrementing until we don't
 
1199
    // have a carry.
 
1200
    do {
 
1201
      ++*--b;
 
1202
    } while (b > addr && 0 == *b);
 
1203
  }
 
1204
  
 
1205
  /// Decrement a metric.
 
1206
  static void dec(
 
1207
    Metric& m ///< Decremented in place.
 
1208
  ) {
 
1209
    uint8_t* addr = m.sin6_addr.s6_addr;
 
1210
    uint8_t* b = addr + TS_IP6_SIZE;
 
1211
    // Ripple borrow. Walk up the address decrementing until we don't
 
1212
    // have a borrow.
 
1213
    do {
 
1214
      --*--b;
 
1215
    } while (b > addr && static_cast<uint8_t>(0xFF) == *b);
 
1216
  }
 
1217
  /// @return Dereferenced @a addr.
 
1218
  static Metric const& deref(
 
1219
    ArgType addr ///< Argument to dereference.
 
1220
  ) {
 
1221
    return *addr;
 
1222
  }
 
1223
  
 
1224
  /// @return The argument type for the @a metric.
 
1225
  static ArgType argue(
 
1226
    Metric const& metric
 
1227
  ) {
 
1228
    return &metric;
 
1229
  }
 
1230
  
 
1231
};
 
1232
 
 
1233
// We declare this after the helper operators and inside this namespace
 
1234
// so that the template uses these for comparisons.
 
1235
 
 
1236
class Ip6Map : public IpMapBase<Ip6Node> {
 
1237
  friend class ::IpMap;
 
1238
};
 
1239
 
 
1240
}} // end ts::detail
 
1241
//----------------------------------------------------------------------------
 
1242
IpMap::~IpMap() {
 
1243
  delete _m4;
 
1244
  delete _m6;
 
1245
}
 
1246
 
 
1247
inline ts::detail::Ip4Map*
 
1248
IpMap::force4() {
 
1249
  if (!_m4) _m4 = new ts::detail::Ip4Map;
 
1250
  return _m4;
 
1251
}
 
1252
 
 
1253
inline ts::detail::Ip6Map*
 
1254
IpMap::force6() {
 
1255
  if (!_m6) _m6 = new ts::detail::Ip6Map;
 
1256
  return _m6;
 
1257
}
 
1258
 
 
1259
bool
 
1260
IpMap::contains(sockaddr const* target, void** ptr) const {
 
1261
  bool zret = false;
 
1262
  if (AF_INET == target->sa_family) {
 
1263
    zret = _m4 && _m4->contains(ntohl(ats_ip4_addr_cast(target)), ptr);
 
1264
  } else if (AF_INET6 == target->sa_family) {
 
1265
    zret = _m6 && _m6->contains(ats_ip6_cast(target), ptr);
 
1266
  }
 
1267
  return zret;
 
1268
}
 
1269
 
 
1270
bool
 
1271
IpMap::contains(in_addr_t target, void** ptr) const {
 
1272
  return _m4 && _m4->contains(ntohl(target), ptr);
 
1273
}
 
1274
 
 
1275
IpMap&
 
1276
IpMap::mark(
 
1277
  sockaddr const* min,
 
1278
  sockaddr const* max,
 
1279
  void* data
 
1280
) {
 
1281
  ink_assert(min->sa_family == max->sa_family);
 
1282
  if (AF_INET == min->sa_family) {
 
1283
    this->force4()->mark(
 
1284
      ntohl(ats_ip4_addr_cast(min)),
 
1285
      ntohl(ats_ip4_addr_cast(max)),
 
1286
      data
 
1287
    );
 
1288
  } else if (AF_INET6 == min->sa_family) {
 
1289
    this->force6()->mark(ats_ip6_cast(min), ats_ip6_cast(max), data);
 
1290
  }
 
1291
  return *this;
 
1292
}
 
1293
 
 
1294
IpMap&
 
1295
IpMap::mark(in_addr_t min, in_addr_t max, void* data) {
 
1296
  this->force4()->mark(ntohl(min), ntohl(max), data);
 
1297
  return *this;
 
1298
}
 
1299
 
 
1300
IpMap&
 
1301
IpMap::unmark(
 
1302
  sockaddr const* min,
 
1303
  sockaddr const* max
 
1304
) {
 
1305
  ink_assert(min->sa_family == max->sa_family);
 
1306
  if (AF_INET == min->sa_family) {
 
1307
    if (_m4)
 
1308
      _m4->unmark(
 
1309
        ntohl(ats_ip4_addr_cast(min)),
 
1310
        ntohl(ats_ip4_addr_cast(max))
 
1311
      );
 
1312
  } else if (AF_INET6 == min->sa_family) {
 
1313
    if (_m6) _m6->unmark(ats_ip6_cast(min), ats_ip6_cast(max));
 
1314
  }
 
1315
  return *this;
 
1316
}
 
1317
 
 
1318
IpMap&
 
1319
IpMap::unmark(in_addr_t min, in_addr_t max) {
 
1320
  if (_m4) _m4->unmark(ntohl(min), ntohl(max));
 
1321
  return *this;
 
1322
}
 
1323
 
 
1324
IpMap&
 
1325
IpMap::fill(
 
1326
  sockaddr const* min,
 
1327
  sockaddr const* max,
 
1328
  void* data
 
1329
) {
 
1330
  ink_assert(min->sa_family == max->sa_family);
 
1331
  if (AF_INET == min->sa_family) {
 
1332
    this->force4()->fill(
 
1333
      ntohl(ats_ip4_addr_cast(min)),
 
1334
      ntohl(ats_ip4_addr_cast(max)),
 
1335
      data
 
1336
    );
 
1337
  } else if (AF_INET6 == min->sa_family) {
 
1338
    this->force6()->fill(ats_ip6_cast(min), ats_ip6_cast(max), data);
 
1339
  }
 
1340
  return *this;
 
1341
}
 
1342
 
 
1343
IpMap&
 
1344
IpMap::fill(in_addr_t min, in_addr_t max, void* data) {
 
1345
  this->force4()->fill(ntohl(min), ntohl(max), data);
 
1346
  return *this;
 
1347
}
 
1348
 
 
1349
size_t
 
1350
IpMap::getCount() const {
 
1351
  size_t zret = 0;
 
1352
  if (_m4) zret += _m4->getCount();
 
1353
  if (_m6) zret += _m6->getCount();
 
1354
  return zret;
 
1355
}
 
1356
 
 
1357
IpMap&
 
1358
IpMap::clear() {
 
1359
  if (_m4) _m4->clear();
 
1360
  if (_m6) _m6->clear();
 
1361
  return *this;
 
1362
}
 
1363
 
 
1364
IpMap::iterator
 
1365
IpMap::begin() {
 
1366
  Node* x = 0;
 
1367
  if (_m4) x = _m4->getHead();
 
1368
  if (!x && _m6) x = _m6->getHead();
 
1369
  return iterator(this, x);
 
1370
}
 
1371
 
 
1372
IpMap::iterator&
 
1373
IpMap::iterator::operator ++ () {
 
1374
  if (_node) {
 
1375
    // If we go past the end of the list see if it was the v4 list
 
1376
    // and if so, move to the v6 list (if it's there).
 
1377
    Node* x = static_cast<Node*>(_node->_next);
 
1378
    if (!x && _tree->_m4 && _tree->_m6 && _node == _tree->_m4->getTail())
 
1379
      x = _tree->_m6->getHead();
 
1380
    _node = x;
 
1381
  }
 
1382
  return *this;
 
1383
}
 
1384
 
 
1385
inline IpMap::iterator&
 
1386
IpMap::iterator::operator--() {
 
1387
  if (_node) {
 
1388
    // At a node, try to back up. Handle the case where we back over the
 
1389
    // start of the v6 addresses and switch to the v4, if there are any.
 
1390
    Node* x = static_cast<Node*>(_node->_prev);
 
1391
    if (!x && _tree->_m4 && _tree->_m6 && _node == _tree->_m6->getHead())
 
1392
      x = _tree->_m4->getTail();
 
1393
    _node = x;
 
1394
  } else if (_tree) {
 
1395
    // We were at the end. Back up to v6 if possible, v4 if not.
 
1396
    if (_tree->_m6) _node = _tree->_m6->getTail();
 
1397
    if (!_node && _tree->_m4) _node = _tree->_m4->getTail();
 
1398
  }
 
1399
  return *this;
 
1400
}
 
1401
 
 
1402
 
 
1403
//----------------------------------------------------------------------------
 
1404
//----------------------------------------------------------------------------
 
1405