A Discrete-Event Network Simulator
API
sqlite-data-output.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Drexel University
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Joe Kopena (tjkopena@cs.drexel.edu)
18  */
19 
20 #include "sqlite-data-output.h"
21 
22 #include "data-calculator.h"
23 #include "data-collector.h"
24 #include "sqlite-output.h"
25 
26 #include "ns3/log.h"
27 #include "ns3/nstime.h"
28 
29 #include <sstream>
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("SqliteDataOutput");
35 
38 {
39  NS_LOG_FUNCTION(this);
40 
41  m_filePrefix = "data";
42 }
43 
45 {
46  NS_LOG_FUNCTION(this);
47 }
48 
49 /* static */
50 TypeId
52 {
53  static TypeId tid = TypeId("ns3::SqliteDataOutput")
55  .SetGroupName("Stats")
56  .AddConstructor<SqliteDataOutput>();
57  return tid;
58 }
59 
60 //----------------------------------------------
61 void
63 {
64  NS_LOG_FUNCTION(this << &dc);
65 
66  std::string m_dbFile = m_filePrefix + ".db";
67  std::string run = dc.GetRunLabel();
68  bool res;
69 
70  m_sqliteOut = new SQLiteOutput(m_dbFile);
71 
72  res = m_sqliteOut->SpinExec("CREATE TABLE IF NOT EXISTS Experiments (run, experiment, "
73  "strategy, input, description text)");
74  NS_ASSERT(res);
75 
76  sqlite3_stmt* stmt;
77  res = m_sqliteOut->WaitPrepare(&stmt,
78  "INSERT INTO Experiments "
79  "(run, experiment, strategy, input, description)"
80  "values (?, ?, ?, ?, ?)");
81  NS_ASSERT(res);
82 
83  // Create temporary strings to hold their value
84  // throughout the lifetime of the Bind and Step
85  // procedures
86  //
87  // DataCollector could return const std::string&,
88  // but that could break the python bindings
89  res = m_sqliteOut->Bind(stmt, 1, run);
90  NS_ASSERT(res);
91  std::string experimentLabel = dc.GetExperimentLabel();
92  res = m_sqliteOut->Bind(stmt, 2, experimentLabel);
93  NS_ASSERT(res);
94  std::string strategyLabel = dc.GetStrategyLabel();
95  res = m_sqliteOut->Bind(stmt, 3, strategyLabel);
96  NS_ASSERT(res);
97  std::string inputLabel = dc.GetInputLabel();
98  res = m_sqliteOut->Bind(stmt, 4, inputLabel);
99  NS_ASSERT(res);
100  std::string description = dc.GetDescription();
101  res = m_sqliteOut->Bind(stmt, 5, description);
102  NS_ASSERT(res);
103 
104  res = m_sqliteOut->SpinStep(stmt);
105  NS_ASSERT(res);
106  res = m_sqliteOut->SpinFinalize(stmt);
107  NS_ASSERT(res == 0);
108 
109  res = m_sqliteOut->WaitExec("CREATE TABLE IF NOT EXISTS "
110  "Metadata ( run text, key text, value)");
111  NS_ASSERT(res);
112 
113  res = m_sqliteOut->WaitPrepare(&stmt,
114  "INSERT INTO Metadata "
115  "(run, key, value)"
116  "values (?, ?, ?)");
117  NS_ASSERT(res);
118 
119  for (MetadataList::iterator i = dc.MetadataBegin(); i != dc.MetadataEnd(); i++)
120  {
121  std::pair<std::string, std::string> blob = (*i);
122  m_sqliteOut->SpinReset(stmt);
123  m_sqliteOut->Bind(stmt, 1, run);
124  m_sqliteOut->Bind(stmt, 2, blob.first);
125  m_sqliteOut->Bind(stmt, 3, blob.second);
126  m_sqliteOut->SpinStep(stmt);
127  }
128 
129  m_sqliteOut->SpinFinalize(stmt);
130 
131  m_sqliteOut->SpinExec("BEGIN");
132  SqliteOutputCallback callback(m_sqliteOut, run);
133  for (DataCalculatorList::iterator i = dc.DataCalculatorBegin(); i != dc.DataCalculatorEnd();
134  i++)
135  {
136  (*i)->Output(callback);
137  }
138  m_sqliteOut->SpinExec("COMMIT");
139  // end SqliteDataOutput::Output
140  m_sqliteOut->Unref();
141 }
142 
144  std::string run)
145  : m_db(db),
146  m_runLabel(run)
147 {
148  NS_LOG_FUNCTION(this << db << run);
149 
150  m_db->WaitExec("CREATE TABLE IF NOT EXISTS Singletons "
151  "( run text, name text, variable text, value )");
152 
153  m_db->WaitPrepare(&m_insertSingletonStatement,
154  "INSERT INTO Singletons "
155  "(run, name, variable, value)"
156  "values (?, ?, ?, ?)");
158 }
159 
161 {
162  m_db->SpinFinalize(m_insertSingletonStatement);
163 }
164 
165 void
167  std::string variable,
168  const StatisticalSummary* statSum)
169 {
170  NS_LOG_FUNCTION(this << key << variable << statSum);
171 
172  OutputSingleton(key, variable + "-count", static_cast<double>(statSum->getCount()));
173  if (!isNaN(statSum->getSum()))
174  {
175  OutputSingleton(key, variable + "-total", statSum->getSum());
176  }
177  if (!isNaN(statSum->getMax()))
178  {
179  OutputSingleton(key, variable + "-max", statSum->getMax());
180  }
181  if (!isNaN(statSum->getMin()))
182  {
183  OutputSingleton(key, variable + "-min", statSum->getMin());
184  }
185  if (!isNaN(statSum->getSqrSum()))
186  {
187  OutputSingleton(key, variable + "-sqrsum", statSum->getSqrSum());
188  }
189  if (!isNaN(statSum->getStddev()))
190  {
191  OutputSingleton(key, variable + "-stddev", statSum->getStddev());
192  }
193 }
194 
195 void
197  std::string variable,
198  int val)
199 {
200  NS_LOG_FUNCTION(this << key << variable << val);
201 
202  m_db->SpinReset(m_insertSingletonStatement);
203  m_db->Bind(m_insertSingletonStatement, 2, key);
204  m_db->Bind(m_insertSingletonStatement, 3, variable);
205  m_db->Bind(m_insertSingletonStatement, 4, val);
206  m_db->SpinStep(m_insertSingletonStatement);
207 }
208 
209 void
211  std::string variable,
212  uint32_t val)
213 {
214  NS_LOG_FUNCTION(this << key << variable << val);
215 
216  m_db->SpinReset(m_insertSingletonStatement);
217  m_db->Bind(m_insertSingletonStatement, 2, key);
218  m_db->Bind(m_insertSingletonStatement, 3, variable);
219  m_db->Bind(m_insertSingletonStatement, 4, val);
220  m_db->SpinStep(m_insertSingletonStatement);
221 }
222 
223 void
225  std::string variable,
226  double val)
227 {
228  NS_LOG_FUNCTION(this << key << variable << val);
229 
230  m_db->SpinReset(m_insertSingletonStatement);
231  m_db->Bind(m_insertSingletonStatement, 2, key);
232  m_db->Bind(m_insertSingletonStatement, 3, variable);
233  m_db->Bind(m_insertSingletonStatement, 4, val);
234  m_db->SpinStep(m_insertSingletonStatement);
235 }
236 
237 void
239  std::string variable,
240  std::string val)
241 {
242  NS_LOG_FUNCTION(this << key << variable << val);
243 
244  m_db->SpinReset(m_insertSingletonStatement);
245  m_db->Bind(m_insertSingletonStatement, 2, key);
246  m_db->Bind(m_insertSingletonStatement, 3, variable);
247  m_db->Bind(m_insertSingletonStatement, 4, val);
248  m_db->SpinStep(m_insertSingletonStatement);
249 }
250 
251 void
253  std::string variable,
254  Time val)
255 {
256  NS_LOG_FUNCTION(this << key << variable << val);
257 
258  m_db->SpinReset(m_insertSingletonStatement);
259  m_db->Bind(m_insertSingletonStatement, 2, key);
260  m_db->Bind(m_insertSingletonStatement, 3, variable);
261  m_db->Bind(m_insertSingletonStatement, 4, val.GetTimeStep());
262  m_db->SpinStep(m_insertSingletonStatement);
263 }
264 
265 } // namespace ns3
Collects data.
std::string GetExperimentLabel() const
Return the experiment label.
DataCalculatorList::iterator DataCalculatorBegin()
Returns an iterator to the beginning of the DataCalculator list.
DataCalculatorList::iterator DataCalculatorEnd()
Returns an iterator to the past-the-end of the DataCalculator list.
std::string GetDescription() const
Return the description label.
MetadataList::iterator MetadataBegin()
Returns an iterator to the beginning of the metadata list.
MetadataList::iterator MetadataEnd()
Returns an iterator to the past-the-end of the metadata list.
std::string GetStrategyLabel() const
Return the strategy label.
std::string GetRunLabel() const
Return the runID label.
std::string GetInputLabel() const
Return the input label.
Abstract Data Output Interface class s.
std::string m_filePrefix
File prefix for the DataOutputInterface.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
A C++ interface towards an SQLITE database.
Definition: sqlite-output.h:47
void OutputStatistic(std::string key, std::string variable, const StatisticalSummary *statSum) override
Generates data statistics.
sqlite3_stmt * m_insertSingletonStatement
Pointer to a Sqlite3 singleton statement.
SqliteOutputCallback(const Ptr< SQLiteOutput > &db, std::string run)
Constructor.
void OutputSingleton(std::string key, std::string variable, int val) override
Generates a single data output.
Outputs data in a format compatible with SQLite.
void Output(DataCollector &dc) override
Outputs information from the provided DataCollector.
static TypeId GetTypeId()
Register this type.
Ptr< SQLiteOutput > m_sqliteOut
Database.
Abstract class for calculating statistical data.
virtual double getMax() const =0
Returns the maximum of the values.
virtual double getStddev() const =0
Returns the standard deviation of the (weighted) observations.
virtual long getCount() const =0
Returns the number of observations.
virtual double getMin() const =0
Returns the minimum of the values.
virtual double getSum() const =0
virtual double getSqrSum() const =0
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:444
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool isNaN(double x)
true if x is NaN