Merge lp:~paul-mccullagh/maria/add-xtstat-util into lp:~maria-captains/maria/5.1-converting

Proposed by Paul McCullagh
Status: Merged
Merged at revision: 2860
Proposed branch: lp:~paul-mccullagh/maria/add-xtstat-util
Merge into: lp:~maria-captains/maria/5.1-converting
Diff against target: 889 lines (+840/-1)
6 files modified
storage/pbxt/Makefile.am (+1/-1)
storage/pbxt/bin/Makefile.am (+14/-0)
storage/pbxt/bin/xtstat_xt.cc (+819/-0)
storage/pbxt/src/ha_pbxt.cc (+1/-0)
storage/pbxt/src/myxt_xt.cc (+1/-0)
storage/pbxt/src/xt_config.h (+4/-0)
To merge this branch: bzr merge lp:~paul-mccullagh/maria/add-xtstat-util
Reviewer Review Type Date Requested Status
Maria-captains Pending
Review via email: mp+25068@code.launchpad.net

Description of the change

This patch includes the PBXT monitoring utility: xtstat. xtstat is installed in the bin directory along with other mysql binaries.

The utility is very useful when using PBXT, as it shows you exactly what is happening in the engine.

More details are provided in the documentation: http://primebase.org/documentation/index.php#xtstat, and in my conference talk: http://www.primebase.org/download/pbxt-uc-2010.pdf.

To post a comment you must log in.
Revision history for this message
Michael Widenius (monty) wrote :

Hi!

>>>>> "Paul" == Paul McCullagh <email address hidden> writes:

Paul> Paul McCullagh has proposed merging lp:~paul-mccullagh/maria/add-xtstat-util into lp:maria.
Paul> Requested reviews:
Paul> Maria-captains (maria-captains)

Paul> This patch includes the PBXT monitoring utility: xtstat. xtstat is installed in the bin directory along with other mysql binaries.

Paul> The utility is very useful when using PBXT, as it shows you exactly what is happening in the engine.

Paul> More details are provided in the documentation: http://primebase.org/documentation/index.php#xtstat, and in my conference talk: http://www.primebase.org/download/pbxt-uc-2010.pdf.

I am now working on this.

Paul, do you mind if we copy some of the documentation to the MariaDB
documentation at askmonty.org ?

Regards,
Monty

Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

Hi Monty,

On May 12, 2010, at 1:06 PM, Michael Widenius wrote:

> Paul> This patch includes the PBXT monitoring utility: xtstat.
> xtstat is installed in the bin directory along with other mysql
> binaries.
>
> Paul> The utility is very useful when using PBXT, as it shows you
> exactly what is happening in the engine.
>
> Paul> More details are provided in the documentation: http://primebase.org/documentation/index.php#xtstat
> , and in my conference talk: http://www.primebase.org/download/pbxt-uc-2010.pdf
> .
>
> I am now working on this.
>
> Paul, do you mind if we copy some of the documentation to the MariaDB
> documentation at askmonty.org ?

You are free to copy any part of the primebase.org documentation to
askmonty.org.

It is not stated, but in general our documentation is also GPL. I will
add this to our Web-site.

Best regards,

Paul

--
Paul McCullagh
PrimeBase Technologies
www.primebase.org
www.blobstreaming.org
pbxt.blogspot.com

Revision history for this message
Arjen Lentz (arjen-lentz) wrote :

Hi Paul

On 12/05/2010, at 9:12 PM, Paul McCullagh wrote:
> On May 12, 2010, at 1:06 PM, Michael Widenius wrote:
>> Paul, do you mind if we copy some of the documentation to the MariaDB
>> documentation at askmonty.org ?
>
> You are free to copy any part of the primebase.org documentation to
> askmonty.org.
>
> It is not stated, but in general our documentation is also GPL. I will
> add this to our Web-site.

GPL does not make sense for docs.
Why not pick a suitable (for you) Creative Commons license for doco?

