mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 12:03:03 +01:00
Collect network statistics and make it available for the user applications. (#8310)
* Make Remote provider collect wire statistics. New info items to query wire stats counters. * New ISQL commands to show wire statistics. * Remove requirement to not mix local and remote handled items in the same info request. * Follow @asfernandes suggestion about class members initialization. * Make ctor explicit, as @sim1984 suggested * Put isc_info_end into response buffer despite of its presence in info items.
This commit is contained in:
parent
8ca2314355
commit
df885d5935
@ -327,10 +327,129 @@ SQL> SET PER_TAB OFF;
|
||||
|
||||
|
||||
|
||||
12) SET WIRE_STATS option.
|
||||
|
||||
Author: Vladyslav Khorsun <hvlad at users sourceforge net>
|
||||
|
||||
When set to ON shows wire (network) statistics after query execution.
|
||||
It is set to OFF by default. The name WIRE_STATS could be shortened up to WIRE.
|
||||
|
||||
The statistics counters shown in two groups: 'logical' and 'physical':
|
||||
- logical counters show numbers of packets in terms of Firebird wire protocol
|
||||
and number of bytes send before compression and received after decompression;
|
||||
- physical counters show number of physical packets and bytes send and
|
||||
received over the wire, number of bytes could be affected by wire compression,
|
||||
if present. Also, number of network roundtrips is shown: it is number of
|
||||
changes of IO direction from 'send' to 'receive'.
|
||||
|
||||
Note, wire statistics is gathered by Remote provider only, i.e. it is always
|
||||
zero for embedded connections. Also, it is collected by client and IO direction
|
||||
(send, receive) is shown from client point of view.
|
||||
|
||||
Examples:
|
||||
|
||||
1. INET protocol with wire compression.
|
||||
Set WireCompression = true in firebird.conf
|
||||
|
||||
>isql inet://employee
|
||||
|
||||
SQL> SET;
|
||||
Print statistics: OFF
|
||||
Print per-table stats: OFF
|
||||
Print wire stats: OFF
|
||||
...
|
||||
|
||||
SQL> SET WIRE;
|
||||
SQL>
|
||||
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;
|
||||
|
||||
COUNT
|
||||
=====================
|
||||
67
|
||||
|
||||
Wire logical statistics:
|
||||
send packets = 6
|
||||
recv packets = 5
|
||||
send bytes = 184
|
||||
recv bytes = 224
|
||||
Wire physical statistics:
|
||||
send packets = 3
|
||||
recv packets = 2
|
||||
send bytes = 123
|
||||
recv bytes = 88
|
||||
roundtrips = 2
|
||||
|
||||
Note difference due to wire compression in send/recv bytes for logical and
|
||||
physical stats.
|
||||
|
||||
|
||||
2. XNET protocol (wire compression is not used).
|
||||
|
||||
>isql xnet://employee
|
||||
|
||||
SQL> SET WIRE;
|
||||
SQL>
|
||||
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;
|
||||
|
||||
COUNT
|
||||
=====================
|
||||
67
|
||||
|
||||
Wire logical statistics:
|
||||
send packets = 5
|
||||
recv packets = 6
|
||||
send bytes = 176
|
||||
recv bytes = 256
|
||||
Wire physical statistics:
|
||||
send packets = 5
|
||||
recv packets = 5
|
||||
send bytes = 176
|
||||
recv bytes = 256
|
||||
roundtrips = 5
|
||||
|
||||
Note, send/recv bytes for logical and physical stats are equal.
|
||||
|
||||
|
||||
3. Embedded connection (wire statistics is absent).
|
||||
|
||||
SQL> SET WIRE;
|
||||
SQL>
|
||||
SQL> select count(*) from rdb$relations;
|
||||
|
||||
COUNT
|
||||
=====================
|
||||
67
|
||||
|
||||
Wire logical statistics:
|
||||
send packets = 0
|
||||
recv packets = 0
|
||||
send bytes = 0
|
||||
recv bytes = 0
|
||||
Wire physical statistics:
|
||||
send packets = 0
|
||||
recv packets = 0
|
||||
send bytes = 0
|
||||
recv bytes = 0
|
||||
roundtrips = 0
|
||||
|
||||
|
||||
|
||||
13) SHOW WIRE_STATISTICS command.
|
||||
|
||||
Author: Vladyslav Khorsun <hvlad at users sourceforge net>
|
||||
|
||||
New ISQL command that shows accumulated wire statistics. There is also
|
||||
shortened alias WIRE_STATS.
|
||||
|
||||
The command show values of wire statistics counters, accumulated since the
|
||||
connection start time. Format is the same as of SET STATS above.
|
||||
|
||||
|
||||
|
||||
Isql enhancements in Firebird v6.
|
||||
---------------------------------
|
||||
|
||||
12) EXPLAIN statement.
|
||||
14) EXPLAIN statement.
|
||||
|
||||
Author: Adriano dos Santos Fernandes
|
||||
|
||||
@ -355,7 +474,7 @@ SQL>
|
||||
SQL> set term ;!
|
||||
|
||||
|
||||
13) SET AUTOTERM ON/OFF
|
||||
15) SET AUTOTERM ON/OFF
|
||||
|
||||
Author: Adriano dos Santos Fernandes
|
||||
|
||||
|
@ -178,6 +178,17 @@ enum db_info_types
|
||||
|
||||
fb_info_parallel_workers = 149,
|
||||
|
||||
// Wire stats items, implemented by Remote provider only
|
||||
fb_info_wire_out_packets = 150,
|
||||
fb_info_wire_in_packets = 151,
|
||||
fb_info_wire_out_bytes = 152,
|
||||
fb_info_wire_in_bytes = 153,
|
||||
fb_info_wire_snd_packets = 154,
|
||||
fb_info_wire_rcv_packets = 155,
|
||||
fb_info_wire_snd_bytes = 156,
|
||||
fb_info_wire_rcv_bytes = 157,
|
||||
fb_info_wire_roundtrips = 158,
|
||||
|
||||
isc_info_db_last_value /* Leave this LAST! */
|
||||
};
|
||||
|
||||
|
@ -4507,6 +4507,15 @@ const
|
||||
fb_info_username = byte(147);
|
||||
fb_info_sqlrole = byte(148);
|
||||
fb_info_parallel_workers = byte(149);
|
||||
fb_info_wire_out_packets = byte(150);
|
||||
fb_info_wire_in_packets = byte(151);
|
||||
fb_info_wire_out_bytes = byte(152);
|
||||
fb_info_wire_in_bytes = byte(153);
|
||||
fb_info_wire_snd_packets = byte(154);
|
||||
fb_info_wire_rcv_packets = byte(155);
|
||||
fb_info_wire_snd_bytes = byte(156);
|
||||
fb_info_wire_rcv_bytes = byte(157);
|
||||
fb_info_wire_roundtrips = byte(158);
|
||||
fb_info_crypt_encrypted = $01;
|
||||
fb_info_crypt_process = $02;
|
||||
fb_feature_multi_statements = byte(1);
|
||||
|
@ -577,6 +577,7 @@ public:
|
||||
KeepTranParams = true;
|
||||
TranParams->assign(DEFAULT_DML_TRANS_SQL);
|
||||
PerTableStats = false;
|
||||
WireStats = false;
|
||||
ExplainCommand = false;
|
||||
}
|
||||
|
||||
@ -603,6 +604,7 @@ public:
|
||||
SCHAR ISQL_charset[MAXCHARSET_SIZE];
|
||||
bool KeepTranParams;
|
||||
bool PerTableStats;
|
||||
bool WireStats;
|
||||
bool ExplainCommand;
|
||||
};
|
||||
|
||||
@ -5453,7 +5455,7 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
exec_path_display,
|
||||
sql, warning, sqlCont, heading, bail,
|
||||
bulk_insert, maxrows, stmtTimeout,
|
||||
keepTranParams, perTableStats,
|
||||
keepTranParams, perTableStats, wireStats,
|
||||
wrong
|
||||
};
|
||||
SetOptions(const optionsMap* inmap, size_t insize, int wrongval)
|
||||
@ -5495,7 +5497,8 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
{SetOptions::stmtTimeout, "LOCAL_TIMEOUT", 0},
|
||||
{SetOptions::sqlCont, "DECFLOAT", 0},
|
||||
{SetOptions::keepTranParams, "KEEP_TRAN_PARAMS", 9},
|
||||
{SetOptions::perTableStats, "PER_TABLE_STATS", 7}
|
||||
{SetOptions::perTableStats, "PER_TABLE_STATS", 7},
|
||||
{SetOptions::wireStats, "WIRE_STATS", 4}
|
||||
};
|
||||
|
||||
// Display current set options
|
||||
@ -5746,6 +5749,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
|
||||
ret = do_set_command(parms[2], &setValues.PerTableStats);
|
||||
break;
|
||||
|
||||
case SetOptions::wireStats:
|
||||
ret = do_set_command(parms[2], &setValues.WireStats);
|
||||
break;
|
||||
|
||||
default:
|
||||
//{
|
||||
// TEXT msg_string[MSG_LENGTH];
|
||||
@ -6372,6 +6379,7 @@ static processing_state print_sets()
|
||||
|
||||
print_set("Print statistics:", setValues.Stats);
|
||||
print_set("Print per-table stats:", setValues.PerTableStats);
|
||||
print_set("Print wire stats:", setValues.WireStats);
|
||||
print_set("Echo commands:", setValues.Echo);
|
||||
print_set("List format:", setValues.List);
|
||||
print_set("Show Row Count:", setValues.Docount);
|
||||
@ -8950,6 +8958,10 @@ static processing_state process_statement(const std::string& str)
|
||||
if (setValues.PerTableStats)
|
||||
perTableStats->getStats(DB, true);
|
||||
|
||||
IsqlWireStats wireStats(DB);
|
||||
if (setValues.WireStats)
|
||||
wireStats.get(true);
|
||||
|
||||
// Prepare the dynamic query stored in string.
|
||||
// But put this on the DDL transaction to get maximum visibility of
|
||||
// metadata.
|
||||
@ -9137,6 +9149,9 @@ static processing_state process_statement(const std::string& str)
|
||||
if (setValues.PerTableStats)
|
||||
perTableStats->getStats(DB, false);
|
||||
|
||||
if (setValues.WireStats)
|
||||
wireStats.print(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9156,6 +9171,9 @@ static processing_state process_statement(const std::string& str)
|
||||
if (setValues.PerTableStats)
|
||||
perTableStats->getStats(DB, false);
|
||||
|
||||
if (setValues.WireStats)
|
||||
wireStats.print(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9203,6 +9221,9 @@ static processing_state process_statement(const std::string& str)
|
||||
if (setValues.PerTableStats)
|
||||
perTableStats->getStats(DB, false);
|
||||
|
||||
if (setValues.WireStats)
|
||||
wireStats.print(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9398,6 +9419,9 @@ static processing_state process_statement(const std::string& str)
|
||||
if (setValues.PerTableStats)
|
||||
perTableStats->getStats(DB, false);
|
||||
|
||||
if (setValues.WireStats)
|
||||
wireStats.print(false);
|
||||
|
||||
if (pad)
|
||||
ISQL_FREE(pad);
|
||||
if (line)
|
||||
@ -9895,3 +9919,112 @@ unsigned PerTableStats::loadRelNames(Firebird::IAttachment* att)
|
||||
|
||||
return maxLen;
|
||||
}
|
||||
|
||||
/// class IsqlWireStats
|
||||
|
||||
bool IsqlWireStats::get(bool initial)
|
||||
{
|
||||
if (!m_att)
|
||||
return false;
|
||||
|
||||
const UCHAR info[] = {
|
||||
fb_info_wire_snd_packets, fb_info_wire_rcv_packets,
|
||||
fb_info_wire_out_packets, fb_info_wire_in_packets,
|
||||
fb_info_wire_snd_bytes, fb_info_wire_rcv_bytes,
|
||||
fb_info_wire_out_bytes, fb_info_wire_in_bytes,
|
||||
fb_info_wire_roundtrips,
|
||||
isc_info_end
|
||||
};
|
||||
|
||||
UCHAR buffer[128];
|
||||
|
||||
m_att->getInfo(fbStatus, sizeof(info), info, sizeof(buffer), buffer);
|
||||
|
||||
if (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS)
|
||||
return false;
|
||||
|
||||
Firebird::ClumpletReader p(Firebird::ClumpletReader::InfoResponse, buffer, sizeof(buffer));
|
||||
for (; !p.isEof(); p.moveNext())
|
||||
{
|
||||
FB_UINT64* pField = nullptr;
|
||||
switch (p.getClumpTag())
|
||||
{
|
||||
case fb_info_wire_snd_packets:
|
||||
pField = &m_snd_packets;
|
||||
break;
|
||||
case fb_info_wire_rcv_packets:
|
||||
pField = &m_rcv_packets;
|
||||
break;
|
||||
case fb_info_wire_out_packets:
|
||||
pField = &m_out_packets;
|
||||
break;
|
||||
case fb_info_wire_in_packets:
|
||||
pField = &m_in_packets;
|
||||
break;
|
||||
case fb_info_wire_snd_bytes:
|
||||
pField = &m_snd_bytes;
|
||||
break;
|
||||
case fb_info_wire_rcv_bytes:
|
||||
pField = &m_rcv_bytes;
|
||||
break;
|
||||
case fb_info_wire_out_bytes:
|
||||
pField = &m_out_bytes;
|
||||
break;
|
||||
case fb_info_wire_in_bytes:
|
||||
pField = &m_in_bytes;
|
||||
break;
|
||||
case fb_info_wire_roundtrips:
|
||||
pField = &m_roundtrips;
|
||||
break;
|
||||
case isc_info_end:
|
||||
break;
|
||||
case isc_info_error:
|
||||
// don't return false here, as we not put error into status
|
||||
return true;
|
||||
/* uncomment to show error (isc_infunk) instead
|
||||
{
|
||||
ISC_STATUS errs[3] = { isc_arg_gds, 0, isc_arg_end };
|
||||
auto b = p.getBytes();
|
||||
errs[1] = isc_portable_integer(b + 1, p.getClumpLength() - 1);
|
||||
fbStatus->setErrors(errs);
|
||||
return false;
|
||||
}*/
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pField)
|
||||
{
|
||||
const FB_UINT64 val = p.getBigInt();
|
||||
*pField = initial ? val : val - *pField;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsqlWireStats::print(bool initial)
|
||||
{
|
||||
if (!get(initial))
|
||||
{
|
||||
ISQL_errmsg(fbStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
IUTILS_printf2(Diag, "Wire logical statistics:%s", NEWLINE);
|
||||
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_out_packets, NEWLINE);
|
||||
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_in_packets, NEWLINE);
|
||||
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_out_bytes, NEWLINE);
|
||||
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_in_bytes, NEWLINE);
|
||||
|
||||
IUTILS_printf2(Diag, "Wire physical statistics:%s", NEWLINE);
|
||||
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_snd_packets, NEWLINE);
|
||||
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_rcv_packets, NEWLINE);
|
||||
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_snd_bytes, NEWLINE);
|
||||
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_rcv_bytes, NEWLINE);
|
||||
IUTILS_printf2(Diag, " roundtrips = %8" SQUADFORMAT "%s", m_roundtrips, NEWLINE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -312,4 +312,28 @@ struct IsqlVar
|
||||
TypeMix value;
|
||||
};
|
||||
|
||||
class IsqlWireStats
|
||||
{
|
||||
public:
|
||||
explicit IsqlWireStats(Firebird::IAttachment* att) :
|
||||
m_att(att)
|
||||
{}
|
||||
|
||||
bool print(bool initial);
|
||||
bool get(bool initial);
|
||||
|
||||
private:
|
||||
|
||||
Firebird::IAttachment* m_att;
|
||||
FB_UINT64 m_snd_packets = 0;
|
||||
FB_UINT64 m_rcv_packets = 0;
|
||||
FB_UINT64 m_out_packets = 0;
|
||||
FB_UINT64 m_in_packets = 0;
|
||||
FB_UINT64 m_snd_bytes = 0;
|
||||
FB_UINT64 m_rcv_bytes = 0;
|
||||
FB_UINT64 m_out_bytes = 0;
|
||||
FB_UINT64 m_in_bytes = 0;
|
||||
FB_UINT64 m_roundtrips = 0;
|
||||
};
|
||||
|
||||
#endif // ISQL_ISQL_H
|
||||
|
@ -116,6 +116,7 @@ static processing_state show_trigger(const SCHAR*, bool, bool);
|
||||
static processing_state show_users();
|
||||
static processing_state show_users12();
|
||||
static void parse_package(const char* procname, MetaString& package, MetaString& procedure);
|
||||
static processing_state show_wireStats();
|
||||
|
||||
const char* const spaces = " ";
|
||||
static TEXT Print_buffer[512];
|
||||
@ -2090,7 +2091,8 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
|
||||
role, table, view, system, index, domain, exception,
|
||||
filter, function, generator, grant, procedure, trigger,
|
||||
check, database, comment, dependency, collation, security_class,
|
||||
users, package, publication, schema, map, wrong
|
||||
users, package, publication, schema, map, wireStats,
|
||||
wrong
|
||||
};
|
||||
ShowOptions(const optionsMap* inmap, size_t insize, int wrongval)
|
||||
: OptionsBase(inmap, insize, wrongval)
|
||||
@ -2148,7 +2150,9 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
|
||||
{ShowOptions::package, "PACKAGES", 4},
|
||||
{ShowOptions::schema, "SCHEMAS", 4},
|
||||
{ShowOptions::map, "MAPPING", 3},
|
||||
{ShowOptions::publication, "PUBLICATIONS", 3}
|
||||
{ShowOptions::publication, "PUBLICATIONS", 3},
|
||||
{ShowOptions::wireStats, "WIRE_STATISTICS", 9},
|
||||
{ShowOptions::wireStats, "WIRE_STATS", 10}
|
||||
};
|
||||
|
||||
const ShowOptions showoptions(options, FB_NELEM(options), ShowOptions::wrong);
|
||||
@ -2805,6 +2809,10 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
|
||||
return ps_ERR;
|
||||
break;
|
||||
|
||||
case ShowOptions::wireStats:
|
||||
ret = show_wireStats();
|
||||
break;
|
||||
|
||||
default:
|
||||
return ps_ERR;
|
||||
} // switch
|
||||
@ -6687,3 +6695,18 @@ static processing_state show_users()
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static processing_state show_wireStats()
|
||||
{
|
||||
if (!DB)
|
||||
{
|
||||
isqlGlob.printf("No database connection.\n");
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
IsqlWireStats stats(DB);
|
||||
if (!stats.print(true))
|
||||
return ps_ERR;
|
||||
|
||||
return SKIP;
|
||||
}
|
@ -937,6 +937,11 @@ private:
|
||||
void internalDropDatabase(CheckStatusWrapper* status);
|
||||
SLONG getSingleInfo(CheckStatusWrapper* status, UCHAR infoItem);
|
||||
|
||||
// Returns nullptr if all items was handled or if user buffer is full, else
|
||||
// returns pointer into unused buffer space. Handled info items are removed.
|
||||
unsigned char* getWireStatsInfo(UCharBuffer& info, unsigned int buffer_length,
|
||||
unsigned char* buffer);
|
||||
|
||||
Rdb* rdb;
|
||||
const PathName dbPath;
|
||||
};
|
||||
@ -1966,6 +1971,65 @@ IAttachment* Loopback::createDatabase(CheckStatusWrapper* status, const char* fi
|
||||
}
|
||||
|
||||
|
||||
unsigned char* Attachment::getWireStatsInfo(UCharBuffer& info, unsigned int buffer_length,
|
||||
unsigned char* buffer)
|
||||
{
|
||||
const rem_port* const port = rdb->rdb_port;
|
||||
|
||||
UCHAR* ptr = buffer;
|
||||
const UCHAR* const end = buffer + buffer_length;
|
||||
|
||||
for (auto item = info.begin(); item < info.end(); )
|
||||
{
|
||||
if (ptr >= end)
|
||||
return nullptr;
|
||||
|
||||
if (*item == isc_info_end)
|
||||
{
|
||||
if (info.getCount() == 1)
|
||||
info.remove(item);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (*item)
|
||||
{
|
||||
case fb_info_wire_snd_packets:
|
||||
case fb_info_wire_rcv_packets:
|
||||
case fb_info_wire_out_packets:
|
||||
case fb_info_wire_in_packets:
|
||||
case fb_info_wire_snd_bytes:
|
||||
case fb_info_wire_rcv_bytes:
|
||||
case fb_info_wire_out_bytes:
|
||||
case fb_info_wire_in_bytes:
|
||||
case fb_info_wire_roundtrips:
|
||||
{
|
||||
const FB_UINT64 value = port->getStatItem(*item);
|
||||
|
||||
if (value <= MAX_SLONG)
|
||||
ptr = fb_utils::putInfoItemInt(*item, (SLONG) value, ptr, end);
|
||||
else
|
||||
ptr = fb_utils::putInfoItemInt(*item, value, ptr, end);
|
||||
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
|
||||
info.remove(item);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
item++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.isEmpty() && ptr < end)
|
||||
*ptr++ = isc_info_end;
|
||||
|
||||
return (info.isEmpty() || (ptr >= end)) ? nullptr : ptr;
|
||||
}
|
||||
|
||||
|
||||
void Attachment::getInfo(CheckStatusWrapper* status,
|
||||
unsigned int item_length, const unsigned char* items,
|
||||
unsigned int buffer_length, unsigned char* buffer)
|
||||
@ -1994,15 +2058,22 @@ void Attachment::getInfo(CheckStatusWrapper* status,
|
||||
|
||||
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
|
||||
|
||||
UCharBuffer tempInfo(items, item_length);
|
||||
UCHAR* ptr = getWireStatsInfo(tempInfo, buffer_length, buffer);
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
buffer_length -= ptr - buffer;
|
||||
|
||||
UCHAR* temp_buffer = temp.getBuffer(buffer_length);
|
||||
|
||||
info(status, rdb, op_info_database, rdb->rdb_id, 0,
|
||||
item_length, items, 0, 0, buffer_length, temp_buffer);
|
||||
tempInfo.getCount(), tempInfo.begin(), 0, 0, buffer_length, temp_buffer);
|
||||
|
||||
string version;
|
||||
port->versionInfo(version);
|
||||
|
||||
MERGE_database_info(temp_buffer, buffer, buffer_length,
|
||||
MERGE_database_info(temp_buffer, ptr, buffer_length,
|
||||
DbImplementation::current.backwardCompatibleImplementation(), 3, 1,
|
||||
reinterpret_cast<const UCHAR*>(version.c_str()),
|
||||
reinterpret_cast<const UCHAR*>(port->port_host->str_data),
|
||||
|
@ -3130,8 +3130,7 @@ static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length,
|
||||
} // end scope
|
||||
#endif
|
||||
|
||||
port->port_rcv_packets++;
|
||||
port->port_rcv_bytes += n;
|
||||
port->bumpPhysStats(rem_port::RECEIVE, n);
|
||||
|
||||
*length = n;
|
||||
|
||||
@ -3306,9 +3305,7 @@ static bool packet_send( rem_port* port, const SCHAR* buffer, SSHORT buffer_leng
|
||||
} // end scope
|
||||
#endif
|
||||
|
||||
port->port_snd_packets++;
|
||||
port->port_snd_bytes += buffer_length;
|
||||
|
||||
port->bumpPhysStats(rem_port::SEND, buffer_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1992,8 +1992,8 @@ static bool_t xnet_read(RemoteXdr* xdrs)
|
||||
{
|
||||
// Client has written some data for us (server) to read
|
||||
|
||||
port->port_rcv_packets++;
|
||||
port->port_rcv_bytes += xch->xch_length;
|
||||
port->bumpPhysStats(rem_port::RECEIVE, xch->xch_length);
|
||||
port->bumpLogBytes(rem_port::RECEIVE, xch->xch_length); // XNET not calls REMOTE_inflate
|
||||
|
||||
xdrs->x_handy = xch->xch_length;
|
||||
xdrs->x_private = xdrs->x_base;
|
||||
@ -2049,8 +2049,8 @@ static bool_t xnet_write(RemoteXdr* xdrs)
|
||||
xch->xch_length = xdrs->x_private - xdrs->x_base;
|
||||
if (SetEvent(xcc->xcc_event_send_channel_filled))
|
||||
{
|
||||
port->port_snd_packets++;
|
||||
port->port_snd_bytes += xch->xch_length;
|
||||
port->bumpPhysStats(rem_port::SEND, xch->xch_length);
|
||||
port->bumpLogBytes(rem_port::SEND, xch->xch_length); // XNET not calls REMOTE_deflate
|
||||
|
||||
xdrs->x_private = xdrs->x_base;
|
||||
xdrs->x_handy = xch->xch_size;
|
||||
|
@ -303,6 +303,9 @@ bool_t xdr_protocol(RemoteXdr* xdrs, PACKET* p)
|
||||
|
||||
const auto port = xdrs->x_public;
|
||||
|
||||
if (xdrs->x_op != XDR_FREE)
|
||||
port->bumpLogPackets(xdrs->x_op == XDR_ENCODE ? rem_port::SEND : rem_port::RECEIVE);
|
||||
|
||||
switch (p->p_operation)
|
||||
{
|
||||
case op_reject:
|
||||
|
@ -1494,7 +1494,12 @@ bool REMOTE_inflate(rem_port* port, PacketReceive* packet_receive, UCHAR* buffer
|
||||
{
|
||||
#ifdef WIRE_COMPRESS_SUPPORT
|
||||
if (!port->port_compressed)
|
||||
return packet_receive(port, buffer, buffer_length, length);
|
||||
{
|
||||
const bool ret = packet_receive(port, buffer, buffer_length, length);
|
||||
if (ret)
|
||||
port->bumpLogBytes(rem_port::RECEIVE, *length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
z_stream& strm = port->port_recv_stream;
|
||||
strm.avail_out = buffer_length;
|
||||
@ -1566,16 +1571,22 @@ bool REMOTE_inflate(rem_port* port, PacketReceive* packet_receive, UCHAR* buffer
|
||||
fprintf(stderr, "ZLib buffer %s\n", port->port_z_data ? "has data" : "is empty");
|
||||
#endif
|
||||
|
||||
port->bumpLogBytes(rem_port::RECEIVE, *length);
|
||||
return true;
|
||||
#else
|
||||
return packet_receive(port, buffer, buffer_length, length);
|
||||
const bool ret = packet_receive(port, buffer, buffer_length, length);
|
||||
if (ret)
|
||||
port->bumpLogBytes(rem_port::RECEIVE, *length);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool REMOTE_deflate(RemoteXdr* xdrs, ProtoWrite* proto_write, PacketSend* packet_send, bool flush)
|
||||
{
|
||||
#ifdef WIRE_COMPRESS_SUPPORT
|
||||
rem_port* port = xdrs->x_public;
|
||||
port->bumpLogBytes(rem_port::SEND, xdrs->x_private - xdrs->x_base);
|
||||
|
||||
#ifdef WIRE_COMPRESS_SUPPORT
|
||||
if (!(port->port_compressed && (port->port_flags & PORT_compressed)))
|
||||
return proto_write(xdrs);
|
||||
|
||||
|
@ -1200,10 +1200,100 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
|
||||
|
||||
UCharArrayAutoPtr port_buffer;
|
||||
|
||||
|
||||
enum io_direction_t {
|
||||
NONE,
|
||||
SEND,
|
||||
RECEIVE
|
||||
};
|
||||
|
||||
private:
|
||||
// packets over physical connection
|
||||
FB_UINT64 port_snd_packets;
|
||||
FB_UINT64 port_rcv_packets;
|
||||
// protocol packets
|
||||
FB_UINT64 port_out_packets;
|
||||
FB_UINT64 port_in_packets;
|
||||
// bytes over physical connection
|
||||
FB_UINT64 port_snd_bytes;
|
||||
FB_UINT64 port_rcv_bytes;
|
||||
// bytes before/after compression
|
||||
FB_UINT64 port_out_bytes;
|
||||
FB_UINT64 port_in_bytes;
|
||||
FB_UINT64 port_roundtrips; // number of changes of IO direction from SEND to RECEIVE
|
||||
io_direction_t port_io_direction; // last direction of IO
|
||||
|
||||
public:
|
||||
void bumpPhysStats(io_direction_t direction, ULONG count)
|
||||
{
|
||||
fb_assert(direction != NONE);
|
||||
|
||||
if (direction == SEND)
|
||||
{
|
||||
port_snd_packets++;
|
||||
port_snd_bytes += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
port_rcv_packets++;
|
||||
port_rcv_bytes += count;
|
||||
}
|
||||
|
||||
if (direction != port_io_direction)
|
||||
{
|
||||
if (port_io_direction != NONE && direction == RECEIVE)
|
||||
port_roundtrips++;
|
||||
port_io_direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
void bumpLogBytes(io_direction_t direction, ULONG count)
|
||||
{
|
||||
fb_assert(direction != NONE);
|
||||
|
||||
if (direction == SEND)
|
||||
port_out_bytes += count;
|
||||
else
|
||||
port_in_bytes += count;
|
||||
}
|
||||
|
||||
void bumpLogPackets(io_direction_t direction)
|
||||
{
|
||||
fb_assert(direction != NONE);
|
||||
|
||||
if (direction == SEND)
|
||||
port_out_packets++;
|
||||
else
|
||||
port_in_packets++;
|
||||
}
|
||||
|
||||
FB_UINT64 getStatItem(UCHAR infoItem) const
|
||||
{
|
||||
switch (infoItem)
|
||||
{
|
||||
case fb_info_wire_snd_packets:
|
||||
return port_snd_packets;
|
||||
case fb_info_wire_rcv_packets:
|
||||
return port_rcv_packets;
|
||||
case fb_info_wire_out_packets:
|
||||
return port_out_packets;
|
||||
case fb_info_wire_in_packets:
|
||||
return port_in_packets;
|
||||
case fb_info_wire_snd_bytes:
|
||||
return port_snd_bytes;
|
||||
case fb_info_wire_rcv_bytes:
|
||||
return port_rcv_bytes;
|
||||
case fb_info_wire_out_bytes:
|
||||
return port_out_bytes;
|
||||
case fb_info_wire_in_bytes:
|
||||
return port_in_bytes;
|
||||
case fb_info_wire_roundtrips:
|
||||
return port_roundtrips;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIRE_COMPRESS_SUPPORT
|
||||
z_stream port_send_stream, port_recv_stream;
|
||||
@ -1243,7 +1333,9 @@ public:
|
||||
port_known_server_keys(getPool()), port_crypt_plugin(NULL),
|
||||
port_client_crypt_callback(NULL), port_server_crypt_callback(NULL), port_crypt_name(getPool()),
|
||||
port_replicator(NULL), port_buffer(FB_NEW_POOL(getPool()) UCHAR[rpt]),
|
||||
port_snd_packets(0), port_rcv_packets(0), port_snd_bytes(0), port_rcv_bytes(0)
|
||||
port_snd_packets(0), port_rcv_packets(0), port_out_packets(0), port_in_packets(0),
|
||||
port_snd_bytes(0), port_rcv_bytes(0), port_out_bytes(0), port_in_bytes(0),
|
||||
port_roundtrips(0), port_io_direction(NONE)
|
||||
{
|
||||
addRef();
|
||||
memset(&port_linger, 0, sizeof port_linger);
|
||||
|
Loading…
Reference in New Issue
Block a user