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