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