Skip to content

Commit

Permalink
Fixed #7304: Events in system attachments (like garbage collector) ar…
Browse files Browse the repository at this point in the history
…e not traced
  • Loading branch information
AlexPeshkoff committed Sep 22, 2022
1 parent 40d09d2 commit a3cfe50
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 81 deletions.
2 changes: 1 addition & 1 deletion src/jrd/Attachment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "firebird.h"
#include "../jrd/Attachment.h"
#include "../jrd/MetaName.h"
#include "../jrd/Database.h"
#include "../jrd/Function.h"
#include "../jrd/nbak.h"
Expand All @@ -47,7 +48,6 @@
#include "../jrd/replication/Manager.h"

#include "../common/classes/fb_string.h"
#include "../jrd/MetaName.h"
#include "../common/StatusArg.h"
#include "../common/TimeZoneUtil.h"
#include "../common/isc_proto.h"
Expand Down
20 changes: 20 additions & 0 deletions src/jrd/Attachment.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,26 @@ class Attachment : public pool_alloc<type_att>
bool dsqlKeepBlr = false;
};

class UseCountHolder
{
public:
explicit UseCountHolder(Attachment* a)
: att(a)
{
if (att)
att->att_use_count++;
}

~UseCountHolder()
{
if (att)
att->att_use_count--;
}

private:
Attachment* att;
};

public:
static Attachment* create(Database* dbb, JProvider* provider);
static void destroy(Attachment* const attachment);
Expand Down
18 changes: 1 addition & 17 deletions src/jrd/CryptoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,23 +960,7 @@ namespace Jrd {
tdbb->markAsSweeper();

DatabaseContextHolder dbHolder(tdbb);

class UseCountHolder
{
public:
explicit UseCountHolder(Attachment* a)
: att(a)
{
att->att_use_count++;
}
~UseCountHolder()
{
att->att_use_count--;
}
private:
Attachment* att;
};
UseCountHolder use_count(att);
Attachment::UseCountHolder use_count(att);

// get ready...
AutoSetRestore<Attachment*> attSet(&cryptAtt, att);
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/Mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ bool Mapping::DbHandle::attach(const char* aliasDb, ICryptKeyCallback* cryptCb)
if (!(missing || down))
check("IProvider::attachDatabase", &st);

// down/missing security DB is not a reason to fail mapping
// down/missing DB is not a reason to fail mapping
}
else
assignRefNoIncr(att);
Expand Down
1 change: 1 addition & 0 deletions src/jrd/cch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,6 +2979,7 @@ void BufferControl::cache_writer(BufferControl* bcb)
attachment->att_user = &user;

BackgroundContextHolder tdbb(dbb, attachment, &status_vector, FB_FUNCTION);
Jrd::Attachment::UseCountHolder use(attachment);

try
{
Expand Down
128 changes: 70 additions & 58 deletions src/jrd/jrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,10 +1331,15 @@ static void check_single_maintenance(thread_db* tdbb);

namespace {
enum VdnResult {VDN_FAIL, VDN_OK/*, VDN_SECURITY*/};

const unsigned UNWIND_INTERNAL = 1;
const unsigned UNWIND_CREATE = 2;
const unsigned UNWIND_NEW = 4;
}
static VdnResult verifyDatabaseName(const PathName&, FbStatusVector*, bool);

static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus, bool internalFlag);
static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus, unsigned flags,
const char* filename, const DatabaseOptions& options, ICryptKeyCallback* callback);
static JAttachment* initAttachment(thread_db*, const PathName&, const PathName&, RefPtr<const Config>, bool,
const DatabaseOptions&, RefMutexUnlock&, IPluginConfig*, JProvider*);
static JAttachment* create_attachment(const PathName&, Database*, JProvider* provider, const DatabaseOptions&, bool newDb);
Expand Down Expand Up @@ -1553,10 +1558,14 @@ static void trace_warning(thread_db* tdbb, FbStatusVector* userStatus, const cha
}


