8
0
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:
Adriano dos Santos Fernandes 2022-06-03 21:52:15 -03:00
parent bb139df3c7
commit 3fe37a6a60
7 changed files with 148 additions and 196 deletions

View File

@ -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`

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();