Interface Documentation
Version: invalid
state.hh
Go to the documentation of this file.
1 /*
2  @@@@@@@@ @@ @@@@@@ @@@@@@@@ @@
3  /@@///// /@@ @@////@@ @@////// /@@
4  /@@ /@@ @@@@@ @@ // /@@ /@@
5  /@@@@@@@ /@@ @@///@@/@@ /@@@@@@@@@/@@
6  /@@//// /@@/@@@@@@@/@@ ////////@@/@@
7  /@@ /@@/@@//// //@@ @@ /@@/@@
8  /@@ @@@//@@@@@@ //@@@@@@ @@@@@@@@ /@@
9  // /// ////// ////// //////// //
10 
11  Copyright (c) 2016, Triad National Security, LLC
12  All rights reserved.
13  */
14 #pragma once
15 
18 #include <flecsi-config.h>
19 
20 #if defined(FLECSI_ENABLE_FLOG)
21 
22 #include "flecsi/log/packet.hh"
23 #include "flecsi/log/types.hh"
24 #include "flecsi/log/utils.hh"
25 
26 #include <bitset>
27 #include <cassert>
28 #include <sstream>
29 #include <string>
30 #include <unordered_map>
31 
32 namespace flecsi {
33 namespace log {
34 
35 // Forward
36 void flush_packets();
37 
52 class flog_t
53 {
54 public:
59  flog_t(const flog_t &) = delete;
60 
65  flog_t & operator=(const flog_t &) = delete;
66 
73  static flog_t & instance() {
74  static flog_t c;
75  return c;
76  } // instance
77 
78  int initialize(std::string active = "none",
79  int verbose = 0,
80  std::size_t one_process = -1) {
81 #if defined(FLOG_ENABLE_DEBUG)
82  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: initializing runtime"
83  << FLOG_COLOR_PLAIN << std::endl;
84 #endif
85 
86  verbose_ = verbose;
87 
88 #if defined(FLOG_ENABLE_TAGS)
89  // Because active tags are specified at runtime, it is
90  // necessary to maintain a map of the compile-time registered
91  // tag names to the id that they get assigned after the flog_t
92  // initialization (register_tag). This map will be used to populate
93  // the tag_bitset_ for fast runtime comparisons of enabled tag groups.
94 
95  // Note: For the time being, the map uses actual strings rather than
96  // hashes. We should consider creating a const_string_t type for
97  // constexpr string creation.
98 
99  // Initialize everything to false. This is the default, i.e., "none".
100  tag_bitset_.reset();
101 
102  // The default group is always active (unscoped). To avoid
103  // output for this tag, make sure to scope all FLOG output.
104  tag_bitset_.set(0);
105  tag_reverse_map_[0] = "all";
106 
107  if(active == "all") {
108  // Turn on all of the bits for "all".
109  tag_bitset_.set();
110  }
111  else if(active != "none") {
112  // Turn on the bits for the selected groups.
113  std::istringstream is(active);
114  std::string tag;
115  while(std::getline(is, tag, ',')) {
116  if(tag_map_.find(tag) != tag_map_.end()) {
117  tag_bitset_.set(tag_map_[tag]);
118  }
119  else {
120  std::cerr << "FLOG WARNING: tag " << tag
121  << " has not been registered. Ignoring this group..."
122  << std::endl;
123  } // if
124  } // while
125  } // if
126 
127 #if defined(FLOG_ENABLE_DEBUG)
128  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: active tags (" << active << ")"
129  << FLOG_COLOR_PLAIN << std::endl;
130 #endif
131 
132 #endif // FLOG_ENABLE_TAGS
133 
134 #if defined(FLOG_ENABLE_MPI)
135 
136 #if defined(FLOG_ENABLE_DEBUG)
137  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: initializing mpi state"
138  << FLOG_COLOR_PLAIN << std::endl;
139 #endif
140 
141  {
142  int p, np;
143  MPI_Comm_rank(MPI_COMM_WORLD, &p);
144  MPI_Comm_size(MPI_COMM_WORLD, &np);
145  process_ = p;
146  processes_ = np;
147  }
148 
149  if(one_process + 1 && one_process >= processes_) {
150  if(process_ == 0) {
151  std::cerr << "flog process " << one_process << " out-of-bounds ("
152  << processes_ << " processes)" << std::endl;
153  } // if
154 
155  return !0;
156  } // if
157 
158  one_process_ = one_process;
159 
160  if(process_ == 0) {
161  std::thread flusher(flush_packets);
162  instance().flusher_thread().swap(flusher);
163  } // if
164 #endif // FLOG_ENABLE_MPI
165 
166  initialized_ = true;
167 
168  return 0;
169  } // initialize
170 
171  void finalize() {
172 #if defined(FLOG_ENABLE_MPI)
173  if(initialized_) {
174  send_to_one();
175 
176  if(process_ == 0) {
177  end_flusher();
178  flusher_thread_.join();
179  flush_packets();
180  } // if
181  } // if
182 #endif // FLOG_ENABLE_MPI
183  } // finalize
184 
185  int verbose() const {
186  return verbose_;
187  }
188 
193  const std::unordered_map<std::string, size_t> & tag_map() {
194  return tag_map_;
195  }
196 
201  std::stringstream & buffer_stream() {
202  return buffer_stream_;
203  }
204 
209  std::ostream & stream() {
210  return *stream_;
211  }
212 
219  std::ostream & severity_stream(bool active = true) {
220  return active ? buffer_stream_ : null_stream_;
221  }
222 
227  std::ostream & null_stream() {
228  return null_stream_;
229  }
230 
237  return *stream_;
238  }
239 
244  size_t register_tag(const char * tag) {
245  // If the tag is already registered, just return the previously
246  // assigned id. This allows tags to be registered in headers.
247  if(tag_map_.find(tag) != tag_map_.end()) {
248  return tag_map_[tag];
249  } // if
250 
251  const size_t id = ++tag_id_;
252  assert(id < FLOG_TAG_BITS && "Tag bits overflow! Increase FLOG_TAG_BITS");
253 #if defined(FLOG_ENABLE_DEBUG)
254  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: registering tag " << tag << ": "
255  << id << FLOG_COLOR_PLAIN << std::endl;
256 #endif
257  tag_map_[tag] = id;
258  tag_reverse_map_[id] = tag;
259  return id;
260  } // next_tag
261 
266  const size_t & active_tag() const {
267  return active_tag_;
268  }
269 
274  size_t & active_tag() {
275  return active_tag_;
276  }
277 
282  std::string tag_name(size_t id) {
283  assert(tag_reverse_map_.find(id) != tag_reverse_map_.end());
284  return tag_reverse_map_[id];
285  }
286 
291  std::string active_tag_name() {
292  assert(tag_reverse_map_.find(active_tag_) != tag_reverse_map_.end());
293  return tag_reverse_map_[active_tag_];
294  }
295 
296  bool tag_enabled() {
297 #if defined(FLOG_ENABLE_TAGS)
298 
299 #if defined(FLOG_ENABLE_DEBUG)
300  auto active_set = tag_bitset_.test(active_tag_) == 1 ? "true" : "false";
301  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: tag " << active_tag_ << " is "
302  << active_set << FLOG_COLOR_PLAIN << std::endl;
303 #endif
304 
305  // If the runtime context hasn't been initialized, return true only
306  // if the user has enabled externally-scoped messages.
307  if(!initialized_) {
308 #if defined(FLOG_ENABLE_EXTERNAL)
309  return true;
310 #else
311  return false;
312 #endif
313  } // if
314 
315  return tag_bitset_.test(active_tag_);
316 #else
317  return true;
318 #endif // FLOG_ENABLE_TAGS
319  } // tag_enabled
320 
321  size_t lookup_tag(const char * tag) {
322  if(tag_map_.find(tag) == tag_map_.end()) {
323  std::cerr << FLOG_COLOR_YELLOW << "FLOG: !!!WARNING " << tag
324  << " has not been registered. Ignoring this group..."
325  << FLOG_COLOR_PLAIN << std::endl;
326  return 0;
327  } // if
328 
329  return tag_map_[tag];
330  }
331 
332  bool initialized() {
333  return initialized_;
334  }
335 
336 #if defined(FLOG_ENABLE_MPI)
337  bool one_process() const {
338  return one_process_ < processes_;
339  }
340 
341  size_t output_process() const {
342  return one_process_;
343  }
344 
345  std::size_t process() {
346  return process_;
347  }
348 
349  std::size_t processes() {
350  return processes_;
351  }
352 
353  std::thread & flusher_thread() {
354  return flusher_thread_;
355  }
356 
357  std::mutex & packets_mutex() {
358  return packets_mutex_;
359  }
360 
361  void buffer_output() {
362  std::string tmp = buffer_stream().str();
363 
364  // Make sure that the string fits within the packet size.
365  if(tmp.size() > FLOG_MAX_MESSAGE_SIZE) {
366  tmp.resize(FLOG_MAX_MESSAGE_SIZE - 100);
367  std::stringstream stream;
368  stream << tmp << FLOG_COLOR_LTRED << " OUTPUT BUFFER TRUNCATED "
369  << FLOG_MAX_MESSAGE_SIZE << "(" << buffer_stream().str().size()
370  << ")" << FLOG_COLOR_PLAIN << std::endl;
371  tmp = stream.str();
372  } // if
373 
374  packets_.push_back({tmp.c_str()});
375  }
376 
377  std::vector<packet_t> & packets() {
378  return packets_;
379  }
380 
381  bool run_flusher() {
382  return run_flusher_;
383  }
384 
385  void end_flusher() {
386  run_flusher_ = false;
387  }
388 
389  void set_serialized() {
390  serialized_ = true;
391  }
392 
393  bool serialized() {
394  return serialized_;
395  }
396 #endif
397 
398 private:
403  flog_t() : null_stream_(0), tag_id_(0), active_tag_(0) {}
404 
405  ~flog_t() {
406 #if defined(FLOG_ENABLE_DEBUG)
407  std::cerr << FLOG_COLOR_LTGRAY << "FLOG: flog_t destructor" << std::endl;
408 #endif
409  }
410 
411  bool initialized_ = false;
412  int verbose_ = 0;
413 
414  tee_stream_t stream_;
415  std::stringstream buffer_stream_;
416  std::ostream null_stream_;
417 
418  size_t tag_id_;
419  size_t active_tag_;
420  std::bitset<FLOG_TAG_BITS> tag_bitset_;
421  std::unordered_map<std::string, size_t> tag_map_;
422  std::unordered_map<size_t, std::string> tag_reverse_map_;
423 
424 #if defined(FLOG_ENABLE_MPI)
425  std::size_t one_process_, process_, processes_;
426  std::thread flusher_thread_;
427  std::mutex packets_mutex_;
428  std::vector<packet_t> packets_;
429  bool run_flusher_ = true;
430  bool serialized_ = false;
431 #endif
432 
433 }; // class flog_t
434 
435 } // namespace log
436 } // namespace flecsi
437 
438 #endif // FLECSI_ENABLE_FLOG
std::ostream & severity_stream(bool active=true)
Definition: state.hh:219
tee_stream_t & config_stream()
Definition: state.hh:236
Definition: state.hh:52
std::stringstream & buffer_stream()
Definition: state.hh:201
size_t register_tag(const char *tag)
Definition: state.hh:244
Definition: types.hh:258
Definition: flog.hh:47
static flog_t & instance()
Definition: state.hh:73
std::ostream & null_stream()
Definition: state.hh:227
std::string active_tag_name()
Definition: state.hh:291
std::ostream & stream()
Definition: state.hh:209
std::string tag_name(size_t id)
Definition: state.hh:282
flog_t & operator=(const flog_t &)=delete
size_t & active_tag()
Definition: state.hh:274
const std::unordered_map< std::string, size_t > & tag_map()
Definition: state.hh:193
Definition: control.hh:31
const size_t & active_tag() const
Definition: state.hh:266