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-11 01:56:02 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      170543 : IFMapServerTable::RequestData::RequestData() {
      24      170543 : }
      25             : 
      26        8022 : IFMapServerTable::RequestData::RequestData(IFMapOrigin::Origin orig,
      27        8022 :         const string &type, const string &name)
      28        8022 :     : origin(orig), id_type(type), id_name(name) {
      29        8021 : }
      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      357132 : IFMapServerTable::RequestData::~RequestData() {
      37             : #if defined(__GNUC__)
      38             : #if (__GNUC_PREREQ(4, 2) > 0)
      39             :     boost::has_virtual_destructor<AutogenProperty>::type has_destructor;
      40      178566 :     assert(has_destructor);
      41             : #endif
      42             : #endif
      43      178566 :     boost::checked_delete(content.release());
      44      357132 : }
      45             : 
      46             : 
      47     1224637 : IFMapServerTable::IFMapServerTable(DB *db, const string &name, DBGraph *graph)
      48     1224637 :         : IFMapTable(db, name, graph) {
      49     1224637 : }
      50             : 
      51      654603 : unique_ptr<DBEntry> IFMapServerTable::AllocEntry(const DBRequestKey *key) const {
      52             :     unique_ptr<DBEntry> entry(
      53      654603 :         new IFMapNode(const_cast<IFMapServerTable *>(this)));
      54      654603 :     entry->SetKey(key);
      55      654603 :     return entry;
      56           0 : }
      57             : 
      58      246476 : static IFMapServerTable *TableFind(DB *db, const string &metadata) {
      59      246476 :     string name = metadata;
      60      246476 :     std::replace(name.begin(), name.end(), '-', '_');
      61      246476 :     name = "__ifmap__." + name + ".0";
      62             :     IFMapServerTable *table =
      63      246476 :             static_cast<IFMapServerTable *>(db->FindTable(name));
      64      246476 :     return table;
      65      246476 : }
      66             : 
      67       58882 : IFMapNode *IFMapServerTable::EntryLookup(RequestKey *request) {
      68       58882 :     unique_ptr<DBEntry> key(AllocEntry(request));
      69       58882 :     IFMapNode *node = static_cast<IFMapNode *>(Find(key.get()));
      70       58882 :     if ((node == NULL) || node->IsDeleted()) {
      71         111 :         return NULL;
      72             :     }
      73       58771 :     return node;
      74       58882 : }
      75             : 
      76      322854 : IFMapNode *IFMapServerTable::EntryLocate(RequestKey *request, bool *changep) {
      77      322854 :     unique_ptr<DBEntry> key(AllocEntry(request));
      78      322854 :     IFMapNode *node = static_cast<IFMapNode *>(Find(key.get()));
      79      322854 :     if (node != NULL) {
      80      133774 :         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      133774 :         return node;
      87             :     }
      88      189080 :     *changep = true;
      89             :     node = const_cast<IFMapNode *>(
      90      189080 :         static_cast<const IFMapNode *>(key.release()));
      91             :     DBTablePartition *partition =
      92      189080 :             static_cast<DBTablePartition *>(GetTablePartition(0));
      93      189080 :     partition->Add(node);
      94      189080 :     graph()->AddNode(node);
      95      189080 :     IFMAP_DEBUG(IFMapNodeOperation, "Creating", node->ToString());
      96      189080 :     return node;
      97      322854 : }
      98             : 
      99       33351 : IFMapNode *IFMapServerTable::TableEntryLookup(IFMapServerTable *table,
     100             :                                               const string &id_name) {
     101       33351 :     RequestKey request;
     102       33351 :     request.id_name = id_name;
     103       66702 :     return table->EntryLookup(&request);
     104       33351 : }
     105             : 
     106      169723 : IFMapNode *IFMapServerTable::TableEntryLocate(IFMapServerTable *table,
     107             :                                               const string &id_name,
     108             :                                               bool *changep) {
     109      169723 :     RequestKey request;
     110      169723 :     request.id_name = id_name;
     111      339446 :     return table->EntryLocate(&request, changep);
     112      169723 : }
     113             : 
     114      203072 : IFMapLink *IFMapServerTable::FindLinkNode(IFMapNode *first, IFMapNode *second,
     115             :                                    const string &metadata) {
     116             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     117      203072 :         database()->FindTable("__ifmap_metadata__.0"));
     118      203072 :     assert(table != NULL);
     119      203072 :     IFMapLink *link =  table->FindLink(metadata, first, second);
     120      203072 :     return (link ? (link->IsDeleted() ? NULL : link) : NULL);
     121             : }
     122             : 
     123      159820 : 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      159820 :         database()->FindTable("__ifmap_metadata__.0"));
     129      159820 :     assert(table != NULL);
     130      159820 :     IFMAP_DEBUG(IFMapLinkOperation, "Creating", metadata);
     131      159820 :     return table->AddLink(first, second, metadata, sequence_number, origin);
     132             : }
     133             : 
     134        9951 : void IFMapServerTable::LinkNodeUpdate(IFMapLink *link, uint64_t sequence_number,
     135             :                                       const IFMapOrigin &origin) {
     136        9951 :     link->set_last_change_at_to_now();
     137        9951 :     link->UpdateProperties(origin, sequence_number);
     138        9951 : }
     139             : 
     140       33294 : void IFMapServerTable::LinkNodeDelete(IFMapLink *link,
     141             :         const IFMapOrigin &origin) {
     142             :     IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
     143       33294 :         database()->FindTable("__ifmap_metadata__.0"));
     144       33294 :     assert(table != NULL);
     145       33294 :     IFMAP_DEBUG(IFMapLinkOperation, "Deleting", link->ToString());
     146       33294 :     table->DeleteLink(link, origin);
     147       33294 : }
     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       79861 : std::string IFMapServerTable::LinkAttrKey(IFMapNode *first, IFMapNode *second) {
     152       79861 :     ostringstream oss;
     153       79861 :     oss << "attr(";
     154       79861 :     if (first->IsLess(*second)) {
     155       67365 :         oss << first->name() << "," << second->name();
     156             :     } else {
     157       12496 :         oss << second->name() << "," << first->name();
     158             :     }
     159       79861 :     oss << ")";
     160      159722 :     return oss.str();
     161       79861 : }
     162             : 
     163       41775 : void IFMapServerTable::DeleteNode(IFMapNode *node) {
     164       41775 :     IFMAP_DEBUG(IFMapNodeOperation, "Deleting", node->ToString());
     165             :     DBTablePartition *partition =
     166       41775 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     167       41775 :     graph()->RemoveNode(node);
     168       41775 :     partition->Delete(node);
     169       41775 : }
     170             : 
     171      120734 : void IFMapServerTable::Notify(IFMapNode *node) {
     172             :     DBTablePartition *partition =
     173      120734 :         static_cast<DBTablePartition *>(GetTablePartition(0));
     174      120734 :     partition->Change(node);
     175      120734 : }
     176             : 
     177       58605 : bool IFMapServerTable::DeleteIfEmpty(IFMapNode *node) {
     178       58605 :     if ((node->GetObject() == NULL) && !node->HasAdjacencies(graph())) {
     179       41775 :         DeleteNode(node);
     180       41775 :         return true;
     181             :     }
     182       16830 :     return false;
     183             : }
     184             : 
     185      114538 : IFMapObject *IFMapServerTable::LocateObject(IFMapNode *node,
     186             :                                             IFMapOrigin origin) {
     187      114538 :     IFMapObject *object = node->Find(origin);
     188      114538 :     if (object == NULL) {
     189       99078 :         object = AllocObject();
     190       99078 :         object->set_origin(origin);
     191       99078 :         node->Insert(object);
     192             :     }
     193      114538 :     return object;
     194             : }
     195             : 
     196       49025 : IFMapIdentifier *IFMapServerTable::LocateIdentifier(IFMapNode *node,
     197             :                                                     IFMapOrigin origin,
     198             :                                                     uint64_t sequence_number) {
     199       49025 :     IFMapObject *object = LocateObject(node, origin);
     200       49025 :     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       49025 :     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       49025 :     return static_cast<IFMapIdentifier *>(object);
     211             : }
     212             : 
     213       65513 : IFMapLinkAttr *IFMapServerTable::LocateLinkAttr(IFMapNode *node,
     214             :                                                 IFMapOrigin origin,
     215             :                                                 uint64_t sequence_number) {
     216       65513 :     IFMapObject *object = LocateObject(node, origin);
     217       65513 :     assert(object);
     218       65513 :     object->set_sequence_number(sequence_number);
     219             : 
     220       65513 :     return static_cast<IFMapLinkAttr *>(object);
     221             : }
     222             : 
     223      178558 : void IFMapServerTable::Input(DBTablePartition *partition, DBClient *client,
     224             :                              DBRequest *request) {
     225      178558 :     assert(request->oper == DBRequest::DB_ENTRY_ADD_CHANGE ||
     226             :            request->oper == DBRequest::DB_ENTRY_DELETE);
     227      178558 :     RequestKey *key = static_cast<RequestKey *>(request->key.get());
     228      178558 :     RequestData *data = static_cast<RequestData *>(request->data.get());
     229      178558 :     assert(data != NULL);
     230             : 
     231      178558 :     IFMapServerTable *rtable = NULL;
     232      178558 :     IFMapServerTable *mtable = NULL;
     233             : 
     234             :     // Sanity checks before allocation resources.
     235      178558 :     if (!data->id_name.empty()) {
     236      123238 :         rtable = TableFind(database(), data->id_type);
     237      123238 :         if (!rtable) {
     238           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table",
     239             :                         data->id_type);
     240       55381 :             return;
     241             :         }
     242      123238 :         mtable = TableFind(database(), data->metadata);
     243      161935 :         if (mtable == NULL && request->oper == DBRequest::DB_ENTRY_ADD_CHANGE &&
     244       38697 :             data->content.get() != NULL) {
     245           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table",
     246             :                         data->metadata);
     247           0 :             return;
     248             :         }
     249             :     }
     250             : 
     251      178558 :     IFMapNode *first = NULL;
     252      178558 :     bool lchanged = false;
     253      178558 :     if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     254       25427 :         first = EntryLookup(key);
     255       25427 :         if (first == NULL) {
     256          74 :             IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     257             :                        key->id_name);
     258          74 :             return;
     259             :         }
     260             :     } else {
     261      153131 :         first = EntryLocate(key, &lchanged);
     262             :     }
     263             : 
     264      178484 :     if (data->id_name.empty()) {
     265             :         // property
     266       55270 :         first->set_last_change_at_to_now();
     267       55270 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     268       48921 :             IFMapIdentifier *identifier = LocateIdentifier(first, data->origin,
     269             :                                                            key->id_seq_num);
     270       48921 :             identifier->SetProperty(data->metadata, data->content.get());
     271       48921 :             partition->Change(first);
     272             :         } else {
     273             :             IFMapIdentifier *identifier = static_cast<IFMapIdentifier *>(
     274        6349 :                     first->Find(data->origin));
     275        6349 :             if (identifier == NULL) {
     276           8 :                 return;
     277             :             }
     278        6341 :             identifier->ClearProperty(data->metadata);
     279             :             // Figure out whether to delete the identifier.
     280        6341 :             if (identifier->empty()) {
     281        5254 :                 first->Remove(identifier);
     282             :             }
     283        6341 :             if (DeleteIfEmpty(first) == false) {
     284        5878 :                 partition->Change(first);
     285             :             }
     286             :         }
     287       55262 :         return;
     288             :     }
     289             : 
     290      123214 :     IFMapNode *second = NULL;
     291      123214 :     bool rchanged = false;
     292      123214 :     if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     293       19004 :         second = TableEntryLookup(rtable, data->id_name);
     294       19004 :         if (second == NULL) {
     295          14 :             IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     296             :                        data->id_name);
     297          14 :             return;
     298             :         }
     299             :     } else {
     300      104210 :         second = TableEntryLocate(rtable, data->id_name, &rchanged);
     301             :     }
     302             : 
     303      123200 :     IFMapNode *midnode = NULL;
     304      123200 :     bool mchanged = false;
     305             : 
     306      123200 :     if (mtable != NULL) {
     307             :         // link with attribute
     308       79860 :         string id_mid = LinkAttrKey(first, second);
     309       79860 :         if (request->oper == DBRequest::DB_ENTRY_DELETE) {
     310       14347 :             midnode = TableEntryLookup(mtable, id_mid);
     311       14347 :             if (midnode == NULL) {
     312          23 :                 IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
     313             :                            id_mid);
     314          23 :                 return;
     315             :             }
     316             :         } else {
     317       65513 :             midnode = TableEntryLocate(mtable, id_mid, &mchanged);
     318             :         }
     319       79837 :         midnode->set_last_change_at_to_now();
     320       79837 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     321             :             IFMapLink *glink =
     322      131026 :                 static_cast<IFMapLink *>(FindLinkNode(first, midnode,
     323       65513 :                                                       data->metadata));
     324       65513 :             if (glink == NULL) {
     325      125474 :                 glink = LinkNodeAdd(first, midnode, data->metadata,
     326       62737 :                             key->id_seq_num, data->origin);
     327       62737 :                 graph()->Link(first, midnode, glink);
     328             :             } else {
     329        2776 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     330             :             }
     331      131026 :             glink = static_cast<IFMapLink *>(FindLinkNode(midnode, second,
     332       65513 :                                                           data->metadata));
     333       65513 :             if (glink == NULL) {
     334      125470 :                 glink = LinkNodeAdd(midnode, second, data->metadata,
     335       62735 :                             key->id_seq_num, data->origin);
     336       62735 :                 graph()->Link(midnode, second, glink);
     337             :             } else {
     338        2778 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     339             :             }
     340       65513 :             IFMapLinkAttr *link_attr = mtable->LocateLinkAttr(midnode,
     341             :                                                               data->origin,
     342             :                                                               key->id_seq_num);
     343       65513 :             mchanged |= link_attr->SetData(data->content.get());
     344             :         } else {
     345       14324 :             IFMapObject *object = midnode->Find(data->origin);
     346       14324 :             if (object == NULL) {
     347           0 :                 return;
     348             :             }
     349       14324 :             midnode->Remove(object);
     350       14324 :             if (midnode->GetObject() != NULL) {
     351           0 :                 return;
     352             :             }
     353       14324 :             IFMapOrigin origin(data->origin);
     354             :             IFMapLink *glink =
     355       28648 :                 static_cast<IFMapLink *>(FindLinkNode(first, midnode,
     356       14324 :                                                       data->metadata));
     357       14324 :             if (glink) LinkNodeDelete(glink, origin);
     358       28648 :             glink = static_cast<IFMapLink *>(FindLinkNode(midnode, second,
     359       14324 :                                                       data->metadata));
     360       14324 :             if (glink) LinkNodeDelete(glink, origin);
     361       14324 :             DeleteIfEmpty(first);
     362       14324 :             rtable->DeleteIfEmpty(second);
     363       14324 :             mtable->DeleteIfEmpty(midnode);
     364             :         }
     365       79860 :     } else {
     366             :         // link
     367       43340 :         if (request->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     368             :             // Link is added if not present
     369             :             IFMapLink *glink =
     370       77394 :                 static_cast<IFMapLink *>(FindLinkNode(first, second,
     371       38697 :                                                       data->metadata));
     372       38697 :             if (glink == NULL) {
     373       68600 :                 glink = LinkNodeAdd(first, second, data->metadata,
     374       34300 :                             key->id_seq_num, data->origin);
     375       34300 :                 graph()->Link(first, second, glink);
     376             :             } else {
     377        4397 :                 LinkNodeUpdate(glink, key->id_seq_num, data->origin);
     378             :             }
     379             :         } else {
     380             :             // TODO: check if the edge is present and ignore otherwise.
     381        4643 :             IFMapLink *glink = FindLinkNode(first, second, data->metadata);
     382        4643 :             if (glink != NULL) {
     383        4640 :                 IFMapOrigin origin(data->origin);
     384        4640 :                 LinkNodeDelete(glink, origin);
     385             :                 // check whether any of the identifiers can be deleted.
     386        4640 :                 DeleteIfEmpty(first);
     387        4640 :                 rtable->DeleteIfEmpty(second);
     388             :             }
     389             :         }
     390             :     }
     391             : 
     392      123177 :     if (lchanged) {
     393       48438 :         partition->Change(first);
     394             :     }
     395      123177 :     if (rchanged) {
     396       55609 :         rtable->Notify(second);
     397             :     }
     398      123177 :     if (mchanged) {
     399       65125 :         mtable->Notify(midnode);
     400             :     }
     401             : }
     402             : 
     403     1221917 : void IFMapServerTable::Clear() {
     404             :     DBTablePartition *partition = static_cast<DBTablePartition *>(
     405     1221917 :         GetTablePartition(0));
     406     1221917 :     assert(!HasListeners());
     407     1221917 :     for (IFMapNode *node = static_cast<IFMapNode *>(partition->GetFirst()),
     408     1221917 :                  *next = NULL;
     409     1369226 :          node != NULL; node = next) {
     410      147309 :         next = static_cast<IFMapNode *>(partition->GetNext(node));
     411      147309 :         if (node->IsDeleted()) {
     412           0 :             continue;
     413             :         }
     414      147309 :         graph()->RemoveNode(node);
     415      147309 :         partition->Delete(node);
     416             :     }
     417     1221917 : }
     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