static void trace_failed_attach(TraceManager* traceManager, const char* filename,
const DatabaseOptions& options, bool create, FbStatusVector* status)
// Report to Trace API that attachment has not been created
static void trace_failed_attach(const char* filename, const DatabaseOptions& options,
unsigned flags, FbStatusVector* status, ICryptKeyCallback* callback)
{
// Report to Trace API that attachment has not been created
// Avoid uncontrolled recursion
if (options.dpb_map_attach)
return;

const char* origFilename = filename;
if (options.dpb_org_filename.hasData())
origFilename = options.dpb_org_filename.c_str();
Expand All @@ -1567,26 +1576,16 @@ static void trace_failed_attach(TraceManager* traceManager, const char* filename
ISC_STATUS s = status->getErrors()[1];
const ntrace_result_t result = (s == isc_login || s == isc_no_priv) ?
ITracePlugin::RESULT_UNAUTHORIZED : ITracePlugin::RESULT_FAILED;
const char* func = create ? "JProvider::createDatabase" : "JProvider::attachDatabase";
const char* func = flags & UNWIND_CREATE ? "JProvider::createDatabase" : "JProvider::attachDatabase";

if (!traceManager)
{
TraceManager tempMgr(origFilename);
// Perform actual trace
TraceManager tempMgr(origFilename, callback, flags & UNWIND_NEW);

if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ATTACH))
tempMgr.event_attach(&conn, create, result);
if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ATTACH))
tempMgr.event_attach(&conn, flags & UNWIND_CREATE, result);

if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ERROR))
tempMgr.event_error(&conn, &traceStatus, func);
}
else
{
if (traceManager->needs(ITraceFactory::TRACE_EVENT_ATTACH))
traceManager->event_attach(&conn, create, result);

if (traceManager->needs(ITraceFactory::TRACE_EVENT_ERROR))
traceManager->event_error(&conn, &traceStatus, func);
}
if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ERROR))
tempMgr.event_error(&conn, &traceStatus, func);
}


Expand Down Expand Up @@ -1709,21 +1708,20 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
catch (const Exception& ex)
{
ex.stuffException(user_status);
trace_failed_attach(NULL, filename, options, false, user_status);
trace_failed_attach(filename, options, 0, user_status, cryptCallback);
throw;
}

// Check database against conf file.
const VdnResult vdn = verifyDatabaseName(expanded_name, tdbb->tdbb_status_vector, is_alias);
if (!is_alias && vdn == VDN_FAIL)
{
trace_failed_attach(NULL, filename, options, false, tdbb->tdbb_status_vector);
trace_failed_attach(filename, options, 0, tdbb->tdbb_status_vector, cryptCallback);
status_exception::raise(tdbb->tdbb_status_vector);
}

Database* dbb = NULL;
Jrd::Attachment* attachment = NULL;
bool attachTraced = false;

// Initialize special error handling
try
Expand Down Expand Up @@ -2201,7 +2199,6 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
TraceConnectionImpl conn(attachment);
attachment->att_trace_manager->event_attach(&conn, false, ITracePlugin::RESULT_SUCCESS);
}
attachTraced = true;

