MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hugoPkRead.cpp
1 /*
2  Copyright (C) 2003-2007 MySQL AB, 2008 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <ndb_global.h>
20 
21 #include <NdbOut.hpp>
22 
23 #include <NdbApi.hpp>
24 #include <NdbMain.h>
25 #include <NDBT.hpp>
26 #include <NDBT_Thread.hpp>
27 #include <NDBT_Stats.hpp>
28 #include <NdbSleep.h>
29 #include <getarg.h>
30 
31 #include <HugoTransactions.hpp>
32 
33 static NDBT_ThreadFunc hugoPkRead;
34 
35 struct ThrInput {
36  const NdbDictionary::Table* pTab;
37  int records;
38  int batch;
39  int stats;
40  int rand;
41 };
42 
43 struct ThrOutput {
44  NDBT_Stats latency;
45 };
46 
47 int main(int argc, const char** argv){
48  ndb_init();
49 
50  int _records = 0;
51  int _loops = 1;
52  int _threads = 1;
53  int _stats = 0;
54  int _abort = 0;
55  int _batch = 1;
56  const char* _tabname = NULL;
57  int _help = 0;
58  int _rand = 0;
59 
60  struct getargs args[] = {
61  { "aborts", 'a', arg_integer, &_abort, "percent of transactions that are aborted", "abort%" },
62  { "loops", 'l', arg_integer, &_loops, "number of times to run this program(0=infinite loop)", "loops" },
63  { "threads", 't', arg_integer, &_threads, "number of threads (default 1)", "threads" },
64  { "stats", 's', arg_flag, &_stats, "report latency per batch", "stats" },
65  { "batch", 'b', arg_integer, &_batch, "batch value(not 0)", "batch" },
66  { "records", 'r', arg_integer, &_records, "Number of records", "records" },
67  { "rand", 0, arg_flag, &_rand, "Read random records within range","rand"},
68  { "usage", '?', arg_flag, &_help, "Print help", "" }
69  };
70  int num_args = sizeof(args) / sizeof(args[0]);
71  int optind = 0;
72  char desc[] =
73  "tabname\n"\
74  "This program will read 'r' records from one table in Ndb. \n"\
75  "It will verify every column read by calculating the expected value.\n";
76 
77  if(getarg(args, num_args, argc, argv, &optind) ||
78  argv[optind] == NULL || _records == 0 || _batch == 0 || _help) {
79  arg_printusage(args, num_args, argv[0], desc);
80  return NDBT_ProgramExit(NDBT_WRONGARGS);
81  }
82  _tabname = argv[optind];
83 
84 
85  // Connect to Ndb
87  if(con.connect(12, 5, 1) != 0)
88  {
89  return NDBT_ProgramExit(NDBT_FAILED);
90  }
91 
92  Ndb MyNdb(&con, "TEST_DB" );
93 
94  if(MyNdb.init() != 0){
95  ERR(MyNdb.getNdbError());
96  return NDBT_ProgramExit(NDBT_FAILED);
97  }
98 
99  while(MyNdb.waitUntilReady() != 0)
100  ndbout << "Waiting for ndb to become ready..." << endl;
101 
102  // Check if table exists in db
103  const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
104  if(pTab == NULL){
105  ndbout << " Table " << _tabname << " does not exist!" << endl;
106  return NDBT_ProgramExit(NDBT_WRONGARGS);
107  }
108 
109  // threads
110  NDBT_ThreadSet ths(_threads);
111 
112  // create Ndb object for each thread
113  if (ths.connect(&con, "TEST_DB") == -1) {
114  ndbout << "connect failed: err=" << ths.get_err() << endl;
115  return NDBT_ProgramExit(NDBT_FAILED);
116  }
117 
118  // input is options
119  ThrInput input;
120  ths.set_input(&input);
121  input.pTab = pTab;
122  input.records = _records;
123  input.batch = _batch;
124  input.stats = _stats;
125  input.rand = _rand;
126 
127  // output is stats
128  ThrOutput output;
129  ths.set_output<ThrOutput>();
130 
131  int i = 0;
132  while (i < _loops || _loops == 0) {
133  ndbout << i << ": ";
134 
135  ths.set_func(hugoPkRead);
136  ths.start();
137  ths.stop();
138 
139  if (ths.get_err())
140  NDBT_ProgramExit(NDBT_FAILED);
141 
142  if (_stats) {
143  NDBT_Stats latency;
144 
145  // add stats from each thread
146  int n;
147  for (n = 0; n < ths.get_count(); n++) {
148  NDBT_Thread& thr = ths.get_thread(n);
149  ThrOutput* output = (ThrOutput*)thr.get_output();
150  latency += output->latency;
151  }
152 
153  ndbout
154  << "latency per batch (us): "
155  << " samples=" << latency.getCount()
156  << " min=" << (int)latency.getMin()
157  << " max=" << (int)latency.getMax()
158  << " mean=" << (int)latency.getMean()
159  << " stddev=" << (int)latency.getStddev()
160  << endl;
161  }
162  i++;
163  }
164 
165  return NDBT_ProgramExit(NDBT_OK);
166 }
167 
168 static void hugoPkRead(NDBT_Thread& thr)
169 {
170  const ThrInput* input = (const ThrInput*)thr.get_input();
171  ThrOutput* output = (ThrOutput*)thr.get_output();
172 
173  HugoTransactions hugoTrans(*input->pTab);
174  output->latency.reset();
175  if (input->stats)
176  hugoTrans.setStatsLatency(&output->latency);
177 
178  int ret;
179  ret = hugoTrans.pkReadRecords(thr.get_ndb(),
180  input->records,
181  input->batch,
183  input->rand);
184  if (ret != 0)
185  thr.set_err(ret);
186 }