mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Do not pass user's transaction to plugin.
Use autonomous transaction in flush.
This commit is contained in:
parent
bb139df3c7
commit
3fe37a6a60
@ -22,7 +22,7 @@ A session may be paused to temporary disable statistics collecting. It may be re
|
|||||||
|
|
||||||
A new session may be started when a session is already active. In this case it has the same semantics of finishing the current session with `RDB$PROFILER.FINISH_SESSION(FALSE)` so snapshots tables are not updated in the same moment.
|
A new session may be started when a session is already active. In this case it has the same semantics of finishing the current session with `RDB$PROFILER.FINISH_SESSION(FALSE)` so snapshots tables are not updated in the same moment.
|
||||||
|
|
||||||
To analyze the collected data, the user must flush the data to the snapshot tables, which may be done finishing or pausing a session (with `FLUSH` parameter set to `TRUE`) or calling `RDB$PROFILER.FLUSH`.
|
To analyze the collected data, the user must flush the data to the snapshot tables, which may be done finishing or pausing a session (with `FLUSH` parameter set to `TRUE`) or calling `RDB$PROFILER.FLUSH`. Data is flushed using an autonomous transaction (a transaction started and finished for the specific purpose of profiler data update).
|
||||||
|
|
||||||
Following is a sample profile session and queries for data analysis.
|
Following is a sample profile session and queries for data analysis.
|
||||||
|
|
||||||
@ -89,6 +89,8 @@ execute procedure rdb$profiler.finish_session(true);
|
|||||||
|
|
||||||
-- Data analysis
|
-- Data analysis
|
||||||
|
|
||||||
|
commit; -- start new transaction
|
||||||
|
|
||||||
select * from plg$prof_sessions;
|
select * from plg$prof_sessions;
|
||||||
|
|
||||||
select * from plg$prof_psql_stats_view;
|
select * from plg$prof_psql_stats_view;
|
||||||
@ -195,9 +197,9 @@ Input parameters:
|
|||||||
|
|
||||||
After update data is stored in tables `PLG$PROF_SESSIONS`, `PLG$PROF_STATEMENTS`, `PLG$PROF_RECORD_SOURCES`, `PLG$PROF_REQUESTS`, `PLG$PROF_PSQL_STATS` and `PLG$PROF_RECORD_SOURCE_STATS` and may be read and analyzed by the user.
|
After update data is stored in tables `PLG$PROF_SESSIONS`, `PLG$PROF_STATEMENTS`, `PLG$PROF_RECORD_SOURCES`, `PLG$PROF_REQUESTS`, `PLG$PROF_PSQL_STATS` and `PLG$PROF_RECORD_SOURCE_STATS` and may be read and analyzed by the user.
|
||||||
|
|
||||||
It also removes finished sessions from memory.
|
Data is updated using an autonomous transaction, so if the procedure is called in a snapshot transaction, data will not be directly readable in the same transaction.
|
||||||
|
|
||||||
If a remote `ATTACHMENT_ID` is used the data is updated in an autonomous transaction.
|
Once flush happens, finished sessions are removed from memory.
|
||||||
|
|
||||||
Input parameters:
|
Input parameters:
|
||||||
- `ATTACHMENT_ID` type `BIGINT NOT NULL` default `CURRENT_CONNECTION`
|
- `ATTACHMENT_ID` type `BIGINT NOT NULL` default `CURRENT_CONNECTION`
|
||||||
|
@ -1700,15 +1700,12 @@ interface ReplicatedSession : PluginBase
|
|||||||
|
|
||||||
interface ProfilerPlugin : PluginBase
|
interface ProfilerPlugin : PluginBase
|
||||||
{
|
{
|
||||||
// The transaction should not be stored for later usage after the method returns.
|
void init(Status status, Attachment attachment);
|
||||||
void init(Status status, Attachment attachment, Transaction transaction);
|
|
||||||
|
|
||||||
// The transaction should not be stored for later usage after the method returns.
|
ProfilerSession startSession(Status status, const string description,
|
||||||
ProfilerSession startSession(Status status, Transaction transaction, const string description,
|
|
||||||
const string options, ISC_TIMESTAMP_TZ timestamp);
|
const string options, ISC_TIMESTAMP_TZ timestamp);
|
||||||
|
|
||||||
// The transaction should not be stored for later usage after the method returns.
|
void flush(Status status);
|
||||||
void flush(Status status, Transaction transaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProfilerSession : Disposable
|
interface ProfilerSession : Disposable
|
||||||
|
@ -6648,9 +6648,9 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
struct VTable : public IPluginBase::VTable
|
struct VTable : public IPluginBase::VTable
|
||||||
{
|
{
|
||||||
void (CLOOP_CARG *init)(IProfilerPlugin* self, IStatus* status, IAttachment* attachment, ITransaction* transaction) throw();
|
void (CLOOP_CARG *init)(IProfilerPlugin* self, IStatus* status, IAttachment* attachment) throw();
|
||||||
IProfilerSession* (CLOOP_CARG *startSession)(IProfilerPlugin* self, IStatus* status, ITransaction* transaction, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) throw();
|
IProfilerSession* (CLOOP_CARG *startSession)(IProfilerPlugin* self, IStatus* status, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) throw();
|
||||||
void (CLOOP_CARG *flush)(IProfilerPlugin* self, IStatus* status, ITransaction* transaction) throw();
|
void (CLOOP_CARG *flush)(IProfilerPlugin* self, IStatus* status) throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -6666,25 +6666,25 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
static const unsigned VERSION = 4;
|
static const unsigned VERSION = 4;
|
||||||
|
|
||||||
template <typename StatusType> void init(StatusType* status, IAttachment* attachment, ITransaction* transaction)
|
template <typename StatusType> void init(StatusType* status, IAttachment* attachment)
|
||||||
{
|
{
|
||||||
StatusType::clearException(status);
|
StatusType::clearException(status);
|
||||||
static_cast<VTable*>(this->cloopVTable)->init(this, status, attachment, transaction);
|
static_cast<VTable*>(this->cloopVTable)->init(this, status, attachment);
|
||||||
StatusType::checkException(status);
|
StatusType::checkException(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StatusType> IProfilerSession* startSession(StatusType* status, ITransaction* transaction, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp)
|
template <typename StatusType> IProfilerSession* startSession(StatusType* status, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp)
|
||||||
{
|
{
|
||||||
StatusType::clearException(status);
|
StatusType::clearException(status);
|
||||||
IProfilerSession* ret = static_cast<VTable*>(this->cloopVTable)->startSession(this, status, transaction, description, options, timestamp);
|
IProfilerSession* ret = static_cast<VTable*>(this->cloopVTable)->startSession(this, status, description, options, timestamp);
|
||||||
StatusType::checkException(status);
|
StatusType::checkException(status);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StatusType> void flush(StatusType* status, ITransaction* transaction)
|
template <typename StatusType> void flush(StatusType* status)
|
||||||
{
|
{
|
||||||
StatusType::clearException(status);
|
StatusType::clearException(status);
|
||||||
static_cast<VTable*>(this->cloopVTable)->flush(this, status, transaction);
|
static_cast<VTable*>(this->cloopVTable)->flush(this, status);
|
||||||
StatusType::checkException(status);
|
StatusType::checkException(status);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -19964,13 +19964,13 @@ namespace Firebird
|
|||||||
this->cloopVTable = &vTable;
|
this->cloopVTable = &vTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CLOOP_CARG cloopinitDispatcher(IProfilerPlugin* self, IStatus* status, IAttachment* attachment, ITransaction* transaction) throw()
|
static void CLOOP_CARG cloopinitDispatcher(IProfilerPlugin* self, IStatus* status, IAttachment* attachment) throw()
|
||||||
{
|
{
|
||||||
StatusType status2(status);
|
StatusType status2(status);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
static_cast<Name*>(self)->Name::init(&status2, attachment, transaction);
|
static_cast<Name*>(self)->Name::init(&status2, attachment);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -19978,13 +19978,13 @@ namespace Firebird
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static IProfilerSession* CLOOP_CARG cloopstartSessionDispatcher(IProfilerPlugin* self, IStatus* status, ITransaction* transaction, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) throw()
|
static IProfilerSession* CLOOP_CARG cloopstartSessionDispatcher(IProfilerPlugin* self, IStatus* status, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) throw()
|
||||||
{
|
{
|
||||||
StatusType status2(status);
|
StatusType status2(status);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return static_cast<Name*>(self)->Name::startSession(&status2, transaction, description, options, timestamp);
|
return static_cast<Name*>(self)->Name::startSession(&status2, description, options, timestamp);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -19993,13 +19993,13 @@ namespace Firebird
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CLOOP_CARG cloopflushDispatcher(IProfilerPlugin* self, IStatus* status, ITransaction* transaction) throw()
|
static void CLOOP_CARG cloopflushDispatcher(IProfilerPlugin* self, IStatus* status) throw()
|
||||||
{
|
{
|
||||||
StatusType status2(status);
|
StatusType status2(status);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
static_cast<Name*>(self)->Name::flush(&status2, transaction);
|
static_cast<Name*>(self)->Name::flush(&status2);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -20071,9 +20071,9 @@ namespace Firebird
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void init(StatusType* status, IAttachment* attachment, ITransaction* transaction) = 0;
|
virtual void init(StatusType* status, IAttachment* attachment) = 0;
|
||||||
virtual IProfilerSession* startSession(StatusType* status, ITransaction* transaction, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) = 0;
|
virtual IProfilerSession* startSession(StatusType* status, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) = 0;
|
||||||
virtual void flush(StatusType* status, ITransaction* transaction) = 0;
|
virtual void flush(StatusType* status) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Name, typename StatusType, typename Base>
|
template <typename Name, typename StatusType, typename Base>
|
||||||
|
@ -714,9 +714,9 @@ type
|
|||||||
IReplicatedSession_startTransactionPtr = function(this: IReplicatedSession; status: IStatus; transaction: ITransaction; number: Int64): IReplicatedTransaction; cdecl;
|
IReplicatedSession_startTransactionPtr = function(this: IReplicatedSession; status: IStatus; transaction: ITransaction; number: Int64): IReplicatedTransaction; cdecl;
|
||||||
IReplicatedSession_cleanupTransactionPtr = procedure(this: IReplicatedSession; status: IStatus; number: Int64); cdecl;
|
IReplicatedSession_cleanupTransactionPtr = procedure(this: IReplicatedSession; status: IStatus; number: Int64); cdecl;
|
||||||
IReplicatedSession_setSequencePtr = procedure(this: IReplicatedSession; status: IStatus; name: PAnsiChar; value: Int64); cdecl;
|
IReplicatedSession_setSequencePtr = procedure(this: IReplicatedSession; status: IStatus; name: PAnsiChar; value: Int64); cdecl;
|
||||||
IProfilerPlugin_initPtr = procedure(this: IProfilerPlugin; status: IStatus; attachment: IAttachment; transaction: ITransaction); cdecl;
|
IProfilerPlugin_initPtr = procedure(this: IProfilerPlugin; status: IStatus; attachment: IAttachment); cdecl;
|
||||||
IProfilerPlugin_startSessionPtr = function(this: IProfilerPlugin; status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; cdecl;
|
IProfilerPlugin_startSessionPtr = function(this: IProfilerPlugin; status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; cdecl;
|
||||||
IProfilerPlugin_flushPtr = procedure(this: IProfilerPlugin; status: IStatus; transaction: ITransaction); cdecl;
|
IProfilerPlugin_flushPtr = procedure(this: IProfilerPlugin; status: IStatus); cdecl;
|
||||||
IProfilerSession_getIdPtr = function(this: IProfilerSession): Int64; cdecl;
|
IProfilerSession_getIdPtr = function(this: IProfilerSession): Int64; cdecl;
|
||||||
IProfilerSession_getFlagsPtr = function(this: IProfilerSession): Cardinal; cdecl;
|
IProfilerSession_getFlagsPtr = function(this: IProfilerSession): Cardinal; cdecl;
|
||||||
IProfilerSession_cancelPtr = procedure(this: IProfilerSession; status: IStatus); cdecl;
|
IProfilerSession_cancelPtr = procedure(this: IProfilerSession; status: IStatus); cdecl;
|
||||||
@ -3775,9 +3775,9 @@ type
|
|||||||
IProfilerPlugin = class(IPluginBase)
|
IProfilerPlugin = class(IPluginBase)
|
||||||
const VERSION = 4;
|
const VERSION = 4;
|
||||||
|
|
||||||
procedure init(status: IStatus; attachment: IAttachment; transaction: ITransaction);
|
procedure init(status: IStatus; attachment: IAttachment);
|
||||||
function startSession(status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
function startSession(status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
||||||
procedure flush(status: IStatus; transaction: ITransaction);
|
procedure flush(status: IStatus);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IProfilerPluginImpl = class(IProfilerPlugin)
|
IProfilerPluginImpl = class(IProfilerPlugin)
|
||||||
@ -3787,9 +3787,9 @@ type
|
|||||||
function release(): Integer; virtual; abstract;
|
function release(): Integer; virtual; abstract;
|
||||||
procedure setOwner(r: IReferenceCounted); virtual; abstract;
|
procedure setOwner(r: IReferenceCounted); virtual; abstract;
|
||||||
function getOwner(): IReferenceCounted; virtual; abstract;
|
function getOwner(): IReferenceCounted; virtual; abstract;
|
||||||
procedure init(status: IStatus; attachment: IAttachment; transaction: ITransaction); virtual; abstract;
|
procedure init(status: IStatus; attachment: IAttachment); virtual; abstract;
|
||||||
function startSession(status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; virtual; abstract;
|
function startSession(status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; virtual; abstract;
|
||||||
procedure flush(status: IStatus; transaction: ITransaction); virtual; abstract;
|
procedure flush(status: IStatus); virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ProfilerSessionVTable = class(DisposableVTable)
|
ProfilerSessionVTable = class(DisposableVTable)
|
||||||
@ -8945,21 +8945,21 @@ begin
|
|||||||
FbException.checkException(status);
|
FbException.checkException(status);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerPlugin.init(status: IStatus; attachment: IAttachment; transaction: ITransaction);
|
procedure IProfilerPlugin.init(status: IStatus; attachment: IAttachment);
|
||||||
begin
|
begin
|
||||||
ProfilerPluginVTable(vTable).init(Self, status, attachment, transaction);
|
ProfilerPluginVTable(vTable).init(Self, status, attachment);
|
||||||
FbException.checkException(status);
|
FbException.checkException(status);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IProfilerPlugin.startSession(status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
function IProfilerPlugin.startSession(status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
||||||
begin
|
begin
|
||||||
Result := ProfilerPluginVTable(vTable).startSession(Self, status, transaction, description, options, timestamp);
|
Result := ProfilerPluginVTable(vTable).startSession(Self, status, description, options, timestamp);
|
||||||
FbException.checkException(status);
|
FbException.checkException(status);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerPlugin.flush(status: IStatus; transaction: ITransaction);
|
procedure IProfilerPlugin.flush(status: IStatus);
|
||||||
begin
|
begin
|
||||||
ProfilerPluginVTable(vTable).flush(Self, status, transaction);
|
ProfilerPluginVTable(vTable).flush(Self, status);
|
||||||
FbException.checkException(status);
|
FbException.checkException(status);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -15576,28 +15576,28 @@ begin
|
|||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerPluginImpl_initDispatcher(this: IProfilerPlugin; status: IStatus; attachment: IAttachment; transaction: ITransaction); cdecl;
|
procedure IProfilerPluginImpl_initDispatcher(this: IProfilerPlugin; status: IStatus; attachment: IAttachment); cdecl;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
IProfilerPluginImpl(this).init(status, attachment, transaction);
|
IProfilerPluginImpl(this).init(status, attachment);
|
||||||
except
|
except
|
||||||
on e: Exception do FbException.catchException(status, e);
|
on e: Exception do FbException.catchException(status, e);
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IProfilerPluginImpl_startSessionDispatcher(this: IProfilerPlugin; status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; cdecl;
|
function IProfilerPluginImpl_startSessionDispatcher(this: IProfilerPlugin; status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; cdecl;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := IProfilerPluginImpl(this).startSession(status, transaction, description, options, timestamp);
|
Result := IProfilerPluginImpl(this).startSession(status, description, options, timestamp);
|
||||||
except
|
except
|
||||||
on e: Exception do FbException.catchException(status, e);
|
on e: Exception do FbException.catchException(status, e);
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerPluginImpl_flushDispatcher(this: IProfilerPlugin; status: IStatus; transaction: ITransaction); cdecl;
|
procedure IProfilerPluginImpl_flushDispatcher(this: IProfilerPlugin; status: IStatus); cdecl;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
IProfilerPluginImpl(this).flush(status, transaction);
|
IProfilerPluginImpl(this).flush(status);
|
||||||
except
|
except
|
||||||
on e: Exception do FbException.catchException(status, e);
|
on e: Exception do FbException.catchException(status, e);
|
||||||
end
|
end
|
||||||
|
@ -192,10 +192,9 @@ IExternalResultSet* ProfilerPackage::flushProcedure(ThrowStatusExceptionWrapper*
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto transaction = tdbb->getTransaction();
|
|
||||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||||
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
profilerManager->flush();
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -234,13 +233,9 @@ IExternalResultSet* ProfilerPackage::finishSessionProcedure(ThrowStatusException
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto transaction = tdbb->getTransaction();
|
|
||||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||||
|
|
||||||
profilerManager->finishSession(tdbb);
|
profilerManager->finishSession(tdbb, in->flush);
|
||||||
|
|
||||||
if (in->flush)
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -258,14 +253,9 @@ IExternalResultSet* ProfilerPackage::pauseSessionProcedure(ThrowStatusExceptionW
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto transaction = tdbb->getTransaction();
|
|
||||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||||
|
|
||||||
if (profilerManager->pauseSession())
|
profilerManager->pauseSession(in->flush);
|
||||||
{
|
|
||||||
if (in->flush)
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -359,7 +349,6 @@ SINT64 ProfilerManager::startSession(thread_db* tdbb, AttNumber attachmentId, co
|
|||||||
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
||||||
|
|
||||||
const auto attachment = tdbb->getAttachment();
|
const auto attachment = tdbb->getAttachment();
|
||||||
const auto transaction = tdbb->getTransaction();
|
|
||||||
ThrowLocalStatus status;
|
ThrowLocalStatus status;
|
||||||
|
|
||||||
const auto timestamp = TimeZoneUtil::getCurrentTimeStamp(attachment->att_current_timezone);
|
const auto timestamp = TimeZoneUtil::getCurrentTimeStamp(attachment->att_current_timezone);
|
||||||
@ -393,14 +382,13 @@ SINT64 ProfilerManager::startSession(thread_db* tdbb, AttNumber attachmentId, co
|
|||||||
plugin.reset(plugins.plugin());
|
plugin.reset(plugins.plugin());
|
||||||
plugin->addRef();
|
plugin->addRef();
|
||||||
|
|
||||||
plugin->init(&status, attachment->getInterface(), transaction->getInterface(true));
|
plugin->init(&status, attachment->getInterface());
|
||||||
|
|
||||||
plugin->addRef();
|
plugin->addRef();
|
||||||
activePlugins.put(pluginName)->reset(plugin.get());
|
activePlugins.put(pluginName)->reset(plugin.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoDispose<IProfilerSession> pluginSession = plugin->startSession(&status,
|
AutoDispose<IProfilerSession> pluginSession = plugin->startSession(&status,
|
||||||
transaction->getInterface(true),
|
|
||||||
description.c_str(),
|
description.c_str(),
|
||||||
options.c_str(),
|
options.c_str(),
|
||||||
timestamp);
|
timestamp);
|
||||||
@ -566,7 +554,7 @@ void ProfilerManager::cancelSession()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerManager::finishSession(thread_db* tdbb)
|
void ProfilerManager::finishSession(thread_db* tdbb, bool flushData)
|
||||||
{
|
{
|
||||||
if (currentSession)
|
if (currentSession)
|
||||||
{
|
{
|
||||||
@ -577,15 +565,18 @@ void ProfilerManager::finishSession(thread_db* tdbb)
|
|||||||
currentSession->pluginSession->finish(&status, timestamp);
|
currentSession->pluginSession->finish(&status, timestamp);
|
||||||
currentSession = nullptr;
|
currentSession = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flushData)
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfilerManager::pauseSession()
|
void ProfilerManager::pauseSession(bool flushData)
|
||||||
{
|
{
|
||||||
if (!currentSession)
|
if (currentSession)
|
||||||
return false;
|
paused = true;
|
||||||
|
|
||||||
paused = true;
|
if (flushData)
|
||||||
return true;
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerManager::resumeSession()
|
void ProfilerManager::resumeSession()
|
||||||
@ -600,7 +591,7 @@ void ProfilerManager::discard()
|
|||||||
activePlugins.clear();
|
activePlugins.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerManager::flush(ITransaction* transaction)
|
void ProfilerManager::flush()
|
||||||
{
|
{
|
||||||
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
||||||
|
|
||||||
@ -612,7 +603,7 @@ void ProfilerManager::flush(ITransaction* transaction)
|
|||||||
auto& plugin = pluginAccessor.current()->second;
|
auto& plugin = pluginAccessor.current()->second;
|
||||||
|
|
||||||
LogLocalStatus status("Profiler flush");
|
LogLocalStatus status("Profiler flush");
|
||||||
plugin->flush(&status, transaction);
|
plugin->flush(&status);
|
||||||
|
|
||||||
hasNext = pluginAccessor.getNext();
|
hasNext = pluginAccessor.getNext();
|
||||||
|
|
||||||
@ -937,122 +928,74 @@ void ProfilerListener::processCommand(thread_db* tdbb)
|
|||||||
const auto header = ipc->sharedMemory->getHeader();
|
const auto header = ipc->sharedMemory->getHeader();
|
||||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||||
|
|
||||||
jrd_tra* transaction = nullptr;
|
using Tag = ProfilerIpc::Tag;
|
||||||
try
|
|
||||||
|
switch (header->tag)
|
||||||
{
|
{
|
||||||
const auto startTransaction = [&]() {
|
case Tag::CANCEL_SESSION:
|
||||||
transaction = TRA_start(tdbb, 0, 0);
|
profilerManager->cancelSession();
|
||||||
tdbb->setTransaction(transaction);
|
header->bufferSize = 0;
|
||||||
};
|
break;
|
||||||
|
|
||||||
using Tag = ProfilerIpc::Tag;
|
case Tag::DISCARD:
|
||||||
|
profilerManager->discard();
|
||||||
|
header->bufferSize = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
switch (header->tag)
|
case Tag::FINISH_SESSION:
|
||||||
{
|
{
|
||||||
case Tag::CANCEL_SESSION:
|
const auto in = reinterpret_cast<const ProfilerPackage::FinishSessionInput::Type*>(header->buffer);
|
||||||
profilerManager->cancelSession();
|
fb_assert(sizeof(*in) == header->bufferSize);
|
||||||
header->bufferSize = 0;
|
profilerManager->finishSession(tdbb, in->flush);
|
||||||
break;
|
header->bufferSize = 0;
|
||||||
|
break;
|
||||||
case Tag::DISCARD:
|
|
||||||
profilerManager->discard();
|
|
||||||
header->bufferSize = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Tag::FINISH_SESSION:
|
|
||||||
{
|
|
||||||
const auto in = reinterpret_cast<const ProfilerPackage::FinishSessionInput::Type*>(header->buffer);
|
|
||||||
fb_assert(sizeof(*in) == header->bufferSize);
|
|
||||||
|
|
||||||
profilerManager->finishSession(tdbb);
|
|
||||||
|
|
||||||
if (in->flush)
|
|
||||||
{
|
|
||||||
startTransaction();
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
header->bufferSize = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Tag::FLUSH:
|
|
||||||
startTransaction();
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
|
||||||
header->bufferSize = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Tag::PAUSE_SESSION:
|
|
||||||
if (profilerManager->currentSession)
|
|
||||||
{
|
|
||||||
const auto in = reinterpret_cast<const ProfilerPackage::PauseSessionInput::Type*>(header->buffer);
|
|
||||||
fb_assert(sizeof(*in) == header->bufferSize);
|
|
||||||
|
|
||||||
if (profilerManager->pauseSession())
|
|
||||||
{
|
|
||||||
if (in->flush)
|
|
||||||
{
|
|
||||||
startTransaction();
|
|
||||||
profilerManager->flush(transaction->getInterface(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
header->bufferSize = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Tag::RESUME_SESSION:
|
|
||||||
profilerManager->resumeSession();
|
|
||||||
header->bufferSize = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Tag::START_SESSION:
|
|
||||||
{
|
|
||||||
startTransaction();
|
|
||||||
|
|
||||||
const auto in = reinterpret_cast<const ProfilerPackage::StartSessionInput::Type*>(header->buffer);
|
|
||||||
fb_assert(sizeof(*in) == header->bufferSize);
|
|
||||||
|
|
||||||
const string description(in->description.str,
|
|
||||||
in->descriptionNull ? 0 : in->description.length);
|
|
||||||
const PathName pluginName(in->pluginName.str,
|
|
||||||
in->pluginNameNull ? 0 : in->pluginName.length);
|
|
||||||
const string pluginOptions(in->pluginOptions.str,
|
|
||||||
in->pluginOptionsNull ? 0 : in->pluginOptions.length);
|
|
||||||
|
|
||||||
const auto out = reinterpret_cast<ProfilerPackage::StartSessionOutput::Type*>(header->buffer);
|
|
||||||
header->bufferSize = sizeof(*out);
|
|
||||||
|
|
||||||
out->sessionIdNull = FB_FALSE;
|
|
||||||
out->sessionId = profilerManager->startSession(tdbb,
|
|
||||||
in->attachmentId, pluginName, description, pluginOptions);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
fb_assert(false);
|
|
||||||
(Arg::Gds(isc_random) << "Invalid profiler's remote command").raise();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transaction)
|
case Tag::FLUSH:
|
||||||
|
profilerManager->flush();
|
||||||
|
header->bufferSize = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tag::PAUSE_SESSION:
|
||||||
{
|
{
|
||||||
TRA_commit(tdbb, transaction, false);
|
const auto in = reinterpret_cast<const ProfilerPackage::PauseSessionInput::Type*>(header->buffer);
|
||||||
tdbb->setTransaction(nullptr);
|
fb_assert(sizeof(*in) == header->bufferSize);
|
||||||
transaction = nullptr;
|
profilerManager->pauseSession(in->flush);
|
||||||
}
|
header->bufferSize = 0;
|
||||||
}
|
break;
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
if (transaction)
|
|
||||||
{
|
|
||||||
TRA_rollback(tdbb, transaction, false, true);
|
|
||||||
tdbb->setTransaction(nullptr);
|
|
||||||
transaction = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
case Tag::RESUME_SESSION:
|
||||||
|
profilerManager->resumeSession();
|
||||||
|
header->bufferSize = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tag::START_SESSION:
|
||||||
|
{
|
||||||
|
const auto in = reinterpret_cast<const ProfilerPackage::StartSessionInput::Type*>(header->buffer);
|
||||||
|
fb_assert(sizeof(*in) == header->bufferSize);
|
||||||
|
|
||||||
|
const string description(in->description.str,
|
||||||
|
in->descriptionNull ? 0 : in->description.length);
|
||||||
|
const PathName pluginName(in->pluginName.str,
|
||||||
|
in->pluginNameNull ? 0 : in->pluginName.length);
|
||||||
|
const string pluginOptions(in->pluginOptions.str,
|
||||||
|
in->pluginOptionsNull ? 0 : in->pluginOptions.length);
|
||||||
|
|
||||||
|
const auto out = reinterpret_cast<ProfilerPackage::StartSessionOutput::Type*>(header->buffer);
|
||||||
|
header->bufferSize = sizeof(*out);
|
||||||
|
|
||||||
|
out->sessionIdNull = FB_FALSE;
|
||||||
|
out->sessionId = profilerManager->startSession(tdbb,
|
||||||
|
in->attachmentId, pluginName, description, pluginOptions);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
fb_assert(false);
|
||||||
|
(Arg::Gds(isc_random) << "Invalid profiler's remote command").raise();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +116,11 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void cancelSession();
|
void cancelSession();
|
||||||
void finishSession(thread_db* tdbb);
|
void finishSession(thread_db* tdbb, bool flushData);
|
||||||
bool pauseSession();
|
void pauseSession(bool flushData);
|
||||||
void resumeSession();
|
void resumeSession();
|
||||||
void discard();
|
void discard();
|
||||||
void flush(Firebird::ITransaction* transaction);
|
void flush();
|
||||||
|
|
||||||
Statement* getStatement(jrd_req* request);
|
Statement* getStatement(jrd_req* request);
|
||||||
SINT64 getRequest(jrd_req* request, unsigned flags);
|
SINT64 getRequest(jrd_req* request, unsigned flags);
|
||||||
|
@ -130,7 +130,7 @@ class Session final :
|
|||||||
public RefCounted
|
public RefCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, ITransaction* transaction,
|
Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin,
|
||||||
const char* aDescription, ISC_TIMESTAMP_TZ aStartTimestamp);
|
const char* aDescription, ISC_TIMESTAMP_TZ aStartTimestamp);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -204,12 +204,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(ThrowStatusExceptionWrapper* status, IAttachment* attachment, ITransaction* transaction) override;
|
void init(ThrowStatusExceptionWrapper* status, IAttachment* attachment) override;
|
||||||
|
|
||||||
IProfilerSession* startSession(ThrowStatusExceptionWrapper* status, ITransaction* transaction,
|
IProfilerSession* startSession(ThrowStatusExceptionWrapper* status,
|
||||||
const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) override;
|
const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) override;
|
||||||
|
|
||||||
void flush(ThrowStatusExceptionWrapper* status, ITransaction* transaction) override;
|
void flush(ThrowStatusExceptionWrapper* status) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<IAttachment> attachment,
|
void createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<IAttachment> attachment,
|
||||||
@ -224,7 +224,7 @@ public:
|
|||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
|
|
||||||
void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* attachment, ITransaction* transaction)
|
void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* attachment)
|
||||||
{
|
{
|
||||||
userAttachment = attachment;
|
userAttachment = attachment;
|
||||||
|
|
||||||
@ -254,12 +254,14 @@ void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* atta
|
|||||||
message.clear();
|
message.clear();
|
||||||
|
|
||||||
RefPtr<IAttachment> refAttachment(attachment);
|
RefPtr<IAttachment> refAttachment(attachment);
|
||||||
RefPtr<ITransaction> refTransaction(transaction);
|
RefPtr<ITransaction> refTransaction;
|
||||||
string currentRole;
|
string currentRole;
|
||||||
bool roleInUse;
|
bool roleInUse;
|
||||||
|
|
||||||
for (unsigned i = 0; i < 2; ++i)
|
for (unsigned i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
|
refTransaction = makeNoIncRef(refAttachment->startTransaction(status, 0, nullptr));
|
||||||
|
|
||||||
auto resultSet = makeNoIncRef(refAttachment->openCursor(status, refTransaction, 0, sql, SQL_DIALECT_CURRENT,
|
auto resultSet = makeNoIncRef(refAttachment->openCursor(status, refTransaction, 0, sql, SQL_DIALECT_CURRENT,
|
||||||
nullptr, nullptr, message.getMetadata(), nullptr, 0));
|
nullptr, nullptr, message.getMetadata(), nullptr, 0));
|
||||||
|
|
||||||
@ -294,8 +296,6 @@ void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* atta
|
|||||||
|
|
||||||
refAttachment = makeNoIncRef(dispatcher->attachDatabase(status, dbName.c_str(),
|
refAttachment = makeNoIncRef(dispatcher->attachDatabase(status, dbName.c_str(),
|
||||||
dpb->getBufferLength(status), dpb->getBuffer(status)));
|
dpb->getBufferLength(status), dpb->getBuffer(status)));
|
||||||
|
|
||||||
refTransaction = makeNoIncRef(refAttachment->startTransaction(status, 0, nullptr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,17 +306,17 @@ void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* atta
|
|||||||
{
|
{
|
||||||
// Refresh roles.
|
// Refresh roles.
|
||||||
|
|
||||||
attachment->execute(status, transaction, 0, "set role plg$profiler",
|
attachment->execute(status, nullptr, 0, "set role plg$profiler",
|
||||||
SQL_DIALECT_CURRENT, nullptr, nullptr, nullptr, nullptr);
|
SQL_DIALECT_CURRENT, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
attachment->execute(status, transaction, 0, ("set role " + currentRole).c_str(),
|
attachment->execute(status, nullptr, 0, ("set role " + currentRole).c_str(),
|
||||||
SQL_DIALECT_CURRENT, nullptr, nullptr, nullptr, nullptr);
|
SQL_DIALECT_CURRENT, nullptr, nullptr, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadMetadata(status);
|
loadMetadata(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* status, ITransaction* transaction,
|
IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* status,
|
||||||
const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp)
|
const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp)
|
||||||
{
|
{
|
||||||
if (options && options[0])
|
if (options && options[0])
|
||||||
@ -333,10 +333,10 @@ IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* stat
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FB_NEW Session(status, this, transaction, description, timestamp);
|
return FB_NEW Session(status, this, description, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status, ITransaction* transaction)
|
void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
||||||
{
|
{
|
||||||
constexpr auto sessionSql = R"""(
|
constexpr auto sessionSql = R"""(
|
||||||
update or insert into plg$prof_sessions
|
update or insert into plg$prof_sessions
|
||||||
@ -514,6 +514,8 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status, ITransaction* tr
|
|||||||
) psqlStatsMessage(status, MasterInterfacePtr());
|
) psqlStatsMessage(status, MasterInterfacePtr());
|
||||||
psqlStatsMessage.clear();
|
psqlStatsMessage.clear();
|
||||||
|
|
||||||
|
auto transaction = makeNoIncRef(userAttachment->startTransaction(status, 0, nullptr));
|
||||||
|
|
||||||
auto sessionStmt = makeNoIncRef(userAttachment->prepare(status, transaction, 0, sessionSql, SQL_DIALECT_CURRENT, 0));
|
auto sessionStmt = makeNoIncRef(userAttachment->prepare(status, transaction, 0, sessionSql, SQL_DIALECT_CURRENT, 0));
|
||||||
auto statementStmt = makeNoIncRef(userAttachment->prepare(
|
auto statementStmt = makeNoIncRef(userAttachment->prepare(
|
||||||
status, transaction, 0, statementSql, SQL_DIALECT_CURRENT, 0));
|
status, transaction, 0, statementSql, SQL_DIALECT_CURRENT, 0));
|
||||||
@ -840,6 +842,9 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status, ITransaction* tr
|
|||||||
}
|
}
|
||||||
|
|
||||||
executeBatches();
|
executeBatches();
|
||||||
|
|
||||||
|
transaction->commit(status);
|
||||||
|
transaction.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<IAttachment> attachment,
|
void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<IAttachment> attachment,
|
||||||
@ -1157,7 +1162,7 @@ void ProfilerPlugin::loadMetadata(ThrowStatusExceptionWrapper* status)
|
|||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
|
|
||||||
Session::Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, ITransaction* transaction,
|
Session::Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin,
|
||||||
const char* aDescription, ISC_TIMESTAMP_TZ aStartTimestamp)
|
const char* aDescription, ISC_TIMESTAMP_TZ aStartTimestamp)
|
||||||
: plugin(aPlugin),
|
: plugin(aPlugin),
|
||||||
startTimestamp(aStartTimestamp),
|
startTimestamp(aStartTimestamp),
|
||||||
@ -1170,6 +1175,8 @@ Session::Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, I
|
|||||||
|
|
||||||
constexpr auto sequenceSql = "select next value for plg$prof_profile_id from rdb$database";
|
constexpr auto sequenceSql = "select next value for plg$prof_profile_id from rdb$database";
|
||||||
|
|
||||||
|
auto transaction = makeNoIncRef(plugin->userAttachment->startTransaction(status, 0, nullptr));
|
||||||
|
|
||||||
auto resultSet = makeNoIncRef(plugin->userAttachment->openCursor(status, transaction, 0, sequenceSql,
|
auto resultSet = makeNoIncRef(plugin->userAttachment->openCursor(status, transaction, 0, sequenceSql,
|
||||||
SQL_DIALECT_CURRENT,
|
SQL_DIALECT_CURRENT,
|
||||||
nullptr, nullptr, sequenceMessage.getMetadata(), nullptr, 0));
|
nullptr, nullptr, sequenceMessage.getMetadata(), nullptr, 0));
|
||||||
@ -1177,6 +1184,9 @@ Session::Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, I
|
|||||||
resultSet->fetchNext(status, sequenceMessage.getData());
|
resultSet->fetchNext(status, sequenceMessage.getData());
|
||||||
id = sequenceMessage->value;
|
id = sequenceMessage->value;
|
||||||
|
|
||||||
|
transaction->commit(status);
|
||||||
|
transaction.clear();
|
||||||
|
|
||||||
plugin->sessions.add(makeRef(this));
|
plugin->sessions.add(makeRef(this));
|
||||||
|
|
||||||
addRef();
|
addRef();
|
||||||
|
Loading…
Reference in New Issue
Block a user