LCOV - code coverage report
Current view: top level - ifmap - ifmap_agent_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 341 381 89.5 %
Date: 2026-06-11 01:56:02 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "ifmap/ifmap_agent_table.h"
       6             : 
       7             : #include <boost/algorithm/string.hpp>
       8             : #include <boost/bind/bind.hpp>
       9             : #include <boost/format.hpp>
      10             : #include "base/logging.h"
      11             : #include "db/db.h"
      12             : #include "db/db_graph.h"
      13             : #include "db/db_table_partition.h"
      14             : #include "ifmap/ifmap_agent_parser.h"
      15             : #include "ifmap/ifmap_node.h"
      16             : #include "ifmap/ifmap_link.h"
      17             : #include "ifmap/ifmap_agent_types.h"
      18             : 
      19             : using namespace std;
      20             : using namespace boost::placeholders;
      21             : 
      22             : SandeshTraceBufferPtr
      23             : IFMapAgentTraceBuf(SandeshTraceBufferCreate("IFMapAgentTrace", 1000));
      24             : 
      25         298 : IFMapAgentTable::IFMapAgentTable(DB *db, const string &name, DBGraph *graph)
      26         298 :         : IFMapTable(db, name, graph), pre_filter_(NULL) {
      27         298 : }
      28             : 
      29         816 : unique_ptr<DBEntry> IFMapAgentTable::AllocEntry(const DBRequestKey *key) const {
      30             :     unique_ptr<DBEntry> entry(
      31         816 :         new IFMapNode(const_cast<IFMapAgentTable *>(this)));
      32         816 :     entry->SetKey(key);
      33         816 :     return entry;
      34           0 : }
      35             : 
      36         401 : IFMapNode* IFMapAgentTable::TableEntryLookup(DB *db, RequestKey *key) {
      37             : 
      38         401 :     IFMapTable *table = FindTable(db, key->id_type);
      39         401 :     if (!table) {
      40           0 :         return NULL;
      41             :     }
      42             : 
      43         401 :     unique_ptr<DBEntry> entry(new IFMapNode(table));
      44         401 :     entry->SetKey(key);
      45         401 :     IFMapNode *node = static_cast<IFMapNode *>(table->Find(entry.get()));
      46         401 :     return node;
      47         401 : }
      48             : 
      49             : 
      50         167 : IFMapAgentTable* IFMapAgentTable::TableFind(const string &node_name) {
      51         167 :     string name = node_name;
      52         167 :     std::replace(name.begin(), name.end(), '-', '_');
      53         167 :     name = "__ifmap__." + name + ".0";
      54             :     IFMapAgentTable *table =
      55         167 :             static_cast<IFMapAgentTable *>(database()->FindTable(name));
      56         167 :     return table;
      57         167 : }
      58             : 
      59         167 : IFMapNode *IFMapAgentTable::EntryLookup(RequestKey *request) {
      60         167 :     unique_ptr<DBEntry> key(AllocEntry(request));
      61         167 :     IFMapNode *node = static_cast<IFMapNode *>(Find(key.get()));
      62         167 :     return node;
      63         167 : }
      64             : 
      65          92 : IFMapNode *IFMapAgentTable::EntryLocate(IFMapNode *node, RequestKey *req) {
      66             : 
      67             :     IFMapObject *obj;
      68             : 
      69          92 :     if (node != NULL) {
      70             :         /* If delete marked, clear it now */
      71          12 :         if (node->IsDeleted()) {
      72           0 :             node->ClearDelete();
      73           0 :             graph()->AddNode(node);
      74             :         }
      75             : 
      76          12 :         obj = node->GetObject();
      77          12 :         assert(obj);
      78             :         //We dont accept lesser sequence number updates
      79          12 :         assert(obj->sequence_number() <= req->id_seq_num);
      80             : 
      81          12 :         node->Remove(obj);
      82             : 
      83             :     } else {
      84          80 :         unique_ptr<DBEntry> key(AllocEntry(req));
      85             :         node = const_cast<IFMapNode *>(
      86          80 :             static_cast<const IFMapNode *>(key.release()));
      87             :         DBTablePartition *partition =
      88          80 :             static_cast<DBTablePartition *>(GetTablePartition(0));
      89          80 :         partition->Add(node);
      90          80 :         graph()->AddNode(node);
      91          80 :     }
      92             : 
      93          92 :     return node;
      94             : }
      95             : 
      96             : // A node is deleted. Move all links for the node to defer-list
      97          25 : void IFMapAgentTable::HandlePendingLinks(IFMapNode *node) {
      98             : 
      99             :     IFMapNode *right;
     100             :     DBGraphEdge *edge;
     101             : 
     102             :     IFMapAgentLinkTable *ltable = static_cast<IFMapAgentLinkTable *>
     103          25 :         (database()->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     104          25 :     assert(ltable != NULL);
     105             : 
     106          25 :     DBGraphVertex::edge_iterator iter;
     107             :     bool origin_exists;
     108             :     uint64_t seq;
     109          25 :     for (iter = node->edge_list_begin(graph());
     110          86 :          iter != node->edge_list_end(graph());) {
     111          61 :         edge = iter.operator->();
     112          61 :         IFMapLink *l = static_cast<IFMapLink *>(edge);
     113          61 :         right = static_cast<IFMapNode *>(iter.target());
     114          61 :         iter++;
     115          61 :         seq = l->sequence_number(IFMapOrigin::UNKNOWN, &origin_exists);
     116          61 :         assert(origin_exists);
     117             :         // Create both the request keys
     118          61 :         unique_ptr <IFMapAgentLinkTable::RequestKey> req_key (new IFMapAgentLinkTable::RequestKey);
     119          61 :         req_key->left_key.id_name = node->name();
     120          61 :         req_key->left_key.id_type = node->table()->Typename();
     121          61 :         req_key->left_key.id_seq_num = seq;
     122             : 
     123          61 :         req_key->right_key.id_name = right->name();
     124          61 :         req_key->right_key.id_type = right->table()->Typename();
     125          61 :         req_key->right_key.id_seq_num = seq;
     126          61 :         req_key->metadata = l->metadata();
     127             : 
     128          61 :         DBRequest req;
     129          61 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     130          61 :         req.key = std::move(req_key);
     131             : 
     132             :         //Add it to defer list
     133          61 :         ltable->LinkDefAdd(&req);
     134             : 
     135          61 :         ltable->DelLink(node, right, edge);
     136          61 :     }
     137          25 : }
     138             : 
     139          80 : void IFMapAgentTable::DeleteNode(IFMapNode *node) {
     140             : 
     141             : 
     142          80 :     if ((node->HasAdjacencies(graph()) == true)) {
     143          25 :         HandlePendingLinks(node);
     144             :     }
     145             : 
     146             :     //Now there should not be any more adjacencies
     147          80 :     assert((node->HasAdjacencies(graph()) == false));
     148             : 
     149             :     DBTablePartition *partition =
     150          80 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     151          80 :     graph()->RemoveNode(node);
     152          80 :     partition->Delete(node);
     153          80 : }
     154             : 
     155          92 : void IFMapAgentTable::NotifyNode(IFMapNode *node) {
     156             :     DBTablePartition *partition =
     157          92 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     158          92 :     partition->Change(node);
     159          92 : }
     160             : 
     161             : // Process link-defer list based for the request.
     162             : // If request is add, create left->right and right-left defer nodes
     163             : // If request is delete, remove left->right and right->left defer nodes
     164             : // The sequence number is valid only in the DeferrendNode entry
     165         143 : void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) {
     166         143 :     RequestKey *key = static_cast<RequestKey *>(request->key.get());
     167             : 
     168         143 :     std::list<DeferredNode>::iterator it;
     169             : 
     170         143 :     std::list<DeferredNode> *left = NULL;
     171         143 :     LinkDefMap::iterator left_it = link_def_map_.find(key->left_key);
     172         143 :     if (link_def_map_.end() != left_it)
     173          93 :         left = left_it->second;
     174             : 
     175         143 :     std::list<DeferredNode> *right = NULL;
     176         143 :     LinkDefMap::iterator right_it = link_def_map_.find(key->right_key);
     177         143 :     if (link_def_map_.end() != right_it)
     178          59 :         right = right_it->second;
     179             : 
     180         143 :     if (request->oper == DBRequest::DB_ENTRY_DELETE)  {
     181             :         //We need to delete the old sequence links as well
     182             :         // remove left->right entry
     183          64 :         if (left) {
     184         115 :             for(it = left->begin(); it != left->end(); it++) {
     185         166 :                 if (((*it).node_key.id_type == key->right_key.id_type) &&
     186          52 :                     ((*it).node_key.id_name == key->right_key.id_name)) {
     187          52 :                     left->erase(it);
     188          52 :                     break;
     189             :                 }
     190             :             }
     191          53 :             RemoveDefListEntry(&link_def_map_, left_it, NULL);
     192             :         }
     193             : 
     194             :         // remove right->left entry
     195          64 :         if (right) {
     196          53 :             for(it = right->begin(); it != right->end(); it++) {
     197         105 :                 if (((*it).node_key.id_type == key->left_key.id_type) &&
     198          52 :                     ((*it).node_key.id_name == key->left_key.id_name)) {
     199          52 :                     right->erase(it);
     200          52 :                     break;
     201             :                 }
     202             :             }
     203          52 :             RemoveDefListEntry(&link_def_map_, right_it, NULL);
     204             :         }
     205             : 
     206          64 :         return;
     207             :     }
     208             : 
     209          79 :     bool push_left = true;
     210             : 
     211             :     // Add/Update left->right entry
     212          79 :     if (left) {
     213             :         // If list already contains, just update the seq number
     214         109 :         for(it = left->begin(); it != left->end(); it++) {
     215          74 :             if (((*it).node_key.id_type == key->right_key.id_type) &&
     216           5 :                     ((*it).node_key.id_name == key->right_key.id_name)) {
     217           0 :                 (*it).node_key.id_seq_num = key->right_key.id_seq_num;
     218           0 :                 (*it).link_metadata = key->metadata;
     219           0 :                 push_left = false;
     220           0 :                 break;
     221             :             }
     222             :         }
     223             :     } else {
     224          39 :         left = new std::list<DeferredNode>();
     225          39 :         link_def_map_[key->left_key] = left;
     226             :     }
     227             : 
     228          79 :     bool push_right = true;
     229             :     // Add/Update right->left entry
     230          79 :     if (right) {
     231             :         // If list already contains, just update the seq number
     232          15 :         for(it = right->begin(); it != right->end(); it++) {
     233           9 :             if (((*it).node_key.id_type == key->left_key.id_type) &&
     234           1 :                     ((*it).node_key.id_name == key->left_key.id_name)) {
     235           0 :                 (*it).node_key.id_seq_num = key->left_key.id_seq_num;
     236           0 :                 (*it).link_metadata = key->metadata;
     237           0 :                 push_right = false;
     238           0 :                 break;
     239             :             }
     240             :         }
     241             :     } else {
     242          72 :         right = new std::list<DeferredNode>();
     243          72 :         link_def_map_[key->right_key] = right;
     244             :     }
     245             : 
     246             :     // Add it to the end of the list
     247          79 :     struct DeferredNode dn;
     248          79 :     dn.link_metadata = key->metadata;
     249          79 :     if (push_left) {
     250          79 :         dn.node_key = key->right_key;
     251          79 :         left->push_back(dn);
     252             :     }
     253          79 :     if (push_right) {
     254          79 :         dn.node_key = key->left_key;
     255          79 :         right->push_back(dn);
     256             :     }
     257          79 :     return;
     258          79 : }
     259             : 
     260         167 : void IFMapAgentTable::Input(DBTablePartition *partition, DBClient *client,
     261             :                              DBRequest *request) {
     262         167 :     RequestKey *key = static_cast<RequestKey *>(request->key.get());
     263         167 :     IFMapAgentTable *table = NULL;
     264             :     struct IFMapAgentData *req_data;
     265             :     IFMapObject *obj;
     266             : 
     267         167 :     table = TableFind(key->id_type);
     268         167 :     if (!table) {
     269           0 :         IFMAP_AGENT_TRACE(Trace, key->id_seq_num,
     270             :                 "Table " + key->id_type + " not found");
     271           0 :         return;
     272             :     }
     273             : 
     274         167 :     IFMapNode *node = EntryLookup(key);
     275         167 :     if (table->pre_filter_) {
     276          83 :         DBRequest::DBOperation old_oper = request->oper;
     277          83 :         if (table->pre_filter_(table, node, request) == false) {
     278           0 :             IFMAP_AGENT_TRACE(Trace, key->id_seq_num,
     279             :                     "Node " + key->id_name + " neglected as filter"
     280             :                     + "suppressed");
     281           0 :             return;
     282             :         }
     283          83 :         if ((old_oper != DBRequest::DB_ENTRY_DELETE) &&
     284          46 :                 (request->oper == DBRequest::DB_ENTRY_DELETE)) {
     285           0 :             IFMAP_AGENT_TRACE(Trace, key->id_seq_num,
     286             :                     "Node " + key->id_name + "ID_PERMS Null");
     287             :         }
     288             :     }
     289             : 
     290         167 :     if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     291          73 :         if (node == NULL) {
     292           6 :             IFMAP_AGENT_TRACE(Trace, key->id_seq_num,
     293             :                     "Node " + key->id_name + " not found in Delete");
     294           6 :             return;
     295             :         }
     296             : 
     297          67 :         if (node->IsDeleted()) {
     298           0 :             IFMAP_AGENT_TRACE(Trace, key->id_seq_num,
     299             :                         "Node " + key->id_name + " already deleted");
     300           0 :             return;
     301             :         }
     302             : 
     303          67 :         obj = node->GetObject();
     304             :         //We dont accept lesser sequence number updates
     305          67 :         assert(obj->sequence_number() <= key->id_seq_num);
     306             : 
     307             :         //Upate the sequence number even for deletion of node
     308          67 :         obj->set_sequence_number(key->id_seq_num);
     309          67 :         DeleteNode(node);
     310          67 :         return;
     311             :     }
     312             : 
     313          94 :     if (request->oper == DBRequest::DB_ENTRY_NOTIFY) {
     314           2 :         if (node) {
     315           2 :             partition->Notify(node);
     316             :         }
     317           2 :         return;
     318             :     }
     319             : 
     320          92 :     node = EntryLocate(node, key);
     321          92 :     assert(node);
     322             : 
     323             :     //Get the data from request key and notify oper tables
     324          92 :     req_data = static_cast<struct IFMapAgentData *>(request->data.get());
     325          92 :     obj = static_cast<IFMapObject *>(req_data->content.release());
     326             : 
     327             :     //Set the sequence number of the object
     328          92 :     obj->set_sequence_number(key->id_seq_num);
     329             : 
     330          92 :     node->Insert(obj);
     331          92 :     NotifyNode(node);
     332             : 
     333             :     IFMapAgentLinkTable *link_table = static_cast<IFMapAgentLinkTable *>(
     334          92 :         database()->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     335          92 :     link_table->EvalDefLink(key);
     336             : }
     337             : 
     338         298 : void IFMapAgentTable::Clear() {
     339         298 :     assert(!HasListeners());
     340             :     DBTablePartition *partition = static_cast<DBTablePartition *>(
     341         298 :         GetTablePartition(0));
     342         298 :     IFMapNode *next = NULL;
     343         298 :     for (IFMapNode *node = static_cast<IFMapNode *>(partition->GetFirst());
     344         298 :          node != NULL; node = next) {
     345           0 :         next = static_cast<IFMapNode *>(partition->GetNext(node));
     346           0 :         if (node->IsDeleted()) {
     347           0 :             continue;
     348             :         }
     349           0 :         graph()->RemoveNode(node);
     350           0 :         partition->Delete(node);
     351             :     }
     352         298 : }
     353             : 
     354             : 
     355             : // Agent link table routines
     356         120 : IFMapLink *IFMapAgentLinkTable::FindLink(IFMapNode *left, IFMapNode *right,
     357             :                                   const std::string &metadata) {
     358             : 
     359             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     360         120 :         database()->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     361         120 :     assert(table != NULL);
     362         120 :     IFMapLink *link = table->FindLink(metadata, left, right);
     363         120 :     return (link ? (link->IsDeleted() ? NULL : link) : NULL);
     364             : }
     365             : 
     366          92 : void IFMapAgentLinkTable::AddLink(IFMapNode *left, IFMapNode *right,
     367             :                                   const std::string &metadata,
     368             :                                   uint64_t seq) {
     369             : 
     370             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     371          92 :         database()->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     372          92 :     assert(table != NULL);
     373             : 
     374          92 :     IFMapLink *link = table->AddLink(left, right, metadata, seq,
     375          92 :                                      IFMapOrigin(IFMapOrigin::UNKNOWN));
     376          92 :     graph()->Link(left, right, (DBGraphEdge *)link);
     377          92 : }
     378             : 
     379          86 : void IFMapAgentLinkTable::DelLink(IFMapNode *left, IFMapNode *right, DBGraphEdge *edge) {
     380             :     IFMapAgentLinkTable *table = static_cast<IFMapAgentLinkTable *>(
     381          86 :         database()->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     382          86 :     assert(table != NULL);
     383          86 :     table->DeleteLink(static_cast<IFMapLink *>(edge));
     384          86 : }
     385             : 
     386           2 : IFMapAgentLinkTable::IFMapAgentLinkTable(DB *db, const string &name, DBGraph *graph)
     387           2 :         : IFMapLinkTable(db, name, graph) {
     388           2 : }
     389             : 
     390           2 : DBTable *IFMapAgentLinkTable::CreateTable(DB *db, const string &name,
     391             :                                      DBGraph *graph) {
     392           2 :     IFMapAgentLinkTable *table = new IFMapAgentLinkTable(db, name, graph);
     393           2 :     table->Init();
     394           2 :     return table;
     395             : }
     396             : 
     397             : 
     398           2 : void IFMapAgentLinkTable_Init(DB *db, DBGraph *graph) {
     399           2 :     db->RegisterFactory(IFMAP_AGENT_LINK_DB_NAME,
     400             :         boost::bind(&IFMapAgentLinkTable::CreateTable, _1, _2, graph));
     401           2 :     db->CreateTable(IFMAP_AGENT_LINK_DB_NAME);
     402           2 : }
     403             : 
     404         202 : void IFMapAgentLinkTable::Input(DBTablePartition *partition, DBClient *client,
     405             :                            DBRequest *req) {
     406             : 
     407         202 :     RequestKey *key = static_cast<RequestKey *>(req->key.get());
     408             : 
     409             :     IFMapNode *left;
     410         202 :     left = IFMapAgentTable::TableEntryLookup(database(), &key->left_key);
     411         202 :     if (!left) {
     412          33 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     413             :                 key->left_key.id_type + ":" + key->left_key.id_name +
     414             :                 " not present for link to " + key->right_key.id_type +
     415             :                 ":" + key->right_key.id_name);
     416          33 :         LinkDefAdd(req);
     417          33 :         return;
     418             :     }
     419             : 
     420             :     IFMapNode *right;
     421         169 :     right = IFMapAgentTable::TableEntryLookup(database(), &key->right_key);
     422         169 :     if (!right) {
     423           9 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     424             :                 key->right_key.id_type + " : " + key->right_key.id_name +
     425             :                 " not present for link to " + key->left_key.id_type + " : " +
     426             :                 key->left_key.id_name);
     427           9 :         LinkDefAdd(req);
     428           9 :         return;
     429             :     }
     430             : 
     431         160 :     if (left->IsDeleted()) {
     432          40 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     433             :             "Adding Link" + key->left_key.id_type + ":" +
     434             :             key->left_key.id_name + "->" + key->right_key.id_type +
     435             :                             ":" + key->right_key.id_name + " to defer "
     436             :                             "list as left is deleted marked");
     437          40 :         LinkDefAdd(req);
     438          40 :         return;
     439             :     }
     440             : 
     441         120 :     if (right->IsDeleted()) {
     442           0 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     443             :             "Adding Link" + key->left_key.id_type + ":" +
     444             :             key->left_key.id_name + "->" + key->right_key.id_type +
     445             :                             ":" + key->right_key.id_name + " to defer "
     446             :                             "list as right is deleted marked");
     447           0 :         LinkDefAdd(req);
     448           0 :         return;
     449             :     }
     450             : 
     451         120 :     IFMapObject *obj = left->GetObject();
     452         120 :     if (obj->sequence_number() < key->left_key.id_seq_num) {
     453           0 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     454             :             "IFMap Link " + left->name() + right->name() +
     455             :             " with wrong seq number");
     456           0 :         LinkDefAdd(req);
     457           0 :         return;
     458             :     }
     459             : 
     460         120 :     obj = right->GetObject();
     461         120 :     if (obj->sequence_number() < key->left_key.id_seq_num) {
     462           0 :         IFMAP_AGENT_TRACE(Trace, key->left_key.id_seq_num,
     463             :             "IFMap Link " + left->name() + right->name() +
     464             :             " with wrong seq number");
     465           0 :         LinkDefAdd(req);
     466           0 :         return;
     467             :     }
     468             : 
     469         120 :     DBGraphEdge *link = FindLink(left, right, key->metadata);
     470             : 
     471         120 :     if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     472          95 :         if (link == NULL) {
     473          92 :             AddLink(left, right, key->metadata, key->left_key.id_seq_num);
     474             :         } else {
     475           3 :             IFMapOrigin origin(IFMapOrigin::UNKNOWN);
     476           3 :             IFMapLink *l = static_cast<IFMapLink *>(link);
     477           3 :             l->UpdateProperties(origin, key->left_key.id_seq_num);
     478             :         }
     479             :     } else {
     480          25 :         if (link == NULL) {
     481           0 :             return;
     482             :         }
     483          25 :         DelLink(left, right, link);
     484             :     }
     485             : }
     486             : 
     487         151 : bool IFMapAgentLinkTable::RemoveDefListEntry
     488             :     (LinkDefMap *map, LinkDefMap::iterator &map_it,
     489             :      std::list<DeferredNode>::iterator *list_it) {
     490             : 
     491         151 :     std::list<DeferredNode> *list = map_it->second;
     492         151 :     if (list_it) {
     493          34 :         list->erase(*list_it);
     494             :     }
     495             : 
     496         151 :     if (list->size()) {
     497          40 :         return false;
     498             :     }
     499         111 :     map->erase(map_it);
     500         111 :     delete list;
     501         111 :     return true;
     502             : }
     503             : 
     504             : // For every link there are 2 entries,
     505             : //  left->right
     506             : //  right->left
     507             : //
     508             : //  If both left and right node are available, remove the entries and try to
     509             : //  add the link
     510          92 : void IFMapAgentLinkTable::EvalDefLink(IFMapTable::RequestKey *key) {
     511          92 :     LinkDefMap::iterator link_defmap_it = link_def_map_.find(*key);
     512          92 :     if (link_def_map_.end() == link_defmap_it)
     513          80 :         return;
     514             : 
     515          12 :     std::list<DeferredNode> *left_list = link_defmap_it->second;
     516          12 :     std::list<DeferredNode>::iterator left_it, left_list_entry;
     517          32 :     for(left_it = left_list->begin(); left_it != left_list->end();) {
     518          20 :         left_list_entry = left_it++;
     519             : 
     520             :         // If link seq is older, dont consider the link.
     521          20 :         if ((*left_list_entry).node_key.id_seq_num < key->id_seq_num)
     522           0 :             continue;
     523             : 
     524             :         // Skip if right-node is not yet present
     525          20 :         IFMapNode *node = IFMapAgentTable::TableEntryLookup(database(),
     526          20 :                     &((*left_list_entry).node_key));
     527          20 :         if (!node)
     528           0 :             continue;
     529             : 
     530             :         //If the other end of the node is not from active control node,
     531             :         //dont consider the link
     532          20 :         IFMapObject *obj = node->GetObject();
     533          20 :         if (obj->sequence_number() < key->id_seq_num)
     534           0 :             continue;
     535             : 
     536             : 
     537             :         // left->right entry found defer-list. Find the right->left entry
     538             :         LinkDefMap::iterator right_defmap_it =
     539          20 :             link_def_map_.find((*left_list_entry).node_key);
     540          20 :         assert(link_def_map_.end() != right_defmap_it);
     541             : 
     542          20 :         std::list<DeferredNode> *right_list = right_defmap_it->second;
     543          20 :         std::list<DeferredNode>::iterator right_it, right_list_entry;
     544          20 :         bool removed_something = false;
     545          40 :         for(right_it = right_list->begin(); right_it !=
     546          40 :                 right_list->end(); right_it++) {
     547             : 
     548             :             // If link seq is older, dont consider the link.
     549          20 :             if ((*right_it).node_key.id_seq_num < key->id_seq_num)
     550           0 :                 continue;
     551             : 
     552          40 :             if ((*right_it).node_key.id_type == key->id_type &&
     553          20 :                     (*right_it).node_key.id_name == key->id_name) {
     554          20 :                 RemoveDefListEntry(&link_def_map_, right_defmap_it, &right_it);
     555          20 :                 removed_something = true;
     556          20 :                 break;
     557             :             }
     558             :         }
     559             : 
     560             :         //We should have removed something in the above iteration
     561          20 :         assert(removed_something);
     562             : 
     563             :         //Remove from deferred list before enqueing
     564          20 :         unique_ptr <RequestKey> req_key (new RequestKey);
     565          20 :         req_key->left_key = *key;
     566          20 :         req_key->right_key = (*left_list_entry).node_key;
     567          20 :         req_key->metadata = (*left_list_entry).link_metadata;
     568             :         // Dont delete left_list_entry. Its passed in req structure
     569          20 :         left_list->erase(left_list_entry);
     570             : 
     571          20 :         DBRequest req;
     572          20 :         req.key = std::move(req_key);
     573          20 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     574          20 :         Enqueue(&req);
     575          20 :     }
     576             : 
     577             :     // If list does not have any entries, delete the list
     578          12 :     RemoveDefListEntry(&link_def_map_, link_defmap_it, NULL);
     579             : }
     580             : 
     581           2 : void IFMapAgentLinkTable::DestroyDefLink(uint64_t seq) {
     582             :     std::list<DeferredNode> *ent;
     583           2 :     std::list<DeferredNode>::iterator it, list_entry;
     584           2 :     IFMapAgentLinkTable::LinkDefMap::iterator dlist_it, temp;
     585             : 
     586          13 :     for(dlist_it = link_def_map_.begin(); dlist_it != link_def_map_.end(); ) {
     587          11 :         temp = dlist_it++;
     588          11 :         ent = temp->second;
     589          14 :         for(it = ent->begin(); it != ent->end();) {
     590          14 :             list_entry = it++;
     591             : 
     592             :             //Delete the deferred link if it is old seq
     593          14 :             if ((*list_entry).node_key.id_seq_num < seq) {
     594          14 :                 if (RemoveDefListEntry(&link_def_map_, temp,
     595          14 :                             &list_entry) == true) {
     596             :                     //The list has been deleted. Move to the next map
     597             :                     //entry
     598          11 :                     break;
     599             :                 }
     600             :             }
     601             :         }
     602             :     }
     603           2 : }
     604             : 
     605             : //Stale Cleaner functionality
     606             : class IFMapAgentStaleCleaner::IFMapAgentStaleCleanerWorker : public Task {
     607             : public:
     608             : 
     609           2 :     IFMapAgentStaleCleanerWorker(DB *db, DBGraph *graph, uint64_t seq):
     610             :         Task(TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0),
     611           2 :         db_(db), graph_(graph), seq_(seq) {
     612           2 :     }
     613             : 
     614           2 :     bool Run() {
     615           2 :         IFMAP_AGENT_TRACE(Trace, seq_,
     616             :                 "IFMap Config Audit start:");
     617             :         //Handle the links first
     618           2 :         DBGraph::edge_iterator e_next(graph_);
     619           2 :         for (DBGraph::edge_iterator e_iter = graph_->edge_list_begin();
     620           8 :             e_iter != graph_->edge_list_end(); e_iter = e_next) {
     621             : 
     622           6 :             const DBGraph::DBEdgeInfo &tuple = *e_iter;
     623             : 
     624           6 :             e_next = ++e_iter;
     625             : 
     626           6 :             IFMapNode *lhs = static_cast<IFMapNode *>(boost::get<0>(tuple));
     627           6 :             IFMapNode *rhs = static_cast<IFMapNode *>(boost::get<1>(tuple));
     628           6 :             IFMapLink *link = static_cast<IFMapLink *>(boost::get<2>(tuple));
     629           6 :             assert(link);
     630             : 
     631           6 :             bool exists = false;
     632             :             IFMapLink::LinkOriginInfo origin_info =
     633           6 :                 link->GetOriginInfo(IFMapOrigin::UNKNOWN, &exists);
     634           6 :             if (exists && (origin_info.sequence_number < seq_ )) {
     635             :                 IFMapAgentLinkTable *ltable = static_cast<IFMapAgentLinkTable *>(
     636           6 :                     db_->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     637           6 :                 IFMAP_AGENT_TRACE(Trace,
     638             :                      origin_info.sequence_number, "Deleting Link between " +
     639             :                      lhs->name() + rhs->name());
     640           6 :                 ltable->DeleteLink(link);
     641             :             }
     642             :         }
     643             : 
     644             :         //Handle the vertices now
     645           2 :         DBGraph::vertex_iterator v_next(graph_);
     646           2 :         for (DBGraph::vertex_iterator v_iter = graph_->vertex_list_begin();
     647          15 :             v_iter != graph_->vertex_list_end(); v_iter = v_next) {
     648             : 
     649          13 :             IFMapNode *node = static_cast<IFMapNode *>(v_iter.operator->());
     650          13 :             v_next = ++v_iter;
     651             : 
     652          13 :             IFMapObject *obj = node->GetObject();
     653          13 :             assert(obj);
     654          13 :             if (obj->sequence_number() < seq_) {
     655          13 :                 IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
     656          13 :                 IFMAP_AGENT_TRACE(Trace, obj->sequence_number(),
     657             :                         "Deleting node " + node->name());
     658          13 :                 table->DeleteNode(node);
     659             :             }
     660             :         }
     661             : 
     662             :         //Handle deferred list
     663             :         IFMapAgentLinkTable *table = static_cast<IFMapAgentLinkTable *>(
     664           2 :                     db_->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     665           2 :         table->DestroyDefLink(seq_);
     666             : 
     667           2 :         return true;
     668             :     }
     669           0 :     std::string Description() const {
     670           0 :         return "IFMapAgentStaleCleaner::IFMapAgentStaleCleanerWorker";
     671             :     }
     672             : 
     673             : private:
     674             :     DB *db_;
     675             :     DBGraph *graph_;
     676             :     uint64_t seq_;
     677             : };
     678             : 
     679           2 : IFMapAgentStaleCleaner::~IFMapAgentStaleCleaner() {
     680           2 : }
     681             : 
     682           2 : IFMapAgentStaleCleaner::IFMapAgentStaleCleaner(DB *db, DBGraph *graph) :
     683           2 :         db_(db), graph_(graph) {
     684           2 : }
     685             : 
     686           2 : bool IFMapAgentStaleCleaner::StaleTimeout(uint64_t seq) {
     687           2 :     seq_ = seq;
     688           2 :     IFMapAgentStaleCleanerWorker *cleaner = new IFMapAgentStaleCleanerWorker(db_, graph_, seq_);
     689           2 :     TaskScheduler *sch = TaskScheduler::GetInstance();
     690           2 :     sch->Enqueue(cleaner);
     691           2 :     return false;
     692             : }
     693             : 
     694           2 : void IFMapAgentStaleCleaner::Clear() {
     695             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     696           2 :         db_->FindTable(IFMAP_AGENT_LINK_DB_NAME));
     697           2 :     table->Clear();
     698           2 :     IFMapTable::ClearTables(db_);
     699           2 : }

Generated by: LCOV version 1.14