8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:43:02 +01:00

Implement improvement CORE-1999 : TimeStamp in the every line output gbak.exe utility

Minor fixes in service manager.
Thanks to Alex for help.
Documentation will follow.
This commit is contained in:
hvlad 2015-07-26 20:49:15 +00:00
parent fa46891583
commit b77bf19e3b
12 changed files with 266 additions and 32 deletions

View File

@ -428,6 +428,9 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
general_on_error();
END_ERROR;
BURP_verbose(369);
// msg 369 total statistics
FINISH
ON_ERROR
general_on_error();

View File

@ -112,13 +112,29 @@ static gbak_action open_files(const TEXT *, const TEXT**, bool, USHORT,
static int svc_api_gbak(Firebird::UtilSvc*, const Switches& switches);
static void burp_output(bool err, const SCHAR*, ...) ATTRIBUTE_FORMAT(2,3);
static void burp_usage(const Switches& switches);
static Switches::in_sw_tab_t* findSwitchOrThrow(Switches& switches, Firebird::string& sw);
static Switches::in_sw_tab_t* findSwitchOrThrow(Firebird::UtilSvc*, Switches& switches, Firebird::string& sw);
// fil.fil_length is FB_UINT64
const ULONG KBYTE = 1024;
const ULONG MBYTE = KBYTE * KBYTE;
const ULONG GBYTE = MBYTE * KBYTE;
// Must be consistent with enum BurpGlobals::StatCounter
struct StatFormat
{
const char* header;
const char* format;
char width;
};
static const char* STAT_CHARS = "TDRW";
static const StatFormat STAT_FORMATS[] =
{
{"time", "%4lu.%03u ", 9},
{"delta", "%2lu.%03u ", 7},
{"reads", "%6"UQUADFORMAT" ", 7},
{"writes", "%6"UQUADFORMAT" ", 7}
};
int BURP_main(Firebird::UtilSvc* uSvc)
{
@ -237,15 +253,13 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
BURP_error(333, true, SafeArg() << inSw->in_sw_name << verbint_val);
if (itr >= argc - 1)
BURP_error(326, true); // verbose interval value parameter missing
argv[itr++] = 0;
verbint_val = get_number(argv[itr]);
verbint_val = get_number(argv[++itr]);
if (verbint_val < MIN_VERBOSE_INTERVAL)
{
// verbose interval value cannot be smaller than @1
BURP_error(327, true, SafeArg() << MIN_VERBOSE_INTERVAL);
}
flag_verbint = true;
argv[itr] = 0;
break;
#ifdef TRUSTED_AUTH
case IN_SW_BURP_TRUSTED_AUTH: // use trusted auth
@ -399,7 +413,7 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
}
static Switches::in_sw_tab_t* findSwitchOrThrow(Switches& switches, Firebird::string& sw)
static Switches::in_sw_tab_t* findSwitchOrThrow(Firebird::UtilSvc* uSvc, Switches& switches, Firebird::string& sw)
{
/**************************************
*
@ -420,11 +434,19 @@ static Switches::in_sw_tab_t* findSwitchOrThrow(Switches& switches, Firebird::st
if (invalid)
{
BURP_print(true, 137, sw.c_str());
// msg 137 unknown switch %s
burp_usage(switches);
BURP_error(1, true);
// msg 1: found unknown switch
if (! uSvc->isService())
{
BURP_print(true, 137, sw.c_str());
// msg 137 unknown switch %s
burp_usage(switches);
BURP_error(1, true);
// msg 1: found unknown switch
}
else
{
BURP_error(137, true, sw.c_str());
// msg 137 unknown switch %s
}
}
return NULL;
@ -538,7 +560,7 @@ int gbak(Firebird::UtilSvc* uSvc)
str = none;
}
Switches::in_sw_tab_t* const in_sw_tab = findSwitchOrThrow(switches, str);
Switches::in_sw_tab_t* const in_sw_tab = findSwitchOrThrow(uSvc, switches, str);
fb_assert(in_sw_tab);
//in_sw_tab->in_sw_state = true; It's not enough with switches that have multiple spellings
switches.activate(in_sw_tab->in_sw);
@ -813,6 +835,28 @@ int gbak(Firebird::UtilSvc* uSvc)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_verbose = true;
break;
case IN_SW_BURP_STATS:
if (tdgbl->gbl_stat_flags)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
if (++itr >= argc)
BURP_error(366, true); // statistics parameter missing
{
const char* perf_val = argv[itr];
const char* c = perf_val;
int len = strlen(STAT_CHARS);
for (; *c && len; c++, len--)
{
const char* pos = strchr(STAT_CHARS, toupper(*c));
if (!pos)
BURP_error(367, true, SafeArg() << *c); // wrong char "@1" at statistics parameter
tdgbl->gbl_stat_flags |= 1 << (pos - STAT_CHARS);
}
if (*c)
BURP_error(368, true); // 'too many chars at statistics parameter'
}
break;
case IN_SW_BURP_CO:
if (tdgbl->gbl_sw_convert_ext_tables)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
@ -1628,7 +1672,12 @@ void BURP_verbose(USHORT number, const SafeArg& arg)
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
if (tdgbl->gbl_sw_verbose)
BURP_print(false, number, arg);
{
tdgbl->print_stats_header();
BURP_msg_partial(false, 169); // msg 169: gbak:
tdgbl->print_stats(number);
BURP_msg_put(false, number, arg);
}
else
burp_output(false, "%s", "");
}
@ -1651,7 +1700,12 @@ void BURP_verbose(USHORT number, const char* str)
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
if (tdgbl->gbl_sw_verbose)
BURP_print(false, number, str);
{
tdgbl->print_stats_header();
BURP_msg_partial(false, 169); // msg 169: gbak:
tdgbl->print_stats(number);
BURP_msg_put(false, number, SafeArg() << str);
}
else
burp_output(false, "%s", "");
}
@ -2399,6 +2453,123 @@ bool BurpGlobals::skipRelation(const char* name)
return skipDataMatcher->result();
}
void BurpGlobals::read_stats(SINT64* stats)
{
if (!db_handle)
return;
const char info[] =
{
isc_info_reads,
isc_info_writes
};
ISC_STATUS_ARRAY status = {0};
char buffer[sizeof(info) * (1 + 2 + 8) + 2];
isc_database_info(status, &db_handle, sizeof(info), info, sizeof(buffer), buffer);
char *p = buffer, *const e = buffer + sizeof(buffer);
while (p < e)
{
int flag = -1;
switch (*p)
{
case isc_info_reads:
flag = READS;
break;
case isc_info_writes:
flag = WRITES;
break;
case isc_info_end:
default:
p = e;
}
if (flag != -1)
{
const int len = isc_vax_integer(p + 1, 2);
stats[flag] = isc_portable_integer((ISC_UCHAR*)p + 1 + 2, len);
p += len + 3;
}
}
}
void BurpGlobals::print_stats(USHORT number)
{
if (!gbl_stat_flags || gbl_stat_done)
return;
const bool total = (number == 369);
// msg 369 total statistics
burp_output(false, " ");
const int time_mask = (1 << TIME_TOTAL) | (1 << TIME_DELTA);
if (gbl_stat_flags & time_mask)
{
const SINT64 t0 = fb_utils::query_performance_counter();
const SINT64 freq_ms = fb_utils::query_performance_frequency() / 1000;
if (gbl_stat_flags & (1 << TIME_TOTAL))
{
SINT64 t1 = (t0 - gbl_stats[TIME_TOTAL]) / freq_ms;
burp_output(false, STAT_FORMATS[TIME_TOTAL].format, (int)(t1 / 1000), (int)(t1 % 1000));
}
if (gbl_stat_flags & (1 << TIME_DELTA))
{
SINT64 t2 = (t0 - gbl_stats[TIME_DELTA]) / freq_ms;
burp_output(false, STAT_FORMATS[TIME_DELTA].format, (int)(t2 / 1000), (int)(t2 % 1000));
gbl_stats[TIME_DELTA] = t0;
}
}
SINT64 cur_stats[LAST_COUNTER] = {0};
if((gbl_stat_flags & ~time_mask) && !gbl_stat_done)
read_stats(cur_stats);
for (int i = READS; i < LAST_COUNTER; i++)
{
if (gbl_stat_flags & (1 << i))
{
SINT64 val = 0;
if (total || gbl_stat_done)
val = cur_stats[i];
else
val = cur_stats[i] - gbl_stats[i];
gbl_stats[i] = cur_stats[i];
burp_output(false, STAT_FORMATS[i].format, val);
}
}
if (total)
gbl_stat_done = true;
}
void BurpGlobals::print_stats_header()
{
if (gbl_stat_header || !gbl_stat_flags)
return;
gbl_stat_header = true;
BURP_msg_partial(false, 169); // msg 169: gbak:
burp_output(false, " ");
for (int i = 0; i < LAST_COUNTER; i++)
{
if (gbl_stat_flags & (1 << i))
burp_output(false, "%-*s", STAT_FORMATS[i].width, STAT_FORMATS[i].header);
}
burp_output(false, "\n");
}
UnicodeCollationHolder::UnicodeCollationHolder(MemoryPool& pool)
{
cs = FB_NEW(pool) charset;

View File

@ -922,6 +922,12 @@ public:
&veryEnd - reinterpret_cast<char*>(&gbl_database_file_name));
memset(status_vector, 0, sizeof(status_vector));
gbl_stat_flags = 0;
gbl_stat_header = false;
gbl_stat_done = false;
memset(gbl_stats, 0, sizeof(gbl_stats));
gbl_stats[TIME_TOTAL] = gbl_stats[TIME_DELTA] = fb_utils::query_performance_counter();
// normal code follows
exit_code = FINI_ERROR; // prevent FINI_OK in case of unknown error thrown
// would be set to FINI_OK (==0) in exit_local
@ -1087,6 +1093,17 @@ public:
public:
Firebird::string toSystem(const Firebird::PathName& from);
enum StatCounter { TIME_TOTAL = 0, TIME_DELTA, READS, WRITES, LAST_COUNTER};
void read_stats(SINT64* stats);
void print_stats(USHORT number);
void print_stats_header();
int gbl_stat_flags; // bitmask, bit numbers see at enum StatCounter
bool gbl_stat_header; // true, if stats header was printed
bool gbl_stat_done; // true, if main process is done, stop to collect db-level stats
SINT64 gbl_stats[LAST_COUNTER];
};
// CVC: This aux routine declared here to not force inclusion of burp.h with burp_proto.h

View File

@ -89,6 +89,7 @@ const int IN_SW_BURP_FIX_FSS_METADATA = 44; // fix unicode_fss metadata
const int IN_SW_BURP_FETCHPASS = 45; // fetch default password from file to use on attach
const int IN_SW_BURP_VERBINT = 46; // verbose but with specific interval
const int IN_SW_BURP_STATS = 47; // print statistics
/**************************************************************************/
// used 0BCDEFGILMNOPRSTUVYZ available AHJQWX
@ -165,6 +166,16 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 277: @1SE(RVICE) use services manager
{IN_SW_BURP_SKIP_DATA, isc_spb_res_skip_data, "SKIP_DATA", 0, 0, 0, false, 355, 6, NULL, boGeneral},
// msg 355: @1SKIP_DATA skip data for table
{IN_SW_BURP_STATS, isc_spb_bkp_stat, "STATISTICS", 0, 0, 0, false, 361, 2, NULL, boGeneral},
// msg 361: @1ST(ATISTICS) TDRW show statistics:
{-1, 0, " ", 0, 0, 0, false, 362, 0, NULL, boGeneral},
// msg 362: T time from start
{-1, 0, " ", 0, 0, 0, false, 363, 0, NULL, boGeneral},
// msg 363: D delta time
{-1, 0, " ", 0, 0, 0, false, 364, 0, NULL, boGeneral},
// msg 364: R page reads
{-1, 0, " ", 0, 0, 0, false, 365, 0, NULL, boGeneral},
// msg 365: W page writes
{IN_SW_BURP_T, 0, "TRANSPORTABLE", 0, 0, 0, false, 175, 1, NULL, boBackup},
// msg 175: @1TRANSPORTABLE transportable backup -- data in XDR format
#ifdef TRUSTED_AUTH

View File

@ -536,6 +536,9 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
//FB_UINT64 cumul_count =
MVOL_fini_read();
BURP_verbose(369);
// msg 369 total statistics
// Close database before we attach to it again.
FINISH
ON_ERROR

View File

@ -331,6 +331,7 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
case isc_spb_dbname:
case isc_spb_res_fix_fss_data:
case isc_spb_res_fix_fss_metadata:
case isc_spb_bkp_stat:
return StringSpb;
case isc_spb_bkp_factor:
case isc_spb_bkp_length:

View File

@ -383,6 +383,7 @@
#define isc_spb_bkp_factor 6
#define isc_spb_bkp_length 7
#define isc_spb_bkp_skip_data 8
#define isc_spb_bkp_stat 15
#define isc_spb_bkp_ignore_checksums 0x01
#define isc_spb_bkp_ignore_limbo 0x02
#define isc_spb_bkp_metadata_only 0x04
@ -489,6 +490,7 @@
#define isc_spb_res_access_mode 12
#define isc_spb_res_fix_fss_data 13
#define isc_spb_res_fix_fss_metadata 14
#define isc_spb_res_stat isc_spb_bkp_stat
#define isc_spb_res_metadata_only isc_spb_bkp_metadata_only
#define isc_spb_res_deactivate_idx 0x0100
#define isc_spb_res_no_shadow 0x0200

View File

@ -136,24 +136,6 @@ namespace {
GlobalPtr<AllServices> allServices; // protected by globalServicesMutex
volatile bool svcShutdown = false;
void put_status_arg(Arg::StatusVector& status, const MsgFormat::safe_cell& value)
{
using MsgFormat::safe_cell;
switch (value.type)
{
case safe_cell::at_int64:
case safe_cell::at_uint64:
status << Arg::Num(static_cast<SLONG>(value.i_value)); // May truncate number!
break;
case safe_cell::at_str:
status << value.st_value.s_string;
break;
default:
break;
}
}
void spbVersionError()
{
ERR_post(Arg::Gds(isc_bad_spb_form) <<
@ -506,6 +488,7 @@ void Service::setServiceStatus(const USHORT facility, const USHORT errcode,
status << Arg::Gds(ENCODE_ISC_MSG(errcode, facility));
// stuff params
svc_arg_ptr = svc_arg_conv;
for (unsigned int loop = 0; loop < args.getCount(); ++loop)
{
put_status_arg(status, args.getCell(loop));
@ -514,6 +497,33 @@ void Service::setServiceStatus(const USHORT facility, const USHORT errcode,
ERR_post_nothrow(status, &svc_status);
}
void Service::put_status_arg(Arg::StatusVector& status, const MsgFormat::safe_cell& value)
{
using MsgFormat::safe_cell;
switch (value.type)
{
case safe_cell::at_int64:
case safe_cell::at_uint64:
status << Arg::Num(static_cast<SLONG>(value.i_value)); // May truncate number!
break;
case safe_cell::at_str:
status << value.st_value.s_string;
break;
case safe_cell::at_char:
svc_arg_ptr[0] = value.c_value;
svc_arg_ptr[1] = 0;
status << svc_arg_ptr;
svc_arg_ptr += 2;
break;
default:
fb_assert(false);
break;
}
}
void Service::hidePasswd(ArgvType&, int)
{
// no action
@ -2770,6 +2780,7 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
break;
case isc_spb_res_fix_fss_data:
case isc_spb_res_fix_fss_metadata:
case isc_spb_bkp_stat:
if (!get_action_svc_parameter(spb.getClumpTag(), reference_burp_in_sw_table, switches))
{
return false;

View File

@ -230,6 +230,8 @@ private:
// Sends stdin for a service
// Returns number of bytes service wants more
ULONG put(const UCHAR* buffer, ULONG length);
// Copies argument value to status vector
void put_status_arg(Firebird::Arg::StatusVector& status, const MsgFormat::safe_cell& value);
// Increment circular buffer pointer
static ULONG add_one(ULONG i);
@ -287,6 +289,8 @@ private:
bool svc_do_shutdown;
bool svc_shutdown_in_progress;
bool svc_timeout;
char svc_arg_conv[MsgFormat::SAFEARG_MAX_ARG * 2];
char* svc_arg_ptr;
Firebird::string svc_username;
Firebird::string svc_sql_role;

View File

@ -9,7 +9,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
('2014-04-22 16:39:03', 'DYN', 8, 290)
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
('1996-11-07 13:38:41', 'TEST', 11, 4)
('2014-05-09 01:30:36', 'GBAK', 12, 361)
('2015-07-23 14:20:00', 'GBAK', 12, 370)
('2015-05-04 13:00:00', 'SQLERR', 13, 1044)
('1996-11-07 13:38:42', 'SQLWARN', 14, 613)
('2006-09-10 03:04:31', 'JRD_BUGCHK', 15, 307)

View File

@ -2333,6 +2333,15 @@ ERROR: Backup incomplete', NULL, NULL);
(NULL, 'update_ownership', 'restore.epp', NULL, 12, 358, NULL, 'updating ownership of packages, procedures and tables', NULL, NULL);
(NULL, 'fix_missing_privileges', 'restore.epp', NULL, 12, 359, NULL, 'adding missing privileges', NULL, NULL);
(NULL, 'RESTORE_restore', 'restore.epp', NULL, 12, 360, NULL, 'adjusting the ONLINE and FORCED WRITES flags', NULL, NULL);
(NULL, 'burp_usage', 'burp.c', NULL, 12, 361, NULL, ' @1ST(ATISTICS) TDRW show statistics:', NULL, NULL);
(NULL, 'burp_usage', 'burp.c', NULL, 12, 362, NULL, ' T time from start', NULL, NULL);
(NULL, 'burp_usage', 'burp.c', NULL, 12, 363, NULL, ' D delta time', NULL, NULL);
(NULL, 'burp_usage', 'burp.c', NULL, 12, 364, NULL, ' R page reads', NULL, NULL);
(NULL, 'burp_usage', 'burp.c', NULL, 12, 365, NULL, ' W page writes', NULL, NULL);
('gbak_missing_perf', 'api_gbak/gbak', 'burp.cpp', NULL, 12, 366, NULL, 'statistics parameter missing', NULL, NULL);
('gbak_wrong_perf', 'api_gbak/gbak', 'burp.cpp', NULL, 12, 367, NULL, 'wrong char "@1" at statistics parameter', NULL, NULL);
('gbak_too_long_perf', 'api_gbak/gbak', 'burp.cpp', NULL, 12, 368, NULL, 'too many chars at statistics parameter', NULL, NULL);
(NULL, 'api_gbak/gbak', 'burp.cpp', NULL, 12, 369, NULL, 'total statistics', NULL, NULL);
-- SQLERR
(NULL, NULL, NULL, NULL, 13, 1, NULL, 'Firebird error', NULL, NULL);
(NULL, NULL, NULL, NULL, 13, 74, NULL, 'Rollback not performed', NULL, NULL);

View File

@ -362,6 +362,7 @@ const SvcSwitches backupOptions[] =
{"bkp_no_triggers", putOption, 0, isc_spb_bkp_no_triggers, 0},
{"verbint", putNumericArgument, 0, isc_spb_verbint, 0},
{"bkp_skip_data", putStringArgument, 0, isc_spb_bkp_skip_data, 0},
{"bkp_stat", putStringArgument, 0, isc_spb_bkp_stat, 0 },
{0, 0, 0, 0, 0}
};
@ -386,6 +387,7 @@ const SvcSwitches restoreOptions[] =
{"res_metadata_only", putOption, 0, isc_spb_res_metadata_only, 0},
{"verbint", putNumericArgument, 0, isc_spb_verbint, 0},
{"res_skip_data", putStringArgument, 0, isc_spb_res_skip_data, 0},
{"res_stat", putStringArgument, 0, isc_spb_res_stat, 0 },
{0, 0, 0, 0, 0}
};