Merge lp:~paul-mccullagh/maria/add-xtstat-util into lp:~maria-captains/maria/5.1-converting
- add-xtstat-util
- Merge into 5.1-converting
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Maria-captains | Pending | ||
Review via email: mp+25068@code.launchpad.net |
Commit message
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://
Michael Widenius (monty) wrote : | # |
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://
> , and in my conference talk: http://
> .
>
> 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.blobstreami
pbxt.blogspot.com
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://
Exceptional Services for MySQL at a fixed budget.
Follow our blog at http://
OurDelta: packages for MySQL and MariaDB @ http://
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.blobstreami
pbxt.blogspot.com
Preview Diff
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 |
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/documentati on/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