Regards,
Arjen.
--
Arjen Lentz, Exec.Director @ Open Query (http://openquery.com)
Exceptional Services for MySQL at a fixed budget.

Follow our blog at http://openquery.com/blog/
OurDelta: packages for MySQL and MariaDB @ http://ourdelta.org

Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

On May 14, 2010, at 1:33 AM, Arjen Lentz wrote:

>> It is not stated, but in general our documentation is also GPL. I
>> will
>> add this to our Web-site.
>
>
> GPL does not make sense for docs.
> Why not pick a suitable (for you) Creative Commons license for doco?

OK, will do.

>
>
> Regards,

--
Paul McCullagh
PrimeBase Technologies
www.primebase.org
www.blobstreaming.org
pbxt.blogspot.com

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storage/pbxt/Makefile.am'
2--- storage/pbxt/Makefile.am 2009-10-06 18:26:11 +0000
3+++ storage/pbxt/Makefile.am 2010-05-11 14:03:30 +0000
4@@ -1,3 +1,3 @@
5-SUBDIRS = src
6+SUBDIRS = src bin
7
8 EXTRA_DIST = CMakeLists.txt plug.in
9
10=== added directory 'storage/pbxt/bin'
11=== added file 'storage/pbxt/bin/Makefile.am'
12--- storage/pbxt/bin/Makefile.am 1970-01-01 00:00:00 +0000
13+++ storage/pbxt/bin/Makefile.am 2010-05-11 14:03:30 +0000
14@@ -0,0 +1,14 @@
15+# Used to build Makefile.in
16+
17+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
18+ -I$(top_srcdir)/regex \
19+ -I$(top_srcdir)/storage/innobase/include \
20+ -I$(top_srcdir)/sql \
21+ -I$(srcdir) \
22+ -I../src
23+
24+bin_PROGRAMS = xtstat
25+
26+xtstat_SOURCES = xtstat_xt.cc ../src/strutil_xt.cc
27+
28+xtstat_LDADD = $(top_srcdir)/libmysql/libmysqlclient.la
29
30=== added file 'storage/pbxt/bin/xtstat_xt.cc'
31--- storage/pbxt/bin/xtstat_xt.cc 1970-01-01 00:00:00 +0000
32+++ storage/pbxt/bin/xtstat_xt.cc 2010-05-11 14:03:30 +0000
33@@ -0,0 +1,819 @@
34+/* Copyright (c) 2005 PrimeBase Technologies GmbH
35+ *
36+ * PrimeBase XT
37+ *
38+ * This program is free software; you can redistribute it and/or modify
39+ * it under the terms of the GNU General Public License as published by
40+ * the Free Software Foundation; either version 2 of the License, or
41+ * (at your option) any later version.
42+ *
43+ * This program is distributed in the hope that it will be useful,
44+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
45+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46+ * GNU General Public License for more details.
47+ *
48+ * You should have received a copy of the GNU General Public License
49+ * along with this program; if not, write to the Free Software
50+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51+ *
52+ * 2008-11-19 Paul McCullagh
53+ *
54+ * H&G2JCtL
55+ */
56+
57+#include "xt_config.h"
58+
59+#include <mysql.h>
60+#include <stdio.h>
61+#include <stdlib.h>
62+#include <ctype.h>
63+#include <string.h>
64+
65+#include "strutil_xt.h"
66+#include "util_xt.h"
67+
68+//#define DEBUG_INTERRUPT
69+
70+#define OPT_NONE -1
71+#define OPT_HELP 0
72+#define OPT_HOST 1
73+#define OPT_USER 2
74+#define OPT_PASSWORD 3
75+#define OPT_DATABASE 4
76+#define OPT_PORT 5
77+#define OPT_SOCKET 6
78+#define OPT_DELAY 7
79+#define OPT_PROTOCOL 8
80+#define OPT_DISPLAY 9
81+
82+#define OPT_HAS_VALUE 1
83+#define OPT_OPTIONAL 2
84+#define OPT_INTEGER 4
85+
86+llong record_cache_size;
87+llong index_cache_size;
88+llong log_cache_size;
89+
90+llong accumulative_values[XT_STAT_CURRENT_MAX];
91+int columns_used;
92+int use_i_s = 0;
93+
94+struct DisplayOrder {
95+ int do_statistic;
96+ bool do_combo;
97+} display_order[XT_STAT_CURRENT_MAX];
98+
99+struct Options {
100+ int opt_id;
101+ const char opt_char;
102+ const char *opt_name;
103+ int opt_flags;
104+ const char *opt_desc;
105+ const char *opt_value_str;
106+ int opt_value_int;
107+ bool opt_value_bool;
108+} options[] = {
109+ { OPT_HELP, '?', "help", 0,
110+ "Prints help text", NULL, 0, false },
111+ { OPT_HOST, 'h', "host", OPT_HAS_VALUE,
112+ "Connect to host", NULL, 0, false },
113+ { OPT_USER, 'u', "user", OPT_HAS_VALUE,
114+ "User for login if not current user", NULL, 0, false },
115+ { OPT_PASSWORD, 'p', "password", OPT_HAS_VALUE | OPT_OPTIONAL,
116+ "Password to use when connecting to server. If password is not given it's asked from the tty", NULL, 0, false },
117+ { OPT_DATABASE, 'd', "database", OPT_HAS_VALUE,
118+ "Database to be used (pbxt or information_schema required), default is information_schema", "information_schema", 0, false },
119+ { OPT_PORT, 'P', "port", OPT_HAS_VALUE | OPT_INTEGER,
120+ "Port number to use for connection", NULL, 3306, false },
121+ { OPT_SOCKET, 'S', "socket", OPT_HAS_VALUE,
122+ "Socket file to use for connection", NULL, 0, false },
123+ { OPT_DELAY, 'D', "delay", OPT_HAS_VALUE | OPT_INTEGER,
124+ "Delay in seconds between polls of the database", NULL, 1, false },
125+ { OPT_PROTOCOL, 0, "protocol", OPT_HAS_VALUE,
126+ "Connection protocol to use: default/tcp/socket/pipe/memory", "default", MYSQL_PROTOCOL_DEFAULT, false },
127+ { OPT_DISPLAY, 0, "display", OPT_HAS_VALUE,
128+ "Columns to display: use short names separated by |, partial match allowed", "time-msec,commt,row-ins,rec,ind,ilog,xlog,data,to,dirty", 0, false },
129+ { OPT_NONE, 0, NULL, 0, NULL, 0, false }
130+};
131+
132+#ifdef XT_WIN
133+#define atoll _atoi64
134+#endif
135+
136+void add_statistic(int stat)
137+{
138+ /* Check if column has already been added: */
139+ for (int i=0; i<columns_used; i++) {
140+ if (display_order[i].do_statistic == stat)
141+ return;
142+ }
143+ display_order[columns_used].do_statistic = stat;
144+ display_order[columns_used].do_combo = false;
145+ columns_used++;
146+}
147+
148+void determine_display_order()
149+{
150+ const char *cols = options[OPT_DISPLAY].opt_value_str;
151+ char column_1[21], column_2[21];
152+ int i;
153+ bool add, added, add_combo;
154+ XTStatMetaDataPtr meta, meta2;
155+
156+ if (strcmp(cols, "all") == 0)
157+ cols = "time,xact,stat,rec,ind,ilog,xlog,data,to,sweep,scan,row";
158+ columns_used = 0;
159+ while (*cols) {
160+ i = 0;
161+ while (*cols && *cols != '-' && *cols != ',') {
162+ if (i < 20) {
163+ column_1[i] = *cols;
164+ i++;
165+ }
166+ cols++;
167+ }
168+ column_1[i] = 0;
169+
170+ i = 0;
171+ if (*cols == '-') {
172+ cols++;
173+ while (*cols && *cols != '-' && *cols != ',') {
174+ if (i < 20) {
175+ column_2[i] = *cols;
176+ i++;
177+ }
178+ cols++;
179+ }
180+ }
181+ column_2[i] = 0;
182+
183+ if (*cols == ',')
184+ cols++;
185+
186+ if (strcmp(column_1, "ms") == 0)
187+ strcpy(column_1, "msec");
188+ if (strcmp(column_2, "ms") == 0)
189+ strcpy(column_2, "msec");
190+ add_combo = false;
191+ if (strcmp(column_1, "syncs/ms") == 0) {
192+ strcpy(column_1, "syncs");
193+ add_combo = true;
194+ }
195+ if (strcmp(column_2, "syncs/ms") == 0) {
196+ strcpy(column_2, "syncs");
197+ add_combo = true;
198+ }
199+
200+ added = false;
201+ for (i=0; i<XT_STAT_MAXIMUM; i++) {
202+ meta = xt_get_stat_meta_data(i);
203+ add = false;
204+ if (strcmp(meta->sm_short_line_1, column_1) == 0) {
205+ if (column_2[0]) {
206+ if (strcmp(meta->sm_short_line_2, column_2) == 0)
207+ add = true;
208+ }
209+ else {
210+ if (i != XT_STAT_XLOG_CACHE_USAGE)
211+ add = true;
212+ }
213+ }
214+ else if (!column_2[0]) {
215+ if (strcmp(meta->sm_short_line_2, column_1) == 0) {
216+ /* XT_STAT_XLOG_CACHE_USAGE is ignored, unless explicity listed! */
217+ if (i != XT_STAT_XLOG_CACHE_USAGE)
218+ add = true;
219+ }
220+ }
221+ if (add) {
222+ added = true;
223+ add_statistic(i);
224+ if (add_combo)
225+ add_statistic(i+1);
226+ }
227+ }
228+ if (!added) {
229+ if (column_2[0])
230+ fprintf(stderr, "ERROR: No statistic matches display option: '%s-%s'\n", column_1, column_2);
231+ else
232+ fprintf(stderr, "ERROR: No statistic matches display option: '%s'\n", column_1);
233+ fprintf(stderr, "Display options: %s\n", options[OPT_DISPLAY].opt_value_str);
234+ exit(1);
235+ }
236+ }
237+
238+ /* Setup "combo" fields: */
239+ for (i=0; i<columns_used; i++) {
240+ meta = xt_get_stat_meta_data(display_order[i].do_statistic);
241+ if (meta->sm_flags & XT_STAT_COMBO_FIELD) {
242+ if (i+1 < columns_used) {
243+ meta2 = xt_get_stat_meta_data(display_order[i+1].do_statistic);
244+ if (meta2->sm_flags & XT_STAT_COMBO_FIELD_2) {
245+ if (strcmp(meta->sm_short_line_1, meta2->sm_short_line_1) == 0)
246+ display_order[i].do_combo = true;
247+ }
248+ }
249+ }
250+ }
251+}
252+
253+void format_percent_value(char *buffer, double value, double perc)
254+{
255+ value = value * (double) 100 / (double) perc;
256+ if (value >= 100)
257+ sprintf(buffer, "%.0f", value);
258+ else
259+ sprintf(buffer, "%.1f", value);
260+ buffer[4] = 0;
261+ if (buffer[3] == '.')
262+ buffer[3] = 0;
263+}
264+
265+#define XT_1_K ((double) 1024)
266+#define XT_1_M ((double) 1024 * (double) 1024)
267+#define XT_1_G ((double) 1024 * (double) 1024 * (double) 1024)
268+#define XT_1_T ((double) 1024 * (double) 1024 * (double) 1024 * (double) 1024)
269+#define XT_10000_K ((double) 10000 * XT_1_K)
270+#define XT_10000_M ((double) 10000 * XT_1_M)
271+#define XT_10000_G ((double) 10000 * XT_1_G)
272+
273+void format_byte_value(char *buffer, double value)
274+{
275+ double dval;
276+ char string[100];
277+ char ch;
278+
279+ if (value < (double) 100000) {
280+ /* byte value from 0 to 99999: */
281+ sprintf(buffer, "%.0f", value);
282+ return;
283+ }
284+
285+ if (value < XT_10000_K) {
286+ dval = value / XT_1_K;
287+ ch = 'K';
288+ }
289+ else if (value < XT_10000_M) {
290+ dval = value / XT_1_M;
291+ ch = 'M';
292+ }
293+ else if (value < XT_10000_G) {
294+ dval = value / XT_1_G;
295+ ch = 'G';
296+ }
297+ else {
298+ dval = value / XT_1_T;
299+ ch = 'T';
300+ }
301+
302+ if (dval < (double) 10.0)
303+ sprintf(string, "%.2f", dval);
304+ else if (dval < (double) 100.0)
305+ sprintf(string, "%.1f", dval);
306+ else
307+ sprintf(string, "%.0f", dval);
308+ if (string[3] == '.')
309+ string[3] = 0;
310+ else
311+ string[4] = 0;
312+ sprintf(buffer, "%s%c", string, ch);
313+}
314+
315+/*
316+ * Uses:
317+ * t = thousands
318+ * m = millions
319+ * b = billions
320+ */
321+void format_mini_count_value(char *buffer, double value)
322+{
323+ double dval;
324+ char string[100];
325+ char ch;
326+
327+ if (value < (double) 100) {
328+ /* Value from 0 to 99: */
329+ sprintf(buffer, "%.0f", value);
330+ return;
331+ }
332+
333+ if (value < (double) 1000) {
334+ sprintf(buffer, "<t");
335+ return;
336+ }
337+
338+ if (value < (double) 10000) {
339+ /* Value is less than 1m */
340+ dval = value / (double) 1000.0;
341+ ch = 't';
342+ }
343+ else if (value < (double) 1000000) {
344+ sprintf(buffer, "<m");
345+ return;
346+ }
347+ else if (value < (double) 10000000) {
348+ /* Value is less than 1b */
349+ dval = value / (double) 1000000.0;
350+ ch = 'm';
351+ }
352+ else if (value < (double) 1000000000) {
353+ sprintf(buffer, "<b");
354+ return;
355+ }
356+ else {
357+ /* Value is greater than 1 billion */
358+ dval = value / (double) 1000000000.0;
359+ ch = 'b';
360+ }
361+
362+ sprintf(string, "%1.0f", dval);
363+ string[1] = 0;
364+ sprintf(buffer, "%s%c", string, ch);
365+}
366+
367+#define XT_1_THOUSAND ((double) 1000)
368+#define XT_1_MILLION ((double) 1000 * (double) 1000)
369+#define XT_1_BILLION ((double) 1000 * (double) 1000 * (double) 1000)
370+#define XT_1_TRILLION ((double) 1000 * (double) 1000 * (double) 1000 * (double) 1000)
371+#define XT_10_THOUSAND ((double) 10 * (double) 1000)
372+#define XT_10_MILLION ((double) 10 * (double) 1000 * (double) 1000)
373+#define XT_10_BILLION ((double) 10 * (double) 1000 * (double) 1000 * (double) 1000)
374+#define XT_10_TRILLION ((double) 10 * (double) 1000 * (double) 1000 * (double) 1000 * (double) 1000)
375+
376+void format_count_value(char *buffer, double value)
377+{
378+ double dval;
379+ char string[100];
380+ char ch;
381+
382+ if (value < (double) 0) {
383+ strcpy(buffer, "0");
384+ return;
385+ }
386+
387+ if (value < XT_10_THOUSAND) {
388+ /* byte value from 0 to 99999: */
389+ sprintf(buffer, "%.0f", value);
390+ return;
391+ }
392+
393+ if (value < XT_10_MILLION) {
394+ /* Value is less than 10 million */
395+ dval = value / XT_1_THOUSAND;
396+ ch = 't';
397+ }
398+ else if (value < XT_10_BILLION) {
399+ /* Value is less than 10 million */
400+ dval = value / XT_1_MILLION;
401+ ch = 'm';
402+ }
403+ else if (value < XT_10_TRILLION) {
404+ /* Value is less than 10 trillion */
405+ dval = value / XT_1_BILLION;
406+ ch = 'b';
407+ }
408+ else {
409+ dval = value / XT_1_TRILLION;
410+ ch = 't';
411+ }
412+
413+ if (dval < (double) 10.0)
414+ sprintf(string, "%.2f", dval);
415+ else if (dval < (double) 100.0)
416+ sprintf(string, "%.1f", dval);
417+ else
418+ sprintf(string, "%.0f", dval);
419+ if (string[3] == '.')
420+ string[3] = 0;
421+ else
422+ string[4] = 0;
423+ sprintf(buffer, "%s%c", string, ch);
424+}
425+
426+void print_help()
427+{
428+ struct Options *opt;
429+ char command[100];
430+
431+ printf("Usage: xtstat [ options ]\n");
432+ printf("e.g. xtstat -D10 : Poll every 10 seconds\n");
433+ opt = options;
434+ printf("Options :-\n");
435+ while (opt->opt_id != OPT_NONE) {
436+ strcpy(command, opt->opt_name);
437+ if (opt->opt_flags & OPT_HAS_VALUE) {
438+ if (opt->opt_flags & OPT_OPTIONAL)
439+ strcat(command, "[=value]");
440+ else
441+ strcat(command, "=value");
442+ }
443+ if (opt->opt_char)
444+ printf("-%c, --%-16s %s.\n", opt->opt_char, command, opt->opt_desc);
445+ else
446+ printf(" --%-16s %s.\n", command, opt->opt_desc);
447+ opt++;
448+ }
449+}
450+
451+void print_stat_key()
452+{
453+ printf("Key :-\n");
454+ printf("K = Kilobytes (1,024 bytes)\n");
455+ printf("M = Megabytes (1,048,576 bytes)\n");
456+ printf("G = Gigabytes (1,073,741,024 bytes)\n");
457+ printf("T = Terabytes (1,099,511,627,776 bytes)\n");
458+ printf("t = thousands (1,000s)\n");
459+ printf("m = millions (1,000,000s)\n");
460+ printf("b = billions (1,000,000,000s)\n");
461+}
462+
463+void print_stat_info()
464+{
465+ XTStatMetaDataPtr meta;
466+ char buffer[40];
467+ char desc[400];
468+
469+ printf("Statistics :-\n");
470+ for (int i=0; i<XT_STAT_CURRENT_MAX; i++) {
471+ meta = xt_get_stat_meta_data(i);
472+ sprintf(desc, meta->sm_description, "milli");
473+ sprintf(buffer, "%s-%s", meta->sm_short_line_1, meta->sm_short_line_2);
474+ if (meta->sm_flags & XT_STAT_COMBO_FIELD) {
475+ /* Combine next 2 fields: */
476+ i++;
477+ strcat(buffer, "/ms");
478+ strcat(desc, "/time taken in milliseconds");
479+ }
480+ printf("%-13s %-21s - %s.\n", buffer, meta->sm_name, desc);
481+ }
482+}
483+
484+bool match_arg(char *what, const char *opt, char **value)
485+{
486+ while (*what && *opt && isalpha(*what)) {
487+ if (*what != *opt)
488+ return false;
489+ what++;
490+ opt++;
491+ }
492+ if (*opt)
493+ return false;
494+ if (*what == '=')
495+ *value = what + 1;
496+ else if (*what)
497+ return false;
498+ else
499+ *value = NULL;
500+ return true;
501+}
502+
503+void parse_args(int argc, char **argv)
504+{
505+ char *ptr;
506+ char *value;
507+ int i = 1;
508+ struct Options *opt;
509+ bool found;
510+
511+ while (i < argc) {
512+ ptr = argv[i];
513+ found = false;
514+ if (*ptr == '-') {
515+ ptr++;
516+ if (*ptr == '-') {
517+ ptr++;
518+ opt = options;
519+ while (opt->opt_id != OPT_NONE) {
520+ if (match_arg(ptr, opt->opt_name, &value)) {
521+ found = true;
522+ opt->opt_value_str = value;
523+ opt->opt_value_bool = true;
524+ break;
525+ }
526+ opt++;
527+ }
528+ }
529+ else {
530+ opt = options;
531+ while (opt->opt_id != OPT_NONE) {
532+ if (*ptr == opt->opt_char) {
533+ ptr++;
534+ if (*ptr)
535+ opt->opt_value_str = ptr;
536+ else {
537+ opt->opt_value_str = NULL;
538+ if (i+1 < argc) {
539+ ptr = argv[i+1];
540+ if (*ptr != '-') {
541+ opt->opt_value_str = ptr;
542+ i++;
543+ }
544+ }
545+ }
546+ found = true;
547+ opt->opt_value_bool = true;
548+ break;
549+ }
550+ opt++;
551+ }
552+ }
553+ }
554+
555+ if (!found) {
556+ fprintf(stderr, "Unknown option: %s\n", argv[i]);
557+ print_help();
558+ exit(1);
559+ }
560+
561+ if (opt->opt_flags & OPT_HAS_VALUE) {
562+ if (!(opt->opt_flags & OPT_OPTIONAL)) {
563+ if (!opt->opt_value_str) {
564+ fprintf(stderr, "Option requires a value: %s\n", argv[i]);
565+ printf("Use --help for help on commands and usage\n");
566+ exit(1);
567+ }
568+ }
569+ }
570+ else {
571+ if (opt->opt_value_str) {
572+ fprintf(stderr, "Option does not accept a value: %s\n", argv[i]);
573+ printf("Use --help for help on commands and usage\n");
574+ exit(1);
575+ }
576+ }
577+
578+ if (opt->opt_value_str && (opt->opt_flags & OPT_INTEGER))
579+ opt->opt_value_int = atoi(opt->opt_value_str);
580+
581+ if (opt->opt_id == OPT_HELP) {
582+ print_help();
583+ print_stat_key();
584+ print_stat_info();
585+ exit(1);
586+ }
587+
588+ i++;
589+ }
590+}
591+
592+#ifdef DEBUG_INTERRUPT
593+void interrupt_pbxt(MYSQL *conn)
594+{
595+ MYSQL_RES *res;
596+
597+ if (mysql_query(conn, "show engine pbxt status")) {
598+ fprintf(stderr, "%s\n", mysql_error(conn));
599+ exit(1);
600+ }
601+
602+ res = mysql_use_result(conn);
603+ mysql_free_result(res);
604+}
605+#endif
606+
607+static bool display_parameters(MYSQL *conn)
608+{
609+ MYSQL_RES *res;
610+ MYSQL_ROW row;
611+
612+ /* send SQL query */
613+ if (mysql_query(conn, "show variables like 'pbxt_%'"))
614+ return false;
615+
616+ if (!(res = mysql_use_result(conn)))
617+ return false;
618+
619+ /* output table name */
620+ printf("-- PBXT System Variables --\n");
621+ while ((row = mysql_fetch_row(res)) != NULL) {
622+ if (strcmp(row[0], "pbxt_index_cache_size") == 0)
623+ index_cache_size = xt_byte_size_to_int8(row[1]);
624+ else if (strcmp(row[0], "pbxt_record_cache_size") == 0)
625+ record_cache_size = xt_byte_size_to_int8(row[1]);
626+ else if (strcmp(row[0], "pbxt_log_cache_size") == 0)
627+ log_cache_size = xt_byte_size_to_int8(row[1]);
628+ printf("%-29s= %s\n", row[0], row[1]);
629+ }
630+
631+ mysql_free_result(res);
632+
633+ for (int i=0; i<XT_STAT_CURRENT_MAX; i++)
634+ accumulative_values[i] = 0;
635+
636+ printf("Display options: %s\n", options[OPT_DISPLAY].opt_value_str);
637+ return true;
638+}
639+
640+static bool connect(MYSQL *conn)
641+{
642+ unsigned int type;
643+
644+ if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "tcp") == 0)
645+ type = MYSQL_PROTOCOL_TCP;
646+ else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "socket") == 0)
647+ type = MYSQL_PROTOCOL_SOCKET;
648+ else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "pipe") == 0)
649+ type = MYSQL_PROTOCOL_PIPE;
650+ else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "memory") == 0)
651+ type = MYSQL_PROTOCOL_MEMORY;
652+ else
653+ type = MYSQL_PROTOCOL_DEFAULT;
654+
655+ if (mysql_options(conn, MYSQL_OPT_PROTOCOL, (char *) &type))
656+ return false;
657+
658+ if (mysql_options(conn, MYSQL_READ_DEFAULT_GROUP, "xtstat"))
659+ return false;
660+
661+ if (strcasecmp(options[OPT_DATABASE].opt_value_str, "pbxt") == 0)
662+ use_i_s = FALSE;
663+ else if (strcasecmp(options[OPT_DATABASE].opt_value_str, "information_schema") == 0)
664+ use_i_s = TRUE;
665+ else
666+ use_i_s = TRUE;
667+
668+ /* Connect to database */
669+ if (!mysql_real_connect(conn,
670+ options[OPT_HOST].opt_value_str,
671+ options[OPT_USER].opt_value_str,
672+ options[OPT_PASSWORD].opt_value_str,
673+ options[OPT_DATABASE].opt_value_str,
674+ options[OPT_PORT].opt_value_int,
675+ options[OPT_SOCKET].opt_value_str,
676+ 0))
677+ return false;
678+
679+ return true;
680+}
681+
682+int main(int argc, char **argv)
683+{
684+ MYSQL *conn;
685+ MYSQL_RES *res;
686+ MYSQL_ROW row;
687+ llong current_values[XT_STAT_CURRENT_MAX];
688+ double value;
689+ char str_value[100];
690+ XTStatMetaDataPtr meta;
691+ int len;
692+ int stat;
693+ int err;
694+ bool select_worked = true;
695+
696+ xt_set_time_unit("msec");
697+ parse_args(argc, argv);
698+
699+ determine_display_order();
700+
701+ if (!(conn = mysql_init(NULL))) {
702+ fprintf(stderr, "Insufficient memory\n");
703+ exit(1);
704+ }
705+
706+ if (!connect(conn) || !display_parameters(conn)) {
707+ fprintf(stderr, "%s\n", mysql_error(conn));
708+ exit(1);
709+ }
710+
711+ retry:
712+ for (int loop = 0; ; loop++) {
713+ if (use_i_s)
714+ err = mysql_query(conn, "select id, Value from information_schema.pbxt_statistics order by ID");
715+ else
716+ err = mysql_query(conn, "select id, Value from pbxt.statistics order by ID");
717+ if (err)
718+ goto reconnect;
719+
720+ if (!(res = mysql_use_result(conn)))
721+ goto reconnect;
722+ select_worked = true;
723+
724+ while ((row = mysql_fetch_row(res)) != NULL) {
725+ stat = atoi(row[0])-1;
726+ current_values[stat] = atoll(row[1]);
727+ }
728+ mysql_free_result(res);
729+
730+#ifdef DEBUG_INTERRUPT
731+ if (current_values[XT_STAT_STAT_WRITES] - accumulative_values[XT_STAT_STAT_WRITES] == 0 &&
732+ current_values[XT_STAT_REC_SYNC_TIME] - accumulative_values[XT_STAT_REC_SYNC_TIME] == 0 &&
733+ current_values[XT_STAT_IND_SYNC_TIME] - accumulative_values[XT_STAT_IND_SYNC_TIME] == 0)
734+ interrupt_pbxt();
735+#endif
736+
737+ if ((loop % 25) == 0) {
738+ for (int column=0; column<columns_used; column++) {
739+ len = 5;
740+ meta = xt_get_stat_meta_data(display_order[column].do_statistic);
741+ strcpy(str_value, meta->sm_short_line_1);
742+ if (display_order[column].do_combo) {
743+ /* Combine next 2 fields: */
744+ len = 8;
745+ column++;
746+ }
747+ else if (meta->sm_flags & XT_STAT_PERCENTAGE)
748+ len = 4;
749+ else if (meta->sm_flags & XT_STAT_DATE)
750+ len = 15;
751+ printf("%*s ", len, str_value);
752+ }
753+ printf("\n");
754+ for (int column=0; column<columns_used; column++) {
755+ len = 5;
756+ meta = xt_get_stat_meta_data(display_order[column].do_statistic);
757+ strcpy(str_value, meta->sm_short_line_2);
758+ if (display_order[column].do_combo) {
759+ /* Combine next 2 fields: */
760+ len = 8;
761+ column++;
762+ strcat(str_value, "/ms");
763+ }
764+ else if (meta->sm_flags & XT_STAT_PERCENTAGE)
765+ len = 4;
766+ else if (meta->sm_flags & XT_STAT_DATE)
767+ len = 15;
768+ printf("%*s ", len, str_value);
769+ }
770+ printf("\n");
771+ }
772+
773+ for (int column=0; column<columns_used; column++) {
774+ len = 5;
775+ stat = display_order[column].do_statistic;
776+ meta = xt_get_stat_meta_data(stat);
777+ if (meta->sm_flags & XT_STAT_ACCUMULATIVE) {
778+ /* Take care of overflow! */
779+ if (current_values[stat] < accumulative_values[stat])
780+ value = (double) (0xFFFFFFFF - (accumulative_values[stat] - current_values[stat]));
781+ else
782+ value = (double) (current_values[stat] - accumulative_values[stat]);
783+ }
784+ else
785+ value = (double) current_values[stat];
786+ accumulative_values[stat] = current_values[stat];
787+ if (meta->sm_flags & XT_STAT_TIME_VALUE)
788+ value = value / (double) 1000;
789+ if (display_order[column].do_combo) {
790+ format_mini_count_value(str_value, value);
791+ strcat(str_value, "/");
792+ column++;
793+ stat = display_order[column].do_statistic;
794+ value = (double) (current_values[stat] - accumulative_values[stat]);
795+ accumulative_values[stat] = current_values[stat];
796+ value = value / (double) 1000;
797+ format_count_value(&str_value[strlen(str_value)], value);
798+ len = 8;
799+ }
800+ else if (meta->sm_flags & XT_STAT_PERCENTAGE) {
801+ double perc = 100;
802+ switch (stat) {
803+ case XT_STAT_REC_CACHE_USAGE: perc = (double)record_cache_size; break;
804+ case XT_STAT_IND_CACHE_USAGE: perc = (double)index_cache_size; break;
805+ case XT_STAT_XLOG_CACHE_USAGE: perc = (double)log_cache_size; break;
806+ }
807+ format_percent_value(str_value, value, perc);
808+ len = 4;
809+ }
810+ else if (meta->sm_flags & XT_STAT_DATE) {
811+ time_t ticks = (time_t) value;
812+ const struct tm *ltime = localtime(&ticks);
813+ strftime(str_value, 99, "%y%m%d %H:%M:%S", ltime);
814+ len = 15;
815+ }
816+ else if (meta->sm_flags & XT_STAT_BYTE_COUNT)
817+ format_byte_value(str_value, value);
818+ else
819+ format_count_value(str_value, value);
820+ if (column == columns_used-1)
821+ printf("%*s\n", len, str_value);
822+ else
823+ printf("%*s ", len, str_value);
824+ }
825+
826+ sleep(options[OPT_DELAY].opt_value_int);
827+ }
828+
829+ /* close connection */
830+ mysql_close(conn);
831+ return 0;
832+
833+ reconnect:
834+ /* Reconnect... */
835+ if (select_worked) {
836+ /* Only print message if the SELECT worked.
837+ * or we will get a screen full of messages:
838+ */
839+ fprintf(stderr, "%s\n", mysql_error(conn));
840+ printf("Reconnecting...\n");
841+ }
842+ mysql_close(conn);
843+ if (!(conn = mysql_init(NULL))) {
844+ fprintf(stderr, "Insufficient memory\n");
845+ exit(1);
846+ }
847+ do {
848+ sleep(2);
849+ } while (!connect(conn));
850+ select_worked = false;
851+ goto retry;
852+}
853
854=== modified file 'storage/pbxt/src/ha_pbxt.cc'
855--- storage/pbxt/src/ha_pbxt.cc 2010-01-06 21:27:53 +0000
856+++ storage/pbxt/src/ha_pbxt.cc 2010-05-11 14:03:30 +0000
857@@ -80,6 +80,7 @@
858 #include "systab_xt.h"
859 #include "xaction_xt.h"
860 #include "backup_xt.h"
861+#include "heap_xt.h"
862
863 #ifdef DEBUG
864 //#define XT_USE_SYS_PAR_DEBUG_SIZES
865
866=== modified file 'storage/pbxt/src/myxt_xt.cc'
867--- storage/pbxt/src/myxt_xt.cc 2009-12-10 11:36:05 +0000
868+++ storage/pbxt/src/myxt_xt.cc 2010-05-11 14:03:30 +0000
869@@ -54,6 +54,7 @@
870 #include "database_xt.h"
871 #include "cache_xt.h"
872 #include "datalog_xt.h"
873+#include "memory_xt.h"
874
875 static void myxt_bitmap_init(XTThreadPtr self, MX_BITMAP *map, u_int n_bits);
876 static void myxt_bitmap_free(XTThreadPtr self, MX_BITMAP *map);
877
878=== modified file 'storage/pbxt/src/xt_config.h'
879--- storage/pbxt/src/xt_config.h 2009-11-24 10:55:06 +0000
880+++ storage/pbxt/src/xt_config.h 2010-05-11 14:03:30 +0000
881@@ -128,4 +128,8 @@
882 #endif
883 #endif
884
885+#if defined(DBUG_ON) && !defined(DBUG_OFF) && !defined(DEBUG)
886+#define DEBUG
887+#endif // DBUG_ON
888+
889 #endif

Subscribers

People subscribed via source and target branches