Fawkes API  Fawkes Development Version
rrd_thread.cpp
1 
2 /***************************************************************************
3  * rrd_thread.cpp - RRD Thread
4  *
5  * Created: Fri Dec 17 00:32:57 2010
6  * Copyright 2006-2010 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "rrd_thread.h"
24 
25 #include <core/exceptions/system.h>
26 #include <core/threading/scoped_rwlock.h>
27 #include <utils/misc/string_conversions.h>
28 #include <utils/system/file.h>
29 
30 #include <cstdarg>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cstring>
34 #include <rrd.h>
35 
36 using namespace fawkes;
37 
38 /** @class RRDThread "rrd_thread.h"
39  * RRD Thread.
40  * This thread maintains an active connection to RRD and provides an
41  * aspect to access RRD to make it convenient for other threads to use
42  * RRD.
43  *
44  * @author Tim Niemueller
45  */
46 
47 /** Constructor. */
49 : Thread("RRDThread", Thread::OPMODE_CONTINUOUS),
50  AspectProviderAspect(&rrd_aspect_inifin_),
51  rrd_aspect_inifin_(this)
52 {
54 }
55 
56 /** Destructor. */
58 {
59 }
60 
61 void
63 {
64  cfg_graph_interval_ = 30.;
65  try {
66  cfg_graph_interval_ = config->get_float("/plugins/rrd/graph_interval");
67  } catch (Exception &e) {
68  }
69 
70  time_wait_ = new TimeWait(clock, time_sec_to_usec(cfg_graph_interval_));
71 }
72 
73 void
75 {
76  delete time_wait_;
77 }
78 
79 void
81 {
82  time_wait_->mark_start();
84  time_wait_->wait_systime();
85 }
86 
87 /** Generate all graphs. */
88 void
90 {
91  ScopedRWLock lock(graphs_.rwlock(), ScopedRWLock::LOCK_READ);
92 
93  std::vector<fawkes::RRDGraphDefinition *>::iterator g;
94  for (g = graphs_.begin(); g != graphs_.end(); ++g) {
95  size_t argc = 0;
96  const char **argv = (*g)->get_argv(argc);
97 
98  //logger->log_debug(name(), "rrd_graph arguments:");
99  //for (size_t j = 0; j < argc; ++j) {
100  // logger->log_debug(name(), " %zu: %s", j, argv[j]);
101  //}
102 
103  rrd_clear_error();
104  rrd_info_t *i = rrd_graph_v(argc, (char **)argv);
105  if (i == NULL) {
106  throw Exception("Creating graph %s (for RRD %s) failed: %s",
107  (*g)->get_name(),
108  (*g)->get_rrd_def()->get_name(),
109  rrd_get_error());
110  }
111  rrd_info_free(i);
112  }
113 }
114 
115 void
117 {
118  // generate filename
119  char *filename;
120  if (asprintf(&filename, "%s/%s.rrd", ".", rrd_def->get_name()) == -1) {
121  throw OutOfMemoryException("Failed to creat filename for RRD %s", rrd_def->get_name());
122  }
123  rrd_def->set_filename(filename);
124  free(filename);
125 
126  if (!File::exists(rrd_def->get_filename()) || rrd_def->get_recreate()) {
127  std::string size_s = StringConversions::to_string(rrd_def->get_step_sec());
128 
129  // build parameter array
130  // "create" filename --step STEP --start START DS... RRA...
131  size_t rrd_argc = 6 + rrd_def->get_ds().size() + rrd_def->get_rra().size();
132  const char *rrd_argv[rrd_argc];
133  size_t i = 0;
134  rrd_argv[i++] = "create";
135  rrd_argv[i++] = rrd_def->get_filename();
136  rrd_argv[i++] = "--step";
137  rrd_argv[i++] = size_s.c_str();
138  rrd_argv[i++] = "--start";
139  rrd_argv[i++] = "0";
140 
141  std::vector<RRDDataSource>::const_iterator d;
142  for (d = rrd_def->get_ds().begin(); d != rrd_def->get_ds().end() && i < rrd_argc; ++d) {
143  rrd_argv[i++] = d->to_string();
144  }
145 
146  std::vector<RRDArchive>::const_iterator a;
147  for (a = rrd_def->get_rra().begin(); a != rrd_def->get_rra().end() && i < rrd_argc; ++a) {
148  rrd_argv[i++] = a->to_string();
149  }
150 
151  //logger->log_debug(name(), "rrd_create arguments:");
152  //for (size_t j = 0; j < i; ++j) {
153  // logger->log_debug(name(), " %zu: %s", j, rrd_argv[j]);
154  //}
155 
156  // Create RRD file
157  rrd_clear_error();
158  if (rrd_create(i, (char **)rrd_argv) == -1) {
159  throw Exception("Creating RRD %s failed: %s", rrd_def->get_name(), rrd_get_error());
160  }
161  }
162 
163  ScopedRWLock lock(rrds_.rwlock());
165  for (r = rrds_.begin(); r != rrds_.end(); ++r) {
166  if (strcmp((*r)->get_name(), rrd_def->get_name()) == 0) {
167  throw Exception("RRD with name %s has already been registered", rrd_def->get_name());
168  }
169  }
170 
171  rrd_def->set_rrd_manager(this);
172  rrds_.push_back(rrd_def);
173 }
174 
175 void
177 {
178  ScopedRWLock rrds_lock(rrds_.rwlock());
180  for (r = rrds_.begin(); r != rrds_.end(); ++r) {
181  if (strcmp((*r)->get_name(), rrd_def->get_name()) == 0) {
182  rrds_.erase(r);
183  break;
184  }
185  }
186 
187  ScopedRWLock graph_lock(graphs_.rwlock());
188  bool graphs_modified = false;
189  do {
190  graphs_modified = false;
192  for (g = graphs_.begin(); g != graphs_.end(); ++g) {
193  if (strcmp((*g)->get_rrd_def()->get_name(), rrd_def->get_name()) == 0) {
194  graphs_.erase(g);
195  graphs_modified = true;
196  break;
197  }
198  }
199  } while (graphs_modified);
200 }
201 
202 void
204 {
205  // generate filename
206  char *filename;
207  if (asprintf(&filename, "%s/%s.png", ".", rrd_graph_def->get_name()) == -1) {
208  throw OutOfMemoryException("Failed to create filename for PNG %s", rrd_graph_def->get_name());
209  }
210  rrd_graph_def->set_filename(filename);
211  free(filename);
212 
213  ScopedRWLock lock(graphs_.rwlock());
215  for (g = graphs_.begin(); g != graphs_.end(); ++g) {
216  if (strcmp((*g)->get_name(), rrd_graph_def->get_name()) == 0) {
217  throw Exception("RRD graph with name %s has already been registered",
218  rrd_graph_def->get_name());
219  }
220  }
221  graphs_.push_back(rrd_graph_def);
222 }
223 
224 void
225 RRDThread::add_data(const char *rrd_name, const char *format, ...)
226 {
227  ScopedRWLock lock(rrds_.rwlock(), ScopedRWLock::LOCK_READ);
228 
229  std::vector<RRDDefinition *>::const_iterator d;
230  for (d = rrds_.begin(); d != rrds_.end(); ++d) {
231  RRDDefinition *rrd_def = *d;
232  if (strcmp(rrd_name, rrd_def->get_name()) == 0) {
233  char * data;
234  va_list arg;
235  va_start(arg, format);
236  if (vasprintf(&data, format, arg) == -1) {
237  va_end(arg);
238  throw OutOfMemoryException("Failed to create data string for %s", rrd_name);
239  }
240  va_end(arg);
241 
242  // filename data
243  size_t rrd_argc = 3;
244  const char *rrd_argv[rrd_argc];
245  size_t i = 0;
246  rrd_argv[i++] = "update";
247  rrd_argv[i++] = rrd_def->get_filename();
248  rrd_argv[i++] = data;
249 
250  //logger->log_debug(name(), "rrd_update arguments:");
251  //for (size_t j = 0; j < i; ++j) {
252  // logger->log_debug(name(), " %zu: %s", j, rrd_argv[j]);
253  //}
254 
255  rrd_clear_error();
256  if (rrd_update(i, (char **)rrd_argv) == -1) {
257  free(data);
258  throw Exception("Failed to update RRD %s: %s", rrd_name, rrd_get_error());
259  }
260 
261  free(data);
262  return;
263  }
264  }
265 
266  throw Exception("No RRD named %s registered", rrd_name);
267 }
268 
271 {
272  return rrds_;
273 }
274 
277 {
278  return graphs_;
279 }
fawkes::RRDDefinition::set_filename
void set_filename(const char *filename)
Set filename.
Definition: rrd_descriptions.cpp:455
fawkes::RRDGraphDefinition
Definition: rrd_descriptions.h:470
fawkes::Thread::set_prepfin_conc_loop
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:722
fawkes::RRDDefinition::get_step_sec
unsigned int get_step_sec() const
Get step size in sec.
Definition: rrd_descriptions.h:197
fawkes::RWLockVector
Definition: rwlock_vector.h:41
fawkes::AspectProviderAspect
Definition: aspect_provider.h:41
fawkes::RRDDefinition::get_rra
const std::vector< RRDArchive > & get_rra() const
Get RRD archives.
Definition: rrd_descriptions.h:224
RRDThread::loop
virtual void loop()
Code to execute in the thread.
Definition: rrd_thread.cpp:80
RRDThread::RRDThread
RRDThread()
Constructor.
Definition: rrd_thread.cpp:48
fawkes::ClockAspect::clock
Clock * clock
Definition: clock.h:56
fawkes::ScopedRWLock
Definition: scoped_rwlock.h:39
fawkes::RRDDefinition::get_ds
const std::vector< RRDDataSource > & get_ds() const
Get data sources.
Definition: rrd_descriptions.h:210
RRDThread::generate_graphs
void generate_graphs()
Generate all graphs.
Definition: rrd_thread.cpp:89
RRDThread::add_data
virtual void add_data(const char *rrd_name, const char *format,...)
Add data.
Definition: rrd_thread.cpp:225
fawkes::RRDDefinition::get_filename
const char * get_filename() const
Get file name.
Definition: rrd_descriptions.h:230
fawkes
RRDThread::remove_rrd
virtual void remove_rrd(fawkes::RRDDefinition *rrd_def)
Remove RRD.
Definition: rrd_thread.cpp:176
fawkes::RRDDefinition::get_name
const char * get_name() const
Get name.
Definition: rrd_descriptions.h:191
fawkes::TimeWait::mark_start
void mark_start()
Mark start of loop.
Definition: wait.cpp:74
RRDThread::init
virtual void init()
Initialize the thread.
Definition: rrd_thread.cpp:62
fawkes::ConfigurableAspect::config
Configuration * config
Definition: configurable.h:53
RRDThread::finalize
virtual void finalize()
Finalize the thread.
Definition: rrd_thread.cpp:74
fawkes::RRDDefinition::get_recreate
bool get_recreate() const
Check recreation flag.
Definition: rrd_descriptions.h:204
fawkes::RWLockVector::rwlock
RefPtr< ReadWriteLock > rwlock() const
Get access to the internal read/write lock.
Definition: rwlock_vector.h:195
RRDThread::get_rrds
virtual const fawkes::RWLockVector< fawkes::RRDDefinition * > & get_rrds() const
Get RRDs.
Definition: rrd_thread.cpp:270
fawkes::RRDGraphDefinition::get_name
const char * get_name() const
Get graph definition name.
Definition: rrd_descriptions.h:492
RRDThread::add_rrd
virtual void add_rrd(fawkes::RRDDefinition *rrd_def)
Add RRD.
Definition: rrd_thread.cpp:116
fawkes::Configuration::get_float
virtual float get_float(const char *path)=0
fawkes::Thread
Definition: thread.h:45
fawkes::TimeWait
Definition: wait.h:38
fawkes::RRDDefinition
Definition: rrd_descriptions.h:168
fawkes::time_sec_to_usec
long int time_sec_to_usec(double sec)
Convert seconds to micro seconds.
Definition: time.h:79
fawkes::TimeWait::wait_systime
void wait_systime()
Wait until minimum loop time has been reached in real time.
Definition: wait.cpp:102
fawkes::RRDDefinition::set_rrd_manager
void set_rrd_manager(RRDManager *rrd_manager)
Set RRD manager.
Definition: rrd_descriptions.cpp:470
RRDThread::~RRDThread
virtual ~RRDThread()
Destructor.
Definition: rrd_thread.cpp:57
fawkes::OutOfMemoryException
Definition: system.h:37
fawkes::RRDGraphDefinition::set_filename
void set_filename(const char *filename)
Set filename.
Definition: rrd_descriptions.cpp:1003
RRDThread::get_graphs
virtual const fawkes::RWLockVector< fawkes::RRDGraphDefinition * > & get_graphs() const
Get graphs.
Definition: rrd_thread.cpp:276
RRDThread::add_graph
virtual void add_graph(fawkes::RRDGraphDefinition *rrd_graph_def)
Add graph.
Definition: rrd_thread.cpp:203
fawkes::Exception
Definition: exception.h:41