LCOV - code coverage report
Current view: top level - ifmap - ifmap_server_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 284 310 91.6 %
Date: 2026-06-22 02:21:21 Functions: 29 30 96.7 %
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_server_table.h"
       6             : 
       7             : #include <boost/algorithm/string.hpp>
       8             : #include <boost/checked_delete.hpp>
       9             : #include <boost/type_traits.hpp>
      10             : 
      11             : #include "base/compiler.h"
      12             : #include "base/logging.h"
      13             : #include "db/db.h"
      14             : #include "db/db_graph.h"
      15             : #include "db/db_table_partition.h"
      16             : #include "ifmap/ifmap_link.h"
      17             : #include "ifmap/ifmap_link_table.h"
      18             : #include "ifmap/ifmap_log.h"
      19             : #include "ifmap/ifmap_log_types.h"
      20             : 
      21             : using namespace std;
      22             : 
      23      170515 : IFMapServerTable::RequestData::RequestData() {
      24      170515 : }
      25             : 
      26        8020 : IFMapServerTable::RequestData::RequestData(IFMapOrigin::Origin orig,
      27        8020 :         const string &type, const string &name)
      28        8020 :     : origin(orig), id_type(type), id_name(name) {
      29        8020 : }
      30             : 
      31             : // Warning: std::unique_ptr<> will not call the destructor if the type is
      32             : // incomplete at the time the unique_ptr destructor is generated. Depending
      33             : // on the compiler this may occur at different times. With clang the
      34             : // unique_ptr appears to be generated when needed by an enclosing type.
      35             : // gcc appears to behave differently.
      36      357070 : IFMapServerTable::RequestData::~RequestData() {
      37             : #if defined(__GNUC__)
      38             : #if (__GNUC_PREREQ(4, 2) > 0)
      39             :     boost::has_virtual_destructor<AutogenProperty>::type has_destructor;
      40      178535 :     assert(has_destructor);
      41             : #endif
      42             : #endif
      43      178535 :     boost::checked_delete(content.release());
      44      357070 : }
      45             : 
      46             : 
      47     1224488 : IFMapServerTable::IFMapServerTable(DB *db, const string &name, DBGraph *graph)
      48     1224488 :         : IFMapTable(db, name, graph) {
      49     1224488 : }
      50             : 
      51      654149 : unique_ptr<DBEntry> IFMapServerTable::AllocEntry(const DBRequestKey *key) const {
      52             :     unique_ptr<DBEntry> entry(
      53      654149 :         new IFMapNode(const_cast<IFMapServerTable *>(this)));
      54      654149 :     entry->SetKey(key);
      55      654149 :     return entry;
      56           0 : }
      57             : 
      58      246440 : static IFMapServerTable *TableFind(DB *db, const string &metadata) {
      59      246440 :     string name = metadata;
      60      246440 :     std::replace(name.begin(), name.end(), '-', '_');
      61      246440 :     name = "__ifmap__." + name + ".0";
      62             :     IFMapServerTable *table =
      63      246440 :             static_cast<IFMapServerTable *>(db->FindTable(name));
      64      246440 :     return table;
      65      246440 : }
      66             : 
      67       58863 : IFMapNode *IFMapServerTable::EntryLookup(RequestKey *request) {
      68       58863 :     unique_ptr<DBEntry> key(AllocEntry(request));
      69       58863 :     IFMapNode *node = static_cast<IFMapNode *>(Find(key.get()));
      70       58863 :     if ((node == NULL) || node->IsDeleted()) {
      71         111 :         return NULL;
      72             :     }
      73       58752 :     return node;
      74       58863 : }
      75             : 
      76      322822 : IFMapNode *IFMapServerTable::EntryLocate(RequestKey *request, bool *changep) {
      77      322822 :     unique_ptr<DBEntry> key(AllocEntry(request));
      78      322822 :     IFMapNode *node = static_cast<IFMapNode *>(Find(key.get()));
      79      322822 :     if (node != NULL) {
      80      133751 :         if (node->IsDeleted()) {
      81           4 :             node->ClearDelete();
      82           4 :             graph()->AddNode(node);
      83           4 :             IFMAP_DEBUG(IFMapNodeOperation, "Re-creating", node->ToString());
      84           4 :             *changep = true;
      85             :         }
      86      133751 :         return node;
      87             :     }
      88      189071 :     *changep = true;
      89             :     node = const_cast<IFMapNode *>(
      90      189071 :         static_cast<const IFMapNode *>(key.release()));
      91             :     DBTablePartition *partition =
      92      189071 :             static_cast<DBTablePartition *>(GetTablePartition(0));
      93      189071 :     partition->Add(node);
      94      189071 :     graph()->AddNode(node);
      95      189071 :     IFMAP_DEBUG(IFMapNodeOperation, "Creating", node->ToString());
      96      189071 :     return node;
      97      322822 : }
      98             : 
      99       33344 : IFMapNode *IFMapServerTable::TableEntryLookup(IFMapServerTable *table,
     100             :                                               const string &id_name) {
     101       33344 :     RequestKey request;
     102       33344 :     request.id_name = id_name;
     103       66688 :     return table->EntryLookup(&request);
     104       33344 : }
     105             : 
     106      169710 : IFMapNode *IFMapServerTable::TableEntryLocate(IFMapServerTable *table,
     107             :                                               const string &id_name,
     108             :                                               bool *changep) {
     109      169710 :     RequestKey request;
     110      169710 :     request.id_name = id_name;
     111      339420 :     return table->EntryLocate(&request, changep);
     112      169710 : }
     113             : 
     114      203052 : IFMapLink *IFMapServerTable::FindLinkNode(IFMapNode *first, IFMapNode *second,
     115             :                                    const string &metadata) {
     116             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     117      203052 :         database()->FindTable("__ifmap_metadata__.0"));
     118      203052 :     assert(table != NULL);
     119      203052 :     IFMapLink *link =  table->FindLink(metadata, first, second);
     120      203052 :     return (link ? (link->IsDeleted() ? NULL : link) : NULL);
     121             : }
     122             : 
     123      159811 : IFMapLink *IFMapServerTable::LinkNodeAdd(IFMapNode *first, IFMapNode *second,
     124             :                                    const string &metadata,
     125             :                                    uint64_t sequence_number,
     126             :                                    const IFMapOrigin &origin) {
     127             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     128      159811 :         database()->FindTable("__ifmap_metadata__.0"));
     129      159811 :     assert(table != NULL);
     130      159811 :     IFMAP_DEBUG(IFMapLinkOperation, "Creating", metadata);
     131      159811 :     return table->AddLink(first, second, metadata, sequence_number, origin);
     132             : }
     133             : 
     134        9947 : void IFMapServerTable::LinkNodeUpdate(IFMapLink *link, uint64_t sequence_number,
     135             :                                       const IFMapOrigin &origin) {
     136        9947 :     link->set_last_change_at_to_now();
     137        9947 :     link->UpdateProperties(origin, sequence_number);
     138        9947 : }
     139             : 
     140       33287 : void IFMapServerTable::LinkNodeDelete(IFMapLink *link,
     141             :         const IFMapOrigin &origin) {
     142             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     143       33287 :         database()->FindTable("__ifmap_metadata__.0"));
     144       33287 :     assert(table != NULL);
     145       33287 :     IFMAP_DEBUG(IFMapLinkOperation, "Deleting", link->ToString());
     146       33287 :     table->DeleteLink(link, origin);
     147       33287 : }
     148             : 
     149             : // Generate an unique key for a Link Attribute element. The generated key should
     150             : // be independent of the order in which the parameters are specified.
     151       79859 : std::string IFMapServerTable::LinkAttrKey(IFMapNode *first, IFMapNode *second) {
     152       79859 :     ostringstream oss;
     153       79859 :     oss << "attr(";
     154       79859 :     if (first->IsLess(*second)) {
     155       67364 :         oss << first->name() << "," << second->name();
     156             :     } else {
     157       12495 :         oss << second->name() << "," << first->name();
     158             :     }
     159       79859 :     oss << ")";
     160      159718 :     return oss.str();
     161       79859 : }
     162             : 
     163       41769 : void IFMapServerTable::DeleteNode(IFMapNode *node) {
     164       41769 :     IFMAP_DEBUG(IFMapNodeOperation, "Deleting", node->ToString());
     165             :     DBTablePartition *partition =
     166       41769 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     167       41769 :     graph()->RemoveNode(node);
     168       41769 :     partition->Delete(node);
     169       41769 : }
     170             : 
     171      120709 : void IFMapServerTable::Notify(IFMapNode *node) {
     172             :     DBTablePartition *partition =
     173      120709 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     174      120709 :     partition->Change(node);
     175      120709 : }
     176             : 
     177       58586 : bool IFMapServerTable::DeleteIfEmpty(IFMapNode *node) {
     178       58586 :     if ((node->GetObject() == NULL) && !node->HasAdjacencies(graph())) {
     179       41769 :         DeleteNode(node);
     180       41769 :         return true;
     181             :     }
     182       16817 :     return false;
     183             : }
     184             : 
     185      114530 : IFMapObject *IFMapServerTable::LocateObject(IFMapNode *node,
     186             :                                             IFMapOrigin origin) {
     187      114530 :     IFMapObject *object = node->Find(origin);
     188      114530 :     if (object == NULL) {
     189       99072 :         object = AllocObject();
     190       99072 :         object->set_origin(origin);
     191       99072 :         node->Insert(object);
     192             :     }
     193      114530 :     return object;
     194             : }
     195             : 
     196       49018 : IFMapIdentifier *IFMapServerTable::LocateIdentifier(IFMapNode *node,
     197             :                                                     IFMapOrigin origin,
     198             :                                                     uint64_t sequence_number) {
     199       49018 :     IFMapObject *object = LocateObject(node, origin);
     200       49018 :     assert(object);
     201             : 
     202             :     // If the sequence number has changed, we are processing updates in a new
     203             :     // connection to the ifmap server. Save the current properties and check
     204             :     // later with the updated properties to find any stale ones.
     205       49018 :     if (object->sequence_number() != sequence_number) {
     206          16 :         IFMapIdentifier *identifier = static_cast<IFMapIdentifier *>(object);
     207          16 :         identifier->TransferPropertyToOldProperty();
     208          16 :         object->set_sequence_number(sequence_number);
     209             :     }
     210       49018 :     return static_cast<IFMapIdentifier *>(object);
     211             : }
     212             : 
     213       65512 : IFMapLinkAttr *IFMapServerTable::LocateLinkAttr(IFMapNode *node,
     214             :                                                 IFMapOrigin origin,
     215             :                                                 uint64_t sequence_number) {
     216       65512 :     IFMapObject *object = LocateObject(node, origin);
     217       65512 :     assert(object);
     218       65512 :     object->set_sequence_number(sequence_number);
     219             : 
     220       65512 :     return static_cast<IFMapLinkAttr *>(object);
     221             : }
     222             : 
     223      178527 : void IFMapServerTable::Input(DBTablePartition *partition, DBClient *client,
     224             :                              DBRequest *request) {
     225      178527 :     assert(request->oper == DBRequest::DB_ENTRY_ADD_CHANGE ||
     226             :            request->oper == DBRequest::DB_ENTRY_DELETE);
     227      178527 :     RequestKey *key = static_cast<RequestKey *>(request->key.get());
     228      178527 :     RequestData *data = static_cast<RequestData *>(request->data.get());
     229      178527 :     assert(data != NULL);
     230             : 
     231      178527 :     IFMapServerTable *rtable = NULL;
     232      178527 :     IFMapServerTable *mtable = NULL;
     233             : 
     234             :     // Sanity checks before allocation resources.
     235      178527 :     if (!data->id_name.empty()) {
     236      123220 :         rtable = TableFind(database(), data->id_type);
     237      123220 :         if (!rtable) {
     238           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table",
     239             :                         data->id_type);
     240       55368 :             return;
     241             :         }
     242      123220 :         mtable = TableFind(database(), data->metadata);
     243      161906 :         if (mtable == NULL && request->oper == DBRequest::DB_ENTRY_ADD_CHANGE &&
     244       38686 :             data->content.get() != NULL) {
     245           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table",
     246             :                         data->metadata);
     247           0 :             return;
     248             :         }
     249             :     }
     250             : 
     251      178527 :     IFMapNode *first = NULL;
     252      178527 :     bool lchanged = false;
     253      178527 :     if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     254       25415 :         first = EntryLookup(key);
     255       25415 :         if (first == NULL) {
     256          74 :             IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     257             :                        key->id_name);
     258          74 :             return;
     259             :         }
     260             :     } else {
     261      153112 :         first = EntryLocate(key, &lchanged);
     262             :     }
     263             : 
     264      178453 :     if (data->id_name.empty()) {
     265             :         // property
     266       55257 :         first->set_last_change_at_to_now();
     267       55257 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     268       48914 :             IFMapIdentifier *identifier = LocateIdentifier(first, data->origin,
     269             :                                                            key->id_seq_num);
     270       48914 :             identifier->SetProperty(data->metadata, data->content.get());
     271       48914 :             partition->Change(first);
     272             :         } else {
     273             :             IFMapIdentifier *identifier = static_cast<IFMapIdentifier *>(
     274        6343 :                     first->Find(data->origin));
     275        6343 :             if (identifier == NULL) {
     276           8 :                 return;
     277             :             }
     278        6335 :             identifier->ClearProperty(data->metadata);
     279             :             // Figure out whether to delete the identifier.
     280        6335 :             if (identifier->empty()) {
     281        5251 :                 first->Remove(identifier);
     282             :             }
     283        6335 :             if (DeleteIfEmpty(first) == false) {
     284        5867 :                 partition->Change(first);
     285             :             }
     286             :         }
     287       55249 :         return;
     288             :     }
     289             : 
     290      123196 :     IFMapNode *second = NULL;
     291      123196 :     bool rchanged = false;
     292      123196 :     if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     293       18998 :         second = TableEntryLookup(rtable, data->id_name);
     294       18998 :         if (second == NULL) {
     295          14 :             IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     296             :                        data->id_name);
     297          14 :             return;
     298             :         }
     299             :     } else {
     300      104198 :         second = TableEntryLocate(rtable, data->id_name, &rchanged);
     301             :     }
     302             : 
     303      123182 :     IFMapNode *midnode = NULL;
     304      123182 :     bool mchanged = false;
     305             : 
     306      123182 :     if (mtable != NULL) {
     307             :         // link with attribute
     308       79858 :         string id_mid = LinkAttrKey(first, second);
     309       79858 :         if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     310       14346 :             midnode = TableEntryLookup(mtable, id_mid);
     311       14346 :             if (midnode == NULL) {
     312          23 :                 IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     313             :                            id_mid);
     314          23 :                 return;
     315             :             }
     316             :         } else {
     317       65512 :             midnode = TableEntryLocate(mtable, id_mid, &mchanged);
     318             :         }
     319       79835 :         midnode->set_last_change_at_to_now();
     320       79835 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     321             :             IFMapLink *glink =
     322      131024 :                 static_cast<IFMapLink *>(FindLinkNode(first, midnode,
     323       65512 :                                                       data->metadata));
     324       65512 :             if (glink == NULL) {
     325      125472 :                 glink = LinkNodeAdd(first, midnode, data->metadata,
     326       62736 :                             key->id_seq_num, data->origin);
     327       62736 :                 graph()->Link(first, midnode, glink);
     328             :             } else {
     329        2776 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     330             :             }
     331      131024 :             glink = static_cast<IFMapLink *>(FindLinkNode(midnode, second,
     332       65512 :                                                           data->metadata));
     333       65512 :             if (glink == NULL) {
     334      125468 :                 glink = LinkNodeAdd(midnode, second, data->metadata,
     335       62734 :                             key->id_seq_num, data->origin);
     336       62734 :                 graph()->Link(midnode, second, glink);
     337             :             } else {
     338        2778 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     339             :             }
     340       65512 :             IFMapLinkAttr *link_attr = mtable->LocateLinkAttr(midnode,
     341             :                                                               data->origin,
     342             :                                                               key->id_seq_num);
     343       65512 :             mchanged |= link_attr->SetData(data->content.get());
     344             :         } else {
     345       14323 :             IFMapObject *object = midnode->Find(data->origin);
     346       14323 :             if (object == NULL) {
     347           0 :                 return;
     348             :             }
     349       14323 :             midnode->Remove(object);
     350       14323 :             if (midnode->GetObject() != NULL) {
     351           0 :                 return;
     352             :             }
     353       14323 :             IFMapOrigin origin(data->origin);
     354             :             IFMapLink *glink =
     355       28646 :                 static_cast<IFMapLink *>(FindLinkNode(first, midnode,
     356       14323 :                                                       data->metadata));
     357       14323 :             if (glink) LinkNodeDelete(glink, origin);
     358       28646 :             glink = static_cast<IFMapLink *>(FindLinkNode(midnode, second,
     359       14323 :                                                       data->metadata));
     360       14323 :             if (glink) LinkNodeDelete(glink, origin);
     361       14323 :             DeleteIfEmpty(first);
     362       14323 :             rtable->DeleteIfEmpty(second);
     363       14323 :             mtable->DeleteIfEmpty(midnode);
     364             :         }
     365       79858 :     } else {
     366             :         // link
     367       43324 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     368             :             // Link is added if not present
     369             :             IFMapLink *glink =
     370       77372 :                 static_cast<IFMapLink *>(FindLinkNode(first, second,
     371       38686 :                                                       data->metadata));
     372       38686 :             if (glink == NULL) {
     373       68586 :                 glink = LinkNodeAdd(first, second, data->metadata,
     374       34293 :                             key->id_seq_num, data->origin);
     375       34293 :                 graph()->Link(first, second, glink);
     376             :             } else {
     377        4393 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     378             :             }
     379             :         } else {
     380             :             // TODO: check if the edge is present and ignore otherwise.
     381        4638 :             IFMapLink *glink = FindLinkNode(first, second, data->metadata);
     382        4638 :             if (glink != NULL) {
     383        4635 :                 IFMapOrigin origin(data->origin);
     384        4635 :                 LinkNodeDelete(glink, origin);
     385             :                 // check whether any of the identifiers can be deleted.
     386        4635 :                 DeleteIfEmpty(first);
     387        4635 :                 rtable->DeleteIfEmpty(second);
     388             :             }
     389             :         }
     390             :     }
     391             : 
     392      123159 :     if (lchanged) {
     393       48433 :         partition->Change(first);
     394             :     }
     395      123159 :     if (rchanged) {
     396       55585 :         rtable->Notify(second);
     397             :     }
     398      123159 :     if (mchanged) {
     399       65124 :         mtable->Notify(midnode);
     400             :     }
     401             : }
     402             : 
     403     1221768 : void IFMapServerTable::Clear() {
     404             :     DBTablePartition *partition = static_cast<DBTablePartition *>(
     405     1221768 :         GetTablePartition(0));
     406     1221768 :     assert(!HasListeners());
     407     1221768 :     for (IFMapNode *node = static_cast<IFMapNode *>(partition->GetFirst()),
     408     1221768 :                  *next = NULL;
     409     1369074 :          node != NULL; node = next) {
     410      147306 :         next = static_cast<IFMapNode *>(partition->GetNext(node));
     411      147306 :         if (node->IsDeleted()) {
     412           0 :             continue;
     413             :         }
     414      147306 :         graph()->RemoveNode(node);
     415      147306 :         partition->Delete(node);
     416             :     }
     417     1221768 : }
     418             : 
     419             : // This is called in the context of the virtual_router table i.e. 'this' points
     420             : // to __ifmap__.virtual_router.0
     421          52 : void IFMapServerTable::IFMapVmSubscribe(const std::string &vr_name,
     422             :                                         const std::string &vm_name,
     423             :                                         bool subscribe, bool has_vms) {
     424          52 :     if (subscribe) {
     425          52 :         IFMapProcVmSubscribe(vr_name, vm_name);
     426             :     } else {
     427           0 :         IFMapProcVmUnsubscribe(vr_name, vm_name, has_vms);
     428             :     }
     429          52 : }
     430             : 
     431          52 : void IFMapServerTable::IFMapAddVrVmLink(IFMapNode *vr_node,
     432             :                                         IFMapNode *vm_node) {
     433             :     // Add the link if it does not exist. If it does, add XMPP as origin
     434          52 :     uint64_t sequence_number = 0;
     435          52 :     IFMapOrigin origin(IFMapOrigin::XMPP);
     436             : 
     437          52 :     std::string metadata = std::string("virtual-router-virtual-machine");
     438             :     IFMapLink *glink =
     439          52 :         static_cast<IFMapLink *>(FindLinkNode(vr_node, vm_node, metadata));
     440          52 :     if (glink == NULL) {
     441          48 :         glink = LinkNodeAdd(vr_node, vm_node, metadata, sequence_number, origin);
     442          48 :         graph()->Link(vr_node, vm_node, glink);
     443             :     } else {
     444           4 :         glink->AddOriginInfo(origin, sequence_number);
     445             :     }
     446          52 : }
     447             : 
     448             : // Process the vm-subscribe only after a config-add of the vm
     449          52 : void IFMapServerTable::IFMapProcVmSubscribe(const std::string &vr_name,
     450             :                                             const std::string &vm_name) {
     451          52 :     bool changed = false;
     452             : 
     453             :     // Lookup the node corresponding to vr_name
     454          52 :     RequestKey request;
     455          52 :     request.id_name = vr_name;
     456          52 :     IFMapNode *vr_node = EntryLookup(&request);
     457          52 :     if (vr_node == NULL) {
     458           0 :         vr_node = EntryLocate(&request, &changed);
     459             :     }
     460          52 :     LocateIdentifier(vr_node, IFMapOrigin(IFMapOrigin::XMPP), 0);
     461             : 
     462             :     // Lookup the node corresponding to vm_name
     463             :     IFMapServerTable *vm_table = static_cast<IFMapServerTable *>(
     464          52 :             database()->FindTable("__ifmap__.virtual_machine.0"));
     465          52 :     assert(vm_table != NULL);
     466          52 :     request.id_name = vm_name;
     467          52 :     IFMapNode *vm_node = vm_table->EntryLookup(&request);
     468          52 :     assert(vm_node != NULL);
     469          52 :     vm_table->LocateIdentifier(vm_node, IFMapOrigin(IFMapOrigin::XMPP), 0);
     470             : 
     471          52 :     IFMapAddVrVmLink(vr_node, vm_node);
     472          52 : }
     473             : 
     474           6 : void IFMapServerTable::IFMapRemoveVrVmLink(IFMapNode *vr_node,
     475             :                                            IFMapNode *vm_node) {
     476             :     // Remove XMPP as origin. If there are no more origin's, delete the link.
     477           6 :     IFMapOrigin origin(IFMapOrigin::XMPP);
     478           6 :     std::string metadata = std::string("virtual-router-virtual-machine");
     479             :     IFMapLink *glink =
     480           6 :         static_cast<IFMapLink *>(FindLinkNode(vr_node, vm_node, metadata));
     481           6 :     LinkNodeDelete(glink, origin);
     482           6 : }
     483             : 
     484           0 : void IFMapServerTable::IFMapProcVmUnsubscribe(const std::string &vr_name,
     485             :                                               const std::string &vm_name,
     486             :                                               bool has_vms) {
     487             :     // Lookup the node corresponding to vr_name
     488           0 :     RequestKey request;
     489           0 :     request.id_name = vr_name;
     490           0 :     IFMapNode *vr_node = EntryLookup(&request);
     491           0 :     assert(vr_node != NULL);
     492             : 
     493             :     // Lookup the node corresponding to vm_name
     494             :     IFMapServerTable *vm_table = static_cast<IFMapServerTable *>(
     495           0 :             database()->FindTable("__ifmap__.virtual_machine.0"));
     496           0 :     assert(vm_table != NULL);
     497           0 :     request.id_name = vm_name;
     498           0 :     IFMapNode *vm_node = vm_table->EntryLookup(&request);
     499           0 :     assert(vm_node != NULL);
     500             : 
     501           0 :     IFMapRemoveVrVmLink(vr_node, vm_node);
     502             : 
     503           0 :     IFMapOrigin origin(IFMapOrigin::XMPP);
     504           0 :     RemoveObjectAndDeleteNode(vm_node, origin);
     505             : 
     506             :     // Remove XMPP as origin from the VR only if all the VMs are gone
     507           0 :     if (!has_vms) {
     508           0 :         RemoveObjectAndDeleteNode(vr_node, origin);
     509             :     }
     510           0 : }
     511             : 
     512          12 : void IFMapServerTable::RemoveObjectAndDeleteNode(IFMapNode *node,
     513             :                                                  const IFMapOrigin &origin) {
     514          12 :     IFMapServerTable *table = static_cast<IFMapServerTable *>(node->table());
     515          12 :     assert(table);
     516          12 :     IFMapObject *object = node->Find(origin);
     517          12 :     if (object) {
     518           0 :         node->Remove(object);
     519             :     }
     520          12 :     table->DeleteIfEmpty(node);
     521          12 : }
     522             : 

Generated by: LCOV version 1.14