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 : // 7 : // sandesh_trace.cc 8 : // 9 : // Sandesh Trace Request Implementation 10 : // 11 : 12 : #include <boost/bind/bind.hpp> 13 : #include <ctime> 14 : #include <base/trace.h> 15 : #include <sandesh/sandesh_types.h> 16 : #include <sandesh/sandesh.h> 17 : #include <sandesh/sandesh_trace_types.h> 18 : #include "sandesh_trace.h" 19 : 20 : using std::string; 21 : using std::vector; 22 : using namespace boost::placeholders; 23 : 24 : int PullSandeshTraceReq = 0; 25 : 26 : template<> TraceSandeshType *TraceSandeshType::trace_ = NULL; 27 : 28 : class SandeshTraceRequestRunner { 29 : public: 30 0 : SandeshTraceRequestRunner(SandeshTraceBufferPtr trace_buf, 31 : const std::string& req_context, 32 : const std::string& read_context, 33 0 : uint32_t count) : 34 0 : req_buf_(trace_buf), 35 0 : req_context_(req_context), 36 0 : read_context_(read_context), 37 0 : sttr_(new SandeshTraceTextResponse), 38 0 : req_count_(count), 39 0 : read_count_(0) { 40 0 : if (!req_count_) { 41 : // Fill the read_count_ with the size of the trace buffer 42 0 : req_count_ = SandeshTraceBufferSizeGet(req_buf_); 43 : } 44 0 : } 45 : 46 0 : ~SandeshTraceRequestRunner() { } 47 : 48 0 : void Run() { 49 0 : SandeshTraceBufferRead(req_buf_, read_context_, req_count_, 50 : boost::bind(&SandeshTraceRequestRunner::SandeshTraceRead, 51 : this, _1, _2)); 52 0 : if ("Collector" != read_context_) { 53 0 : sttr_->set_context(req_context_); 54 0 : sttr_->Response(); 55 0 : SandeshTraceBufferReadDone(req_buf_, read_context_); 56 : } 57 0 : } 58 : 59 : private: 60 0 : void SandeshTraceRead(SandeshTrace *tsnh, bool more) { 61 0 : read_count_++; 62 0 : assert(tsnh); 63 0 : vector<string>& tracebuf = const_cast<vector<string>&>(sttr_->get_traces()); 64 : 65 0 : if ("Collector" != read_context_) { 66 0 : tracebuf.push_back(tsnh->ToString()); 67 0 : return; 68 : } 69 : 70 0 : if (!more || (read_count_ == req_count_)) { 71 0 : tsnh->SendTrace(req_context_, false); 72 : } else { 73 0 : tsnh->SendTrace(req_context_, true); 74 : } 75 : } 76 : 77 : SandeshTraceBufferPtr req_buf_; 78 : std::string req_context_; 79 : std::string read_context_; 80 : SandeshTraceTextResponse *sttr_; 81 : uint32_t req_count_; 82 : uint32_t read_count_; 83 : }; 84 : 85 0 : void SandeshTraceRequest::HandleRequest() const { 86 0 : std::string read_context; 87 : 88 : // TODO: 89 : // We should get the Sandesh Header to differentiate 90 : // trace requests from non-http modules. 91 0 : if ((0 == context().find("http%")) || (0 == context().find("https%"))) { 92 0 : read_context = "Http"; 93 : } else { 94 0 : read_context = "Collector"; 95 : } 96 : 97 0 : SandeshTraceBufferPtr trace_buf(SandeshTraceBufferGet(get_buf_name())); 98 0 : if (!trace_buf) { 99 0 : if (read_context != "Collector") { 100 0 : SandeshTraceTextResponse *sttr = new SandeshTraceTextResponse; 101 0 : sttr->set_context(context()); 102 0 : sttr->Response(); 103 : } 104 0 : return; 105 : } 106 : std::unique_ptr<SandeshTraceRequestRunner> trace_req_runner(new 107 0 : SandeshTraceRequestRunner(trace_buf, context(), 108 0 : read_context, get_count())); 109 0 : trace_req_runner->Run(); 110 0 : } 111 : 112 0 : void SandeshTraceSend(const std::string& buf_name, uint32_t trace_count) { 113 : // TODO: 114 : // Handle this in a separate task, so that the generator can resume its execution. 115 : // Need to ensure that we don't run parallel tasks that send trace messages 116 : // [in the same trace buffer] to the collector. It is possible that when the 117 : // generator invoked this api, there may be another task running that handles 118 : // the trace request (for the same trace buffer) from the Collector. 119 0 : SandeshTraceBufferPtr trace_buf(SandeshTraceBufferGet(buf_name)); 120 0 : if (!trace_buf) { 121 0 : return; 122 : } 123 : std::unique_ptr<SandeshTraceRequestRunner> trace_req_runner(new 124 0 : SandeshTraceRequestRunner(trace_buf, "", "Collector", trace_count)); 125 0 : trace_req_runner->Run(); 126 0 : } 127 : 128 0 : void SandeshTraceBufferListRequest::HandleRequest() const { 129 0 : std::vector<std::string> trace_buf_list; 130 0 : SandeshTraceBufferListGet(trace_buf_list); 131 0 : std::vector<SandeshTraceBufInfo> trace_buf_info_list; 132 0 : for (std::vector<std::string>::const_iterator it = trace_buf_list.begin(); 133 0 : it != trace_buf_list.end(); ++it) { 134 0 : SandeshTraceBufInfo trace_buf_info; 135 0 : trace_buf_info.set_trace_buf_name(*it); 136 0 : trace_buf_info_list.push_back(trace_buf_info); 137 0 : } 138 0 : SandeshTraceBufferListResponse *resp = new SandeshTraceBufferListResponse; 139 0 : resp->set_trace_buffer_list(trace_buf_info_list); 140 0 : resp->set_context(context()); 141 0 : resp->set_more(false); 142 0 : resp->Response(); 143 0 : } 144 : 145 0 : void SandeshTraceEnableDisableReq::HandleRequest() const { 146 0 : std::string status; 147 0 : if (__isset.enable) { 148 0 : if (get_enable()) { 149 0 : SandeshTraceEnable(); 150 0 : status = "Sandesh Trace Enabled"; 151 : } else { 152 0 : SandeshTraceDisable(); 153 0 : status = "Sandesh Trace Disabled"; 154 : } 155 : } else { 156 : // If the user has not specified whether to enable or disable 157 : // trace, then toggle the trace status. 158 0 : if (IsSandeshTraceEnabled()) { 159 0 : SandeshTraceDisable(); 160 0 : status = "Sandesh Trace Disabled"; 161 : } else { 162 0 : SandeshTraceEnable(); 163 0 : status = "Sandesh Trace Enabled"; 164 : } 165 : } 166 : SandeshTraceEnableDisableRes *resp = new 167 0 : SandeshTraceEnableDisableRes; 168 0 : resp->set_enable_disable_status(status); 169 0 : resp->set_context(context()); 170 0 : resp->set_more(false); 171 0 : resp->Response(); 172 0 : } 173 : 174 0 : void SandeshTraceBufStatusReq::HandleRequest() const { 175 0 : std::vector<std::string> trace_buf_list; 176 0 : SandeshTraceBufferListGet(trace_buf_list); 177 0 : std::vector<SandeshTraceBufStatusInfo> trace_buf_status_list; 178 0 : for (std::vector<std::string>::const_iterator it = trace_buf_list.begin(); 179 0 : it != trace_buf_list.end(); ++it) { 180 0 : SandeshTraceBufStatusInfo trace_buf_status; 181 0 : trace_buf_status.set_trace_buf_name(*it); 182 0 : SandeshTraceBufferPtr tbp = SandeshTraceBufferGet(*it); 183 0 : assert(tbp); 184 0 : if (IsSandeshTraceBufferEnabled(tbp)) { 185 0 : trace_buf_status.set_enable_disable("Enabled"); 186 : } else { 187 0 : trace_buf_status.set_enable_disable("Disabled"); 188 : } 189 0 : trace_buf_status_list.push_back(trace_buf_status); 190 0 : trace_buf_status.set_buffer_length(SandeshTraceBufferSizeGet(tbp)); 191 0 : } 192 0 : SandeshTraceBufStatusRes *resp = new SandeshTraceBufStatusRes; 193 0 : resp->set_trace_buf_status_list(trace_buf_status_list); 194 0 : resp->set_context(context()); 195 0 : resp->set_more(false); 196 0 : resp->Response(); 197 0 : } 198 : 199 0 : void SandeshTraceBufferEnableDisableReq::HandleRequest() const { 200 : SandeshTraceBufferEnableDisableRes *resp = new 201 0 : SandeshTraceBufferEnableDisableRes; 202 0 : std::string status; 203 : SandeshTraceBufferPtr trace_buf( 204 0 : SandeshTraceBufferGet(get_trace_buf_name())); 205 0 : if (trace_buf) { 206 0 : if (__isset.enable) { 207 0 : if (get_enable()) { 208 0 : SandeshTraceBufferEnable(trace_buf); 209 0 : status = "Trace buffer Enabled"; 210 : } else { 211 0 : SandeshTraceBufferDisable(trace_buf); 212 0 : status = "Trace buffer Disabled"; 213 : } 214 : } else { 215 : // If the user has not specified whether to enable or disable 216 : // trace, then toggle the trace status. 217 0 : if (IsSandeshTraceBufferEnabled(trace_buf)) { 218 0 : SandeshTraceBufferDisable(trace_buf); 219 0 : status = "Trace buffer Disabled"; 220 : } else { 221 0 : SandeshTraceBufferEnable(trace_buf); 222 0 : status = "Trace buffer Enabled"; 223 : } 224 : } 225 : } else { 226 0 : status = "Invalid Trace buffer"; 227 : } 228 0 : resp->set_enable_disable_status(status); 229 0 : resp->set_context(context()); 230 0 : resp->set_more(false); 231 0 : resp->Response(); 232 0 : }