1 /* -*- mode: java; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  *  vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
3  *
4  *  Copyright (c) 2010, 2011, 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, version 2.0,
8  *  as published by the Free Software Foundation.
9  *
10  *  This program is also distributed with certain software (including
11  *  but not limited to OpenSSL) that is licensed under separate terms,
12  *  as designated in a particular file or component or in included license
13  *  documentation.  The authors of MySQL hereby grant you an additional
14  *  permission to link the program and your derivative works with the
15  *  separately licensed software that they have included with MySQL.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License, version 2.0, for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25  */
26 
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30 #include <cassert>
31 
32 #include "helpers.hpp"
33 #include "string_helpers.hpp"
34 
35 #include "CrundDriver.hpp"
36 
37 using std::cout;
38 using std::flush;
39 using std::endl;
40 using std::ios_base;
41 using std::ostringstream;
42 using std::string;
43 using std::wstring;
44 
45 using utils::toBool;
46 using utils::toInt;
47 using utils::toString;
48 
49 // ----------------------------------------------------------------------
50 
51 void
init()52 CrundDriver::init() {
53     Driver::init();
54     // do work here
55 }
56 
57 void
close()58 CrundDriver::close() {
59     // do work here
60     Driver::close();
61 }
62 
63 void
initProperties()64 CrundDriver::initProperties() {
65     Driver::initProperties();
66 
67     cout << "setting crund properties ..." << flush;
68 
69     ostringstream msg;
70 
71     renewConnection = toBool(props[L"renewConnection"], false);
72     renewOperations = toBool(props[L"renewOperations"], false);
73 
74     string lm = toString(props[L"lockMode"]);
75     if (lm.empty()) {
76         lockMode = READ_COMMITTED;
77     } else if (lm.compare("READ_COMMITTED") == 0) {
78         lockMode = READ_COMMITTED;
79     } else if (lm.compare("SHARED") == 0) {
80         lockMode = SHARED;
81     } else if (lm.compare("EXCLUSIVE") == 0) {
82         lockMode = EXCLUSIVE;
83     } else {
84         msg << "[ignored] lockMode:         '" << lm << "'" << endl;
85         lockMode = READ_COMMITTED;
86     }
87 
88     logSumOfOps = toBool(props[L"logSumOfOps"], true);
89     //allowExtendedPC = toBool(props[L"allowExtendedPC"], false); // not used
90 
91     nOpsStart = toInt(props[L"nOpsStart"], 256, 0);
92     if (nOpsStart < 1) {
93         msg << "[ignored] nOpsStart:            '"
94             << toString(props[L"nOpsStart"]) << "'" << endl;
95         nOpsStart = 256;
96     }
97     nOpsEnd = toInt(props[L"nOpsEnd"], nOpsStart, 0);
98     if (nOpsEnd < nOpsStart) {
99         msg << "[ignored] nOpsEnd:              '"
100             << toString(props[L"nOpsEnd"]) << "'" << endl;
101         nOpsEnd = nOpsStart;
102     }
103     nOpsScale = toInt(props[L"nOpsScale"], 2, 0);
104     if (nOpsScale < 2) {
105         msg << "[ignored] nOpsScale:            '"
106             << toString(props[L"nOpsScale"]) << "'" << endl;
107         nOpsScale = 2;
108     }
109 
110     maxVarbinaryBytes = toInt(props[L"maxVarbinaryBytes"], 100, 0);
111     if (maxVarbinaryBytes < 1) {
112         msg << "[ignored] maxVarbinaryBytes:    '"
113             << toString(props[L"maxVarbinaryBytes"]) << "'" << endl;
114         maxVarbinaryBytes = 100;
115     }
116     maxVarcharChars = toInt(props[L"maxVarcharChars"], 100, 0);
117     if (maxVarcharChars < 1) {
118         msg << "[ignored] maxVarcharChars:      '"
119             << toString(props[L"maxVarcharChars"]) << "'" << endl;
120         maxVarcharChars = 100;
121     }
122 
123     maxBlobBytes = toInt(props[L"maxBlobBytes"], 1000, 0);
124     if (maxBlobBytes < 1) {
125         msg << "[ignored] maxBlobBytes:         '"
126             << toString(props[L"maxBlobBytes"]) << "'" << endl;
127         maxBlobBytes = 1000;
128     }
129     maxTextChars = toInt(props[L"maxTextChars"], 1000, 0);
130     if (maxTextChars < 1) {
131         msg << "[ignored] maxTextChars:         '"
132             << toString(props[L"maxTextChars"]) << "'" << endl;
133         maxTextChars = 1000;
134     }
135 
136     // initialize exclude set
137     const wstring& estr = props[L"exclude"];
138     //cout << "estr='" << toString(estr) << "'" << endl;
139     const size_t len = estr.length();
140     size_t beg = 0, next;
141     while (beg < len
142            && ((next = estr.find_first_of(L",", beg)) != wstring::npos)) {
143         // add substring if not empty
144         if (beg < next) {
145             const wstring& s = estr.substr(beg, next - beg);
146             exclude.insert(toString(s));
147         }
148         beg = next + 1;
149     }
150     // add last substring if any
151     if (beg < len) {
152         const wstring& s = estr.substr(beg, len - beg);
153         exclude.insert(toString(s));
154     }
155 
156     if (!msg.tellp()) {
157         cout << "    [ok: "
158              << "nOps=" << nOpsStart << ".." << nOpsEnd << "]" << endl;
159     } else {
160         cout << endl << msg.str() << endl;
161     }
162 }
163 
164 void
printProperties()165 CrundDriver::printProperties() {
166     Driver::printProperties();
167 
168     const ios_base::fmtflags f = cout.flags();
169     // no effect calling manipulator function, not sure why
170     //cout << ios_base::boolalpha;
171     cout.flags(ios_base::boolalpha);
172 
173     cout << endl << "crund settings ..." << endl;
174     cout << "renewConnection:                " << renewConnection << endl;
175     cout << "renewOperations:                " << renewOperations << endl;
176     cout << "lockMode:                       " << toStr(lockMode) << endl;
177     cout << "logSumOfOps:                    " << logSumOfOps << endl;
178     //cout << "allowExtendedPC:                " << allowExtendedPC << endl;
179     cout << "nOpsStart:                      " << nOpsStart << endl;
180     cout << "nOpsEnd:                        " << nOpsEnd << endl;
181     cout << "nOpsScale:                      " << nOpsScale << endl;
182     cout << "maxVarbinaryBytes:              " << maxVarbinaryBytes << endl;
183     cout << "maxVarcharChars:                " << maxVarcharChars << endl;
184     cout << "maxBlobBytes:                   " << maxBlobBytes << endl;
185     cout << "maxTextChars:                   " << maxTextChars << endl;
186     cout << "exclude:                        " << toString(exclude) << endl;
187 
188     cout.flags(f);
189 }
190 
191 // ----------------------------------------------------------------------
192 
193 void
runTests()194 CrundDriver::runTests() {
195     cout << endl;
196     initConnection();
197     initOperations();
198 
199     assert(nOpsStart <= nOpsEnd && nOpsScale > 1);
200     for (int i = nOpsStart; i <= nOpsEnd; i *= nOpsScale) {
201         runLoads(i);
202     }
203 
204     cout << endl
205          << "------------------------------------------------------------" << endl
206          << endl;
207     clearData();
208     closeOperations();
209     closeConnection();
210 }
211 
212 void
runLoads(int nOps)213 CrundDriver::runLoads(int nOps) {
214     cout << endl
215          << "------------------------------------------------------------" << endl;
216 
217     cout << "running operations ..."
218          << "          [nOps=" << nOps << "]" << endl;
219 
220     // log buffers
221     if (logRealTime) {
222         rtimes << nOps;
223         rta = 0L;
224     }
225     if (logCpuTime) {
226         ctimes << nOps;
227         cta = 0L;
228     }
229 
230     // pre-run cleanup
231     if (renewConnection) {
232         closeOperations();
233         closeConnection();
234         initConnection();
235         initOperations();
236     } else if (renewOperations) {
237         closeOperations();
238         initOperations();
239     }
240     clearData();
241 
242     runOperations(nOps);
243 
244     if (logSumOfOps) {
245         cout << endl
246              << "total" << endl;
247         if (logRealTime) {
248             cout << "tx real time                    " << rta
249                  << "\tms" << endl;
250         }
251         if (logSumOfOps) {
252             cout << "tx cpu time                     " << cta
253                  << "\tms" << endl;
254         }
255     }
256 
257     // log buffers
258     if (logHeader) {
259         if (logSumOfOps) {
260             header << "\ttotal";
261         }
262         logHeader = false;
263     }
264     if (logRealTime) {
265         if (logSumOfOps) {
266             rtimes << "\t" << rta;
267         }
268         rtimes << endl;
269     }
270     if (logCpuTime) {
271         if (logSumOfOps) {
272             ctimes << "\t" << cta;
273         }
274         ctimes << endl;
275     }
276 }
277 
278 void
runOperations(int nOps)279 CrundDriver::runOperations(int nOps) {
280     for (Operations::const_iterator i = operations.begin();
281          i != operations.end(); ++i) {
282         // no need for pre-tx cleanup with NDBAPI-based loads
283         //if (!allowExtendedPC) {
284         //    // effectively prevent caching beyond Tx scope by clearing
285         //    // any data/result caches before the next transaction
286         //    clearPersistenceContext();
287         //}
288         runOp(**i, nOps);
289     }
290 }
291 
292 void
runOp(const Op & op,int nOps)293 CrundDriver::runOp(const Op& op, int nOps) {
294     const string& name = op.name;
295     if (exclude.find(name) == exclude.end()) {
296         begin(name);
297         op.run(nOps);
298         commit(name);
299     }
300 }
301 
302 const char*
toStr(XMode mode)303 CrundDriver::toStr(XMode mode) {
304     switch (mode) {
305     case SINGLE:
306         return "single";
307     case BULK:
308         return "bulk";
309     case BATCH:
310         return "batch";
311     default:
312         assert(false);
313         return "<invalid value>";
314     };
315 }
316 
317 const char*
toStr(LockMode mode)318 CrundDriver::toStr(LockMode mode) {
319     switch (mode) {
320     case SINGLE:
321         return "read_committed";
322     case SHARED:
323         return "shared";
324     case EXCLUSIVE:
325         return "exclusive";
326     default:
327         assert(false);
328         return "<invalid value>";
329     };
330 }
331 
332 //---------------------------------------------------------------------------
333