mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:03:03 +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.
|
||||
|
||||
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.
|
||||
|
||||
@ -89,6 +89,8 @@ execute procedure rdb$profiler.finish_session(true);
|
||||
|
||||
-- Data analysis
|
||||
|
||||
commit; -- start new transaction
|
||||
|
||||
select * from plg$prof_sessions;
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
- `ATTACHMENT_ID` type `BIGINT NOT NULL` default `CURRENT_CONNECTION`
|
||||
|
@ -1700,15 +1700,12 @@ interface ReplicatedSession : PluginBase
|
||||
|
||||
interface ProfilerPlugin : PluginBase
|
||||
{
|
||||
// The transaction should not be stored for later usage after the method returns.
|
||||
void init(Status status, Attachment attachment, Transaction transaction);
|
||||
void init(Status status, Attachment attachment);
|
||||
|
||||
// The transaction should not be stored for later usage after the method returns.
|
||||
ProfilerSession startSession(Status status, Transaction transaction, const string description,
|
||||
ProfilerSession startSession(Status status, const string description,
|
||||
const string options, ISC_TIMESTAMP_TZ timestamp);
|
||||
|
||||
// The transaction should not be stored for later usage after the method returns.
|
||||
void flush(Status status, Transaction transaction);
|
||||
void flush(Status status);
|
||||
}
|
||||
|
||||
interface ProfilerSession : Disposable
|
||||
|
@ -6648,9 +6648,9 @@ namespace Firebird
|
||||
public:
|
||||
struct VTable : public IPluginBase::VTable
|
||||
{
|
||||
void (CLOOP_CARG *init)(IProfilerPlugin* self, IStatus* status, IAttachment* attachment, ITransaction* transaction) throw();
|
||||
IProfilerSession* (CLOOP_CARG *startSession)(IProfilerPlugin* self, IStatus* status, ITransaction* transaction, 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 *init)(IProfilerPlugin* self, IStatus* status, IAttachment* attachment) 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) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -6666,25 +6666,25 @@ namespace Firebird
|
||||
public:
|
||||
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);
|
||||
static_cast<VTable*>(this->cloopVTable)->init(this, status, attachment, transaction);
|
||||
static_cast<VTable*>(this->cloopVTable)->init(this, status, attachment);
|
||||
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);
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename StatusType> void flush(StatusType* status, ITransaction* transaction)
|
||||
template <typename StatusType> void flush(StatusType* status)
|
||||
{
|
||||
StatusType::clearException(status);
|
||||
static_cast<VTable*>(this->cloopVTable)->flush(this, status, transaction);
|
||||
static_cast<VTable*>(this->cloopVTable)->flush(this, status);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
};
|
||||
@ -19964,13 +19964,13 @@ namespace Firebird
|
||||
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);
|
||||
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::init(&status2, attachment, transaction);
|
||||
static_cast<Name*>(self)->Name::init(&status2, attachment);
|
||||
}
|
||||
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);
|
||||
|
||||
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 (...)
|
||||
{
|
||||
@ -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);
|
||||
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::flush(&status2, transaction);
|
||||
static_cast<Name*>(self)->Name::flush(&status2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -20071,9 +20071,9 @@ namespace Firebird
|
||||
{
|
||||
}
|
||||
|
||||
virtual void init(StatusType* status, IAttachment* attachment, ITransaction* transaction) = 0;
|
||||
virtual IProfilerSession* startSession(StatusType* status, ITransaction* transaction, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) = 0;
|
||||
virtual void flush(StatusType* status, ITransaction* transaction) = 0;
|
||||
virtual void init(StatusType* status, IAttachment* attachment) = 0;
|
||||
virtual IProfilerSession* startSession(StatusType* status, const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp) = 0;
|
||||
virtual void flush(StatusType* status) = 0;
|
||||
};
|
||||
|
||||
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_cleanupTransactionPtr = procedure(this: IReplicatedSession; status: IStatus; number: 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_startSessionPtr = function(this: IProfilerPlugin; status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; cdecl;
|
||||
IProfilerPlugin_flushPtr = procedure(this: IProfilerPlugin; status: IStatus; transaction: ITransaction); cdecl;
|
||||
IProfilerPlugin_initPtr = procedure(this: IProfilerPlugin; status: IStatus; attachment: IAttachment); 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); cdecl;
|
||||
IProfilerSession_getIdPtr = function(this: IProfilerSession): Int64; cdecl;
|
||||
IProfilerSession_getFlagsPtr = function(this: IProfilerSession): Cardinal; cdecl;
|
||||
IProfilerSession_cancelPtr = procedure(this: IProfilerSession; status: IStatus); cdecl;
|
||||
@ -3775,9 +3775,9 @@ type
|
||||
IProfilerPlugin = class(IPluginBase)
|
||||
const VERSION = 4;
|
||||
|
||||
procedure init(status: IStatus; attachment: IAttachment; transaction: ITransaction);
|
||||
function startSession(status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
||||
procedure flush(status: IStatus; transaction: ITransaction);
|
||||
procedure init(status: IStatus; attachment: IAttachment);
|
||||
function startSession(status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession;
|
||||
procedure flush(status: IStatus);
|
||||
end;
|
||||
|
||||
IProfilerPluginImpl = class(IProfilerPlugin)
|
||||
@ -3787,9 +3787,9 @@ type
|
||||
function release(): Integer; virtual; abstract;
|
||||
procedure setOwner(r: IReferenceCounted); virtual; abstract;
|
||||
function getOwner(): IReferenceCounted; virtual; abstract;
|
||||
procedure init(status: IStatus; attachment: IAttachment; transaction: ITransaction); virtual; abstract;
|
||||
function startSession(status: IStatus; transaction: ITransaction; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; virtual; abstract;
|
||||
procedure flush(status: IStatus; transaction: ITransaction); virtual; abstract;
|
||||
procedure init(status: IStatus; attachment: IAttachment); virtual; abstract;
|
||||
function startSession(status: IStatus; description: PAnsiChar; options: PAnsiChar; timestamp: ISC_TIMESTAMP_TZ): IProfilerSession; virtual; abstract;
|
||||
procedure flush(status: IStatus); virtual; abstract;
|
||||
end;
|
||||
|
||||
ProfilerSessionVTable = class(DisposableVTable)
|
||||
@ -8945,21 +8945,21 @@ begin
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
procedure IProfilerPlugin.init(status: IStatus; attachment: IAttachment; transaction: ITransaction);
|
||||
procedure IProfilerPlugin.init(status: IStatus; attachment: IAttachment);
|
||||
begin
|
||||
ProfilerPluginVTable(vTable).init(Self, status, attachment, transaction);
|
||||
ProfilerPluginVTable(vTable).init(Self, status, attachment);
|
||||
FbException.checkException(status);
|
||||
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
|
||||
Result := ProfilerPluginVTable(vTable).startSession(Self, status, transaction, description, options, timestamp);
|
||||
Result := ProfilerPluginVTable(vTable).startSession(Self, status, description, options, timestamp);
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
procedure IProfilerPlugin.flush(status: IStatus; transaction: ITransaction);
|
||||
procedure IProfilerPlugin.flush(status: IStatus);
|
||||
begin
|
||||
ProfilerPluginVTable(vTable).flush(Self, status, transaction);
|
||||
ProfilerPluginVTable(vTable).flush(Self, status);
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
@ -15576,28 +15576,28 @@ begin
|
||||
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
|
||||
try
|
||||
IProfilerPluginImpl(this).init(status, attachment, transaction);
|
||||
IProfilerPluginImpl(this).init(status, attachment);
|
||||
except
|
||||
on e: Exception do FbException.catchException(status, e);
|
||||
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
|
||||
try
|
||||
Result := IProfilerPluginImpl(this).startSession(status, transaction, description, options, timestamp);
|
||||
Result := IProfilerPluginImpl(this).startSession(status, description, options, timestamp);
|
||||
except
|
||||
on e: Exception do FbException.catchException(status, e);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure IProfilerPluginImpl_flushDispatcher(this: IProfilerPlugin; status: IStatus; transaction: ITransaction); cdecl;
|
||||
procedure IProfilerPluginImpl_flushDispatcher(this: IProfilerPlugin; status: IStatus); cdecl;
|
||||
begin
|
||||
try
|
||||
IProfilerPluginImpl(this).flush(status, transaction);
|
||||
IProfilerPluginImpl(this).flush(status);
|
||||
except
|
||||
on e: Exception do FbException.catchException(status, e);
|
||||
end
|
||||
|
@ -192,10 +192,9 @@ IExternalResultSet* ProfilerPackage::flushProcedure(ThrowStatusExceptionWrapper*
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto transaction = tdbb->getTransaction();
|
||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||
|
||||
profilerManager->flush(transaction->getInterface(true));
|
||||
profilerManager->flush();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -234,13 +233,9 @@ IExternalResultSet* ProfilerPackage::finishSessionProcedure(ThrowStatusException
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto transaction = tdbb->getTransaction();
|
||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||
|
||||
profilerManager->finishSession(tdbb);
|
||||
|
||||
if (in->flush)
|
||||
profilerManager->flush(transaction->getInterface(true));
|
||||
profilerManager->finishSession(tdbb, in->flush);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -258,14 +253,9 @@ IExternalResultSet* ProfilerPackage::pauseSessionProcedure(ThrowStatusExceptionW
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto transaction = tdbb->getTransaction();
|
||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||
|
||||
if (profilerManager->pauseSession())
|
||||
{
|
||||
if (in->flush)
|
||||
profilerManager->flush(transaction->getInterface(true));
|
||||
}
|
||||
profilerManager->pauseSession(in->flush);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -359,7 +349,6 @@ SINT64 ProfilerManager::startSession(thread_db* tdbb, AttNumber attachmentId, co
|
||||
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
||||
|
||||
const auto attachment = tdbb->getAttachment();
|
||||
const auto transaction = tdbb->getTransaction();
|
||||
ThrowLocalStatus status;
|
||||
|
||||
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->addRef();
|
||||
|
||||
plugin->init(&status, attachment->getInterface(), transaction->getInterface(true));
|
||||
plugin->init(&status, attachment->getInterface());
|
||||
|
||||
plugin->addRef();
|
||||
activePlugins.put(pluginName)->reset(plugin.get());
|
||||
}
|
||||
|
||||
AutoDispose<IProfilerSession> pluginSession = plugin->startSession(&status,
|
||||
transaction->getInterface(true),
|
||||
description.c_str(),
|
||||
options.c_str(),
|
||||
timestamp);
|
||||
@ -566,7 +554,7 @@ void ProfilerManager::cancelSession()
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilerManager::finishSession(thread_db* tdbb)
|
||||
void ProfilerManager::finishSession(thread_db* tdbb, bool flushData)
|
||||
{
|
||||
if (currentSession)
|
||||
{
|
||||
@ -577,15 +565,18 @@ void ProfilerManager::finishSession(thread_db* tdbb)
|
||||
currentSession->pluginSession->finish(&status, timestamp);
|
||||
currentSession = nullptr;
|
||||
}
|
||||
|
||||
if (flushData)
|
||||
flush();
|
||||
}
|
||||
|
||||
bool ProfilerManager::pauseSession()
|
||||
void ProfilerManager::pauseSession(bool flushData)
|
||||
{
|
||||
if (!currentSession)
|
||||
return false;
|
||||
if (currentSession)
|
||||
paused = true;
|
||||
|
||||
paused = true;
|
||||
return true;
|
||||
if (flushData)
|
||||
flush();
|
||||
}
|
||||
|
||||
void ProfilerManager::resumeSession()
|
||||
@ -600,7 +591,7 @@ void ProfilerManager::discard()
|
||||
activePlugins.clear();
|
||||
}
|
||||
|
||||
void ProfilerManager::flush(ITransaction* transaction)
|
||||
void ProfilerManager::flush()
|
||||
{
|
||||
AutoSetRestore<bool> pauseProfiler(&paused, true);
|
||||
|
||||
@ -612,7 +603,7 @@ void ProfilerManager::flush(ITransaction* transaction)
|
||||
auto& plugin = pluginAccessor.current()->second;
|
||||
|
||||
LogLocalStatus status("Profiler flush");
|
||||
plugin->flush(&status, transaction);
|
||||
plugin->flush(&status);
|
||||
|
||||
hasNext = pluginAccessor.getNext();
|
||||
|
||||
@ -937,122 +928,74 @@ void ProfilerListener::processCommand(thread_db* tdbb)
|
||||
const auto header = ipc->sharedMemory->getHeader();
|
||||
const auto profilerManager = attachment->getProfilerManager(tdbb);
|
||||
|
||||
jrd_tra* transaction = nullptr;
|
||||
try
|
||||
using Tag = ProfilerIpc::Tag;
|
||||
|
||||
switch (header->tag)
|
||||
{
|
||||
const auto startTransaction = [&]() {
|
||||
transaction = TRA_start(tdbb, 0, 0);
|
||||
tdbb->setTransaction(transaction);
|
||||
};
|
||||
case Tag::CANCEL_SESSION:
|
||||
profilerManager->cancelSession();
|
||||
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:
|
||||
profilerManager->cancelSession();
|
||||
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;
|
||||
const auto in = reinterpret_cast<const ProfilerPackage::FinishSessionInput::Type*>(header->buffer);
|
||||
fb_assert(sizeof(*in) == header->bufferSize);
|
||||
profilerManager->finishSession(tdbb, in->flush);
|
||||
header->bufferSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transaction)
|
||||
case Tag::FLUSH:
|
||||
profilerManager->flush();
|
||||
header->bufferSize = 0;
|
||||
break;
|
||||
|
||||
case Tag::PAUSE_SESSION:
|
||||
{
|
||||
TRA_commit(tdbb, transaction, false);
|
||||
tdbb->setTransaction(nullptr);
|
||||
transaction = nullptr;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (transaction)
|
||||
{
|
||||
TRA_rollback(tdbb, transaction, false, true);
|
||||
tdbb->setTransaction(nullptr);
|
||||
transaction = nullptr;
|
||||
const auto in = reinterpret_cast<const ProfilerPackage::PauseSessionInput::Type*>(header->buffer);
|
||||
fb_assert(sizeof(*in) == header->bufferSize);
|
||||
profilerManager->pauseSession(in->flush);
|
||||
header->bufferSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
void cancelSession();
|
||||
void finishSession(thread_db* tdbb);
|
||||
bool pauseSession();
|
||||
void finishSession(thread_db* tdbb, bool flushData);
|
||||
void pauseSession(bool flushData);
|
||||
void resumeSession();
|
||||
void discard();
|
||||
void flush(Firebird::ITransaction* transaction);
|
||||
void flush();
|
||||
|
||||
Statement* getStatement(jrd_req* request);
|
||||
SINT64 getRequest(jrd_req* request, unsigned flags);
|
||||
|
@ -130,7 +130,7 @@ class Session final :
|
||||
public RefCounted
|
||||
{
|
||||
public:
|
||||
Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, ITransaction* transaction,
|
||||
Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin,
|
||||
const char* aDescription, ISC_TIMESTAMP_TZ aStartTimestamp);
|
||||
|
||||
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;
|
||||
|
||||
void flush(ThrowStatusExceptionWrapper* status, ITransaction* transaction) override;
|
||||
void flush(ThrowStatusExceptionWrapper* status) override;
|
||||
|
||||
private:
|
||||
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;
|
||||
|
||||
@ -254,12 +254,14 @@ void ProfilerPlugin::init(ThrowStatusExceptionWrapper* status, IAttachment* atta
|
||||
message.clear();
|
||||
|
||||
RefPtr<IAttachment> refAttachment(attachment);
|
||||
RefPtr<ITransaction> refTransaction(transaction);
|
||||
RefPtr<ITransaction> refTransaction;
|
||||
string currentRole;
|
||||
bool roleInUse;
|
||||
|
||||
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,
|
||||
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(),
|
||||
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.
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
loadMetadata(status);
|
||||
}
|
||||
|
||||
IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* status, ITransaction* transaction,
|
||||
IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* status,
|
||||
const char* description, const char* options, ISC_TIMESTAMP_TZ timestamp)
|
||||
{
|
||||
if (options && options[0])
|
||||
@ -333,10 +333,10 @@ IProfilerSession* ProfilerPlugin::startSession(ThrowStatusExceptionWrapper* stat
|
||||
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"""(
|
||||
update or insert into plg$prof_sessions
|
||||
@ -514,6 +514,8 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status, ITransaction* tr
|
||||
) psqlStatsMessage(status, MasterInterfacePtr());
|
||||
psqlStatsMessage.clear();
|
||||
|
||||
auto transaction = makeNoIncRef(userAttachment->startTransaction(status, 0, nullptr));
|
||||
|
||||
auto sessionStmt = makeNoIncRef(userAttachment->prepare(status, transaction, 0, sessionSql, SQL_DIALECT_CURRENT, 0));
|
||||
auto statementStmt = makeNoIncRef(userAttachment->prepare(
|
||||
status, transaction, 0, statementSql, SQL_DIALECT_CURRENT, 0));
|
||||
@ -840,6 +842,9 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status, ITransaction* tr
|
||||
}
|
||||
|
||||
executeBatches();
|
||||
|
||||
transaction->commit(status);
|
||||
transaction.clear();
|
||||
}
|
||||
|
||||
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)
|
||||
: plugin(aPlugin),
|
||||
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";
|
||||
|
||||
auto transaction = makeNoIncRef(plugin->userAttachment->startTransaction(status, 0, nullptr));
|
||||
|
||||
auto resultSet = makeNoIncRef(plugin->userAttachment->openCursor(status, transaction, 0, sequenceSql,
|
||||
SQL_DIALECT_CURRENT,
|
||||
nullptr, nullptr, sequenceMessage.getMetadata(), nullptr, 0));
|
||||
@ -1177,6 +1184,9 @@ Session::Session(ThrowStatusExceptionWrapper* status, ProfilerPlugin* aPlugin, I
|
||||
resultSet->fetchNext(status, sequenceMessage.getData());
|
||||
id = sequenceMessage->value;
|
||||
|
||||
transaction->commit(status);
|
||||
transaction.clear();
|
||||
|
||||
plugin->sessions.add(makeRef(this));
|
||||
|
||||
addRef();
|
||||
|
Loading…
Reference in New Issue
Block a user