OpenSDN source code
ifmap_exporter.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "ifmap/ifmap_exporter.h"
6 
7 #include <boost/bind/bind.hpp>
8 #include <boost/checked_delete.hpp>
9 
10 #include "db/db.h"
11 #include "db/db_table_partition.h"
12 #include "ifmap/ifmap_client.h"
14 #include "ifmap/ifmap_link.h"
15 #include "ifmap/ifmap_log.h"
16 #include "ifmap/ifmap_server.h"
17 #include "ifmap/ifmap_log_types.h"
18 #include "ifmap/ifmap_table.h"
19 #include "ifmap/ifmap_update.h"
22 #include "ifmap/ifmap_util.h"
23 
24 using namespace std;
25 using namespace boost::algorithm;
26 using namespace boost::placeholders;
27 
29 public:
31  : id_(id) {
32  }
33  DBTableBase::ListenerId id() const { return id_; }
34 
35 private:
37 };
38 
40  : server_(server), link_table_(NULL) {
41 }
42 
44  Shutdown();
45 }
46 
48  for (DB::iterator iter = db->lower_bound("__ifmap__");
49  iter != db->end(); ++iter) {
50  DBTable *table = static_cast<DBTable *>(iter->second);
51  if (table->name().find("__ifmap__") != 0) {
52  break;
53  }
55  table->Register(
56  boost::bind(&IFMapExporter::NodeTableExport, this, _1, _2));
57  table_map_.insert(make_pair(table, new TableInfo(id)));
58  }
59 
60  link_table_ = static_cast<DBTable *>(
61  db->FindTable("__ifmap_metadata__.0"));
62  assert(link_table_);
65  boost::bind(&IFMapExporter::LinkTableExport, this, _1, _2));
66  table_map_.insert(make_pair(link_table_, new TableInfo(id)));
67 
68  walker_.reset(new IFMapGraphWalker(server_->graph(), this));
69 }
70 
72  for (int i = 0; i < TT_END; ++i) {
73  for (size_t index = 0; index < client_config_tracker_[i].size(); ++index) {
74  ConfigSet *set = client_config_tracker_[i][index];
75  if (set) {
76  set->clear();
77  delete set;
78  client_config_tracker_[i][index] = NULL;
79  }
80  }
81  }
82  for (TableMap::iterator iter = table_map_.begin(); iter != table_map_.end();
83  ++iter) {
84  DBTable *table = iter->first;
85  TableInfo *info = iter->second;
86  table->Unregister(info->id());
87  TableStateClear(table, info->id());
88  delete info;
89  }
90  table_map_.clear();
91 }
92 
94  const DBTable *table) const {
95  TableMap::const_iterator loc =
96  table_map_.find(const_cast<DBTable *>(table));
97  if (loc != table_map_.end()) {
98  return loc->second;
99  }
100  return NULL;
101 }
102 
104  const DBTable *table) const {
105  const IFMapExporter::TableInfo *tinfo = Find(table);
106  if (tinfo == NULL) {
108  }
109  return tinfo->id();
110 }
111 
113  if (node->IsDeleted()) {
114  return false;
115  }
116  return true;
117 }
118 
120  IFMapNode * node, IFMapNodeState *state, std::unique_ptr<BitSet> *ptr) {
121 
122  const BitSet *set = &state->interest();
123  IFMapTable *table = node->table();
124 
125  if (table->name() == "__ifmap__.virtual_router.0") {
126  IFMapClient *client = server_->FindClient(node->name());
127  if (!client) {
128  return set;
129  }
130  BitSet *merged_set = new BitSet(*set);
131  merged_set->set(client->index());
132  ptr->reset(merged_set);
133  StateInterestSet(state, *merged_set);
134  return merged_set;
135  }
136 
137  return set;
138 }
139 
141  const TableInfo *tinfo = Find(node->table());
142  IFMapNodeState *state = static_cast<IFMapNodeState *>(
143  node->GetState(node->table(), tinfo ? tinfo->id() : 0));
144  return state;
145 }
146 
148  const TableInfo *tinfo = Find(node->table());
149  IFMapNodeState *state = static_cast<IFMapNodeState *>(
150  node->GetState(node->table(), tinfo->id()));
151  if (state == NULL) {
152  state = new IFMapNodeState(node);
153  node->SetState(node->table(), tinfo->id(), state);
154  }
155  return state;
156 }
157 
159  return server_->queue();
160 }
161 
163  return server_->sender();
164 }
165 
166 template <class ObjectType>
167 bool IFMapExporter::UpdateAddChange(ObjectType *obj, IFMapState *state,
168  const BitSet &add_set, const BitSet &rm_set,
169  bool change) {
170  // Remove any bit in "advertise" from the positive update.
171  // This is a NOP in case the interest set is non empty and this is change.
172  IFMapUpdate *update = state->GetUpdate(IFMapListEntry::UPDATE);
173  if (update != NULL) {
174  update->AdvertiseReset(rm_set);
175  }
176 
177  if (state->interest().empty()) {
178  if (update != NULL) {
179  queue()->Dequeue(update);
180  state->Remove(update);
181  delete update;
182  }
183  return false;
184  }
185 
186  if (!change && add_set.empty()) {
187  return false;
188  }
189 
190  bool is_move = false;
191  if (update != NULL) {
192  if (!change) {
193  if (update->advertise().Contains(add_set)) {
194  return false;
195  }
196  } else {
197  if (state->interest() == update->advertise()) {
198  return false;
199  }
200  }
201  is_move = true;
202  queue()->Dequeue(update);
203  } else {
204  update = new IFMapUpdate(obj, true);
205  state->Insert(update);
206  }
207 
208  if (!change) {
209  update->AdvertiseOr(add_set);
210  } else {
211  update->SetAdvertise(state->interest());
212  }
213  queue()->Enqueue(update);
214  sender()->QueueActive();
215  return is_move;
216 }
217 
218 template <class ObjectType>
219 bool IFMapExporter::UpdateRemove(ObjectType *obj, IFMapState *state,
220  const BitSet &rm_set) {
221  // Remove any bit in "interest" from the delete update.
222  IFMapUpdate *update = state->GetUpdate(IFMapListEntry::DEL);
223  if (update != NULL) {
224  update->AdvertiseReset(state->interest());
225  }
226 
227  if (rm_set.empty()) {
228  if (update != NULL) {
229  queue()->Dequeue(update);
230  state->Remove(update);
231  delete update;
232  }
233  return false;
234  }
235 
236  bool is_move = false;
237  if (update != NULL) {
238  if (rm_set == update->advertise()) {
239  return false;
240  }
241  is_move = true;
242  queue()->Dequeue(update);
243  } else {
244  update = new IFMapUpdate(obj, false);
245  state->Insert(update);
246  }
247 
248  update->SetAdvertise(rm_set);
249  queue()->Enqueue(update);
250  sender()->QueueActive();
251  return is_move;
252 }
253 
254 template <class ObjectType>
255 void IFMapExporter::EnqueueDelete(ObjectType *obj, IFMapState *state) {
256  IFMapUpdate *update = state->GetUpdate(IFMapListEntry::UPDATE);
257  if (update != NULL) {
258  queue()->Dequeue(update);
259  state->Remove(update);
260  delete update;
261  }
262 
263  update = state->GetUpdate(IFMapListEntry::DEL);
264  if (update != NULL) {
265  queue()->Dequeue(update);
266  }
267  if (state->advertised().empty()) {
268  assert(update == NULL);
269  return;
270  }
271 
272  if (update == NULL) {
273  update = new IFMapUpdate(obj, false);
274  state->Insert(update);
275  }
276  update->SetAdvertise(state->advertised());
277  queue()->Enqueue(update);
278  sender()->QueueActive();
279 }
280 
282  const TableInfo *tinfo = Find(link_table_);
283  if (!tinfo)
284  return NULL;
285  IFMapLinkState *state = static_cast<IFMapLinkState *>(
286  link->GetState(link_table_, tinfo->id()));
287  return state;
288 }
289 
291  for (IFMapNodeState::iterator iter = state->begin(); iter != state->end();
292  ++iter) {
293  IFMapLink *link = iter.operator->();
294  IFMapLinkState *ls = LinkStateLookup(link);
295  if (ls == NULL) {
296  continue;
297  }
299  if (update == NULL) {
300  continue;
301  }
302  assert(!update->advertise().empty());
303  queue()->Dequeue(update);
304  queue()->Enqueue(update);
305  sender()->QueueActive();
306  }
307 }
308 
310  IFMapUpdate *update = state->GetUpdate(IFMapListEntry::DEL);
311  if (update != NULL) {
312  assert(!update->advertise().empty());
313  queue()->Dequeue(update);
314  queue()->Enqueue(update);
315  sender()->QueueActive();
316  }
317 }
318 
320  const BitSet &rm_set) {
321  for (IFMapNodeState::iterator iter = state->begin(), next = state->begin();
322  iter != state->end(); iter = next) {
323  IFMapLink *link = iter.operator->();
324  next = ++iter;
325  IFMapLinkState *ls = LinkStateLookup(link);
326  if (ls == NULL) {
327  continue;
328  }
329  BitSet common = ls->advertised() & rm_set;
330  if (!common.empty()) {
331  LinkTableExport(link->get_table_partition(), link);
332  }
333  }
334 }
335 
337  IFMapNodeState *state, bool force_process) {
338  BitSet current = state->advertised();
339  IFMapUpdate *update = state->GetUpdate(IFMapListEntry::UPDATE);
340  if (update) {
341  current |= update->advertise();
342  }
343  if (!current.Contains(add_set)) {
344  NodeTableExport(node->get_table_partition(), node);
345  } else {
346  if (force_process) {
347  if (update) {
348  update->AdvertiseReset(update->advertise());
349  }
350  state->AdvertisedReset(state->advertised());
351  NodeTableExport(node->get_table_partition(), node);
352  }
353  }
354 }
355 
357  IFMapState *state) {
358  if (state->CanDelete()) {
359  assert(state->advertised().empty());
360  assert(state->interest().empty());
361  entry->ClearState(table, TableListenerId(table));
362  delete state;
363  }
364 }
365 
366 // Propagate changes to all the interested peers.
367 //
368 // Update order:
369 // link updates (adds) should only be advertised after the corresponding nodes
370 // are advertised.
371 // node membership removal (deletes) should only be advertised after all the
372 // refering links are removed.
373 // When enqueuing a link add, the code forces node processing of adjacent links
374 // before the link update is added to the queue.
375 // When enqueueing a node removal, the corresponding link removals are placed
376 // in the queue before the node.
377 // When a node update moves, any dependent (positive) link update moves also.
378 // When a (negative) link update moves the corresponding node removals move
379 // also.
381  DBEntryBase *entry) {
382  IFMapNode *node = static_cast<IFMapNode *>(entry);
383  DBTable *table = static_cast<DBTablePartition *>(partition)->table();
384 
385  const TableInfo *tinfo = Find(table);
386  DBState *entry_state = entry->GetState(table, tinfo->id());
387  IFMapNodeState *state = static_cast<IFMapNodeState *>(entry_state);
388 
389  if (IsFeasible(node)) {
390  if (state == NULL) {
391  state = new IFMapNodeState(node);
392  entry->SetState(table, tinfo->id(), state);
393  }
394  state->SetValid(node);
395 
396  // This is an add operation for nodes that are interested and
397  // have not seen the advertisement.
398  BitSet add_set;
399  add_set.BuildComplement(state->interest(), state->advertised());
400 
401  // This is a delete operation for nodes that have seen it but are no
402  // longer interested.
403  BitSet rm_set;
404  rm_set.BuildComplement(state->advertised(), state->interest());
405 
406  bool change = ConfigChanged(node);
407 
408  // enqueue update
409  // If there is a previous update in the queue, if that update has
410  // been seen by any of receivers, we need to move the update to
411  // the tail of the list. When that happens, dependent updates
412  // moved also.
413  bool move = UpdateAddChange(node, state, add_set, rm_set, change);
414  if (move) {
415  MoveDependentLinks(state);
416  }
417 
418  // For the subset of clients being removed, make sure that all
419  // dependent links are removed before.
420  if (!rm_set.empty()) {
421  RemoveDependentLinks(state, rm_set);
422  }
423  UpdateRemove(node, state, rm_set);
424  } else if (state != NULL) {
425  // Link deletes must preceed node deletes.
426  ConfigChanged(node);
427  state->ClearValid();
428  if (!state->HasDependents()) {
429  // enqueue delete.
430  StateInterestReset(state, state->interest());
431  EnqueueDelete(node, state);
432  if (state->update_list().empty()) {
433  DeleteStateIfAppropriate(table, entry, state);
434  }
435  }
436  }
437 }
438 
440  if (node->IsDeleted() && !state->HasDependents()) {
441  IFMapTable *table = node->table();
442  table->Change(node);
443  }
444 }
445 
446 // When a link is created or deleted this may affect the interest graph for
447 // the agents.
448 // Link changes should only be propagated after the respective nodes are
449 // feasible.
451  DBEntryBase *entry) {
452  IFMapLink *link = static_cast<IFMapLink *>(entry);
453  DBTable *table = static_cast<DBTablePartition *>(partition)->table();
454  const TableInfo *tinfo = Find(table);
455  DBState *entry_state = entry->GetState(table, tinfo->id());
456  IFMapLinkState *state = static_cast<IFMapLinkState *>(entry_state);
457 
458  if (!entry->IsDeleted()) {
459  IFMapNodeState *s_left = NULL;
460  IFMapNodeState *s_right = NULL;
461 
462  bool add_link = false;
463  bool force_update = false;
464  if (state == NULL) {
465  state = new IFMapLinkState(link);
466  entry->SetState(table, tinfo->id(), state);
467  s_left = NodeStateLocate(link->left());
468  s_right = NodeStateLocate(link->right());
469  add_link = true;
470  // This is special as internally generated
471  // We can end up in this situation where add comes just after
472  // delete but processing of delete happens just before
473  // Delete for link comes and link is marked for deletion
474  // Delete event gets picked up, state gets deleted and delete
475  // event is raised to send updates
476  // Add event comes in and revives the link since it is only
477  // marked for deletion, add event is enqueued
478  // Send update gets picked up but CleanupInterest does not
479  // do anything because old interest is same as new one
480  // Add event gets picked up but state was deleted earlier
481  // This is a corner case and should not happen for other
482  // config based events
483  if (starts_with(link->left()->ToString(), "virtual-router") &&
484  (starts_with(link->right()->ToString(), "virtual-machine:"))) {
485  if (!s_right->advertised().empty())
486  s_right->AdvertisedReset(s_right->advertised());
487  force_update = true;
488  }
489  } else {
490  if (state->IsValid() && !link->link_revival()) {
491  // Link change
492  assert(state->HasDependency());
493  s_left = state->left();
494  s_right = state->right();
495  } else if (state->IsValid() && link->link_revival()) {
496  link->SetLinkRevival(false);
497  assert(state->HasDependency());
498  s_left = state->left();
499  s_right = state->right();
500  force_update = true;
501  state->AdvertisedReset(state->advertised());
502  if (s_left->advertised().Contains(state->interest()))
503  s_left->AdvertisedReset(state->interest());
504  if (s_right->advertised().Contains(state->interest()))
505  s_right->AdvertisedReset(state->interest());
506  } else {
507  // Link revival i.e. delete quickly followed by add
508  assert(!state->HasDependency());
509  s_left = NodeStateLocate(link->left());
510  s_right = NodeStateLocate(link->right());
511  add_link = true;
512  force_update = true;
513  state->AdvertisedReset(state->advertised());
514  link->SetLinkRevival(false);
515  if (s_left->advertised().Contains(state->interest()))
516  s_left->AdvertisedReset(state->interest());
517  if (s_right->advertised().Contains(state->interest()))
518  s_right->AdvertisedReset(state->interest());
519  }
520  }
521 
522  // If one of the nodes is a vswitch node, then the interest mask
523  // is the corresponding peer bit.
524  std::unique_ptr<BitSet> ml, mr;
525  const BitSet *lset = MergeClientInterest(link->left(), s_left, &ml);
526  const BitSet *rset = MergeClientInterest(link->right(), s_right, &mr);
527  if (*lset != *rset) {
528  walker_->LinkAdd(link, link->left(), *lset, link->right(), *rset);
529  }
530 
531  if (add_link) {
532  // Establish dependency.
533  state->SetDependency(s_left, s_right);
534  state->SetValid();
535  }
536 
537  if (IsFeasible(link->left()) && IsFeasible(link->right())) {
538  // Interest mask is the intersection of left and right nodes.
539  StateInterestSet(state, (s_left->interest() & s_right->interest()));
540  } else {
541  StateInterestSet(state, BitSet());
542  }
543 
544  // This is an add operation for nodes that are interested and
545  // have not seen the advertisement.
546  BitSet add_set;
547  add_set.BuildComplement(state->interest(), state->advertised());
548 
549  BitSet rm_set;
550  rm_set.BuildComplement(state->advertised(), state->interest());
551 
552  if (!add_set.empty()) {
553  ProcessAdjacentNode(link->left(), add_set, s_left, force_update);
554  ProcessAdjacentNode(link->right(), add_set, s_right, force_update);
555  }
556 
557  UpdateAddChange(link, state, add_set, rm_set, false);
558 
559  bool move = UpdateRemove(link, state, rm_set);
560  if (move) {
561  MoveAdjacentNode(s_left);
562  MoveAdjacentNode(s_right);
563  }
564  } else if ((state != NULL) && state->IsValid()) {
565  IFMapNode *left = link->LeftNode(server_->database());
566  IFMapNodeState *s_left = state->left();
567  assert((left != NULL) && (s_left != NULL));
568  IFMapNode *right = link->RightNode(server_->database());
569  IFMapNodeState *s_right = state->right();
570  assert((right != NULL) && (s_right != NULL));
571  BitSet interest = s_left->interest() & s_right->interest();
572  StateInterestReset(state, state->interest());
573 
574  IFMAP_DEBUG(LinkOper, "LinkRemove", left->ToString(), right->ToString(),
575  s_left->interest().ToString(), s_right->interest().ToString());
576  walker_->LinkRemove(interest);
577 
578  state->RemoveDependency();
579  state->ClearValid();
580 
581  // enqueue update.
582  EnqueueDelete(link, state);
583  if (state->update_list().empty()) {
584  DeleteStateIfAppropriate(table, entry, state);
585  }
586 
587  MaybeNotifyOnLinkDelete(left, s_left);
588  MaybeNotifyOnLinkDelete(right, s_right);
589  }
590 }
591 
593  const BitSet &dequeue_set,
594  bool is_delete) {
595  DBTable *table = NULL;
596  DBEntry *db_entry = NULL;
597 
598  IFMapState *state = NULL;
599  if (update->data().type == IFMapObjectPtr::NODE) {
600  IFMapNode *node = update->data().u.node;
601  db_entry = node;
602  table = node->table();
603  } else if (update->data().type == IFMapObjectPtr::LINK) {
604  db_entry = update->data().u.link;
605  table = link_table_;
606  }
607  state = static_cast<IFMapState *>(
608  db_entry->GetState(table, TableListenerId(table)));
609  if (is_delete) {
610  // For any bit in dequeue_set, its possible that advertised is not set.
611  // EG: update is UPDATE and we are called from UpdateQ.Leave(). Reset
612  // only the bits that are really set.
613  BitSet adv_bits = state->advertised() & dequeue_set;
614  StateAdvertisedReset(state, adv_bits);
615  } else {
616  StateAdvertisedOr(state, dequeue_set);
617  }
618 
619  if (update->advertise().empty()) {
620  state->Remove(update);
621  if (update->IsDelete()) {
622  DeleteStateIfAppropriate(table, db_entry, state);
623  }
624  delete update;
625  }
626 }
627 
629  explicit IFMapUpdateDisposer(IFMapUpdateQueue *queue) : queue_(queue) { }
630  void operator()(IFMapUpdate *ptr) {
631  queue_->Dequeue(ptr);
632  boost::checked_delete(ptr);
633  }
634 
635  private:
637 };
638 
640  DBTable::ListenerId tsid) {
641  DBTablePartition *partition = static_cast<DBTablePartition *>(
642  table->GetTablePartition(0));
643 
644  IFMapUpdateDisposer disposer(queue());
645  for (DBEntry *entry = static_cast<DBEntry *>(partition->GetFirst()),
646  *next = NULL; entry != NULL; entry = next) {
647  next = static_cast<DBEntry *>(partition->GetNext(entry));
648  IFMapState *state = static_cast<IFMapState *>(
649  entry->GetState(table, tsid));
650  if (state == NULL) {
651  continue;
652  }
653  entry->ClearState(table, tsid);
654  state->ClearAndDispose(disposer);
655  boost::checked_delete(state);
656  }
657 
658 }
659 
661  return walker_->FilterNeighbor(lnode, link);
662 }
663 
665  IFMapNodeState *state = NodeStateLookup(node);
666  bool changed = false;
667  assert(state);
668 
669  IFMapExporter::crc32type node_crc = node->GetConfigCrc();
670  if (state->crc() != node_crc) {
671  changed = true;
672  state->SetCrc(node_crc);
673  }
674 
675  return changed;
676 }
677 
679  for (int tracker_type = 0; tracker_type < TT_END; ++tracker_type) {
680  if (index >= (int)client_config_tracker_[tracker_type].size()) {
681  client_config_tracker_[tracker_type].resize(index + 1, NULL);
682  }
683  assert(client_config_tracker_[tracker_type][index] == NULL);
684  ConfigSet *set = new ConfigSet();
685  client_config_tracker_[tracker_type][index] = set;
686  }
687 }
688 
690  for (int tracker_type = 0; tracker_type < TT_END; ++tracker_type) {
691  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
692  assert(set);
693  delete set;
694  client_config_tracker_[tracker_type][index] = NULL;
695  }
696 }
697 
699  const BitSet& client_bits, bool add, TrackerType tracker_type) {
700  for (size_t pos = client_bits.find_first(); pos != BitSet::npos;
701  pos = client_bits.find_next(pos)) {
702  ConfigSet *set = client_config_tracker_[tracker_type].at(pos);
703  assert(set);
704  if (add) {
705  set->insert(state);
706  } else {
707  CsSz_t num = set->erase(state);
708  assert(num == 1);
709  }
710  }
711 }
712 
714  BitSet rm_bs;
715  rm_bs.set(index);
716 
717  ConfigSet *set = client_config_tracker_[INTEREST].at(index);
718  assert(set);
719  for (ConfigSet::iterator iter = set->begin(); iter != set->end(); ++iter) {
720  IFMapState *state = *iter;
721  state->InterestReset(rm_bs);
722  }
723 
724  set = client_config_tracker_[ADVERTISED].at(index);
725  assert(set);
726  for (ConfigSet::iterator iter = set->begin(); iter != set->end(); ++iter) {
727  IFMapState *state = *iter;
728  state->AdvertisedReset(rm_bs);
729  }
730 }
731 
733  int index) {
734  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
735  return ((set != NULL) ? true : false);
736 }
737 
739  int index, IFMapState *state) {
740  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
741  assert(set);
742  ConfigSet::iterator iter = set->find(state);
743  return (iter == set->end() ? false : true);
744 }
745 
747  int index) {
748  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
749  assert(set);
750  return set->empty();
751 }
752 
754  int index) {
755  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
756  assert(set);
757  return set->size();
758 }
759 
761  TrackerType tracker_type, int index) const {
762  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
763  assert(set);
764  return set->begin();
765 }
766 
768  TrackerType tracker_type, int index) const {
769  ConfigSet *set = client_config_tracker_[tracker_type].at(index);
770  assert(set);
771  return set->end();
772 }
773 
775  const BitSet& interest_bits) {
776  // Add the node to the config-tracker of all clients that just became
777  // interested in this node.
778  bool add = true;
779  BitSet new_clients;
780  new_clients.BuildComplement(interest_bits, state->interest());
781  if (!new_clients.empty()) {
782  UpdateClientConfigTracker(state, new_clients, add, INTEREST);
783  }
784 
785  // Remove the node from the config-tracker of all clients that are no longer
786  // interested in this node.
787  add = false;
788  BitSet old_clients;
789  old_clients.BuildComplement(state->interest(), interest_bits);
790  if (!old_clients.empty()) {
791  UpdateClientConfigTracker(state, old_clients, add, INTEREST);
792  }
793 
794  state->SetInterest(interest_bits);
795 }
796 
797 // Add the node to the config-tracker of all clients that just became interested
798 // in this node.
800  const BitSet& interest_bits) {
801  bool add = true;
802  UpdateClientConfigTracker(state, interest_bits, add, INTEREST);
803  state->InterestOr(interest_bits);
804 }
805 
806 // Remove the node from the config-tracker of all clients that are no longer
807 // interested in this node.
809  const BitSet& interest_bits) {
810  bool add = false;
811  UpdateClientConfigTracker(state, interest_bits, add, INTEREST);
812  state->InterestReset(interest_bits);
813 }
814 
815 // Add the node to the config-tracker of all clients that just sent this node.
817  const BitSet& advertised_bits) {
818  bool add = true;
819  UpdateClientConfigTracker(state, advertised_bits, add, ADVERTISED);
820  state->AdvertisedOr(advertised_bits);
821 }
822 
823 // Remove the node from the config-tracker of all clients from whom the node
824 // was withdrawn.
826  const BitSet& advertised_bits) {
827  bool add = false;
828  UpdateClientConfigTracker(state, advertised_bits, add, ADVERTISED);
829  state->AdvertisedReset(advertised_bits);
830 }
831 
833  return walker_->get_traversal_white_list();
834 }
835 
837  walker_->ResetLinkDeleteClients(bset);
838 }
839 
Definition: bitset.h:17
BitSet & reset(size_t pos)
Definition: bitset.cc:136
static const size_t npos
Definition: bitset.h:19
size_t find_first() const
Definition: bitset.cc:242
void BuildComplement(const BitSet &lhs, const BitSet &rhs)
Definition: bitset.cc:486
size_t find_next(size_t pos) const
Definition: bitset.cc:255
bool empty() const
Definition: bitset.cc:165
bool Contains(const BitSet &rhs) const
Definition: bitset.cc:536
BitSet & set(size_t pos)
Definition: bitset.cc:125
std::string ToString() const
Definition: bitset.cc:551
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
bool IsDeleted() const
Definition: db_entry.h:48
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:207
static const int kInvalidId
Definition: db_table.h:64
void Unregister(ListenerId listener)
Definition: db_table.cc:212
int ListenerId
Definition: db_table.h:62
const std::string & name() const
Definition: db_table.h:110
virtual DBEntry * GetNext(const DBEntryBase *entry)
virtual DBEntry * GetFirst()
virtual void Change(DBEntryBase *entry)
Definition: db_table.cc:433
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:462
Definition: db.h:24
iterator lower_bound(const std::string &name)
Definition: db.h:70
iterator end()
Definition: db.h:69
TableMap::iterator iterator
Definition: db.h:29
DBTableBase * FindTable(const std::string &name)
Definition: db.cc:68
int index() const
Definition: ifmap_client.h:31
DBTableBase::ListenerId id() const
DBTableBase::ListenerId id_
TableInfo(DBTable::ListenerId id)
IFMapUpdateQueue * queue()
Cs_citer ClientConfigTrackerEnd(TrackerType tracker_type, int index) const
void AddClientConfigTracker(int index)
ConfigSet::size_type CsSz_t
bool IsFeasible(const IFMapNode *node)
void DeleteStateIfAppropriate(DBTable *table, DBEntryBase *entry, IFMapState *state)
void UpdateClientConfigTracker(IFMapState *state, const BitSet &client_bits, bool add, TrackerType tracker_type)
void StateInterestOr(IFMapState *state, const BitSet &interest_bits)
void StateUpdateOnDequeue(IFMapUpdate *update, const BitSet &dequeue_set, bool is_delete)
void StateInterestReset(IFMapState *state, const BitSet &interest_bits)
DBTable * link_table_
size_t ClientConfigTrackerSize(TrackerType tracker_type, int index)
Cs_citer ClientConfigTrackerBegin(TrackerType tracker_type, int index) const
void DeleteClientConfigTracker(int index)
void ProcessAdjacentNode(IFMapNode *node, const BitSet &add_set, IFMapNodeState *state, bool force_process=false)
void StateAdvertisedReset(IFMapState *state, const BitSet &interest_bits)
boost::unordered_set< IFMapState * > ConfigSet
void RemoveDependentLinks(IFMapNodeState *state, const BitSet &rm_set)
void Initialize(DB *db)
IFMapLinkState * LinkStateLookup(IFMapLink *link)
void NodeTableExport(DBTablePartBase *partition, DBEntryBase *entry)
bool ClientConfigTrackerHasState(TrackerType tracker_type, int index, IFMapState *state)
void StateInterestSet(IFMapState *state, const BitSet &interest_bits)
const TableInfo * Find(const DBTable *table) const
IFMapUpdateSender * sender()
bool ClientConfigTrackerEmpty(TrackerType tracker_type, int index)
ConfigSet::const_iterator Cs_citer
void ResetLinkDeleteClients(const BitSet &bset)
bool ConfigChanged(IFMapNode *node)
void MoveAdjacentNode(IFMapNodeState *state)
void MoveDependentLinks(IFMapNodeState *state)
DBTable::ListenerId TableListenerId(const DBTable *table) const
boost::crc_32_type::value_type crc32type
bool UpdateAddChange(ObjectType *obj, IFMapState *state, const BitSet &add_set, const BitSet &rm_set, bool change)
const BitSet * MergeClientInterest(IFMapNode *node, IFMapNodeState *state, std::unique_ptr< BitSet > *ptr)
void LinkTableExport(DBTablePartBase *partition, DBEntryBase *entry)
void CleanupClientConfigTrackedEntries(int index)
IFMapServer * server_
bool FilterNeighbor(IFMapNode *lnode, IFMapLink *link)
bool ClientHasConfigTracker(TrackerType tracker_type, int index)
IFMapExporter(IFMapServer *server)
void TableStateClear(DBTable *table, DBTable::ListenerId tsid)
void StateAdvertisedOr(IFMapState *state, const BitSet &interest_bits)
ClientConfigTracker client_config_tracker_[TT_END]
bool UpdateRemove(ObjectType *obj, IFMapState *state, const BitSet &rm_set)
const IFMapTypenameWhiteList & get_traversal_white_list() const
IFMapNodeState * NodeStateLookup(IFMapNode *node)
TableMap table_map_
boost::scoped_ptr< IFMapGraphWalker > walker_
void EnqueueDelete(ObjectType *obj, IFMapState *state)
IFMapNodeState * NodeStateLocate(IFMapNode *node)
void SetDependency(IFMapNodeState *first, IFMapNodeState *second)
bool HasDependency() const
IFMapNodeState * left()
Definition: ifmap_update.h:215
IFMapNodeState * right()
Definition: ifmap_update.h:216
void RemoveDependency()
iterator end()
Definition: ifmap_update.h:188
iterator begin()
Definition: ifmap_update.h:187
bool HasDependents() const
IFMapTable * table()
Definition: ifmap_node.h:29
crc32type GetConfigCrc()
Definition: ifmap_node.cc:77
const std::string & name() const
Definition: ifmap_node.h:48
virtual std::string ToString() const
Definition: ifmap_node.cc:31
IFMapUpdateQueue * queue()
Definition: ifmap_server.h:84
DB * database()
Definition: ifmap_server.h:82
IFMapUpdateSender * sender()
Definition: ifmap_server.h:85
DBGraph * graph()
Definition: ifmap_server.h:83
IFMapClient * FindClient(const std::string &id)
void AdvertisedReset(const BitSet &set)
Definition: ifmap_update.h:142
virtual bool CanDelete()=0
void Remove(IFMapUpdate *update)
virtual void ClearValid()
Definition: ifmap_update.h:150
void InterestOr(const BitSet &bset)
Definition: ifmap_update.h:137
void ClearAndDispose(Disposer disposer)
Definition: ifmap_update.h:145
void AdvertisedOr(const BitSet &set)
Definition: ifmap_update.h:141
void InterestReset(const BitSet &set)
Definition: ifmap_update.h:139
const crc32type & crc() const
Definition: ifmap_update.h:153
void Insert(IFMapUpdate *update)
IFMapUpdate * GetUpdate(IFMapListEntry::EntryType type)
Definition: ifmap_update.cc:91
const BitSet & interest() const
Definition: ifmap_update.h:129
const BitSet & advertised() const
Definition: ifmap_update.h:130
virtual bool IsValid() const
Definition: ifmap_update.h:151
void SetInterest(const BitSet &bset)
Definition: ifmap_update.h:138
void SetCrc(crc32type &crc)
Definition: ifmap_update.h:154
const UpdateList & update_list() const
Definition: ifmap_update.h:132
void Dequeue(IFMapUpdate *update)
bool Enqueue(IFMapUpdate *update)
virtual void QueueActive()
const BitSet & advertise() const
Definition: ifmap_update.h:94
void AdvertiseReset(const BitSet &set)
Definition: ifmap_update.cc:59
void SetAdvertise(const BitSet &set)
Definition: ifmap_update.cc:67
void AdvertiseOr(const BitSet &set)
Definition: ifmap_update.cc:63
const IFMapObjectPtr & data() const
Definition: ifmap_update.h:96
static void MaybeNotifyOnLinkDelete(IFMapNode *node, IFMapNodeState *state)
#define IFMAP_DEBUG(obj,...)
Definition: ifmap_log.h:33
bool IsDelete() const
Definition: ifmap_update.h:66
IFMapNode * node
Definition: ifmap_update.h:41
ObjectType type
Definition: ifmap_update.h:38
IFMapLink * link
Definition: ifmap_update.h:42
union IFMapObjectPtr::@5 u
IFMapUpdateQueue * queue_
IFMapUpdateDisposer(IFMapUpdateQueue *queue)
void operator()(IFMapUpdate *ptr)