// Recover database after crash during backup difference file merge
dbb->dbb_backup_manager->endBackup(tdbb, true); // true = do recovery
Expand Down Expand Up @@ -2264,27 +2261,8 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
catch (const Exception& ex)
{
ex.stuffException(user_status);
if (attachTraced)
{
TraceManager* traceManager = attachment->att_trace_manager;
TraceConnectionImpl conn(attachment);
TraceStatusVectorImpl traceStatus(user_status, TraceStatusVectorImpl::TS_ERRORS);

if (traceManager->needs(ITraceFactory::TRACE_EVENT_ERROR))
traceManager->event_error(&conn, &traceStatus, "JProvider::attachDatabase");

if (traceManager->needs(ITraceFactory::TRACE_EVENT_DETACH))
traceManager->event_detach(&conn, false);
}
else
{
trace_failed_attach(attachment && attachment->att_trace_manager &&
attachment->att_trace_manager->isActive() ? attachment->att_trace_manager : NULL,
filename, options, false, user_status);
}

mapping.clearMainHandle();
unwindAttach(tdbb, ex, user_status, existingId);
unwindAttach(tdbb, ex, user_status, existingId ? UNWIND_INTERNAL : 0, filename, options, cryptCallback);
}
}
catch (const Exception& ex)
Expand Down Expand Up @@ -2878,15 +2856,15 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
catch (const Exception& ex)
{
ex.stuffException(user_status);
trace_failed_attach(NULL, filename, options, true, user_status);
trace_failed_attach(filename, options, UNWIND_CREATE, user_status, cryptCallback);
throw;
}

// Check database against conf file.
const VdnResult vdn = verifyDatabaseName(expanded_name, tdbb->tdbb_status_vector, is_alias);
if (!is_alias && vdn == VDN_FAIL)
{
trace_failed_attach(NULL, filename, options, true, tdbb->tdbb_status_vector);
trace_failed_attach(filename, options, UNWIND_CREATE, tdbb->tdbb_status_vector, cryptCallback);
status_exception::raise(tdbb->tdbb_status_vector);
}

Expand Down Expand Up @@ -3206,12 +3184,8 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
catch (const Exception& ex)
{
ex.stuffException(user_status);
trace_failed_attach(attachment && attachment->att_trace_manager &&
attachment->att_trace_manager->isActive() ? attachment->att_trace_manager : NULL,
filename, options, true, user_status);

mapping.clearMainHandle();
unwindAttach(tdbb, ex, user_status, false);
unwindAttach(tdbb, ex, user_status, UNWIND_CREATE, filename, options, cryptCallback);
}
}
catch (const Exception& ex)
Expand Down Expand Up @@ -5009,10 +4983,16 @@ void SysStableAttachment::initDone()
{
Jrd::Attachment* attachment = getHandle();
Database* dbb = attachment->att_database;
SyncLockGuard guard(&dbb->dbb_sys_attach, SYNC_EXCLUSIVE, "SysStableAttachment::initDone");

attachment->att_next = dbb->dbb_sys_attachments;
dbb->dbb_sys_attachments = attachment;
{ // scope
SyncLockGuard guard(&dbb->dbb_sys_attach, SYNC_EXCLUSIVE, "SysStableAttachment::initDone");

attachment->att_next = dbb->dbb_sys_attachments;
dbb->dbb_sys_attachments = attachment;
}

// make system attachments traceable
attachment->att_trace_manager->activate();
}


Expand Down Expand Up @@ -8579,9 +8559,41 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options, const char
}
}

static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus, bool internalFlag)
static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus, unsigned flags,
const char* filename, const DatabaseOptions& options, ICryptKeyCallback* callback)
{
transliterateException(tdbb, ex, userStatus, NULL);
try
{
const auto att = tdbb->getAttachment();
TraceManager* traceManager = att ? att->att_trace_manager : nullptr;
if (att && traceManager && traceManager->isActive())
{
TraceConnectionImpl conn(att);
TraceStatusVectorImpl traceStatus(userStatus, TraceStatusVectorImpl::TS_ERRORS);

if (traceManager->needs(ITraceFactory::TRACE_EVENT_ATTACH))
traceManager->event_attach(&conn, flags & UNWIND_CREATE, ITracePlugin::RESULT_FAILED);
}
else
{
auto dbb = tdbb->getDatabase();
if (dbb && (dbb->dbb_flags & DBB_new))
{
// attach failed before completion of DBB initialization
// that's hardly recoverable error - avoid extra problems in mapping
flags |= UNWIND_NEW;
}

trace_failed_attach(filename, options, flags, userStatus, callback);
}

const char* func = flags & UNWIND_CREATE ? "JProvider::createDatabase" : "JProvider::attachDatabase";
transliterateException(tdbb, ex, userStatus, func);
}
catch (const Exception&)
{
// no-op
}

try
{
Expand Down Expand Up @@ -8619,7 +8631,7 @@ static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* u
}

JRD_shutdown_database(dbb, SHUT_DBB_RELEASE_POOLS |
(internalFlag ? SHUT_DBB_OVERWRITE_CHECK : 0));
(flags & UNWIND_INTERNAL ? SHUT_DBB_OVERWRITE_CHECK : 0));
}
}
catch (const Exception&)
Expand Down
29 changes: 27 additions & 2 deletions src/jrd/trace/TraceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ TraceManager::TraceManager(Service* in_svc) :
init();
}

