MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndb_index_stat.cpp
1 /* Copyright (C) 2003 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 #include <ndb_global.h>
17 #include <ndb_opts.h>
18 
19 #include <NdbOut.hpp>
20 #include <NdbApi.hpp>
21 #include <NDBT.hpp>
22 #include <NdbIndexStatImpl.hpp>
23 #include <ndb_rand.h>
24 
25 // stats options
26 static const char* _dbname = 0;
27 static my_bool _delete = false;
28 static my_bool _update = false;
29 static my_bool _dump = false;
30 static int _query = 0;
31 static int _stats_any = 0;
32 // sys options
33 static my_bool _sys_drop = false;
34 static my_bool _sys_create = false;
35 static my_bool _sys_create_if_not_exist = false;
36 static my_bool _sys_create_if_not_valid = false;
37 static my_bool _sys_check = false;
38 static my_bool _sys_skip_tables = false;
39 static my_bool _sys_skip_events = false;
40 static int _sys_any = 0;
41 // other
42 static my_bool _verbose = false;
43 static int _loops = 1;
44 
45 static Ndb_cluster_connection* g_ncc = 0;
46 static Ndb* g_ndb = 0;
47 static Ndb* g_ndb_sys = 0;
48 static NdbDictionary::Dictionary* g_dic = 0;
49 static NdbIndexStat* g_is = 0;
50 
51 static const char* g_tabname = 0;
52 static const NdbDictionary::Table* g_tab = 0;
53 static int g_indcount = 0;
54 static const char** g_indnames = 0;
55 static const NdbDictionary::Index** g_indlist = 0;
56 // current index in loop
57 static const char* g_indname = 0;
58 static const NdbDictionary::Index* g_ind = 0;
59 
60 #define CHK1(b) \
61  if (!(b)) { \
62  ret = -1; \
63  break; \
64  }
65 
66 #define CHK2(b, e) \
67  if (!(b)) { \
68  g_err << "ERR: " << #b << " failed at line " << __LINE__ \
69  << ": " << e << endl; \
70  ret = -1; \
71  break; \
72  }
73 
74 static NdbError
75 getNdbError(Ndb_cluster_connection* ncc)
76 {
77  NdbError err;
78  err.code = g_ncc->get_latest_error();
79  err.message = g_ncc->get_latest_error_msg();
80  return err;
81 }
82 
83 static int
84 doconnect()
85 {
86  int ret = 0;
87  do
88  {
89  g_ncc = new Ndb_cluster_connection(opt_ndb_connectstring);
90  CHK2(g_ncc->connect(6, 5) == 0, getNdbError(g_ncc));
91  CHK2(g_ncc->wait_until_ready(30, 10) == 0, getNdbError(g_ncc));
92 
93  if (!_sys_any)
94  {
95  g_ndb = new Ndb(g_ncc, _dbname);
96  CHK2(g_ndb->init() == 0, g_ndb->getNdbError());
97  CHK2(g_ndb->waitUntilReady(30) == 0, g_ndb->getNdbError());
98  g_dic = g_ndb->getDictionary();
99  }
100 
101  g_ndb_sys = new Ndb(g_ncc, NDB_INDEX_STAT_DB);
102  CHK2(g_ndb_sys->init() == 0, g_ndb_sys->getNdbError());
103  CHK2(g_ndb_sys->waitUntilReady(30) == 0, g_ndb_sys->getNdbError());
104 
105  g_is = new NdbIndexStat;
106  g_info << "connected" << endl;
107  }
108  while (0);
109  return ret;
110 }
111 
112 static void
113 dodisconnect()
114 {
115  delete g_is;
116  delete g_ndb_sys;
117  delete g_ndb;
118  delete g_ncc;
119  g_info << "disconnected" << endl;
120 }
121 
122 static const char*
123 format(Uint64 us64, char* buf)
124 {
125  Uint32 ms = (Uint32)(us64 / (Uint64)1000);
126  Uint32 us = (Uint32)(us64 % (Uint64)1000);
127  sprintf(buf, "%u.%03u", ms, us);
128  return buf;
129 }
130 
131 static const char*
132 format(double x, char* buf)
133 {
134  sprintf(buf, "%.02f", x);
135  return buf;
136 }
137 
138 static void
139 show_head(const NdbIndexStat::Head& head)
140 {
141  setOutputLevel(2);
142  g_info << "table:" << g_tabname;
143  g_info << " index:" << g_indname;
144  g_info << " fragCount:" << head.m_fragCount;
145  g_info << endl;
146  g_info << "sampleVersion:" << head.m_sampleVersion;
147  g_info << " loadTime:" << head.m_loadTime;
148  g_info << " sampleCount:" << head.m_sampleCount;
149  g_info << " keyBytes:" << head.m_keyBytes;
150  g_info << endl;
151  setOutputLevel(_verbose ? 2 : 0);
152 }
153 
154 static void
155 show_cache_info(const char* name, const NdbIndexStat::CacheInfo& info)
156 {
157  Uint64 us64;
158  char buf[100];
159  setOutputLevel(2);
160  g_info << name << ":";
161  g_info << " valid:" << info.m_valid;
162  g_info << " sampleCount:" << info.m_sampleCount;
163  g_info << " totalBytes:" << info.m_totalBytes;
164  g_info << endl;
165  g_info << "times in ms:";
166  g_info << " save: " << format(info.m_save_time, buf);
167  g_info << " sort: " << format(info.m_sort_time, buf);
168  if (info.m_sampleCount != 0)
169  {
170  us64 = info.m_sort_time / (Uint64)info.m_sampleCount;
171  g_info << " sort per sample: " << format(us64, buf);
172  }
173  g_info << endl;
174  setOutputLevel(_verbose ? 2 : 0);
175 }
176 
177 static void
178 show_cache_entry(const NdbIndexStatImpl::CacheIter& iter)
179 {
180  setOutputLevel(2);
181  const NdbPack::DataC& key = iter.m_keyData;
182  const NdbPack::DataC& value = iter.m_valueData;
183  char buf[8000];
184  key.print(buf, sizeof(buf));
185  g_info << "key:" << buf << endl;
186  value.print(buf, sizeof(buf));
187  g_info << "value:" << buf << endl;
188  setOutputLevel(_verbose ? 2 : 0);
189 }
190 
191 static int
192 doquery()
193 {
194  int ret = 0;
195  char buf[100];
196 
197  Uint8 b_lo_buffer[NdbIndexStat::BoundBufferBytes];
198  Uint8 b_hi_buffer[NdbIndexStat::BoundBufferBytes];
199  NdbIndexStat::Bound b_lo(g_is, b_lo_buffer);
200  NdbIndexStat::Bound b_hi(g_is, b_hi_buffer);
201  do
202  {
203  NdbIndexStat::Range r(b_lo, b_hi);
204  Uint8 s_buffer[NdbIndexStat::StatBufferBytes];
205  NdbIndexStat::Stat s(s_buffer);
206 
207  for (int n = 0; n < _query; n++)
208  {
209  g_is->reset_range(r);
210  for (int i = 0; i <= 1; i++)
211  {
212  NdbIndexStat::Bound& b = (i == 0 ? b_lo : b_hi);
213 
214  bool strict = false;
215  if (ndb_rand() % 3 != 0)
216  {
217  if (ndb_rand() % 3 != 0)
218  {
219  Uint32 x = ndb_rand();
220  CHK2(g_is->add_bound(b, &x) == 0, g_is->getNdbError());
221  }
222  else
223  {
224  CHK2(g_is->add_bound_null(b) == 0, g_is->getNdbError());
225  }
226  bool strict = (ndb_rand() % 2 == 0);
227  g_is->set_bound_strict(b, strict);
228  }
229  }
230  CHK2(ret == 0, "failed");
231  CHK2(g_is->finalize_range(r) == 0, g_is->getNdbError());
232  CHK2(g_is->query_stat(r, s) == 0, g_is->getNdbError());
233  double rir = -1.0;
234  NdbIndexStat::get_rir(s, &rir);
235  g_info << "rir: " << format(rir, buf) << endl;
236  }
237  CHK2(ret == 0, "failed");
238  }
239  while (0);
240 
241  return ret;
242 }
243 
244 static int
245 dostats(int i)
246 {
247  int ret = 0;
248  do
249  {
250  g_indname = g_indnames[i];
251  g_ind = g_indlist[i];
252 
253  g_is->reset_index();
254  CHK2(g_is->set_index(*g_ind, *g_tab) == 0, g_is->getNdbError());
255 
256  if (_delete)
257  {
258  g_info << g_indname << ": delete stats" << endl;
259  if (ndb_rand() % 2 == 0)
260  {
261  CHK2(g_dic->deleteIndexStat(*g_ind, *g_tab) == 0, g_dic->getNdbError());
262  }
263  else
264  {
265  CHK2(g_is->delete_stat(g_ndb_sys) == 0, g_is->getNdbError());
266  }
267  }
268 
269  if (_update)
270  {
271  g_info << g_indname << ": update stats" << endl;
272  if (ndb_rand() % 2 == 0)
273  {
274  CHK2(g_dic->updateIndexStat(*g_ind, *g_tab) == 0, g_dic->getNdbError());
275  }
276  else
277  {
278  CHK2(g_is->update_stat(g_ndb_sys) == 0, g_is->getNdbError());
279  }
280  }
281 
282  NdbIndexStat::Head head;
283  g_is->read_head(g_ndb_sys);
284  g_is->get_head(head);
285  CHK2(head.m_found != -1, g_is->getNdbError());
286  if (head.m_found == false)
287  {
288  g_info << "no stats" << endl;
289  break;
290  }
291  show_head(head);
292 
293  g_info << "read stats" << endl;
294  CHK2(g_is->read_stat(g_ndb_sys) == 0, g_is->getNdbError());
295  g_is->move_cache();
296  g_is->clean_cache();
297  g_info << "query cache created" << endl;
298 
299  NdbIndexStat::CacheInfo infoQuery;
300  g_is->get_cache_info(infoQuery, NdbIndexStat::CacheQuery);
301  show_cache_info("query cache", infoQuery);
302 
303  if (_dump)
304  {
305  NdbIndexStatImpl& impl = g_is->getImpl();
306  NdbIndexStatImpl::CacheIter iter(impl);
307  CHK2(impl.dump_cache_start(iter) == 0, g_is->getNdbError());
308  while (impl.dump_cache_next(iter) == true)
309  {
310  show_cache_entry(iter);
311  }
312  }
313 
314  if (_query > 0)
315  {
316  CHK2(doquery() == 0, "failed");
317  }
318  }
319  while (0);
320  return ret;
321 }
322 
323 static int
324 dostats()
325 {
326  int ret = 0;
327  do
328  {
329  for (int i = 0; i < g_indcount; i++)
330  {
331  CHK1(dostats(i) == 0);
332  }
333  CHK1(ret == 0);
334  }
335  while (0);
336  return ret;
337 }
338 
339 static int
340 checkobjs()
341 {
342  int ret = 0;
343  do
344  {
345  CHK2((g_tab = g_dic->getTable(g_tabname)) != 0,
346  g_tabname << ": " << g_dic->getNdbError());
347 
348  if (g_indcount == 0)
349  {
351  CHK2(g_dic->listIndexes(list, g_tabname) == 0, g_dic->getNdbError());
352  const int count = list.count;
353  g_indnames = (const char**)my_malloc(sizeof(char*) * count, MYF(0));
354  CHK2(g_indnames != 0, "out of memory");
355  for (int i = 0; i < count; i++)
356  {
359  {
360  g_indcount++;
361  g_indnames[i] = my_strdup(e.name, MYF(0));
362  CHK2(g_indnames[i] != 0, "out of memory");
363  }
364  }
365  CHK1(ret == 0);
366  }
367  g_indlist = (const NdbDictionary::Index**)my_malloc(sizeof(NdbDictionary::Index*) * g_indcount, MYF(0));
368  CHK2(g_indlist != 0, "out of memory");
369  for (int i = 0; i < g_indcount; i++)
370  {
371  CHK2((g_indlist[i] = g_dic->getIndex(g_indnames[i], g_tabname)) != 0,
372  g_tabname << "." << g_indnames[i] << ": " << g_dic->getNdbError());
373  }
374  }
375  while (0);
376  return ret;
377 }
378 
379 static int
380 dosys()
381 {
382  int ret = 0;
383  do
384  {
385  if (_sys_drop)
386  {
387  if (!_sys_skip_events)
388  {
389  g_info << "dropping sys events" << endl;
390  CHK2(g_is->drop_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
391  CHK2(g_is->check_sysevents(g_ndb_sys) == -1, "unexpected success");
392  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysEvents,
393  "unexpected error: " << g_is->getNdbError());
394  }
395 
396  if (!_sys_skip_tables)
397  {
398  g_info << "dropping all sys tables" << endl;
399  CHK2(g_is->drop_systables(g_ndb_sys) == 0, g_is->getNdbError());
400  CHK2(g_is->check_systables(g_ndb_sys) == -1, "unexpected success");
401  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysTables,
402  "unexpected error: " << g_is->getNdbError());
403  }
404  g_info << "drop done" << endl;
405  }
406 
407  if (_sys_create)
408  {
409  if (!_sys_skip_tables)
410  {
411  g_info << "creating all sys tables" << endl;
412  CHK2(g_is->create_systables(g_ndb_sys) == 0, g_is->getNdbError());
413  CHK2(g_is->check_systables(g_ndb_sys) == 0, g_is->getNdbError());
414  }
415 
416  if (!_sys_skip_events)
417  {
418  g_info << "creating sys events" << endl;
419  CHK2(g_is->create_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
420  CHK2(g_is->check_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
421  g_info << "create done" << endl;
422  }
423  }
424 
425  if (_sys_create_if_not_exist)
426  {
427  if (!_sys_skip_tables)
428  {
429  if (g_is->check_systables(g_ndb_sys) == -1)
430  {
431  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysTables,
432  g_is->getNdbError());
433  g_info << "creating all sys tables" << endl;
434  CHK2(g_is->create_systables(g_ndb_sys) == 0, g_is->getNdbError());
435  CHK2(g_is->check_systables(g_ndb_sys) == 0, g_is->getNdbError());
436  g_info << "create done" << endl;
437  }
438  else
439  {
440  g_info << "using existing sys tables" << endl;
441  }
442  }
443 
444  if (!_sys_skip_events)
445  {
446  if (g_is->check_sysevents(g_ndb_sys) == -1)
447  {
448  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysEvents,
449  g_is->getNdbError());
450  g_info << "creating sys events" << endl;
451  CHK2(g_is->create_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
452  g_info << "create done" << endl;
453  }
454  else
455  {
456  g_info << "using existing sys events" << endl;
457  }
458  }
459  }
460 
461  if (_sys_create_if_not_valid)
462  {
463  if (!_sys_skip_tables)
464  {
465  if (g_is->check_systables(g_ndb_sys) == -1)
466  {
467  if (g_is->getNdbError().code != NdbIndexStat::NoSysTables)
468  {
469  CHK2(g_is->getNdbError().code == NdbIndexStat::BadSysTables,
470  g_is->getNdbError());
471  g_info << "dropping invalid sys tables" << endl;
472  CHK2(g_is->drop_systables(g_ndb_sys) == 0, g_is->getNdbError());
473  CHK2(g_is->check_systables(g_ndb_sys) == -1, "unexpected success");
474  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysTables,
475  "unexpected error: " << g_is->getNdbError());
476  g_info << "drop done" << endl;
477  }
478  g_info << "creating all sys tables" << endl;
479  CHK2(g_is->create_systables(g_ndb_sys) == 0, g_is->getNdbError());
480  CHK2(g_is->check_systables(g_ndb_sys) == 0, g_is->getNdbError());
481  g_info << "create done" << endl;
482  }
483  else
484  {
485  g_info << "using existing sys tables" << endl;
486  }
487  }
488  if (!_sys_skip_events)
489  {
490  if (g_is->check_sysevents(g_ndb_sys) == -1)
491  {
492  if (g_is->getNdbError().code != NdbIndexStat::NoSysEvents)
493  {
494  CHK2(g_is->getNdbError().code == NdbIndexStat::BadSysEvents,
495  g_is->getNdbError());
496  g_info << "dropping invalid sys events" << endl;
497  CHK2(g_is->drop_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
498  CHK2(g_is->check_sysevents(g_ndb_sys) == -1, "unexpected success");
499  CHK2(g_is->getNdbError().code == NdbIndexStat::NoSysEvents,
500  "unexpected error: " << g_is->getNdbError());
501  g_info << "drop done" << endl;
502  }
503  g_info << "creating sys events" << endl;
504  CHK2(g_is->create_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
505  CHK2(g_is->check_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
506  g_info << "create done" << endl;
507  }
508  else
509  {
510  g_info << "using existing sys events" << endl;
511  }
512  }
513  }
514 
515  if (_sys_check)
516  {
517  if (!_sys_skip_tables)
518  {
519  CHK2(g_is->check_systables(g_ndb_sys) == 0, g_is->getNdbError());
520  g_info << "sys tables ok" << endl;
521  }
522  if (!_sys_skip_events)
523  {
524  CHK2(g_is->check_sysevents(g_ndb_sys) == 0, g_is->getNdbError());
525  g_info << "sys events ok" << endl;
526  }
527  }
528  }
529  while (0);
530  return ret;
531 }
532 
533 static int
534 doall()
535 {
536  int ret = 0;
537  do
538  {
539  CHK2(doconnect() == 0, "connect to NDB");
540 
541  int loop = 0;
542  while (++loop <= _loops)
543  {
544  g_info << "loop " << loop << " of " << _loops << endl;
545  if (!_sys_any)
546  {
547  if (loop == 1)
548  {
549  CHK1(checkobjs() == 0);
550  }
551  CHK2(dostats() == 0, "at loop " << loop);
552  }
553  else
554  {
555  CHK2(dosys() == 0, "at loop " << loop);
556  }
557  }
558  CHK1(ret == 0);
559  }
560  while (0);
561 
562  dodisconnect();
563  return ret;
564 }
565 
566 static int oi = 1000;
567 static struct my_option
568 my_long_options[] =
569 {
570  NDB_STD_OPTS("ndb_index_stat"),
571  // stats options
572  { "database", 'd',
573  "Name of database table is in",
574  (uchar**) &_dbname, (uchar**) &_dbname, 0,
575  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
576  { "delete", ++oi,
577  "Delete index stats of given table"
578  " and stop any configured auto update",
579  (uchar **)&_delete, (uchar **)&_delete, 0,
580  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
581  { "update", ++oi,
582  "Update index stats of given table"
583  " and restart any configured auto update",
584  (uchar **)&_update, (uchar **)&_update, 0,
585  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
586  { "dump", ++oi,
587  "Dump query cache",
588  (uchar **)&_dump, (uchar **)&_dump, 0,
589  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
590  { "query", NDB_OPT_NOSHORT,
591  "Perform random range queries on first key attr (must be int unsigned)",
592  (uchar **)&_query, (uchar **)&_query, 0,
593  GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
594  // sys options
595  { "sys-drop", ++oi,
596  "Drop any stats tables and events in NDB kernel (all stats is lost)",
597  (uchar **)&_sys_drop, (uchar **)&_sys_drop, 0,
598  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
599  { "sys-create", ++oi,
600  "Create stats tables and events in NDB kernel (must not exist)",
601  (uchar **)&_sys_create, (uchar **)&_sys_create, 0,
602  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
603  { "sys-create-if-not-exist", ++oi,
604  "Like --sys-create but do nothing if correct objects exist",
605  (uchar **)&_sys_create_if_not_exist, (uchar **)&_sys_create_if_not_exist, 0,
606  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
607  { "sys-create-if-not-valid", ++oi,
608  "Like --sys-create-if-not-exist but first drop any invalid objects",
609  (uchar **)&_sys_create_if_not_valid, (uchar **)&_sys_create_if_not_valid, 0,
610  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
611  { "sys-check", ++oi,
612  "Check that correct stats tables and events exist in NDB kernel",
613  (uchar **)&_sys_check, (uchar **)&_sys_check, 0,
614  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
615  { "sys-skip-tables", ++oi,
616  "Do not apply sys options to tables",
617  (uchar **)&_sys_skip_tables, (uchar **)&_sys_skip_tables, 0,
618  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
619  { "sys-skip-events", ++oi,
620  "Do not apply sys options to events",
621  (uchar **)&_sys_skip_events, (uchar **)&_sys_skip_events, 0,
622  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
623  // other
624  { "verbose", 'v',
625  "Verbose messages",
626  (uchar **)&_verbose, (uchar **)&_verbose, 0,
627  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
628  { "loops", NDB_OPT_NOSHORT,
629  "Repeat same commands a number of times (for testing)",
630  (uchar **)&_loops, (uchar **)&_loops, 0,
631  GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 },
632  { 0, 0,
633  0,
634  0, 0, 0,
635  GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
636 };
637 
638 const char*
639 load_default_groups[]= { "mysql_cluster", 0 };
640 
641 static void
642 short_usage_sub(void)
643 {
644  ndb_short_usage_sub("[table [index...]]");
645 }
646 
647 static void
648 usage()
649 {
650  printf("%s: ordered index stats tool and test\n", my_progname);
651  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
652 }
653 
654 static int
655 checkopts(int argc, char** argv)
656 {
657  int ret = 0;
658  do
659  {
660  _stats_any =
661  (_dbname != 0) +
662  (_delete != 0) +
663  (_update != 0) +
664  (_dump != 0) +
665  (_query != 0);
666  _sys_any =
667  (_sys_create != 0) +
668  (_sys_create_if_not_exist != 0) +
669  (_sys_create_if_not_valid != 0) +
670  (_sys_drop != 0) +
671  ( _sys_check != 0) +
672  (_sys_skip_tables != 0) +
673  (_sys_skip_events != 0);
674  if (!_sys_any)
675  {
676  if (_dbname == 0)
677  _dbname = "TEST_DB";
678  CHK2(argc >= 1, "stats options require table");
679  g_tabname = my_strdup(argv[0], MYF(0));
680  CHK2(g_tabname != 0, "out of memory");
681  g_indcount = argc - 1;
682  if (g_indcount != 0)
683  {
684  g_indnames = (const char**)my_malloc(sizeof(char*) * g_indcount, MYF(0));
685  CHK2(g_indnames != 0, "out of memory");
686  for (int i = 0; i < g_indcount; i++)
687  {
688  g_indnames[i] = my_strdup(argv[1 + i], MYF(0));
689  CHK2(g_indnames[i] != 0, "out of memory");
690  }
691  CHK1(ret == 0);
692  }
693  }
694  else
695  {
696  CHK2(_stats_any == 0, "cannot mix --sys options with stats options");
697  CHK2(argc == 0, "--sys options take no args");
698  }
699  }
700  while (0);
701  return ret;
702 }
703 
704 int
705 main(int argc, char** argv)
706 {
707  my_progname = "ndb_index_stat";
708  int ret;
709 
710  ndb_init();
711  ndb_opt_set_usage_funcs(short_usage_sub, usage);
712  ret = handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option);
713  if (ret != 0 || checkopts(argc, argv) != 0)
714  return NDBT_ProgramExit(NDBT_WRONGARGS);
715 
716  setOutputLevel(_verbose ? 2 : 0);
717 
718  unsigned seed = (unsigned)time(0);
719  g_info << "random seed " << seed << endl;
720  ndb_srand(seed);
721 
722  ret = doall();
723  if (ret == -1)
724  return NDBT_ProgramExit(NDBT_FAILED);
725  return NDBT_ProgramExit(NDBT_OK);
726 }