Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "ifmap/ifmap_encoder.h" 6 : 7 : #include <sstream> 8 : #include "ifmap/ifmap_link.h" 9 : #include "ifmap/ifmap_object.h" 10 : #include "ifmap/ifmap_update.h" 11 : 12 : using namespace pugi; 13 : using namespace std; 14 : 15 573 : IFMapMessage::IFMapMessage() : op_type_(NONE), node_count_(0), 16 191 : objects_per_message_(kObjectsPerMessage) { 17 : // init empty document 18 191 : Open(); 19 191 : } 20 : 21 305 : void IFMapMessage::Open() { 22 305 : xml_node iq = doc_.append_child("iq"); 23 : // set iq (type, from, to) attributes 24 305 : iq.append_attribute("type") = "set"; 25 305 : iq.append_attribute("from") = "network-control@contrailsystems.com"; 26 305 : iq.append_attribute("to") = ""; 27 305 : config_ = iq.append_child("config"); 28 305 : } 29 : 30 116 : void IFMapMessage::Close() { 31 116 : ostringstream oss; 32 116 : doc_.save(oss); 33 116 : str_ = oss.str(); 34 116 : } 35 : 36 116 : void IFMapMessage::SetReceiverInMsg(const std::string &cli_identifier) { 37 116 : xml_node iq = doc_.child("iq"); 38 116 : assert(iq); 39 116 : xml_attribute iqattr = iq.attribute("to"); 40 116 : assert(iqattr); 41 116 : std::string str(cli_identifier); 42 116 : str += "/config"; 43 116 : iqattr.set_value(str.c_str()); 44 116 : } 45 : 46 0 : void IFMapMessage::SetObjectsPerMessage(int num) { 47 0 : objects_per_message_ = num; 48 0 : } 49 : 50 903 : void IFMapMessage::EncodeUpdate(const IFMapUpdate *update) { 51 : // update is either of type UPDATE OR DELETE 52 903 : if (update->IsUpdate()) { 53 903 : if (op_type_ != UPDATE) { 54 114 : op_node_ = config_.append_child("update"); 55 114 : op_type_ = UPDATE; 56 : } 57 903 : if (update->data().type == IFMapObjectPtr::NODE) { 58 435 : EncodeNode(update); 59 468 : } else if (update->data().type == IFMapObjectPtr::LINK) { 60 468 : EncodeLink(update); 61 : } else { 62 0 : assert(0); 63 : } 64 : } else { 65 0 : if (op_type_ != DEL) { 66 0 : op_node_ = config_.append_child("delete"); 67 0 : op_type_ = DEL; 68 : } 69 0 : if (update->data().type == IFMapObjectPtr::NODE) { 70 0 : EncodeNode(update); 71 0 : } else if (update->data().type == IFMapObjectPtr::LINK) { 72 0 : EncodeLink(update); 73 : } else { 74 0 : assert(0); 75 : } 76 : } 77 903 : node_count_++; 78 903 : } 79 : 80 435 : void IFMapMessage::EncodeNode(const IFMapUpdate *update) { 81 435 : IFMapNode *node = update->data().u.node; 82 435 : if (update->IsUpdate()) { 83 435 : node->EncodeNodeDetail(&op_node_); 84 : } else { 85 0 : node->EncodeNode(&op_node_); 86 : } 87 435 : } 88 : 89 468 : void IFMapMessage::EncodeLink(const IFMapUpdate *update) { 90 468 : xml_node link_node = op_node_.append_child("link"); 91 : 92 468 : const IFMapLink *link = update->data().u.link; 93 : 94 468 : IFMapNode::EncodeNode(link->left_id(), &link_node); 95 468 : IFMapNode::EncodeNode(link->right_id(), &link_node); 96 468 : link->EncodeLinkInfo(&link_node); 97 : 98 468 : node_count_++; 99 468 : } 100 : 101 903 : bool IFMapMessage::IsFull() { 102 903 : return ((node_count_ >= objects_per_message_) ? true : false); 103 : } 104 : 105 171 : bool IFMapMessage::IsEmpty() { 106 171 : return ((node_count_ == 0) ? true : false); 107 : } 108 : 109 : // 110 : // Reset the IFMapMessage to initial state so that it can be used to build 111 : // the next config message. 112 : // 113 : // Using remove_child to remove the only child of the document is a better 114 : // way to clear the document than using reset. The pugixml library allocates 115 : // memory for a document in increments of 32KB pages and then manages smaller 116 : // allocations (nodes or attributes) using these pages. Calling reset method 117 : // on a document frees all the pages. In contrast, removing the only child 118 : // node of the document returns the smaller allocations to the free pool of 119 : // memory for the document, but doesn't free the pages themselves. This lets 120 : // the library reuse the same memory when building the tree for each message. 121 : // 122 114 : void IFMapMessage::Reset() { 123 114 : doc_.remove_child("iq"); 124 114 : node_count_ = 0; 125 114 : op_type_ = NONE; 126 114 : Open(); 127 114 : }