OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
trace.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef __TRACE_H__
6 #define __TRACE_H__
7 
8 #include <tbb/mutex.h>
9 #include <map>
10 #include <vector>
11 #include <stdexcept>
12 #include <boost/function.hpp>
13 #include <boost/ptr_container/ptr_circular_buffer.hpp>
14 #include <boost/weak_ptr.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include "base/util.h"
17 
18 template<typename TraceEntryT>
19 class TraceBuffer {
20 public:
21  TraceBuffer(const std::string& buf_name, size_t size, bool trace_enable)
22  : trace_buf_name_(buf_name),
23  trace_buf_size_(size),
25  write_index_(0),
26  read_index_(0),
27  wrap_(false) {
28  seqno_ = 0;
29  trace_enable_ = trace_enable;
30  }
31 
33  read_context_map_.clear();
34  trace_buf_.clear();
35  }
36 
37  std::string Name() {
38  return trace_buf_name_;
39  }
40 
41  void TraceOn() {
42  trace_enable_ = true;
43  }
44 
45  void TraceOff() {
46  trace_enable_ = false;
47  }
48 
49  bool IsTraceOn() {
50  return trace_enable_;
51  }
52 
53  size_t TraceBufSizeGet() {
54  return trace_buf_size_;
55  }
56 
58  return trace_buf_.capacity();
59  }
60 
61 
62  void TraceBufCapacityReset(size_t size) {
63  trace_buf_.rset_capacity(size);
64  trace_buf_size_ = size;
65  }
66 
67  void TraceWrite(TraceEntryT *trace_entry) {
68  tbb::mutex::scoped_lock lock(mutex_);
69 
70  // Add the trace
71  trace_buf_.push_back(trace_entry);
72 
73  // Once the trace buffer is wrapped, increment the read index
74  if (wrap_) {
75  if (++read_index_ == trace_buf_size_) {
76  read_index_ = 0;
77  }
78  }
79 
80  // Increment the write_index_ and reset upon reaching trace_buf_size_
81  if (++write_index_ == trace_buf_size_) {
82  write_index_ = 0;
83  wrap_ = true;
84  }
85 
86  // Trace messages could be read in batches instead of reading
87  // the entire trace buffer in one shot. Therefore, trace messages
88  // could be added between subsequent read requests. If the
89  // read_index_ [points to the oldest message in the trace buffer]
90  // becomes same as the read index [points to the position in the
91  // trace buffer from where the next trace message should be read]
92  // stored in the read context, then there is no need to remember the
93  // read context.
94  ReadContextMap::iterator it = read_context_map_.begin();
95  ReadContextMap::iterator next = it;
96  for (size_t i = 0, cnt = read_context_map_.size(); i < cnt;
97  i++, it = next) {
98  ++next;
99  if (*it->second.get() == read_index_) {
100  read_context_map_.erase(it);
101  }
102  }
103  }
104 
105  uint32_t GetNextSeqNum() {
106  uint32_t nseqno(seqno_.fetch_and_increment());
107  // Reset seqno_ if it reaches max value
108  if (nseqno > kMaxSeqno) {
109  seqno_ = kMinSeqno;
110  }
111  return nseqno;
112  }
113 
114  void TraceRead(const std::string& context, const int count,
115  boost::function<void (TraceEntryT *, bool)> cb) {
116  tbb::mutex::scoped_lock lock(mutex_);
117  if (trace_buf_.empty()) {
118  // No message in the trace buffer
119  return;
120  }
121 
122  // if count = 0, then set the cnt equal to the size of trace_buf_
123  size_t cnt = count ? count : trace_buf_.size();
124 
125  size_t *read_index_ptr;
126  typename ContainerType::iterator it;
127  ReadContextMap::iterator context_it =
128  read_context_map_.find(context);
129  if (context_it != read_context_map_.end()) {
130  // If the read context is present, manipulate the position
131  // from where we wanna start
132  read_index_ptr = context_it->second.get();
133  size_t offset = *read_index_ptr - read_index_;
134  offset = offset > 0 ? offset : trace_buf_size_ + offset;
135  it = trace_buf_.begin() + offset;
136  } else {
137  // Create read context
138  boost::shared_ptr<size_t> read_context(new size_t(read_index_));
139  read_index_ptr = read_context.get();
140  read_context_map_.insert(std::make_pair(context, read_context));
141  it = trace_buf_.begin();
142  }
143 
144  size_t i;
145  typename ContainerType::iterator next = it;
146  for (i = 0; (it != trace_buf_.end()) && (i < cnt); i++, it = next) {
147  ++next;
148  cb(&(*it), next != trace_buf_.end());
149  }
150 
151  // Update the read index in the read context
152  size_t offset = *read_index_ptr + i;
153  *read_index_ptr = offset >= trace_buf_size_ ?
154  offset - trace_buf_size_ : offset;
155  }
156 
157  void TraceReadDone(const std::string& context) {
158  tbb::mutex::scoped_lock lock(mutex_);
159  ReadContextMap::iterator context_it =
160  read_context_map_.find(context);
161  if (context_it != read_context_map_.end()) {
162  read_context_map_.erase(context_it);
163  }
164  }
165 
166 private:
167  typedef boost::ptr_circular_buffer<TraceEntryT> ContainerType;
168  typedef std::map<const std::string, boost::shared_ptr<size_t> >
170 
171  std::string trace_buf_name_;
174  tbb::atomic<bool> trace_enable_;
175  size_t write_index_; // points to the position in the trace buffer,
176  // where the next trace message would be added
177  size_t read_index_; // points to the position of the oldest
178  // trace message in the trace buffer
179  bool wrap_; // indicates if the trace buffer is wrapped
180  ReadContextMap read_context_map_; // stores the read context
181  tbb::atomic<uint32_t> seqno_;
182  tbb::mutex mutex_;
183 
184  // Reserve 0 and max(uint32_t)
185  static const uint32_t kMaxSeqno = ((2 ^ 32) - 1) - 1;
186  static const uint32_t kMinSeqno = 1;
187 
189 };
190 
191 template<typename TraceEntryT>
193 public:
194  typedef std::map<const std::string, boost::weak_ptr<TraceBuffer<TraceEntryT> > > TraceBufMap;
195 
196  explicit TraceBufferDeleter(TraceBufMap &trace_buf_map, tbb::mutex &mutex) :
197  trace_buf_map_(trace_buf_map),
198  mutex_(mutex) {
199  }
200 
201  void operator()(TraceBuffer<TraceEntryT> *trace_buffer) const {
202  tbb::mutex::scoped_lock lock(mutex_);
203  for (typename TraceBufMap::iterator it = trace_buf_map_.begin();
204  it != trace_buf_map_.end();
205  it++) {
206  if (it->second.lock() == NULL) {
207  trace_buf_map_.erase(it->first);
208  delete trace_buffer;
209  break;
210  }
211  }
212  }
213 
214 private:
216  tbb::mutex &mutex_;
217 };
218 
219 template<typename TraceEntryT>
220 class Trace {
221 public:
222  typedef std::map<const std::string, boost::weak_ptr<TraceBuffer<TraceEntryT> > > TraceBufMap;
223 
224  static Trace* GetInstance() {
225  if (!trace_) {
226  trace_ = new Trace;
227  }
228  return trace_;
229  }
230 
231  void TraceOn() {
232  trace_enable_ = true;
233  }
234 
235  void TraceOff() {
236  trace_enable_ = false;
237  }
238 
239  bool IsTraceOn() {
240  return trace_enable_;
241  }
242 
243  boost::shared_ptr<TraceBuffer<TraceEntryT> > TraceBufGet(const std::string& buf_name) {
244  tbb::mutex::scoped_lock lock(mutex_);
245  typename TraceBufMap::iterator it = trace_buf_map_.find(buf_name);
246  if (it != trace_buf_map_.end()) {
247  return it->second.lock();
248  } else {
249  return boost::shared_ptr<TraceBuffer<TraceEntryT> >();
250  }
251  }
252 
253  boost::shared_ptr<TraceBuffer<TraceEntryT> > TraceBufAdd(const std::string& buf_name, size_t size,
254  bool trace_enable) {
255  // should we have a default size for the buffer?
256  if (!size) {
257  return boost::shared_ptr<TraceBuffer<TraceEntryT> >();
258  }
259  tbb::mutex::scoped_lock lock(mutex_);
260  typename TraceBufMap::iterator it = trace_buf_map_.find(buf_name);
261  if (it == trace_buf_map_.end()) {
262  boost::shared_ptr<TraceBuffer<TraceEntryT> > trace_buf(
263  new TraceBuffer<TraceEntryT>(buf_name, size, trace_enable),
265  trace_buf_map_.insert(std::make_pair(buf_name, trace_buf));
266  return trace_buf;
267  }
268  return it->second.lock();
269  }
270 
271  void TraceBufListGet(std::vector<std::string>& trace_buf_list) {
272  tbb::mutex::scoped_lock lock(mutex_);
273  typename TraceBufMap::iterator it;
274  for (it = trace_buf_map_.begin(); it != trace_buf_map_.end(); ++it) {
275  trace_buf_list.push_back(it->first);
276  }
277  }
278 
279  size_t TraceBufCapacityGet(const std::string& buf_name) {
280  tbb::mutex::scoped_lock lock(mutex_);
281  typename TraceBufMap::iterator it = trace_buf_map_.find(buf_name);
282  if (it != trace_buf_map_.end()) {
283  boost::shared_ptr<TraceBuffer<TraceEntryT> > trace_buf =
284  it->second.lock();
285  return trace_buf->TraceBufCapacityGet();
286  } else {
287  return 0;
288  }
289  }
290 
291  boost::shared_ptr<TraceBuffer<TraceEntryT> > TraceBufCapacityReset(
292  const std::string& buf_name, size_t size) {
293  tbb::mutex::scoped_lock lock(mutex_);
294  typename TraceBufMap::iterator it = trace_buf_map_.find(buf_name);
295  if (it != trace_buf_map_.end()) {
296  boost::shared_ptr<TraceBuffer<TraceEntryT> > trace_buf =
297  it->second.lock();
298  trace_buf->TraceBufCapacityReset(size);
299  return trace_buf;
300  } else {
301  boost::shared_ptr<TraceBuffer<TraceEntryT> > trace_buf(
302  new TraceBuffer<TraceEntryT>(buf_name, size, true),
304  trace_buf_map_.insert(std::make_pair(buf_name, trace_buf));
305  return trace_buf;
306  }
307  }
308 
309 private:
310  Trace() {
311  trace_enable_ = true;
312  }
313 
314  ~Trace() {
315  delete trace_;
316  }
317 
318  static Trace *trace_;
319  tbb::atomic<bool> trace_enable_;
321  tbb::mutex mutex_;
322 
324 };
325 
326 #endif // __TRACE_H__
tbb::atomic< bool > trace_enable_
Definition: trace.h:174
std::string trace_buf_name_
Definition: trace.h:171
size_t write_index_
Definition: trace.h:175
void TraceOn()
Definition: trace.h:231
bool IsTraceOn()
Definition: trace.h:49
ContainerType trace_buf_
Definition: trace.h:173
tbb::mutex mutex_
Definition: trace.h:321
ReadContextMap read_context_map_
Definition: trace.h:180
bool IsTraceOn()
Definition: trace.h:239
size_t trace_buf_size_
Definition: trace.h:172
DISALLOW_COPY_AND_ASSIGN(Trace)
void TraceBufListGet(std::vector< std::string > &trace_buf_list)
Definition: trace.h:271
std::map< const std::string, boost::shared_ptr< size_t > > ReadContextMap
Definition: trace.h:169
void TraceOn()
Definition: trace.h:41
TraceBufferDeleter(TraceBufMap &trace_buf_map, tbb::mutex &mutex)
Definition: trace.h:196
void TraceOff()
Definition: trace.h:235
boost::shared_ptr< TraceBuffer< TraceEntryT > > TraceBufGet(const std::string &buf_name)
Definition: trace.h:243
bool wrap_
Definition: trace.h:179
~Trace()
Definition: trace.h:314
TraceBuffer(const std::string &buf_name, size_t size, bool trace_enable)
Definition: trace.h:21
uint32_t GetNextSeqNum()
Definition: trace.h:105
void TraceReadDone(const std::string &context)
Definition: trace.h:157
boost::shared_ptr< TraceBuffer< TraceEntryT > > TraceBufCapacityReset(const std::string &buf_name, size_t size)
Definition: trace.h:291
std::map< const std::string, boost::weak_ptr< TraceBuffer< TraceEntryT > > > TraceBufMap
Definition: trace.h:222
void TraceOff()
Definition: trace.h:45
Definition: trace.h:220
size_t TraceBufSizeGet()
Definition: trace.h:53
boost::ptr_circular_buffer< TraceEntryT > ContainerType
Definition: trace.h:167
size_t TraceBufCapacityGet()
Definition: trace.h:57
std::map< const std::string, boost::weak_ptr< TraceBuffer< TraceEntryT > > > TraceBufMap
Definition: trace.h:194
std::string Name()
Definition: trace.h:37
void TraceRead(const std::string &context, const int count, boost::function< void(TraceEntryT *, bool)> cb)
Definition: trace.h:114
~TraceBuffer()
Definition: trace.h:32
static Trace * GetInstance()
Definition: trace.h:224
size_t read_index_
Definition: trace.h:177
DISALLOW_COPY_AND_ASSIGN(TraceBuffer)
TraceBufMap trace_buf_map_
Definition: trace.h:320
tbb::mutex & mutex_
Definition: trace.h:216
tbb::atomic< uint32_t > seqno_
Definition: trace.h:181
void operator()(TraceBuffer< TraceEntryT > *trace_buffer) const
Definition: trace.h:201
static const uint32_t kMaxSeqno
Definition: trace.h:185
TraceBufMap & trace_buf_map_
Definition: trace.h:215
static const uint32_t kMinSeqno
Definition: trace.h:186
boost::shared_ptr< TraceBuffer< TraceEntryT > > TraceBufAdd(const std::string &buf_name, size_t size, bool trace_enable)
Definition: trace.h:253
Trace()
Definition: trace.h:310
void TraceBufCapacityReset(size_t size)
Definition: trace.h:62
tbb::mutex mutex_
Definition: trace.h:182
static Trace * trace_
Definition: trace.h:318
tbb::atomic< bool > trace_enable_
Definition: trace.h:319
void TraceWrite(TraceEntryT *trace_entry)
Definition: trace.h:67
size_t TraceBufCapacityGet(const std::string &buf_name)
Definition: trace.h:279