8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 01:23:03 +01:00

Fixed CORE-2017: I/O statistics for stored procedures is not accounted in monitoring tables.

This patch adds lazy statistics increments to the whole request call stack.
This commit is contained in:
dimitr 2008-11-06 16:07:49 +00:00
parent 4a3c3dde3e
commit ea6fbf9e6b
5 changed files with 81 additions and 22 deletions

View File

@ -838,6 +838,24 @@ ClumpletReader* DatabaseSnapshot::dumpData(thread_db* tdbb, bool broadcast)
putTransaction(transaction, *writer, dbb->generateId());
}
// Call stack information
for (transaction = attachment->att_transactions;
transaction; transaction = transaction->tra_next)
{
for (request = transaction->tra_requests; request;
request = request->req_caller)
{
request->adjustCallerStats();
if (!(request->req_flags & (req_internal | req_sys_trigger)) &&
request->req_caller)
{
putCall(request, *writer, dbb->generateId());
}
}
}
// Request information
for (request = attachment->att_requests;
@ -848,22 +866,6 @@ ClumpletReader* DatabaseSnapshot::dumpData(thread_db* tdbb, bool broadcast)
putRequest(request, *writer, dbb->generateId());
}
}
// Call stack information
for (transaction = attachment->att_transactions;
transaction; transaction = transaction->tra_next)
{
for (request = transaction->tra_requests;
request; request = request->req_tra_next)
{
if (!(request->req_flags & (req_internal | req_sys_trigger)) &&
request->req_caller)
{
putCall(request, *writer, dbb->generateId());
}
}
}
}
}
@ -1159,8 +1161,7 @@ void DatabaseSnapshot::putCall(const jrd_req* request,
writer.insertInt(f_mon_call_caller_id, 0);
}
else {
writer.insertInt(f_mon_call_caller_id,
request->req_caller->req_id);
writer.insertInt(f_mon_call_caller_id, request->req_caller->req_id);
}
// object name/type
if (request->req_procedure) {

View File

@ -25,6 +25,7 @@
#include "../jrd/RuntimeStatistics.h"
using namespace Firebird;
namespace Jrd {
RuntimeStatistics RuntimeStatistics::dummy;
@ -34,4 +35,40 @@ void RuntimeStatistics::reset()
memset(values, 0, sizeof values);
}
bool RuntimeStatistics::operator==(const RuntimeStatistics& other) const
{
return !memcmp(values, other.values, sizeof(values));
}
bool RuntimeStatistics::operator!=(const RuntimeStatistics& other) const
{
return !(*this == other);
}
RuntimeStatistics& RuntimeStatistics::operator+=(const RuntimeStatistics& other)
{
for (size_t i = 0; i < TOTAL_ITEMS; ++i)
values[i] += other.values[i];
return *this;
}
RuntimeStatistics& RuntimeStatistics::operator-=(const RuntimeStatistics& other)
{
for (size_t i = 0; i < TOTAL_ITEMS; ++i)
values[i] -= other.values[i];
return *this;
}
RuntimeStatistics RuntimeStatistics::operator+(const RuntimeStatistics& other) const
{
return RuntimeStatistics(*this) += other;
}
RuntimeStatistics RuntimeStatistics::operator-(const RuntimeStatistics& other) const
{
return RuntimeStatistics(*this) -= other;
}
} // namespace

View File

@ -74,17 +74,23 @@ public:
++values[index];
}
bool operator==(const RuntimeStatistics& other) const;
bool operator!=(const RuntimeStatistics& other) const;
RuntimeStatistics& operator+=(const RuntimeStatistics& other);
RuntimeStatistics& operator-=(const RuntimeStatistics& other);
RuntimeStatistics operator+(const RuntimeStatistics& other) const;
RuntimeStatistics operator-(const RuntimeStatistics& other) const;
static RuntimeStatistics* getDummy()
{
return &dummy;
}
private:
// copying is prohibited
RuntimeStatistics(const RuntimeStatistics&);
RuntimeStatistics& operator= (const RuntimeStatistics&);
SINT64 values[TOTAL_ITEMS];
// This dummy RuntimeStatistics is used instead of missing elements in tdbb,
// helping us avoid conditional checks in time-critical places of code.
// Values of it contain actually garbage - don't be surprised when debugging.

View File

@ -681,6 +681,7 @@ jrd_req* EXE_find_request(thread_db* tdbb, jrd_req* request, bool validate)
}
clone->req_attachment = tdbb->getAttachment();
clone->req_stats.reset();
clone->req_base_stats.reset();
clone->req_flags |= req_in_use;
dbb->dbb_mutexes[DBB_MUTX_clone].leave();
return clone;
@ -2729,11 +2730,15 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
BUGCHECK(168); /* msg 168 looper: action not yet implemented */
}
request->adjustCallerStats();
} // try
catch (const Firebird::Exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
request->adjustCallerStats();
// Skip this handling for errors coming from the nested looper calls,
// as they're already handled properly. The only need is to undo
// our own savepoints.

View File

@ -232,6 +232,7 @@ public:
ULONG req_records_updated; /* count of records updated by request */
ULONG req_records_deleted; /* count of records deleted by request */
RuntimeStatistics req_stats;
RuntimeStatistics req_base_stats;
AffectedRows req_records_affected; /* records affected by the last statement */
USHORT req_view_flags; /* special flags for virtual ops on views */
@ -282,6 +283,15 @@ public:
StatusXcp req_last_xcp; /* last known exception */
record_param req_rpb[1]; /* record parameter blocks */
void adjustCallerStats()
{
if (req_caller)
{
req_caller->req_stats += req_stats - req_base_stats;
}
req_base_stats = req_stats;
}
};
// Size of request without rpb items at the tail. Used to calculate impure area size