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

Generated by: LCOV version 1.14