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 585 : IFMapMessage::IFMapMessage() : op_type_(NONE), node_count_(0), 16 195 : objects_per_message_(kObjectsPerMessage) { 17 : // init empty document 18 195 : Open(); 19 195 : } 20 : 21 311 : void IFMapMessage::Open() { 22 311 : xml_node iq = doc_.append_child("iq"); 23 : // set iq (type, from, to) attributes 24 311 : iq.append_attribute("type") = "set"; 25 311 : iq.append_attribute("from") = "network-control@contrailsystems.com"; 26 311 : iq.append_attribute("to") = ""; 27 311 : config_ = iq.append_child("config"); 28 311 : } 29 : 30 118 : void IFMapMessage::Close() { 31 118 : ostringstream oss; 32 118 : doc_.save(oss); 33 118 : str_ = oss.str(); 34 118 : } 35 : 36 118 : void IFMapMessage::SetReceiverInMsg(const std::string &cli_identifier) { 37 118 : xml_node iq = doc_.child("iq"); 38 118 : assert(iq); 39 118 : xml_attribute iqattr = iq.attribute("to"); 40 118 : assert(iqattr); 41 118 : std::string str(cli_identifier); 42 118 : str += "/config"; 43 118 : iqattr.set_value(str.c_str()); 44 118 : } 45 : 46 0 : void IFMapMessage::SetObjectsPerMessage(int num) { 47 0 : objects_per_message_ = num; 48 0 : } 49 : 50 892 : void IFMapMessage::EncodeUpdate(const IFMapUpdate *update) { 51 : // update is either of type UPDATE OR DELETE 52 892 : if (update->IsUpdate()) { 53 892 : if (op_type_ != UPDATE) { 54 116 : op_node_ = config_.append_child("update"); 55 116 : op_type_ = UPDATE; 56 : } 57 892 : if (update->data().type == IFMapObjectPtr::NODE) { 58 434 : EncodeNode(update); 59 458 : } else if (update->data().type == IFMapObjectPtr::LINK) { 60 458 : 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 892 : node_count_++; 78 892 : } 79 : 80 434 : void IFMapMessage::EncodeNode(const IFMapUpdate *update) { 81 434 : IFMapNode *node = update->data().u.node; 82 434 : if (update->IsUpdate()) { 83 434 : node->EncodeNodeDetail(&op_node_); 84 : } else { 85 0 : node->EncodeNode(&op_node_); 86 : } 87 434 : } 88 : 89 458 : void IFMapMessage::EncodeLink(const IFMapUpdate *update) { 90 458 : xml_node link_node = op_node_.append_child("link"); 91 : 92 458 : const IFMapLink *link = update->data().u.link; 93 : 94 458 : IFMapNode::EncodeNode(link->left_id(), &link_node); 95 458 : IFMapNode::EncodeNode(link->right_id(), &link_node); 96 458 : link->EncodeLinkInfo(&link_node); 97 : 98 458 : node_count_++; 99 458 : } 100 : 101 892 : bool IFMapMessage::IsFull() { 102 892 : return ((node_count_ >= objects_per_message_) ? true : false); 103 : } 104 : 105 176 : bool IFMapMessage::IsEmpty() { 106 176 : 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 116 : void IFMapMessage::Reset() { 123 116 : doc_.remove_child("iq"); 124 116 : node_count_ = 0; 125 116 : op_type_ = NONE; 126 116 : Open(); 127 116 : }