MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Driver.cpp
1 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
3  *
4  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include "Driver.hpp"
21 
22 #include <cassert>
23 
24 #include "helpers.hpp"
25 #include "string_helpers.hpp"
26 
27 using std::cout;
28 using std::flush;
29 using std::endl;
30 using std::ios_base;
31 using std::string;
32 using std::vector;
33 
34 using utils::Properties;
35 using utils::toBool;
36 using utils::toInt;
37 using utils::toString;
38 
39 // ---------------------------------------------------------------------------
40 // Helper Macros & Functions
41 // ---------------------------------------------------------------------------
42 
43 #define ABORT_GETTIMEOFDAY_ERROR() \
44  do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
45  << ", gettimeofday() returned an error code." << endl; \
46  exit(-1); \
47  } while (0)
48 
49 // ---------------------------------------------------------------------------
50 // Driver Implementation
51 // ---------------------------------------------------------------------------
52 
53 vector< string > Driver::propFileNames;
54 string Driver::logFileName;
55 
56 void
57 Driver::exitUsage()
58 {
59  cout << "usage: [options]" << endl
60  << " [-p <file name>]... properties file name" << endl
61  << " [-l <file name>] log file name for data output" << endl
62  << " [-h|--help] print usage message and exit" << endl
63  << endl;
64  exit(1); // return an error code
65 }
66 
67 void
68 Driver::parseArguments(int argc, const char* argv[])
69 {
70  for (int i = 1; i < argc; i++) {
71  const string arg = argv[i];
72  if (arg.compare("-p") == 0) {
73  if (i >= argc) {
74  exitUsage();
75  }
76  propFileNames.push_back(argv[++i]);
77  } else if (arg.compare("-l") == 0) {
78  if (i >= argc) {
79  exitUsage();
80  }
81  logFileName = argv[++i];
82  } else if (arg.compare("-h") == 0 || arg.compare("--help") == 0) {
83  exitUsage();
84  } else {
85  cout << "unknown option: " << arg << endl;
86  exitUsage();
87  }
88  }
89 
90  if (propFileNames.size() == 0) {
91  propFileNames.push_back("run.properties");
92  }
93 
94  if (logFileName.empty()) {
95  logFileName = "log_";
96 
97  // format, destination strings (static size)
98  const char format[] = "%Y%m%d_%H%M%S";
99  const int size = sizeof("yyyymmdd_HHMMSS");
100  char dest[size];
101 
102  // get time, convert to timeinfo (statically allocated) then to string
103  const time_t now = time(0);
104  const int nchars = strftime(dest, size, format, localtime(&now));
105  assert(nchars == size-1);
106  (void)nchars;
107 
108  logFileName += dest;
109  logFileName += ".txt";
110  }
111  //cout << "logFileName='" << logFileName << "'" << endl;
112 }
113 
114 // ----------------------------------------------------------------------
115 
116 void
117 Driver::run() {
118  init();
119 
120  if (warmupRuns > 0) {
121  cout << endl
122  << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
123  << "warmup runs ..." << endl
124  << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
125 
126  for (int i = 0; i < warmupRuns; i++) {
127  runTests();
128  }
129 
130  // truncate log file, reset log buffers
131  closeLogFile();
132  openLogFile();
133  clearLogBuffers();
134  }
135 
136  cout << endl
137  << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
138  << "hot runs ..." << endl
139  << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
140  runTests();
141 
142  cout << endl
143  << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
144  close();
145 }
146 
147 void
148 Driver::init() {
149  loadProperties();
150  initProperties();
151  printProperties();
152  openLogFile();
153  clearLogBuffers();
154 }
155 
156 void
157 Driver::close() {
158  clearLogBuffers();
159  closeLogFile();
160 }
161 
162 void
163 Driver::loadProperties() {
164  cout << endl;
165  for (vector<string>::const_iterator i = propFileNames.begin();
166  i != propFileNames.end(); ++i) {
167  cout << "reading properties file: " << *i << endl;
168  props.load(i->c_str());
169  //cout << "props = {" << endl << props << "}" << endl;
170  }
171 }
172 
173 void
174 Driver::initProperties() {
175  cout << "setting driver properties ..." << flush;
176 
177  ostringstream msg;
178 
179  warmupRuns = toInt(props[L"warmupRuns"], 0, -1);
180  if (warmupRuns < 0) {
181  msg << "[ignored] warmupRuns: '"
182  << toString(props[L"warmupRuns"]) << "'" << endl;
183  warmupRuns = 0;
184  }
185 
186  //if (msg.tellp() == 0) // netbeans reports amibuities
187  if (msg.str().empty()) {
188  cout << " [ok]" << endl;
189  } else {
190  cout << endl << msg.str() << endl;
191  }
192 }
193 
194 void
195 Driver::printProperties() {
196  const ios_base::fmtflags f = cout.flags();
197  // no effect calling manipulator function, not sure why
198  //cout << ios_base::boolalpha;
199  cout.flags(ios_base::boolalpha);
200 
201  cout << endl << "driver settings ..." << endl;
202  cout << "warmupRuns: " << warmupRuns << endl;
203 
204  cout.flags(f);
205 }
206 
207 void
208 Driver::openLogFile() {
209  cout << endl
210  << "opening results file:" << flush;
211  log.open(logFileName.c_str(), ios_base::out | ios_base::trunc);
212  assert(log.good());
213  cout << " [ok: " << logFileName << "]" << endl;
214 }
215 
216 void
217 Driver::closeLogFile() {
218  cout << endl
219  << "closing results file:" << flush;
220  log.close();
221  cout << " [ok: " << logFileName << "]" << endl;
222 }
223 
224 // ---------------------------------------------------------------------------
225 
226 void
227 Driver::clearLogBuffers() {
228  logHeader = true;
229  header.rdbuf()->str("");
230  rtimes.rdbuf()->str("");
231 }
232 
233 void
234 Driver::writeLogBuffers() {
235  log << descr << ", rtime[ms]"
236  << header.rdbuf()->str() << endl
237  << rtimes.rdbuf()->str() << endl;
238 }
239 
240 void
241 Driver::begin(const string& name) {
242  cout << endl;
243  cout << name << endl;
244 
245  if (gettimeofday(&t0, NULL) != 0)
246  ABORT_GETTIMEOFDAY_ERROR();
247 }
248 
249 void
250 Driver::finish(const string& name) {
251  if (gettimeofday(&t1, NULL) != 0)
252  ABORT_GETTIMEOFDAY_ERROR();
253 
254  const long r_usec = (((t1.tv_sec - t0.tv_sec) * 1000000)
255  + (t1.tv_usec - t0.tv_usec));
256  const long r_msec = r_usec / 1000;
257 
258  cout << "tx real time: " << r_msec
259  << "\tms" << endl;
260  rtimes << "\t" << r_msec;
261  rta += r_msec;
262 
263  if (logHeader)
264  header << "\t" << name;
265 }
266 
267 //---------------------------------------------------------------------------