MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CrundDriver.java
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 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 package com.mysql.cluster.crund;
21 
22 import java.util.ArrayList;
23 import java.util.EnumSet;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 
47 abstract public class CrundDriver extends Driver {
48 
49  enum XMode { INDY, EACH, BULK }
50 
51  // benchmark settings
52  protected final EnumSet< XMode > xMode = EnumSet.noneOf(XMode.class);
53  protected boolean renewConnection;
54  protected boolean renewOperations;
55  protected boolean logSumOfOps;
56  protected boolean allowExtendedPC;
57  protected int nOpsStart;
58  protected int nOpsEnd;
59  protected int nOpsScale;
60  protected int maxVarbinaryBytes;
61  protected int maxVarcharChars;
62  protected int maxBlobBytes;
63  protected int maxTextChars;
64  protected final Set<String> exclude = new HashSet<String>();
65  protected final Set<String> include = new HashSet<String>();
66 
67  // the name of the test currently being performed
68  protected String operationName;
69 
71  protected StringBuilder errorBuffer;
72 
74  protected boolean failOnError;
75 
76  // ----------------------------------------------------------------------
77  // benchmark intializers/finalizers
78  // ----------------------------------------------------------------------
79 
80  protected void init() throws Exception {
81  out.println();
82  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
83  out.println("initializing benchmark ...");
84  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
85  super.init();
86 
87 /*
88  // XXX support multiple load instances
89  // initialize load classes
90  if (doJdbc) {
91  assert (jdbcLoad == null);
92  jdbcLoad = new JdbcLoad(this);
93  jdbcLoad.init();
94  }
95  if (doClusterj) {
96  assert (clusterjLoad == null);
97  clusterjLoad = new ClusterjLoad(this);
98  clusterjLoad.init();
99  }
100  if (doNdbjtie) {
101  assert (ndbjtieLoad == null);
102  ndbjtieLoad = new NdbjtieLoad(this);
103  ndbjtieLoad.init();
104  }
105 */
106  initLoad();
107  }
108 
109  protected void close() throws Exception {
110  out.println();
111  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
112  out.println("closing benchmark ...");
113  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
114 
115 /*
116  // XXX support multiple load instances
117  // close load classes
118  if (doJdbc) {
119  assert (jdbcLoad != null);
120  jdbcLoad.close();
121  jdbcLoad = null;
122  }
123  if (doClusterj) {
124  assert (clusterjLoad != null);
125  clusterjLoad.close();
126  clusterjLoad = null;
127  }
128  if (doNdbjtie) {
129  assert (ndbjtieLoad != null);
130  ndbjtieLoad.close();
131  ndbjtieLoad = null;
132  }
133 */
134  closeLoad();
135 
136  super.close();
137  }
138 
139  protected void initProperties() {
140  super.initProperties();
141 
142  out.print("setting crund properties ...");
143 
144  final StringBuilder msg = new StringBuilder();
145  final String eol = System.getProperty("line.separator");
146 
147  // parse execution modes
148  final String[] xm = props.getProperty("xMode", "").split(",");
149  for (int i = 0; i < xm.length; i++) {
150  if (!"".equals(xm[i]))
151  xMode.add(XMode.valueOf(XMode.class, xm[i]));
152  }
153 
154  renewConnection = parseBoolean("renewConnection", false);
155  renewOperations = parseBoolean("renewOperations", false);
156  logSumOfOps = parseBoolean("logSumOfOps", true);
157  allowExtendedPC = parseBoolean("allowExtendedPC", false);
158  failOnError = parseBoolean("failOnError", false);
159 
160  nOpsStart = parseInt("nOpsStart", 256);
161  if (nOpsStart < 1) {
162  msg.append("[ignored] nOpsStart: " + nOpsStart + eol);
163  nOpsStart = 256;
164  }
165  nOpsEnd = parseInt("nOpsEnd", nOpsStart);
166  if (nOpsEnd < nOpsStart) {
167  msg.append("[ignored] nOpsEnd: "+ nOpsEnd + eol);
168  nOpsEnd = nOpsStart;
169  }
170  nOpsScale = parseInt("nOpsScale", 2);
171  if (nOpsScale < 2) {
172  msg.append("[ignored] nOpsScale: " + nOpsScale + eol);
173  nOpsScale = 2;
174  }
175 
176  maxVarbinaryBytes = parseInt("maxVarbinaryBytes", 100);
177  if (maxVarbinaryBytes < 0) {
178  msg.append("[ignored] maxVarbinaryBytes: "
179  + maxVarbinaryBytes + eol);
180  maxVarbinaryBytes = 100;
181  }
182  maxVarcharChars = parseInt("maxVarcharChars", 100);
183  if (maxVarcharChars < 0) {
184  msg.append("[ignored] maxVarcharChars: "
185  + maxVarcharChars + eol);
186  maxVarcharChars = 100;
187  }
188 
189  maxBlobBytes = parseInt("maxBlobBytes", 1000);
190  if (maxBlobBytes < 0) {
191  msg.append("[ignored] maxBlobBytes: "
192  + maxBlobBytes + eol);
193  maxBlobBytes = 1000;
194  }
195  maxTextChars = parseInt("maxTextChars", 1000);
196  if (maxTextChars < 0) {
197  msg.append("[ignored] maxTextChars: "
198  + maxTextChars + eol);
199  maxTextChars = 1000;
200  }
201 
202  // initialize exclude set
203  final String[] excludeProperty = props.getProperty("exclude", "").split(",");
204  for (int i = 0; i < excludeProperty.length; i++) {
205  String excludeTest = excludeProperty[i];
206  if (!excludeTest.isEmpty()) {
207  exclude.add(excludeTest);
208  }
209  }
210 
211  // initialize include set
212  final String[] includeProperty = props.getProperty("include", "").split(",");
213  for (int i = 0; i < includeProperty.length; ++i) {
214  String includeTest = includeProperty[i];
215  if (!includeTest.isEmpty()) {
216  include.add(includeTest);
217  }
218  }
219 
220  if (msg.length() == 0) {
221  out.println(" [ok: "
222  + "nOps=" + nOpsStart + ".." + nOpsEnd + "]");
223  } else {
224  out.println();
225  out.print(msg.toString());
226  }
227  }
228 
229  protected void printProperties() {
230  super.printProperties();
231 
232  out.println();
233  out.println("crund settings ...");
234  out.println("xMode: " + xMode);
235  out.println("renewConnection: " + renewConnection);
236  out.println("renewOperations: " + renewOperations);
237  out.println("logSumOfOps: " + logSumOfOps);
238  out.println("allowExtendedPC: " + allowExtendedPC);
239  out.println("nOpsStart: " + nOpsStart);
240  out.println("nOpsEnd: " + nOpsEnd);
241  out.println("nOpsScale: " + nOpsScale);
242  out.println("maxVarbinaryBytes: " + maxVarbinaryBytes);
243  out.println("maxVarcharChars: " + maxVarcharChars);
244  out.println("maxBlobBytes: " + maxBlobBytes);
245  out.println("maxTextChars: " + maxTextChars);
246  out.println("exclude: " + exclude);
247  out.println("include: " + include);
248  }
249 
250  // ----------------------------------------------------------------------
251  // benchmark operations
252  // ----------------------------------------------------------------------
253 
254  // XXX move to generic load class
255  // a database operation to be benchmarked
256  protected abstract class Op {
257  final protected String name;
258 
259  public Op(String name) { this.name = name; }
260 
261  public String getName() { return name; }
262 
263  public abstract void run(int nOps) throws Exception;
264  };
265 
266  // XXX move to generic load class
267  // the list of database operations to be benchmarked
268  protected final List<Op> ops = new ArrayList<Op>();
269 
270  // manages list of database operations
271  abstract protected void initOperations() throws Exception;
272  abstract protected void closeOperations() throws Exception;
273 
274  protected void runTests() throws Exception {
275  initConnections();
276  runLoads();
277  closeConnections();
278  }
279 
280  protected void runLoads() throws Exception {
281 /*
282  // XXX support multiple load instances
283  if (doJdbc)
284  runLoads(jdbcLoad);
285  if (doClusterj)
286  runLoads(clusterjLoad);
287  if (doNdbjtie)
288  runLoads(ndbjtieLoad);
289 */
290  runLoad();
291  }
292 
293  protected void runLoad() throws Exception {
294  assert (nOpsStart <= nOpsEnd && nOpsScale > 1);
295  for (int i = nOpsStart; i <= nOpsEnd; i *= nOpsScale) {
296  try {
297  out.println();
298  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
299  // XXX support multiple load instances
300  //out.print("running load nOps = " + i + " on "
301  // + load.getDescriptor());
302  out.println("running load [" + i + " nOps] on " + descr);
303  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
304  runSeries(i);
305  } catch (Exception ex) {
306  // already in rollback for database/orm exceptions
307  throw ex;
308  }
309  }
310  }
311 
312  protected void runSeries(int nOps) throws Exception {
313  if (nRuns == 0)
314  return; // nothing to do
315 
316  for (int i = 1; i <= nRuns; i++) {
317  out.println();
318  out.println("------------------------------------------------------------");
319  out.println("run " + i + " of " + nRuns + " [" + nOps + " nOps]");
320  out.println("------------------------------------------------------------");
321  // XXX runLoad(load);
322  runLoad(nOps);
323  }
324 
325  // XXX support multiple load instances
326  //writeLogBuffers(load.getDescriptor());
327  writeLogBuffers(descr);
328  clearLogBuffers();
329  }
330 
331  protected void runLoad(int nOps) throws Exception {
332  // log buffers
333  if (logRealTime) {
334  rtimes.append(nOps);
335  ta = 0;
336  }
337  if (logMemUsage) {
338  musage.append(nOps);
339  ma = 0;
340  }
341 
342  // pre-run cleanup
343  if (renewConnection) {
344  // XXX move to generic load class?
345  closeOperations();
346  closeConnection();
347  initConnection();
348  initOperations();
349  } else if (renewOperations) {
350  closeOperations();
351  initOperations();
352  }
353  clearData();
354 
355  runSequence(nOps);
356 
357  if (logSumOfOps) {
358  out.println();
359  out.println("total");
360  if (logRealTime) {
361  out.println("tx real time " + ta
362  + "\tms");
363  }
364  if (logMemUsage) {
365  out.println("net mem usage "
366  + (ma >= 0 ? "+" : "") + ma
367  + "\tKiB");
368  }
369  }
370 
371  // log buffers
372  if (logHeader) {
373  if (logSumOfOps) {
374  header.append("\ttotal");
375  }
376  logHeader = false;
377  }
378  if (logRealTime) {
379  if (logSumOfOps) {
380  rtimes.append("\t" + ta);
381  }
382  rtimes.append(endl);
383  }
384  if (logMemUsage) {
385  if (logSumOfOps) {
386  musage.append("\t" + ma);
387  }
388  musage.append(endl);
389  }
390  }
391 
392  // XXX move to generic load class
393  protected void runSequence(int nOps) throws Exception {
394  for (Op op : ops) {
395  // pre-tx cleanup
396  if (!allowExtendedPC) {
397  // effectively prevent caching beyond Tx scope by clearing
398  // any data/result caches before the next transaction
399  clearPersistenceContext();
400  }
401  runOperation(op, nOps);
402  reportErrors();
403  }
404  }
405 
406  // XXX move to generic load class
407  protected void runOperation(Op op, int nOps) throws Exception {
408  operationName = op.getName();
409  // if there is an include list and this test is included, or
410  // there is not an include list and this test is not excluded
411  if ((include.size() != 0 && include.contains(operationName))
412  || (include.size() == 0 && !exclude.contains(operationName))) {
413  begin(operationName);
414  op.run(nOps);
415  finish(operationName);
416  }
417  }
418 
420  protected void appendError(String where) {
421  if (errorBuffer == null) {
422  errorBuffer = new StringBuilder();
423  }
424  errorBuffer.append("Error in operation ");
425  errorBuffer.append(operationName);
426  errorBuffer.append(": ");
427  errorBuffer.append(where);
428  errorBuffer.append('\n');
429  }
430 
432  protected void reportErrors() {
433  if (errorBuffer != null) {
434  if (failOnError) {
435  throw new RuntimeException(errorBuffer.toString());
436  }
437  System.out.println(errorBuffer.toString());
438  errorBuffer = null;
439  }
440  }
441  // XXX move to generic load class
442  // reports an error if a condition is not met
443  static protected final void verify(boolean cond) {
444  //assert (cond);
445  if (!cond)
446  throw new RuntimeException("data verification failed.");
447  }
448 
449  // XXX move to generic load class
450  static protected final void verify(int exp, int act) {
451  if (exp != act)
452  throw new RuntimeException("data verification failed:"
453  + " expected = " + exp
454  + ", actual = " + act);
455  }
456 
457  // XXX move to generic load class
458  protected final void verify(String where, int exp, int act) {
459  if (exp != act)
460  appendError(" data verification failed:"
461  + " expected = " + exp
462  + ", actual = " + act);
463  }
464 
465  // XXX move to generic load class
466  static protected final void verify(String exp, String act) {
467  if ((exp == null && act != null)
468  || (exp != null && !exp.equals(act)))
469  throw new RuntimeException("data verification failed:"
470  + " expected = '" + exp + "'"
471  + ", actual = '" + act + "'");
472  }
473 
474  // ----------------------------------------------------------------------
475  // helpers
476  // ----------------------------------------------------------------------
477 
478  // XXX move to generic load class
479  static final protected String myString(int n) {
480  final StringBuilder s = new StringBuilder();
481  switch (n) {
482  case 1:
483  s.append('i');
484  break;
485  case 2:
486  for (int i = 0; i < 10; i++) s.append('x');
487  break;
488  case 3:
489  for (int i = 0; i < 100; i++) s.append('c');
490  break;
491  case 4:
492  for (int i = 0; i < 1000; i++) s.append('m');
493  break;
494  case 5:
495  for (int i = 0; i < 10000; i++) s.append('X');
496  break;
497  case 6:
498  for (int i = 0; i < 100000; i++) s.append('C');
499  break;
500  case 7:
501  for (int i = 0; i < 1000000; i++) s.append('M');
502  break;
503  default:
504  throw new IllegalArgumentException("unsupported 10**n = " + n);
505  }
506  return s.toString();
507  }
508 
509  // XXX move to generic load class
510  static final protected byte[] myBytes(String s) {
511  final char[] c = s.toCharArray();
512  final int n = c.length;
513  final byte[] b = new byte[n];
514  for (int i = 0; i < n; i++) b[i] = (byte)c[i];
515  return b;
516  }
517 
518  // XXX move to generic load class
519  // some string and byte constants
520  static final protected String string1 = myString(1);
521  static final protected String string2 = myString(2);
522  static final protected String string3 = myString(3);
523  static final protected String string4 = myString(4);
524  static final protected String string5 = myString(5);
525  static final protected String string6 = myString(6);
526  static final protected String string7 = myString(7);
527  static final protected byte[] bytes1 = myBytes(string1);
528  static final protected byte[] bytes2 = myBytes(string2);
529  static final protected byte[] bytes3 = myBytes(string3);
530  static final protected byte[] bytes4 = myBytes(string4);
531  static final protected byte[] bytes5 = myBytes(string5);
532  static final protected byte[] bytes6 = myBytes(string6);
533  static final protected byte[] bytes7 = myBytes(string7);
534  static final protected String[] strings
535  = { string1, string2, string3, string4, string5, string6, string7 };
536  static final protected byte[][] bytes
537  = { bytes1, bytes2, bytes3, bytes4, bytes5, bytes6, bytes7 };
538 
539  // ----------------------------------------------------------------------
540  // datastore operations
541  // ----------------------------------------------------------------------
542 
543  protected void initConnections() throws Exception {
544  out.println();
545  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
546  out.println("initializing connections ...");
547  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
548 
549 /*
550  // XXX support multiple load instances
551  if (doJdbc) {
552  assert (jdbcLoad != null);
553  jdbcLoad.initConnection();
554  }
555  if (doClusterj) {
556  assert (clusterjLoad != null);
557  clusterjLoad.initConnection();
558  }
559  if (doNdbjtie) {
560  assert (ndbjtieLoad != null);
561  ndbjtieLoad.initConnection();
562  }
563 */
564  initConnection();
565 
566  // XXX move to generic load class
567  initOperations();
568  }
569 
570  protected void closeConnections() throws Exception {
571  out.println();
572  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
573  out.println("closing connections ...");
574  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
575 
576  // XXX move to generic load class
577  closeOperations();
578 
579  closeConnection();
580 /*
581  // XXX support multiple load instances
582  if (doJdbc) {
583  assert (jdbcLoad != null);
584  jdbcLoad.closeConnection();
585  }
586  if (doClusterj) {
587  assert (clusterjLoad != null);
588  clusterjLoad.closeConnection();
589  }
590  if (doNdbjtie) {
591  assert (ndbjtieLoad != null);
592  ndbjtieLoad.closeConnection();
593  }
594 */
595  }
596 
597  abstract protected void initLoad() throws Exception;
598  abstract protected void closeLoad() throws Exception;
599  abstract protected void initConnection() throws Exception;
600  abstract protected void closeConnection() throws Exception;
601  abstract protected void clearPersistenceContext() throws Exception;
602  abstract protected void clearData() throws Exception;
603 }