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