OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ifmap_server.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "ifmap/ifmap_server.h"
6 
7 #include <boost/asio/io_service.hpp>
8 #include <boost/algorithm/string.hpp>
9 
10 #include "base/logging.h"
11 #include "base/regex.h"
12 #include "base/task_annotations.h"
13 #include "base/time_util.h"
16 #include "config_client_show_types.h"
17 #include "db/db.h"
18 #include "db/db_graph.h"
19 #include "db/db_graph_edge.h"
20 #include "ifmap/ifmap_client.h"
21 #include "ifmap/ifmap_exporter.h"
23 #include "ifmap/ifmap_link_table.h"
24 #include "ifmap/ifmap_log.h"
25 #include "ifmap/ifmap_node.h"
27 #include "ifmap/ifmap_server_show_types.h"
28 #include "ifmap/ifmap_log_types.h"
29 #include "ifmap/ifmap_table.h"
32 #include "ifmap/ifmap_xmpp.h"
34 #include "schema/vnc_cfg_types.h"
35 
36 #include "control-node/sandesh/control_node_types.h"
37 
38 using contrail::regex;
41 using std::make_pair;
42 
44 public:
46  Task(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"), 0),
47  db_(db), graph_(graph), ifmap_server_(server) {
48  }
49 
50  bool Run() {
51  // objects_deleted indicates the count of objects-deleted-but-not-node
52  uint32_t nodes_deleted = 0, nodes_changed = 0, links_deleted = 0,
53  objects_deleted = 0;
54  uint64_t curr_seq_num =
56 
59  e_iter != graph_->edge_list_end(); e_iter = e_next) {
60  const DBGraph::DBEdgeInfo &tuple = *e_iter;
61  // increment only after dereferencing
62  e_next = ++e_iter;
63 
64  IFMapLink *link = static_cast<IFMapLink *>(boost::get<2>(tuple));
65  assert(link);
66 
67  bool exists = false;
68  IFMapLink::LinkOriginInfo origin_info =
69  link->GetOriginInfo(IFMapOrigin::CASSANDRA, &exists);
70  if (exists && (origin_info.sequence_number < curr_seq_num)) {
71  IFMapLinkTable *ltable = static_cast<IFMapLinkTable *>(
72  db_->FindTable("__ifmap_metadata__.0"));
73  // Cleanup the node and remove from the graph
75  if (link->is_origin_empty()) {
76  ltable->DeleteLink(link);
77  }
78  links_deleted++;
79  }
80  }
81 
84  v_iter != graph_->vertex_list_end(); v_iter = v_next) {
85 
86  IFMapNode *node = static_cast<IFMapNode *>(v_iter.operator->());
87  // increment only after dereferencing
88  v_next = ++v_iter;
89 
90  IFMapObject *object =
92  IFMapServerTable *ntable =
93  static_cast<IFMapServerTable *>(node->table());
94  if (object != NULL) {
95  if (object->sequence_number() < curr_seq_num) {
96  node->Remove(object);
97  bool retb = ntable->DeleteIfEmpty(node);
98  if (retb) {
99  nodes_deleted++;
100  } else {
101  objects_deleted++;
102  }
103  } else {
104  // There could be stale properties
105  bool changed = object->ResolveStaleness();
106  if (changed) {
107  nodes_changed++;
108  ntable->Notify(node);
109  }
110  }
111  } else {
112  // The node doesnt have any object. We should delete it if it
113  // does not have any neighbors either.
114  bool retb = ntable->DeleteIfEmpty(node);
115  if (retb) {
116  nodes_deleted++;
117  }
118  }
119  }
120  IFMAP_DEBUG(IFMapStaleEntriesCleanerInfo, curr_seq_num, nodes_deleted,
121  nodes_changed, links_deleted, objects_deleted);
122 
123  return true;
124  }
125  std::string Description() const {
126  return "IFMapServer::IFMapStaleEntriesCleaner";
127  }
128 
129 private:
130  DB *db_;
133 };
134 
136 public:
138  const std::string &vr_name, const std::string &vm_uuid,
139  bool subscribe, bool has_vms):
140  Task(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"), 0),
141  db_(db), ifmap_server_(server), vr_name_(vr_name),
142  vm_uuid_(vm_uuid), subscribe_(subscribe), has_vms_(has_vms) {
143  }
144 
145  bool Run() {
146 
147  IFMapServerTable *vm_table = static_cast<IFMapServerTable *>(
148  db_->FindTable("__ifmap__.virtual_machine.0"));
149  assert(vm_table != NULL);
150 
151  // We are processing a VM-sub/unsub. If the client is gone by the time
152  // we get here, there is nothing to do.
154  if (!client) {
155  return true;
156  }
157 
158  // Find the vm's node using its UUID. If the config has not added the
159  // vm yet, treat this request as pending since we cant process it right
160  // now. If the node is marked deleted, mark it as pending since the
161  // node might get revived. In this case, the pending entry will get
162  // cleaned up either via an unsub from the client or client-delete.
164  if (vm_node && !vm_node->IsDeleted()) {
165  IFMapServerTable *vr_table = static_cast<IFMapServerTable *>(
166  db_->FindTable("__ifmap__.virtual_router.0"));
167  assert(vr_table != NULL);
168 
169  std::string vm_name = vm_node->name();
170  vr_table->IFMapVmSubscribe(vr_name_, vm_name, subscribe_, has_vms_);
171 
172  if (subscribe_) {
174  }
175  } else {
177  subscribe_);
178  }
179 
180  return true;
181  }
182  std::string Description() const { return "IFMapServer::IFMapVmSubscribe"; }
183 
184 private:
185  DB *db_;
187  std::string vr_name_;
188  std::string vm_uuid_;
190  bool has_vms_;
191 };
192 
194  boost::asio::io_context *io_service)
195  : db_(db), graph_(graph),
196  queue_(new IFMapUpdateQueue(this)),
197  exporter_(new IFMapExporter(this)),
198  sender_(new IFMapUpdateSender(this, queue())),
199  vm_uuid_mapper_(new IFMapVmUuidMapper(db_, this)),
200  work_queue_(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"),
201  0, boost::bind(&IFMapServer::ClientWorker, this, _1)),
202  io_service_(io_service), config_manager_(NULL),
203  ifmap_channel_manager_(NULL) {
204 }
205 
207 }
208 
210  exporter_->Initialize(db_);
211  vm_uuid_mapper_->Initialize();
212 }
213 
215  vm_uuid_mapper_->Shutdown();
216  exporter_->Shutdown();
217 }
218 
220  size_t index = client_indexes_.find_first_clear();
221  if (index == BitSet::npos) {
222  index = client_indexes_.size();
223  }
224  client_indexes_.set(index);
225 
226  std::pair<ClientMap::iterator, bool> cm_ret;
227  cm_ret = client_map_.insert(make_pair(client->identifier(), client));
228  assert(cm_ret.second);
229 
230  std::pair<IndexMap::iterator, bool> im_ret;
231  im_ret = index_map_.insert(make_pair(index, client));
232  assert(im_ret.second);
233 
234  client->Initialize(exporter_.get(), index);
235  queue_->Join(index);
236  IFMAP_DEBUG(IFMapServerClientRegUnreg, "Register request for client ",
237  client->identifier(), index);
238 }
239 
241  if (client_history_.size() >= kClientHistorySize) {
242  // Remove the oldest entry.
243  client_history_.pop_front();
244  }
245  ClientHistoryInfo info(client->identifier(), client->index(),
246  client->created_at(), UTCTimestampUsec());
247  client_history_.push_back(info);
248 }
249 
251  IFMAP_DEBUG(IFMapServerClientRegUnreg, "Un-register request for client ",
252  client->identifier(), client->index());
253  size_t index = client->index();
254  sender_->CleanupClient(index);
255  queue_->Leave(index);
256  ImSz_t iret = index_map_.erase(index);
257  assert(iret == 1);
258  CmSz_t cret = client_map_.erase(client->identifier());
259  assert(cret == 1);
260  client_indexes_.reset(index);
261 }
262 
264  if (add) {
265  ClientRegister(client);
266  ClientExporterSetup(client);
267  ClientGraphDownload(client);
268  } else {
270  CleanupUuidMapper(client);
271  SaveClientHistory(client);
272  int index = client->index();
273  ClientUnregister(client);
274  // Exporter cleanup must happen after ClientUnregister() which does
275  // Q-Leave which needs the config trackers in the exporters.
276  ClientExporterCleanup(index);
277  }
278  return true;
279 }
280 
281 // To be used only by tests.
283  // Let ClientWorker() do all the work in the context of the db-task
284  QueueEntry entry;
285  entry.op = ADD;
286  entry.client = client;
287  work_queue_.Enqueue(entry);
288 }
289 
290 // To be used only by tests.
292  // Let ClientWorker() do all the work in the context of the db-task
293  QueueEntry entry;
294  entry.op = DEL;
295  entry.client = client;
296  work_queue_.Enqueue(entry);
297 }
298 
299 // To be used only by tests.
301  QueueEntry entry;
302  entry.op = DEL;
303  entry.client = client;
304  ClientWorker(entry);
305 }
306 
308  bool add = (work_entry.op == ADD) ? true : false;
309  IFMapClient *client = work_entry.client;
310 
311  bool done = ProcessClientWork(add, client);
312 
313  return done;
314 }
315 
316 // Get the list of subscribed VMs. For each item in the list, if it exist in the
317 // list of pending vm registration requests, remove it.
319  std::vector<std::string> vmlist = client->vm_list();
320  for (size_t count = 0; count < vmlist.size(); ++count) {
321  vm_uuid_mapper_->CleanupPendingVmRegEntry(vmlist.at(count));
322  }
323 }
324 
326  IFMapServerTable *vr_table = static_cast<IFMapServerTable *>(
327  db_->FindTable("__ifmap__.virtual_router.0"));
328  assert(vr_table != NULL);
329 
330  IFMapNode *node = vr_table->FindNode(client->identifier());
331  if ((node != NULL) && node->IsVertexValid()) {
333  for (DBGraphVertex::adjacency_iterator iter = node->begin(graph_), next;
334  iter != node->end(graph_); iter = next) {
335  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
336  next = ++iter;
337  if (adj->table()->name() == "__ifmap__.virtual_machine.0") {
338  vr_table->IFMapRemoveVrVmLink(node, adj);
340  }
341  }
343  }
344 }
345 
347  IFMapTable *table = IFMapTable::FindTable(db_, "virtual-router");
348  assert(table);
349 
350  IFMapNode *node = table->FindNode(client->identifier());
351  if ((node != NULL) && node->IsVertexValid()) {
353  iter != node->edge_list_end(graph_); ++iter) {
354  IFMapLink *link = static_cast<IFMapLink *>(iter.operator->());
355  if (exporter_->FilterNeighbor(node, link)) {
356  continue;
357  }
358  DBTable *link_table = static_cast<DBTable *>(
359  db_->FindTable("__ifmap_metadata__.0"));
360  link_table->Change(link);
361  }
362  }
363 }
364 
366  exporter_->AddClientConfigTracker(client->index());
367 }
368 
370  exporter_->CleanupClientConfigTrackedEntries(index);
371  exporter_->DeleteClientConfigTracker(index);
372 
373  BitSet rm_bs;
374  rm_bs.set(index);
375  exporter_->ResetLinkDeleteClients(rm_bs);
376 }
377 
378 IFMapClient *IFMapServer::FindClient(const std::string &id) {
379  ClientMap::iterator loc = client_map_.find(id);
380  if (loc != client_map_.end()) {
381  return loc->second;
382  }
383  return NULL;
384 }
385 
387  IndexMap::iterator loc = index_map_.find(index);
388  if (loc != index_map_.end()) {
389  return loc->second;
390  }
391  return NULL;
392 }
393 
394 bool IFMapServer::ClientNameToIndex(const std::string &id, int *index) {
395  IFMapClient *client = FindClient(id);
396  if (client) {
397  *index = client->index();
398  return true;
399  }
400  return false;
401 }
402 
403 void IFMapServer::ProcessVmSubscribe(std::string vr_name, std::string vm_uuid,
404  bool subscribe, bool has_vms) {
405  IFMapVmSubscribe *vm_sub = new IFMapVmSubscribe(db_, graph_, this,
406  vr_name, vm_uuid,
407  subscribe, has_vms);
409  scheduler->Enqueue(vm_sub);
410 }
411 
412 void IFMapServer::ProcessVmSubscribe(std::string vr_name, std::string vm_uuid,
413  bool subscribe) {
414  IFMapClient *client = FindClient(vr_name);
415  assert(client);
416  IFMapVmSubscribe *vm_sub =
417  new IFMapVmSubscribe(db_, graph_, this, vr_name, vm_uuid, subscribe,
418  client->HasVms());
420  scheduler->Enqueue(vm_sub);
421 }
422 
423 void IFMapServer::ProcessVmRegAsPending(std::string vm_uuid,
424  std::string vr_name, bool subscribe) {
425  IFMAP_DEBUG(IFMapServerPendingVmReg, vm_uuid, vr_name, subscribe);
426  vm_uuid_mapper_->ProcessVmRegAsPending(vm_uuid, vr_name, subscribe);
427 }
428 
429 IFMapNode *IFMapServer::GetVmNodeByUuid(const std::string &vm_uuid) {
430  return vm_uuid_mapper_->GetVmNodeByUuid(vm_uuid);
431 }
432 
433 void IFMapServer::FillClientMap(IFMapServerShowClientMap *out_map,
434  const std::string &search_string) {
435  regex search_expr(search_string);
436  out_map->set_table_count(client_map_.size());
437  for (ClientMap::const_iterator iter = client_map_.begin();
438  iter != client_map_.end(); ++iter) {
439  IFMapClient *client = iter->second;
440  if (!regex_search(client->identifier(), search_expr)) {
441  continue;
442  }
443  IFMapServerClientMapShowEntry entry;
444  entry.set_client_name(client->identifier());
445  entry.set_interest_tracker_entries(exporter_->ClientConfigTrackerSize(
446  IFMapExporter::INTEREST, client->index()));
447  entry.set_advertised_tracker_entries(exporter_->ClientConfigTrackerSize(
448  IFMapExporter::ADVERTISED, client->index()));
449  out_map->clients.push_back(entry);
450  }
451  out_map->set_print_count(out_map->clients.size());
452 }
453 
454 void IFMapServer::FillIndexMap(IFMapServerShowIndexMap *out_map,
455  const std::string &search_string) {
456  regex search_expr(search_string);
457  out_map->set_table_count(index_map_.size());
459  iter != index_map_.end(); ++iter) {
460  IFMapClient *client = iter->second;
461  if (!regex_search(client->identifier(), search_expr)) {
462  continue;
463  }
464  IFMapServerIndexMapShowEntry entry;
465  entry.set_client_index(iter->first);
466  entry.set_client_name(client->identifier());
467  out_map->clients.push_back(entry);
468  }
469  out_map->set_print_count(out_map->clients.size());
470 }
471 
474 }
475 
477  return duration_usecs_to_string(UTCTimestampUsec() - history_created_at);
478 }
479 
480 void IFMapServer::FillClientHistory(IFMapServerClientHistoryList *out_list,
481  const std::string &search_string) {
482  regex search_expr(search_string);
483  out_list->set_table_count(client_history_.size());
484  for (ClientHistory::const_iterator iter = client_history_.begin();
485  iter != client_history_.end(); ++iter) {
486  ClientHistoryInfo info = *iter;
487  if (!regex_search(info.client_name, search_expr)) {
488  continue;
489  }
490  IFMapServerClientHistoryEntry entry;
491  entry.set_client_name(info.client_name);
492  entry.set_client_index(info.client_index);
493  entry.set_creation_time_ago(info.client_created_at_str());
494  entry.set_deletion_time_ago(info.history_created_at_str());
495  out_list->clients.push_back(entry);
496  }
497  out_list->set_print_count(out_list->clients.size());
498 }
499 
500 void IFMapServer::GetUIInfo(IFMapServerInfoUI *server_info) const {
501  server_info->set_num_peer_clients(GetClientMapSize());
502 }
503 
504 bool IFMapServer::CollectStats(BgpRouterState *state, bool first) const {
505  CHECK_CONCURRENCY("bgp::ShowCommand");
506 
507  ConfigDBConnInfo db_conn_info;
508  const ConfigClientManager *ccmgr = get_config_manager();
509  bool change = false;
510 
511  ccmgr->config_db_client()->GetConnectionInfo(db_conn_info);
512  if (first || db_conn_info != state->get_db_conn_info()) {
513  state->set_db_conn_info(db_conn_info);
514  change = true;
515  }
516 
517  if (ccmgr->config_amqp_client()) {
518  ConfigAmqpConnInfo amqp_conn_info;
519  ccmgr->config_amqp_client()->GetConnectionInfo(amqp_conn_info);
520  if (first || amqp_conn_info != state->get_amqp_conn_info()) {
521  state->set_amqp_conn_info(amqp_conn_info);
522  change = true;
523  }
524  }
525 
526  IFMapServerInfoUI server_info;
527  GetUIInfo(&server_info);
528  if (first || server_info != state->get_ifmap_server_info()) {
529  state->set_ifmap_server_info(server_info);
530  change = true;
531  }
532 
533  return change;
534 }
535 
537  IFMapStaleEntriesCleaner *cleaner =
538  new IFMapStaleEntriesCleaner(db_, graph_, this);
540  scheduler->Enqueue(cleaner);
541 }
edge_iterator edge_list_begin()
Definition: db_graph.cc:262
void Notify(IFMapNode *node)
boost::scoped_ptr< IFMapVmUuidMapper > vm_uuid_mapper_
Definition: ifmap_server.h:159
void ClientExporterSetup(IFMapClient *client)
ClientMap::size_type CmSz_t
Definition: ifmap_server.h:61
static const int kClientHistorySize
Definition: ifmap_server.h:57
static void RemoveObjectAndDeleteNode(IFMapNode *node, const IFMapOrigin &origin)
virtual const std::string & identifier() const =0
iterator end()
Definition: index_map.h:113
ConfigClientManager * get_config_manager()
Definition: ifmap_server.h:92
std::vector< std::string > vm_list() const
Definition: ifmap_client.cc:27
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
virtual void GetConnectionInfo(ConfigDBConnInfo &status) const
IFMapClient * FindClient(const std::string &id)
boost::scoped_ptr< IFMapExporter > exporter_
Definition: ifmap_server.h:157
int index() const
Definition: ifmap_client.h:31
void Initialize()
boost::scoped_ptr< IFMapUpdateSender > sender_
Definition: ifmap_server.h:158
void CleanupStaleEntries()
DBGraph * graph()
Definition: ifmap_server.h:83
BitSet & reset(size_t pos)
Definition: bitset.cc:136
void Remove(IFMapObject *obj)
Definition: ifmap_node.cc:58
bool IsDeleted() const
Definition: db_entry.h:49
ConfigDbClient * config_db_client() const
void Initialize(IFMapExporter *exporter, int index)
Definition: ifmap_client.cc:22
const std::string client_created_at_str() const
void FillClientHistory(IFMapServerClientHistoryList *out_list, const std::string &search_string)
ConfigAmqpClient * config_amqp_client() const
IFMapStaleEntriesCleaner(DB *db, DBGraph *graph, IFMapServer *server)
Definition: ifmap_server.cc:45
virtual void Change(DBEntryBase *entry)
Definition: db_table.cc:407
iterator begin()
Definition: index_map.h:112
bool ClientNameToIndex(const std::string &id, int *index)
const CmSz_t GetClientMapSize() const
Definition: ifmap_server.h:122
adjacency_iterator end(DBGraph *graph)
IFMapTable * table()
Definition: ifmap_node.h:29
DBGraph * graph_
Definition: ifmap_server.h:155
void DeleteLink(IFMapLink *link, const IFMapOrigin &origin)
boost::scoped_ptr< IFMapUpdateQueue > queue_
Definition: ifmap_server.h:156
vertex_iterator vertex_list_begin()
Definition: db_graph.cc:293
vertex_iterator vertex_list_end()
Definition: db_graph.cc:297
edge_iterator edge_list_end()
Definition: db_graph.cc:266
bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
Definition: ifmap_server.cc:50
#define IFMAP_DEBUG(obj,...)
Definition: ifmap_log.h:33
static bool regex_match(const std::string &input, const regex &regex)
Definition: regex.h:34
Definition: db.h:24
std::string Description() const
void Shutdown()
void GetConnectionInfo(ConfigAmqpConnInfo &info) const
void ClientRegister(IFMapClient *client)
size_t find_first_clear() const
Definition: bitset.cc:307
IFMapClient * GetClient(int index)
IFMapVmSubscribe(DB *db, DBGraph *graph, IFMapServer *server, const std::string &vr_name, const std::string &vm_uuid, bool subscribe, bool has_vms)
void CleanupUuidMapper(IFMapClient *client)
void IFMapVmSubscribe(const std::string &vr_name, const std::string &vm_name, bool subscribe, bool has_vms)
uint64_t sequence_number()
Definition: ifmap_object.h:33
const std::string history_created_at_str() const
static const size_t npos
Definition: bitset.h:19
ClientMap client_map_
Definition: ifmap_server.h:161
static TaskScheduler * GetInstance()
Definition: task.cc:547
void Enqueue(Task *task)
Enqueues a task for running. Starts task if all policy rules are met else puts task in waitq...
Definition: task.cc:636
void IFMapRemoveVrVmLink(IFMapNode *vr_node, IFMapNode *vm_node)
IFMapNode * FindNode(const std::string &name)
Definition: ifmap_table.cc:23
IFMapNode * GetVmNodeByUuid(const std::string &vm_uuid)
IFMapServer(DB *db, DBGraph *graph, boost::asio::io_context *io_service)
#define CHECK_CONCURRENCY(...)
static const std::string duration_usecs_to_string(const uint64_t usecs)
Definition: time_util.h:62
IFMapObject * Find(IFMapOrigin origin)
Definition: ifmap_node.cc:38
size_t size() const
Definition: bitset.cc:187
void DeleteClient(IFMapClient *client)
const std::string & name() const
Definition: db_table.h:110
IndexMap::size_type ImSz_t
Definition: ifmap_server.h:62
bool HasVms()
Definition: ifmap_client.h:68
static bool regex_search(const std::string &input, const regex &regex)
Definition: regex.h:25
const std::string & name() const
Definition: ifmap_node.h:48
void ClientGraphDownload(IFMapClient *client)
Definition: bitset.h:17
void RemoveSelfAddedLinksAndObjects(IFMapClient *client)
bool ClientWorker(QueueEntry work_entry)
BitSet & set(size_t pos)
Definition: bitset.cc:125
int GetTaskId() const
Definition: task.h:118
void ProcessVmSubscribe(std::string vr_name, std::string vm_uuid, bool subscribe, bool has_vms)
void SimulateDeleteClient(IFMapClient *client)
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
IndexMap index_map_
Definition: ifmap_server.h:162
MapType::const_iterator const_iterator
Definition: index_map.h:24
static IFMapTable * FindTable(DB *db, const std::string &element_type)
Definition: ifmap_table.cc:39
bool CollectStats(BgpRouterState *state, bool first) const
size_t size() const
Definition: index_map.h:100
MapType::iterator iterator
Definition: index_map.h:23
uint64_t created_at() const
Definition: ifmap_client.h:40
void ClientUnregister(IFMapClient *client)
WorkQueue< QueueEntry > work_queue_
Definition: ifmap_server.h:163
edge_iterator edge_list_end(DBGraph *graph)
bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
void FillIndexMap(IFMapServerShowIndexMap *out_map, const std::string &search_string)
ClientHistory client_history_
Definition: ifmap_server.h:167
void ClientExporterCleanup(int index)
void ProcessVmRegAsPending(std::string vm_uuid, std::string vr_name, bool subscribe)
boost::tuple< DBGraphVertex *, DBGraphVertex *, DBGraphEdge * > DBEdgeInfo
Definition: db_graph.h:45
void FillClientMap(IFMapServerShowClientMap *out_map, const std::string &search_string)
virtual ~IFMapServer()
adjacency_iterator begin(DBGraph *graph)
bool DeleteIfEmpty(IFMapNode *node)
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
uint64_t get_config_generation_number()
Definition: ifmap_server.h:101
BitSet client_indexes_
Definition: ifmap_server.h:160
void SaveClientHistory(IFMapClient *client)
DBTableBase * FindTable(const std::string &name)
Definition: db.cc:68
bool ProcessClientWork(bool add, IFMapClient *client)
void AddClient(IFMapClient *client)
edge_iterator edge_list_begin(DBGraph *graph)
void GetUIInfo(IFMapServerInfoUI *server_info) const