Merge to get PBXT's xstat program
scripts/make_binary_distribution.sh: Added copying of xstat scripts/make_win_bin_dist: Added copying of xstat
This commit is contained in:
commit
8b2abdcf41
@ -276,6 +276,7 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; then
|
||||
# Do a install that we later are to pack. Use the same paths as in
|
||||
# the build for the relevant directories.
|
||||
# ----------------------------------------------------------------------
|
||||
set -x -v
|
||||
@MAKE@ DESTDIR=$BASE install \
|
||||
pkglibdir=@pkglibdir@ \
|
||||
pkgincludedir=@pkgincludedir@ \
|
||||
@ -444,6 +445,7 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
|
||||
tests/mysql_client_test$BS \
|
||||
libmysqld/examples/mysql_client_test_embedded$BS \
|
||||
libmysqld/examples/mysqltest_embedded$BS \
|
||||
storage/pbxt/bin/xtstat$BS \
|
||||
";
|
||||
|
||||
# Platform-specific bin dir files:
|
||||
|
@ -158,6 +158,11 @@ for eng in $MARIA_BINARIES ; do
|
||||
cp storage/maria/$TARGET/$eng.{exe,pdb} $DESTDIR/bin
|
||||
done
|
||||
|
||||
# PBXT
|
||||
if [ -f "storage/pbxt/bin/xtstat.exe" ] ; then
|
||||
cp storage/pbxt/bin/xtstat.{exe,pdb} $DESTDIR/bin
|
||||
fi
|
||||
|
||||
cp server-tools/instance-manager/$TARGET/*.{exe,map} $DESTDIR/bin/
|
||||
if [ x"$TARGET" != x"release" ] ; then
|
||||
cp server-tools/instance-manager/$TARGET/*.pdb $DESTDIR/bin/
|
||||
|
@ -1,3 +1,3 @@
|
||||
SUBDIRS = src
|
||||
SUBDIRS = src bin
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt plug.in
|
||||
|
14
storage/pbxt/bin/Makefile.am
Normal file
14
storage/pbxt/bin/Makefile.am
Normal file
@ -0,0 +1,14 @@
|
||||
# Used to build Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/regex \
|
||||
-I$(top_srcdir)/storage/innobase/include \
|
||||
-I$(top_srcdir)/sql \
|
||||
-I$(srcdir) \
|
||||
-I../src
|
||||
|
||||
bin_PROGRAMS = xtstat
|
||||
|
||||
xtstat_SOURCES = xtstat_xt.cc ../src/strutil_xt.cc
|
||||
|
||||
xtstat_LDADD = $(top_srcdir)/libmysql/libmysqlclient.la
|
819
storage/pbxt/bin/xtstat_xt.cc
Normal file
819
storage/pbxt/bin/xtstat_xt.cc
Normal file
@ -0,0 +1,819 @@
|
||||
/* Copyright (c) 2005 PrimeBase Technologies GmbH
|
||||
*
|
||||
* PrimeBase XT
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 2008-11-19 Paul McCullagh
|
||||
*
|
||||
* H&G2JCtL
|
||||
*/
|
||||
|
||||
#include "xt_config.h"
|
||||
|
||||
#include <mysql.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "strutil_xt.h"
|
||||
#include "util_xt.h"
|
||||
|
||||
//#define DEBUG_INTERRUPT
|
||||
|
||||
#define OPT_NONE -1
|
||||
#define OPT_HELP 0
|
||||
#define OPT_HOST 1
|
||||
#define OPT_USER 2
|
||||
#define OPT_PASSWORD 3
|
||||
#define OPT_DATABASE 4
|
||||
#define OPT_PORT 5
|
||||
#define OPT_SOCKET 6
|
||||
#define OPT_DELAY 7
|
||||
#define OPT_PROTOCOL 8
|
||||
#define OPT_DISPLAY 9
|
||||
|
||||
#define OPT_HAS_VALUE 1
|
||||
#define OPT_OPTIONAL 2
|
||||
#define OPT_INTEGER 4
|
||||
|
||||
llong record_cache_size;
|
||||
llong index_cache_size;
|
||||
llong log_cache_size;
|
||||
|
||||
llong accumulative_values[XT_STAT_CURRENT_MAX];
|
||||
int columns_used;
|
||||
int use_i_s = 0;
|
||||
|
||||
struct DisplayOrder {
|
||||
int do_statistic;
|
||||
bool do_combo;
|
||||
} display_order[XT_STAT_CURRENT_MAX];
|
||||
|
||||
struct Options {
|
||||
int opt_id;
|
||||
const char opt_char;
|
||||
const char *opt_name;
|
||||
int opt_flags;
|
||||
const char *opt_desc;
|
||||
const char *opt_value_str;
|
||||
int opt_value_int;
|
||||
bool opt_value_bool;
|
||||
} options[] = {
|
||||
{ OPT_HELP, '?', "help", 0,
|
||||
"Prints help text", NULL, 0, false },
|
||||
{ OPT_HOST, 'h', "host", OPT_HAS_VALUE,
|
||||
"Connect to host", NULL, 0, false },
|
||||
{ OPT_USER, 'u', "user", OPT_HAS_VALUE,
|
||||
"User for login if not current user", NULL, 0, false },
|
||||
{ OPT_PASSWORD, 'p', "password", OPT_HAS_VALUE | OPT_OPTIONAL,
|
||||
"Password to use when connecting to server. If password is not given it's asked from the tty", NULL, 0, false },
|
||||
{ OPT_DATABASE, 'd', "database", OPT_HAS_VALUE,
|
||||
"Database to be used (pbxt or information_schema required), default is information_schema", "information_schema", 0, false },
|
||||
{ OPT_PORT, 'P', "port", OPT_HAS_VALUE | OPT_INTEGER,
|
||||
"Port number to use for connection", NULL, 3306, false },
|
||||
{ OPT_SOCKET, 'S', "socket", OPT_HAS_VALUE,
|
||||
"Socket file to use for connection", NULL, 0, false },
|
||||
{ OPT_DELAY, 'D', "delay", OPT_HAS_VALUE | OPT_INTEGER,
|
||||
"Delay in seconds between polls of the database", NULL, 1, false },
|
||||
{ OPT_PROTOCOL, 0, "protocol", OPT_HAS_VALUE,
|
||||
"Connection protocol to use: default/tcp/socket/pipe/memory", "default", MYSQL_PROTOCOL_DEFAULT, false },
|
||||
{ OPT_DISPLAY, 0, "display", OPT_HAS_VALUE,
|
||||
"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 },
|
||||
{ OPT_NONE, 0, NULL, 0, NULL, 0, false }
|
||||
};
|
||||
|
||||
#ifdef XT_WIN
|
||||
#define atoll _atoi64
|
||||
#endif
|
||||
|
||||
void add_statistic(int stat)
|
||||
{
|
||||
/* Check if column has already been added: */
|
||||
for (int i=0; i<columns_used; i++) {
|
||||
if (display_order[i].do_statistic == stat)
|
||||
return;
|
||||
}
|
||||
display_order[columns_used].do_statistic = stat;
|
||||
display_order[columns_used].do_combo = false;
|
||||
columns_used++;
|
||||
}
|
||||
|
||||
void determine_display_order()
|
||||
{
|
||||
const char *cols = options[OPT_DISPLAY].opt_value_str;
|
||||
char column_1[21], column_2[21];
|
||||
int i;
|
||||
bool add, added, add_combo;
|
||||
XTStatMetaDataPtr meta, meta2;
|
||||
|
||||
if (strcmp(cols, "all") == 0)
|
||||
cols = "time,xact,stat,rec,ind,ilog,xlog,data,to,sweep,scan,row";
|
||||
columns_used = 0;
|
||||
while (*cols) {
|
||||
i = 0;
|
||||
while (*cols && *cols != '-' && *cols != ',') {
|
||||
if (i < 20) {
|
||||
column_1[i] = *cols;
|
||||
i++;
|
||||
}
|
||||
cols++;
|
||||
}
|
||||
column_1[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if (*cols == '-') {
|
||||
cols++;
|
||||
while (*cols && *cols != '-' && *cols != ',') {
|
||||
if (i < 20) {
|
||||
column_2[i] = *cols;
|
||||
i++;
|
||||
}
|
||||
cols++;
|
||||
}
|
||||
}
|
||||
column_2[i] = 0;
|
||||
|
||||
if (*cols == ',')
|
||||
cols++;
|
||||
|
||||
if (strcmp(column_1, "ms") == 0)
|
||||
strcpy(column_1, "msec");
|
||||
if (strcmp(column_2, "ms") == 0)
|
||||
strcpy(column_2, "msec");
|
||||
add_combo = false;
|
||||
if (strcmp(column_1, "syncs/ms") == 0) {
|
||||
strcpy(column_1, "syncs");
|
||||
add_combo = true;
|
||||
}
|
||||
if (strcmp(column_2, "syncs/ms") == 0) {
|
||||
strcpy(column_2, "syncs");
|
||||
add_combo = true;
|
||||
}
|
||||
|
||||
added = false;
|
||||
for (i=0; i<XT_STAT_MAXIMUM; i++) {
|
||||
meta = xt_get_stat_meta_data(i);
|
||||
add = false;
|
||||
if (strcmp(meta->sm_short_line_1, column_1) == 0) {
|
||||
if (column_2[0]) {
|
||||
if (strcmp(meta->sm_short_line_2, column_2) == 0)
|
||||
add = true;
|
||||
}
|
||||
else {
|
||||
if (i != XT_STAT_XLOG_CACHE_USAGE)
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
else if (!column_2[0]) {
|
||||
if (strcmp(meta->sm_short_line_2, column_1) == 0) {
|
||||
/* XT_STAT_XLOG_CACHE_USAGE is ignored, unless explicity listed! */
|
||||
if (i != XT_STAT_XLOG_CACHE_USAGE)
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
added = true;
|
||||
add_statistic(i);
|
||||
if (add_combo)
|
||||
add_statistic(i+1);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
if (column_2[0])
|
||||
fprintf(stderr, "ERROR: No statistic matches display option: '%s-%s'\n", column_1, column_2);
|
||||
else
|
||||
fprintf(stderr, "ERROR: No statistic matches display option: '%s'\n", column_1);
|
||||
fprintf(stderr, "Display options: %s\n", options[OPT_DISPLAY].opt_value_str);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup "combo" fields: */
|
||||
for (i=0; i<columns_used; i++) {
|
||||
meta = xt_get_stat_meta_data(display_order[i].do_statistic);
|
||||
if (meta->sm_flags & XT_STAT_COMBO_FIELD) {
|
||||
if (i+1 < columns_used) {
|
||||
meta2 = xt_get_stat_meta_data(display_order[i+1].do_statistic);
|
||||
if (meta2->sm_flags & XT_STAT_COMBO_FIELD_2) {
|
||||
if (strcmp(meta->sm_short_line_1, meta2->sm_short_line_1) == 0)
|
||||
display_order[i].do_combo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void format_percent_value(char *buffer, double value, double perc)
|
||||
{
|
||||
value = value * (double) 100 / (double) perc;
|
||||
if (value >= 100)
|
||||
sprintf(buffer, "%.0f", value);
|
||||
else
|
||||
sprintf(buffer, "%.1f", value);
|
||||
buffer[4] = 0;
|
||||
if (buffer[3] == '.')
|
||||
buffer[3] = 0;
|
||||
}
|
||||
|
||||
#define XT_1_K ((double) 1024)
|
||||
#define XT_1_M ((double) 1024 * (double) 1024)
|
||||
#define XT_1_G ((double) 1024 * (double) 1024 * (double) 1024)
|
||||
#define XT_1_T ((double) 1024 * (double) 1024 * (double) 1024 * (double) 1024)
|
||||
#define XT_10000_K ((double) 10000 * XT_1_K)
|
||||
#define XT_10000_M ((double) 10000 * XT_1_M)
|
||||
#define XT_10000_G ((double) 10000 * XT_1_G)
|
||||
|
||||
void format_byte_value(char *buffer, double value)
|
||||
{
|
||||
double dval;
|
||||
char string[100];
|
||||
char ch;
|
||||
|
||||
if (value < (double) 100000) {
|
||||
/* byte value from 0 to 99999: */
|
||||
sprintf(buffer, "%.0f", value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < XT_10000_K) {
|
||||
dval = value / XT_1_K;
|
||||
ch = 'K';
|
||||
}
|
||||
else if (value < XT_10000_M) {
|
||||
dval = value / XT_1_M;
|
||||
ch = 'M';
|
||||
}
|
||||
else if (value < XT_10000_G) {
|
||||
dval = value / XT_1_G;
|
||||
ch = 'G';
|
||||
}
|
||||
else {
|
||||
dval = value / XT_1_T;
|
||||
ch = 'T';
|
||||
}
|
||||
|
||||
if (dval < (double) 10.0)
|
||||
sprintf(string, "%.2f", dval);
|
||||
else if (dval < (double) 100.0)
|
||||
sprintf(string, "%.1f", dval);
|
||||
else
|
||||
sprintf(string, "%.0f", dval);
|
||||
if (string[3] == '.')
|
||||
string[3] = 0;
|
||||
else
|
||||
string[4] = 0;
|
||||
sprintf(buffer, "%s%c", string, ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses:
|
||||
* t = thousands
|
||||
* m = millions
|
||||
* b = billions
|
||||
*/
|
||||
void format_mini_count_value(char *buffer, double value)
|
||||
{
|
||||
double dval;
|
||||
char string[100];
|
||||
char ch;
|
||||
|
||||
if (value < (double) 100) {
|
||||
/* Value from 0 to 99: */
|
||||
sprintf(buffer, "%.0f", value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < (double) 1000) {
|
||||
sprintf(buffer, "<t");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < (double) 10000) {
|
||||
/* Value is less than 1m */
|
||||
dval = value / (double) 1000.0;
|
||||
ch = 't';
|
||||
}
|
||||
else if (value < (double) 1000000) {
|
||||
sprintf(buffer, "<m");
|
||||
return;
|
||||
}
|
||||
else if (value < (double) 10000000) {
|
||||
/* Value is less than 1b */
|
||||
dval = value / (double) 1000000.0;
|
||||
ch = 'm';
|
||||
}
|
||||
else if (value < (double) 1000000000) {
|
||||
sprintf(buffer, "<b");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* Value is greater than 1 billion */
|
||||
dval = value / (double) 1000000000.0;
|
||||
ch = 'b';
|
||||
}
|
||||
|
||||
sprintf(string, "%1.0f", dval);
|
||||
string[1] = 0;
|
||||
sprintf(buffer, "%s%c", string, ch);
|
||||
}
|
||||
|
||||
#define XT_1_THOUSAND ((double) 1000)
|
||||
#define XT_1_MILLION ((double) 1000 * (double) 1000)
|
||||
#define XT_1_BILLION ((double) 1000 * (double) 1000 * (double) 1000)
|
||||
#define XT_1_TRILLION ((double) 1000 * (double) 1000 * (double) 1000 * (double) 1000)
|
||||
#define XT_10_THOUSAND ((double) 10 * (double) 1000)
|
||||
#define XT_10_MILLION ((double) 10 * (double) 1000 * (double) 1000)
|
||||
#define XT_10_BILLION ((double) 10 * (double) 1000 * (double) 1000 * (double) 1000)
|
||||
#define XT_10_TRILLION ((double) 10 * (double) 1000 * (double) 1000 * (double) 1000 * (double) 1000)
|
||||
|
||||
void format_count_value(char *buffer, double value)
|
||||
{
|
||||
double dval;
|
||||
char string[100];
|
||||
char ch;
|
||||
|
||||
if (value < (double) 0) {
|
||||
strcpy(buffer, "0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < XT_10_THOUSAND) {
|
||||
/* byte value from 0 to 99999: */
|
||||
sprintf(buffer, "%.0f", value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < XT_10_MILLION) {
|
||||
/* Value is less than 10 million */
|
||||
dval = value / XT_1_THOUSAND;
|
||||
ch = 't';
|
||||
}
|
||||
else if (value < XT_10_BILLION) {
|
||||
/* Value is less than 10 million */
|
||||
dval = value / XT_1_MILLION;
|
||||
ch = 'm';
|
||||
}
|
||||
else if (value < XT_10_TRILLION) {
|
||||
/* Value is less than 10 trillion */
|
||||
dval = value / XT_1_BILLION;
|
||||
ch = 'b';
|
||||
}
|
||||
else {
|
||||
dval = value / XT_1_TRILLION;
|
||||
ch = 't';
|
||||
}
|
||||
|
||||
if (dval < (double) 10.0)
|
||||
sprintf(string, "%.2f", dval);
|
||||
else if (dval < (double) 100.0)
|
||||
sprintf(string, "%.1f", dval);
|
||||
else
|
||||
sprintf(string, "%.0f", dval);
|
||||
if (string[3] == '.')
|
||||
string[3] = 0;
|
||||
else
|
||||
string[4] = 0;
|
||||
sprintf(buffer, "%s%c", string, ch);
|
||||
}
|
||||
|
||||
void print_help()
|
||||
{
|
||||
struct Options *opt;
|
||||
char command[100];
|
||||
|
||||
printf("Usage: xtstat [ options ]\n");
|
||||
printf("e.g. xtstat -D10 : Poll every 10 seconds\n");
|
||||
opt = options;
|
||||
printf("Options :-\n");
|
||||
while (opt->opt_id != OPT_NONE) {
|
||||
strcpy(command, opt->opt_name);
|
||||
if (opt->opt_flags & OPT_HAS_VALUE) {
|
||||
if (opt->opt_flags & OPT_OPTIONAL)
|
||||
strcat(command, "[=value]");
|
||||
else
|
||||
strcat(command, "=value");
|
||||
}
|
||||
if (opt->opt_char)
|
||||
printf("-%c, --%-16s %s.\n", opt->opt_char, command, opt->opt_desc);
|
||||
else
|
||||
printf(" --%-16s %s.\n", command, opt->opt_desc);
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
|
||||
void print_stat_key()
|
||||
{
|
||||
printf("Key :-\n");
|
||||
printf("K = Kilobytes (1,024 bytes)\n");
|
||||
printf("M = Megabytes (1,048,576 bytes)\n");
|
||||
printf("G = Gigabytes (1,073,741,024 bytes)\n");
|
||||
printf("T = Terabytes (1,099,511,627,776 bytes)\n");
|
||||
printf("t = thousands (1,000s)\n");
|
||||
printf("m = millions (1,000,000s)\n");
|
||||
printf("b = billions (1,000,000,000s)\n");
|
||||
}
|
||||
|
||||
void print_stat_info()
|
||||
{
|
||||
XTStatMetaDataPtr meta;
|
||||
char buffer[40];
|
||||
char desc[400];
|
||||
|
||||
printf("Statistics :-\n");
|
||||
for (int i=0; i<XT_STAT_CURRENT_MAX; i++) {
|
||||
meta = xt_get_stat_meta_data(i);
|
||||
sprintf(desc, meta->sm_description, "milli");
|
||||
sprintf(buffer, "%s-%s", meta->sm_short_line_1, meta->sm_short_line_2);
|
||||
if (meta->sm_flags & XT_STAT_COMBO_FIELD) {
|
||||
/* Combine next 2 fields: */
|
||||
i++;
|
||||
strcat(buffer, "/ms");
|
||||
strcat(desc, "/time taken in milliseconds");
|
||||
}
|
||||
printf("%-13s %-21s - %s.\n", buffer, meta->sm_name, desc);
|
||||
}
|
||||
}
|
||||
|
||||
bool match_arg(char *what, const char *opt, char **value)
|
||||
{
|
||||
while (*what && *opt && isalpha(*what)) {
|
||||
if (*what != *opt)
|
||||
return false;
|
||||
what++;
|
||||
opt++;
|
||||
}
|
||||
if (*opt)
|
||||
return false;
|
||||
if (*what == '=')
|
||||
*value = what + 1;
|
||||
else if (*what)
|
||||
return false;
|
||||
else
|
||||
*value = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv)
|
||||
{
|
||||
char *ptr;
|
||||
char *value;
|
||||
int i = 1;
|
||||
struct Options *opt;
|
||||
bool found;
|
||||
|
||||
while (i < argc) {
|
||||
ptr = argv[i];
|
||||
found = false;
|
||||
if (*ptr == '-') {
|
||||
ptr++;
|
||||
if (*ptr == '-') {
|
||||
ptr++;
|
||||
opt = options;
|
||||
while (opt->opt_id != OPT_NONE) {
|
||||
if (match_arg(ptr, opt->opt_name, &value)) {
|
||||
found = true;
|
||||
opt->opt_value_str = value;
|
||||
opt->opt_value_bool = true;
|
||||
break;
|
||||
}
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
opt = options;
|
||||
while (opt->opt_id != OPT_NONE) {
|
||||
if (*ptr == opt->opt_char) {
|
||||
ptr++;
|
||||
if (*ptr)
|
||||
opt->opt_value_str = ptr;
|
||||
else {
|
||||
opt->opt_value_str = NULL;
|
||||
if (i+1 < argc) {
|
||||
ptr = argv[i+1];
|
||||
if (*ptr != '-') {
|
||||
opt->opt_value_str = ptr;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
opt->opt_value_bool = true;
|
||||
break;
|
||||
}
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (opt->opt_flags & OPT_HAS_VALUE) {
|
||||
if (!(opt->opt_flags & OPT_OPTIONAL)) {
|
||||
if (!opt->opt_value_str) {
|
||||
fprintf(stderr, "Option requires a value: %s\n", argv[i]);
|
||||
printf("Use --help for help on commands and usage\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (opt->opt_value_str) {
|
||||
fprintf(stderr, "Option does not accept a value: %s\n", argv[i]);
|
||||
printf("Use --help for help on commands and usage\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt->opt_value_str && (opt->opt_flags & OPT_INTEGER))
|
||||
opt->opt_value_int = atoi(opt->opt_value_str);
|
||||
|
||||
if (opt->opt_id == OPT_HELP) {
|
||||
print_help();
|
||||
print_stat_key();
|
||||
print_stat_info();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INTERRUPT
|
||||
void interrupt_pbxt(MYSQL *conn)
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
|
||||
if (mysql_query(conn, "show engine pbxt status")) {
|
||||
fprintf(stderr, "%s\n", mysql_error(conn));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
mysql_free_result(res);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool display_parameters(MYSQL *conn)
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
/* send SQL query */
|
||||
if (mysql_query(conn, "show variables like 'pbxt_%'"))
|
||||
return false;
|
||||
|
||||
if (!(res = mysql_use_result(conn)))
|
||||
return false;
|
||||
|
||||
/* output table name */
|
||||
printf("-- PBXT System Variables --\n");
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
if (strcmp(row[0], "pbxt_index_cache_size") == 0)
|
||||
index_cache_size = xt_byte_size_to_int8(row[1]);
|
||||
else if (strcmp(row[0], "pbxt_record_cache_size") == 0)
|
||||
record_cache_size = xt_byte_size_to_int8(row[1]);
|
||||
else if (strcmp(row[0], "pbxt_log_cache_size") == 0)
|
||||
log_cache_size = xt_byte_size_to_int8(row[1]);
|
||||
printf("%-29s= %s\n", row[0], row[1]);
|
||||
}
|
||||
|
||||
mysql_free_result(res);
|
||||
|
||||
for (int i=0; i<XT_STAT_CURRENT_MAX; i++)
|
||||
accumulative_values[i] = 0;
|
||||
|
||||
printf("Display options: %s\n", options[OPT_DISPLAY].opt_value_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool connect(MYSQL *conn)
|
||||
{
|
||||
unsigned int type;
|
||||
|
||||
if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "tcp") == 0)
|
||||
type = MYSQL_PROTOCOL_TCP;
|
||||
else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "socket") == 0)
|
||||
type = MYSQL_PROTOCOL_SOCKET;
|
||||
else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "pipe") == 0)
|
||||
type = MYSQL_PROTOCOL_PIPE;
|
||||
else if (strcasecmp(options[OPT_PROTOCOL].opt_value_str, "memory") == 0)
|
||||
type = MYSQL_PROTOCOL_MEMORY;
|
||||
else
|
||||
type = MYSQL_PROTOCOL_DEFAULT;
|
||||
|
||||
if (mysql_options(conn, MYSQL_OPT_PROTOCOL, (char *) &type))
|
||||
return false;
|
||||
|
||||
if (mysql_options(conn, MYSQL_READ_DEFAULT_GROUP, "xtstat"))
|
||||
return false;
|
||||
|
||||
if (strcasecmp(options[OPT_DATABASE].opt_value_str, "pbxt") == 0)
|
||||
use_i_s = FALSE;
|
||||
else if (strcasecmp(options[OPT_DATABASE].opt_value_str, "information_schema") == 0)
|
||||
use_i_s = TRUE;
|
||||
else
|
||||
use_i_s = TRUE;
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn,
|
||||
options[OPT_HOST].opt_value_str,
|
||||
options[OPT_USER].opt_value_str,
|
||||
options[OPT_PASSWORD].opt_value_str,
|
||||
options[OPT_DATABASE].opt_value_str,
|
||||
options[OPT_PORT].opt_value_int,
|
||||
options[OPT_SOCKET].opt_value_str,
|
||||
0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
llong current_values[XT_STAT_CURRENT_MAX];
|
||||
double value;
|
||||
char str_value[100];
|
||||
XTStatMetaDataPtr meta;
|
||||
int len;
|
||||
int stat;
|
||||
int err;
|
||||
bool select_worked = true;
|
||||
|
||||
xt_set_time_unit("msec");
|
||||
parse_args(argc, argv);
|
||||
|
||||
determine_display_order();
|
||||
|
||||
if (!(conn = mysql_init(NULL))) {
|
||||
fprintf(stderr, "Insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!connect(conn) || !display_parameters(conn)) {
|
||||
fprintf(stderr, "%s\n", mysql_error(conn));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
retry:
|
||||
for (int loop = 0; ; loop++) {
|
||||
if (use_i_s)
|
||||
err = mysql_query(conn, "select id, Value from information_schema.pbxt_statistics order by ID");
|
||||
else
|
||||
err = mysql_query(conn, "select id, Value from pbxt.statistics order by ID");
|
||||
if (err)
|
||||
goto reconnect;
|
||||
|
||||
if (!(res = mysql_use_result(conn)))
|
||||
goto reconnect;
|
||||
select_worked = true;
|
||||
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
stat = atoi(row[0])-1;
|
||||
current_values[stat] = atoll(row[1]);
|
||||
}
|
||||
mysql_free_result(res);
|
||||
|
||||
#ifdef DEBUG_INTERRUPT
|
||||
if (current_values[XT_STAT_STAT_WRITES] - accumulative_values[XT_STAT_STAT_WRITES] == 0 &&
|
||||
current_values[XT_STAT_REC_SYNC_TIME] - accumulative_values[XT_STAT_REC_SYNC_TIME] == 0 &&
|
||||
current_values[XT_STAT_IND_SYNC_TIME] - accumulative_values[XT_STAT_IND_SYNC_TIME] == 0)
|
||||
interrupt_pbxt();
|
||||
#endif
|
||||
|
||||
if ((loop % 25) == 0) {
|
||||
for (int column=0; column<columns_used; column++) {
|
||||
len = 5;
|
||||
meta = xt_get_stat_meta_data(display_order[column].do_statistic);
|
||||
strcpy(str_value, meta->sm_short_line_1);
|
||||
if (display_order[column].do_combo) {
|
||||
/* Combine next 2 fields: */
|
||||
len = 8;
|
||||
column++;
|
||||
}
|
||||
else if (meta->sm_flags & XT_STAT_PERCENTAGE)
|
||||
len = 4;
|
||||
else if (meta->sm_flags & XT_STAT_DATE)
|
||||
len = 15;
|
||||
printf("%*s ", len, str_value);
|
||||
}
|
||||
printf("\n");
|
||||
for (int column=0; column<columns_used; column++) {
|
||||
len = 5;
|
||||
meta = xt_get_stat_meta_data(display_order[column].do_statistic);
|
||||
strcpy(str_value, meta->sm_short_line_2);
|
||||
if (display_order[column].do_combo) {
|
||||
/* Combine next 2 fields: */
|
||||
len = 8;
|
||||
column++;
|
||||
strcat(str_value, "/ms");
|
||||
}
|
||||
else if (meta->sm_flags & XT_STAT_PERCENTAGE)
|
||||
len = 4;
|
||||
else if (meta->sm_flags & XT_STAT_DATE)
|
||||
len = 15;
|
||||
printf("%*s ", len, str_value);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (int column=0; column<columns_used; column++) {
|
||||
len = 5;
|
||||
stat = display_order[column].do_statistic;
|
||||
meta = xt_get_stat_meta_data(stat);
|
||||
if (meta->sm_flags & XT_STAT_ACCUMULATIVE) {
|
||||
/* Take care of overflow! */
|
||||
if (current_values[stat] < accumulative_values[stat])
|
||||
value = (double) (0xFFFFFFFF - (accumulative_values[stat] - current_values[stat]));
|
||||
else
|
||||
value = (double) (current_values[stat] - accumulative_values[stat]);
|
||||
}
|
||||
else
|
||||
value = (double) current_values[stat];
|
||||
accumulative_values[stat] = current_values[stat];
|
||||
if (meta->sm_flags & XT_STAT_TIME_VALUE)
|
||||
value = value / (double) 1000;
|
||||
if (display_order[column].do_combo) {
|
||||
format_mini_count_value(str_value, value);
|
||||
strcat(str_value, "/");
|
||||
column++;
|
||||
stat = display_order[column].do_statistic;
|
||||
value = (double) (current_values[stat] - accumulative_values[stat]);
|
||||
accumulative_values[stat] = current_values[stat];
|
||||
value = value / (double) 1000;
|
||||
format_count_value(&str_value[strlen(str_value)], value);
|
||||
len = 8;
|
||||
}
|
||||
else if (meta->sm_flags & XT_STAT_PERCENTAGE) {
|
||||
double perc = 100;
|
||||
switch (stat) {
|
||||
case XT_STAT_REC_CACHE_USAGE: perc = (double)record_cache_size; break;
|
||||
case XT_STAT_IND_CACHE_USAGE: perc = (double)index_cache_size; break;
|
||||
case XT_STAT_XLOG_CACHE_USAGE: perc = (double)log_cache_size; break;
|
||||
}
|
||||
format_percent_value(str_value, value, perc);
|
||||
len = 4;
|
||||
}
|
||||
else if (meta->sm_flags & XT_STAT_DATE) {
|
||||
time_t ticks = (time_t) value;
|
||||
const struct tm *ltime = localtime(&ticks);
|
||||
strftime(str_value, 99, "%y%m%d %H:%M:%S", ltime);
|
||||
len = 15;
|
||||
}
|
||||
else if (meta->sm_flags & XT_STAT_BYTE_COUNT)
|
||||
format_byte_value(str_value, value);
|
||||
else
|
||||
format_count_value(str_value, value);
|
||||
if (column == columns_used-1)
|
||||
printf("%*s\n", len, str_value);
|
||||
else
|
||||
printf("%*s ", len, str_value);
|
||||
}
|
||||
|
||||
sleep(options[OPT_DELAY].opt_value_int);
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_close(conn);
|
||||
return 0;
|
||||
|
||||
reconnect:
|
||||
/* Reconnect... */
|
||||
if (select_worked) {
|
||||
/* Only print message if the SELECT worked.
|
||||
* or we will get a screen full of messages:
|
||||
*/
|
||||
fprintf(stderr, "%s\n", mysql_error(conn));
|
||||
printf("Reconnecting...\n");
|
||||
}
|
||||
mysql_close(conn);
|
||||
if (!(conn = mysql_init(NULL))) {
|
||||
fprintf(stderr, "Insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
do {
|
||||
sleep(2);
|
||||
} while (!connect(conn));
|
||||
select_worked = false;
|
||||
goto retry;
|
||||
}
|
@ -80,6 +80,7 @@ using drizzled::plugin::InfoSchemaMethods;
|
||||
#include "systab_xt.h"
|
||||
#include "xaction_xt.h"
|
||||
#include "backup_xt.h"
|
||||
#include "heap_xt.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
//#define XT_USE_SYS_PAR_DEBUG_SIZES
|
||||
|
@ -54,6 +54,7 @@ extern pthread_key_t THR_Session;
|
||||
#include "database_xt.h"
|
||||
#include "cache_xt.h"
|
||||
#include "datalog_xt.h"
|
||||
#include "memory_xt.h"
|
||||
|
||||
static void myxt_bitmap_init(XTThreadPtr self, MX_BITMAP *map, u_int n_bits);
|
||||
static void myxt_bitmap_free(XTThreadPtr self, MX_BITMAP *map);
|
||||
|
@ -128,4 +128,8 @@ const int max_connections = 500;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DBUG_ON) && !defined(DBUG_OFF) && !defined(DEBUG)
|
||||
#define DEBUG
|
||||
#endif // DBUG_ON
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user