TraceManager::TraceManager(const char* in_filename) :
TraceManager::TraceManager(const char* in_filename, ICryptKeyCallback* cb, bool failed) :
attachment(NULL),
service(NULL),
filename(in_filename),
callback(cb),
trace_sessions(*getDefaultMemoryPool()),
active(true)
active(true),
failedAttach(failed)
{
init();
}
Expand Down Expand Up @@ -281,6 +283,8 @@ void TraceManager::update_session(const TraceSession& session)
mapping.setAuthBlock(session.ses_auth);
mapping.setSqlRole(session.ses_role);
mapping.setSecurityDbAlias(dbb->dbb_config->getSecurityDatabase(), dbb->dbb_filename.c_str());

fb_assert(attachment->getInterface());
mapping.setDb(attachment->att_filename.c_str(), dbb->dbb_filename.c_str(),
attachment->getInterface());

Expand Down Expand Up @@ -308,6 +312,27 @@ void TraceManager::update_session(const TraceSession& session)
mapResult = mapping.mapUser(s_user, t_role);
}
}
else if (filename)
{
if (session.ses_auth.hasData())
{
Mapping mapping(Mapping::MAP_NO_FLAGS, callback);
mapping.needSystemPrivileges(priv);
mapping.setAuthBlock(session.ses_auth);
mapping.setSqlRole(session.ses_role);

RefPtr<const Config> config;
PathName org_filename(filename), expanded_name;
if (! expandDatabaseName(org_filename, expanded_name, &config))
expanded_name = filename;

mapping.setSecurityDbAlias(config->getSecurityDatabase(), expanded_name.c_str());
if (!failedAttach)
mapping.setDb(filename, expanded_name.c_str(), nullptr);

mapResult = mapping.mapUser(s_user, t_role);
}
}
else
{
// failed attachment attempts traced by admin trace only
Expand Down
5 changes: 3 additions & 2 deletions src/jrd/trace/TraceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class TraceManager
/* Initializes plugins. */
explicit TraceManager(Attachment* in_att);
explicit TraceManager(Service* in_svc);
explicit TraceManager(const char* in_filename);
TraceManager(const char* in_filename, Firebird::ICryptKeyCallback* callback, bool failedAttach);

/* Finalize plugins. Called when database is closed by the engine */
~TraceManager();
Expand Down Expand Up @@ -168,6 +168,7 @@ class TraceManager
Service* service;
const char* filename;
NotificationNeeds trace_needs, new_needs;
Firebird::ICryptKeyCallback* callback;

// This structure should be POD-like to be stored in Array
struct FactoryInfo
Expand Down Expand Up @@ -252,7 +253,7 @@ class TraceManager
static Firebird::GlobalPtr<StorageInstance, Firebird::InstanceControl::PRIORITY_DELETE_FIRST> storageInstance;

ULONG changeNumber;
bool active;
bool active, failedAttach;
};

}
Expand Down
Loading

0 comments on commit a3cfe50

Please sign in to comment.