~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to plugin/pbxt/bin/xtstat_xt.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-10-02 14:17:48 UTC
  • mfrom: (1.1.1 upstream)
  • mto: (2.1.17 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101002141748-m6vbfbfjhrw1153e
Tags: 2010.09.1802-1
* New upstream release.
* Removed pid-file argument hack.
* Updated GPL-2 address to be new address.
* Directly copy in drizzledump.1 since debian doesn't have sphinx 1.0 yet.
* Link to jquery from libjs-jquery. Add it as a depend.
* Add drizzled.8 symlink to the install files.

Show diffs side-by-side

added added

removed removed

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