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

Fixed CORE-5433: Minor performance optimization - avoid additional database attachment from security objects mapping code

This commit is contained in:
AlexPeshkoff 2016-12-30 19:28:37 +03:00
parent dbc73bff06
commit 5e70385a16
15 changed files with 135 additions and 85 deletions

View File

@ -724,12 +724,19 @@ void AttachmentsRefHolder::debugHelper(const char* from)
RefDeb(DEB_RLS_JATT, from);
}
void StableAttachmentPart::manualLock(ULONG& flags)
void StableAttachmentPart::manualLock(ULONG& flags, const ULONG whatLock)
{
fb_assert(!(flags & ATT_manual_lock));
asyncMutex.enter(FB_FUNCTION);
mainMutex.enter(FB_FUNCTION);
flags |= (ATT_manual_lock | ATT_async_manual_lock);
fb_assert(!(flags & whatLock));
if (whatLock & ATT_async_manual_lock)
{
asyncMutex.enter(FB_FUNCTION);
flags |= ATT_async_manual_lock;
}
if (whatLock & ATT_manual_lock)
{
mainMutex.enter(FB_FUNCTION);
flags |= ATT_manual_lock;
}
}
void StableAttachmentPart::manualUnlock(ULONG& flags)

View File

@ -114,9 +114,35 @@ struct DdlTriggerContext
};
struct bid;
// Attachment flags
const ULONG ATT_no_cleanup = 0x00001L; // Don't expunge, purge, or garbage collect
const ULONG ATT_shutdown = 0x00002L; // attachment has been shutdown
const ULONG ATT_shutdown_manager = 0x00004L; // attachment requesting shutdown
const ULONG ATT_exclusive = 0x00008L; // attachment wants exclusive database access
const ULONG ATT_attach_pending = 0x00010L; // Indicate attachment is only pending
const ULONG ATT_exclusive_pending = 0x00020L; // Indicate exclusive attachment pending
const ULONG ATT_notify_gc = 0x00040L; // Notify garbage collector to expunge, purge ..
const ULONG ATT_garbage_collector = 0x00080L; // I'm a garbage collector
const ULONG ATT_cancel_raise = 0x00100L; // Cancel currently running operation
const ULONG ATT_cancel_disable = 0x00200L; // Disable cancel operations
const ULONG ATT_no_db_triggers = 0x00400L; // Don't execute database triggers
const ULONG ATT_manual_lock = 0x00800L; // Was locked manually
const ULONG ATT_async_manual_lock = 0x01000L; // Async mutex was locked manually
//const ULONG ATT_purge_started = 0x02000L; // Purge already started - avoid 2 purges at once
const ULONG ATT_overwrite_check = 0x02000L; // Attachment checks is it possible to overwrite DB
const ULONG ATT_system = 0x04000L; // Special system attachment
const ULONG ATT_creator = 0x08000L; // This attachment created the DB
const ULONG ATT_monitor_done = 0x10000L; // Monitoring data is refreshed
const ULONG ATT_security_db = 0x20000L; // Attachment used for security purposes
const ULONG ATT_mapping = 0x40000L; // Attachment used for mapping auth block
const ULONG ATT_crypt_thread = 0x80000L; // Attachment from crypt thread
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
class Attachment;
struct bid;
//
// RefCounted part of Attachment object, placed into permanent pool
@ -172,7 +198,7 @@ public:
return getInterface()->getTransactionInterface(status, tra);
}
void manualLock(ULONG& flags);
void manualLock(ULONG& flags, const ULONG whatLock = ATT_manual_lock | ATT_async_manual_lock);
void manualUnlock(ULONG& flags);
void manualAsyncUnlock(ULONG& flags);
@ -384,33 +410,6 @@ private:
};
// Attachment flags
const ULONG ATT_no_cleanup = 0x00001L; // Don't expunge, purge, or garbage collect
const ULONG ATT_shutdown = 0x00002L; // attachment has been shutdown
const ULONG ATT_shutdown_manager = 0x00004L; // attachment requesting shutdown
const ULONG ATT_exclusive = 0x00008L; // attachment wants exclusive database access
const ULONG ATT_attach_pending = 0x00010L; // Indicate attachment is only pending
const ULONG ATT_exclusive_pending = 0x00020L; // Indicate exclusive attachment pending
const ULONG ATT_notify_gc = 0x00040L; // Notify garbage collector to expunge, purge ..
const ULONG ATT_garbage_collector = 0x00080L; // I'm a garbage collector
const ULONG ATT_cancel_raise = 0x00100L; // Cancel currently running operation
const ULONG ATT_cancel_disable = 0x00200L; // Disable cancel operations
const ULONG ATT_no_db_triggers = 0x00400L; // Don't execute database triggers
const ULONG ATT_manual_lock = 0x00800L; // Was locked manually
const ULONG ATT_async_manual_lock = 0x01000L; // Async mutex was locked manually
//const ULONG ATT_purge_started = 0x02000L; // Purge already started - avoid 2 purges at once
const ULONG ATT_overwrite_check = 0x02000L; // Attachment checks is it possible to overwrite DB
const ULONG ATT_system = 0x04000L; // Special system attachment
const ULONG ATT_creator = 0x08000L; // This attachment created the DB
const ULONG ATT_monitor_done = 0x10000L; // Monitoring data is refreshed
const ULONG ATT_security_db = 0x20000L; // Attachment used for security purposes
const ULONG ATT_mapping = 0x40000L; // Attachment used for mapping auth block
const ULONG ATT_crypt_thread = 0x80000L; // Attachment from crypt thread
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
inline bool Attachment::locksmith(thread_db* tdbb, SystemPrivilege sp) const
{
return att_user && att_user->locksmith(tdbb, sp);

View File

@ -662,7 +662,7 @@ Firebird::ITransaction* ExtEngineManager::ExternalContextImpl::getTransaction(
const char* ExtEngineManager::ExternalContextImpl::getUserName()
{
return internalAttachment->att_user->getUserName().c_str();
return internalAttachment->att_user ? internalAttachment->att_user->getUserName().c_str() : "";
}
const char* ExtEngineManager::ExternalContextImpl::getDatabaseName()

View File

@ -903,7 +903,10 @@ public:
: AutoPtr(att)
{
if (att)
{
MAP_DEBUG(fprintf(stderr, "Using existing db handle %p\n", att));
att->addRef();
}
}
bool attach(FbLocalStatus& st, const char* aliasDb, ICryptKeyCallback* cryptCb)
@ -911,7 +914,10 @@ public:
bool down = false; // true if on attach db is shutdown
if (hasData())
{
MAP_DEBUG(fprintf(stderr, "Already attached %s\n", aliasDb));
return down;
}
DispatcherPtr prov;
if (cryptCb)
@ -1337,7 +1343,11 @@ ULONG mapUser(const bool throwNotFoundError,
}
if (cDb)
{
MAP_DEBUG(fprintf(stderr, "Populate cache for main DB %p\n", iDb.get()));
cDb->populate(iDb, dbDown);
}
MAP_DEBUG(fprintf(stderr, "Populate cache for sec DB %p\n", iSec.get()));
cSec->populate(iSec, secDown);
sSec.downgrade(SYNC_SHARED);

View File

@ -391,9 +391,8 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
// Enumerate active sessions
const MetaName& user_name = attachment->att_user->getUserName();
const bool locksmith = attachment->locksmith(tdbb, MONITOR_ANY_ATTACHMENT);
const char* user_name_ptr = locksmith ? NULL : user_name.c_str();
const char* user_name_ptr = locksmith ? NULL : attachment->att_user ? attachment->att_user->getUserName().c_str() : "";
MonitoringData::SessionList sessions(pool);
@ -856,7 +855,9 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record)
void Monitoring::putAttachment(SnapshotData::DumpRecord& record, const Jrd::Attachment* attachment)
{
fb_assert(attachment && attachment->att_user);
fb_assert(attachment);
if (!attachment->att_user)
return;
record.reset(rel_mon_attachments);
@ -1309,10 +1310,10 @@ void Monitoring::publishAttachment(thread_db* tdbb)
if (!dbb->dbb_monitoring_data)
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
const MetaName& user_name = attachment->att_user->getUserName();
const char* user_name = attachment->att_user ? attachment->att_user->getUserName().c_str() : "";
MonitoringData::Guard guard(dbb->dbb_monitoring_data);
dbb->dbb_monitoring_data->setup(attachment->att_attachment_id, user_name.c_str());
dbb->dbb_monitoring_data->setup(attachment->att_attachment_id, user_name);
}
void Monitoring::cleanupAttachment(thread_db* tdbb)

View File

@ -3814,8 +3814,8 @@ dsc* evlRoleInUse(thread_db* tdbb, const SysFunction*, const NestValueArray& arg
string roleStr(MOV_make_string2(tdbb, value, ttype_none));
roleStr.upper();
impure->vlu_misc.vlu_uchar = attachment->att_user->roleInUse(tdbb, roleStr.c_str()) ?
FB_TRUE : FB_FALSE;
impure->vlu_misc.vlu_uchar = (attachment->att_user &&
attachment->att_user->roleInUse(tdbb, roleStr.c_str())) ? FB_TRUE : FB_FALSE;
impure->vlu_desc.makeBoolean(&impure->vlu_misc.vlu_uchar);
@ -3837,7 +3837,8 @@ dsc* evlSystemPrivilege(thread_db* tdbb, const SysFunction*, const NestValueArra
USHORT p = *((USHORT*) value->dsc_address);
Jrd::Attachment* attachment = tdbb->getAttachment();
impure->vlu_misc.vlu_uchar = attachment->att_user->locksmith(tdbb, p) ? FB_TRUE : FB_FALSE;
impure->vlu_misc.vlu_uchar = (attachment->att_user &&
attachment->att_user->locksmith(tdbb, p)) ? FB_TRUE : FB_FALSE;
impure->vlu_desc.makeBoolean(&impure->vlu_misc.vlu_uchar);
return &impure->vlu_desc;

View File

@ -47,12 +47,12 @@ namespace
// ILogonInfo implementation
const char* name()
{
return att->att_user->getUserName().c_str();
return att->att_user ? att->att_user->getUserName().c_str() : "";
}
const char* role()
{
return att->att_user->getSqlRole().c_str();
return att->att_user ? att->att_user->getSqlRole().c_str() : "";
}
const char* networkProtocol()
@ -67,6 +67,8 @@ namespace
const unsigned char* authBlock(unsigned* length)
{
if (!att->att_user)
return NULL;
const Auth::AuthenticationBlock& aBlock = att->att_user->usr_auth_block;
*length = aBlock.getCount();
return aBlock.getCount() ? aBlock.begin() : NULL;

View File

@ -320,7 +320,7 @@ void Connection::generateDPB(thread_db* tdbb, ClumpletWriter& dpb,
dpb.insertInt(isc_dpb_ext_call_depth, attachment->att_ext_call_depth + 1);
if ((m_provider.getFlags() & prvTrustedAuth) &&
user.isEmpty() && pwd.isEmpty() && role.isEmpty())
user.isEmpty() && pwd.isEmpty() && role.isEmpty() && attachment->att_user)
{
attachment->att_user->populateDpb(dpb);
}

View File

@ -147,7 +147,8 @@ void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
setWrapErrors(false);
Jrd::Attachment* attachment = tdbb->getAttachment();
if ((user.isEmpty() || user == attachment->att_user->getUserName()) &&
if (attachment->att_user &&
(user.isEmpty() || user == attachment->att_user->getUserName()) &&
pwd.isEmpty() &&
(role.isEmpty() || role == attachment->att_user->getSqlRole()))
{
@ -249,7 +250,8 @@ bool InternalConnection::isSameDatabase(thread_db* tdbb, const PathName& dbName,
if (m_isCurrent)
{
const UserId* attUser = m_attachment->getHandle()->att_user;
return ((user.isEmpty() || user == attUser->getUserName()) &&
return (attUser &&
(user.isEmpty() || user == attUser->getUserName()) &&
pwd.isEmpty() &&
(role.isEmpty() || role == attUser->getSqlRole()));
}

View File

@ -172,6 +172,8 @@ void validatePassword(thread_db* tdbb, const PathName& file, ClumpletWriter& dpb
if (ISC_check_if_remote(file, false)) // check for remote connection
return;
UserId* usr = tdbb->getAttachment()->att_user;
if (!usr)
return;
if (!usr->usr_auth_block.hasData()) // check for embedded attachment
return;

View File

@ -745,7 +745,7 @@ namespace
UserId* u = attachment->att_user;
Arg::Gds err(isc_adm_task_denied);
err << Arg::Gds(isc_miss_prvlg) << missPriv;
if (u->testFlag(USR_mapdown))
if (u && u->testFlag(USR_mapdown))
err << Arg::Gds(isc_map_down);
ERR_post(err);
@ -1038,7 +1038,7 @@ static void release_attachment(thread_db*, Jrd::Attachment*);
static void rollback(thread_db*, jrd_tra*, const bool);
static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*,
const RefPtr<Config>*, bool, ICryptKeyCallback*);
const RefPtr<Config>*, bool, IAttachment*, ICryptKeyCallback*);
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
@ -1051,7 +1051,7 @@ TraceFailedConnection::TraceFailedConnection(const char* filename, const Databas
m_filename(filename),
m_options(options)
{
getUserInfo(m_id, *m_options, m_filename, NULL, NULL, false, NULL);
getUserInfo(m_id, *m_options, m_filename, NULL, NULL, false, NULL, NULL);
}
@ -1324,7 +1324,6 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
{
ThreadContextHolder tdbb(user_status);
UserId userId;
DatabaseOptions options;
RefPtr<Config> config;
bool invalid_client_SQL_dialect = false;
@ -1368,15 +1367,6 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
if (ISC_check_if_remote(expanded_name, true))
ERR_post(Arg::Gds(isc_unavailable));
// Check for correct credentials supplied
if (existingId)
userId = *existingId;
else
{
getUserInfo(userId, options, org_filename.c_str(), expanded_name.c_str(),
&config, false, cryptCallback);
}
#ifdef WIN_NT
guardDbInit.enter(); // Required to correctly expand name of just created database
@ -1626,8 +1616,28 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
break;
}
userId.makeRoleName(options.dpb_sql_dialect);
// Check for correct credentials supplied
UserId userId;
if (existingId)
userId = *existingId;
else
{
jAtt->getStable()->manualUnlock(attachment->att_flags);
try
{
getUserInfo(userId, options, org_filename.c_str(), expanded_name.c_str(),
&config, false, jAtt, cryptCallback);
}
catch(const Exception&)
{
jAtt->getStable()->manualLock(attachment->att_flags, ATT_manual_lock);
throw;
}
jAtt->getStable()->manualLock(attachment->att_flags, ATT_manual_lock);
}
userId.makeRoleName(options.dpb_sql_dialect);
UserId::sclInit(tdbb, false, userId);
// This pair (SHUT_database/SHUT_online) checks itself for valid user name
@ -1695,7 +1705,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
// Note we throw exception here when entering full-shutdown mode
Arg::Gds v(isc_shutdown);
v << Arg::Str(org_filename);
if (attachment->att_user->testFlag(USR_mapdown))
if (attachment->att_user && attachment->att_user->testFlag(USR_mapdown))
v << Arg::Gds(isc_map_down);
ERR_post(v);
}
@ -2441,7 +2451,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
ERR_post(Arg::Gds(isc_unavailable));
// Check for correct credentials supplied
getUserInfo(userId, options, org_filename.c_str(), NULL, &config, true, cryptCallback);
getUserInfo(userId, options, org_filename.c_str(), NULL, &config, true, nullptr, cryptCallback);
#ifdef WIN_NT
guardDbInit.enter(); // Required to correctly expand name of just created database
@ -2595,7 +2605,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
if (attachment2)
{
allow_overwrite = attachment2->getHandle()->att_user->locksmith(tdbb, DROP_DATABASE);
allow_overwrite = attachment2->getHandle()->locksmith(tdbb, DROP_DATABASE);
attachment2->detach(user_status);
}
else
@ -2681,6 +2691,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
if (options.dpb_set_no_reserve)
PAG_set_no_reserve(tdbb, options.dpb_no_reserve);
fb_assert(attachment->att_user); // set by UserId::sclInit()
INI_format(attachment->att_user->getUserName().c_str(),
options.dpb_set_db_charset.c_str());
@ -7126,12 +7137,17 @@ static VdnResult verifyDatabaseName(const PathName& name, FbStatusVector* status
@param user
@param options
@param
@param aliasName
@param dbName
@param config
@param creating
@param iAtt
@param cryptCb
**/
static void getUserInfo(UserId& user, const DatabaseOptions& options,
const char* aliasName, const char* dbName, const RefPtr<Config>* config, bool creating,
ICryptKeyCallback* cryptCb)
IAttachment* iAtt, ICryptKeyCallback* cryptCb)
{
bool wheel = false;
int id = -1, group = -1; // CVC: This var contained trash
@ -7159,7 +7175,7 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
{
if (mapUser(true, name, trusted_role, &auth_method, &user.usr_auth_block, NULL,
options.dpb_auth_block, aliasName, dbName,
(config ? (*config)->getSecurityDatabase() : NULL), "", cryptCb, NULL) & MAPUSER_MAP_DOWN)
(config ? (*config)->getSecurityDatabase() : NULL), "", cryptCb, iAtt) & MAPUSER_MAP_DOWN)
{
user.setFlag(USR_mapdown);
}

View File

@ -1517,8 +1517,10 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb,
if (userName.hasData())
user.setUserName(userName);
else
else if (attachment->att_user)
user = *attachment->att_user;
else
user.setUserName("");
SecurityClass::flags_t privilege = 0;
const UCHAR* a = acl.begin();

View File

@ -161,7 +161,7 @@ void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard)
if (!attachment->locksmith(tdbb, CHANGE_SHUTDOWN_MODE))
{
ERR_post_nothrow(Arg::Gds(isc_no_priv) << "shutdown" << "database" << dbb->dbb_filename);
if (attachment->att_user->testFlag(USR_mapdown))
if (attachment->att_user && attachment->att_user->testFlag(USR_mapdown))
ERR_post_nothrow(Arg::Gds(isc_map_down));
ERR_punt();
}
@ -340,10 +340,10 @@ void SHUT_online(thread_db* tdbb, SSHORT flag, Sync* guard)
// Only platform's user locksmith can shutdown or bring online a database
if (!attachment->att_user->locksmith(tdbb, CHANGE_SHUTDOWN_MODE))
if (!attachment->locksmith(tdbb, CHANGE_SHUTDOWN_MODE))
{
ERR_post_nothrow(Arg::Gds(isc_no_priv) << "bring online" << "database" << dbb->dbb_filename);
if (attachment->att_user->testFlag(USR_mapdown))
if (attachment->att_user && attachment->att_user->testFlag(USR_mapdown))
ERR_post_nothrow(Arg::Gds(isc_map_down));
ERR_punt();
}

View File

@ -3632,7 +3632,8 @@ void jrd_tra::checkBlob(thread_db* tdbb, const bid* blob_id)
USHORT rel_id = blob_id->bid_internal.bid_relation_id;
if (tra_attachment->isGbak() ||
tra_attachment->att_user->locksmith(tdbb, SELECT_ANY_OBJECT_IN_DATABASE) ||
(tra_attachment->att_user &&
tra_attachment->att_user->locksmith(tdbb, SELECT_ANY_OBJECT_IN_DATABASE)) ||
rel_id == 0)
{
return;
@ -3677,7 +3678,7 @@ TraceSweepEvent::TraceSweepEvent(thread_db* tdbb)
gds__log("Sweep is started by %s\n"
"\tDatabase \"%s\" \n"
"\tOIT %" SQUADFORMAT", OAT %" SQUADFORMAT", OST %" SQUADFORMAT", Next %" SQUADFORMAT,
att->att_user->getUserName().c_str(),
att->att_user ? att->att_user->getUserName().c_str() : "<Unknown user>",
att->att_filename.c_str(),
m_sweep_info.getOIT(),
m_sweep_info.getOAT(),

View File

@ -3900,10 +3900,13 @@ static void check_owner(thread_db* tdbb,
return;
const Jrd::Attachment* const attachment = tdbb->getAttachment();
const Firebird::MetaName name(attachment->att_user->getUserName());
desc2.makeText((USHORT) name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (!MOV_compare(&desc1, &desc2))
return;
if (attachment->att_user)
{
const Firebird::MetaName name(attachment->att_user->getUserName());
desc2.makeText((USHORT) name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (!MOV_compare(&desc1, &desc2))
return;
}
ERR_post(Arg::Gds(isc_protect_ownership));
}
@ -3925,7 +3928,8 @@ static bool check_user(thread_db* tdbb, const dsc* desc)
const TEXT* p = (TEXT *) desc->dsc_address;
const TEXT* const end = p + desc->dsc_length;
const TEXT* q = tdbb->getAttachment()->att_user->getUserName().c_str();
const UserId* user = tdbb->getAttachment()->att_user;
const TEXT* q = user ? user->getUserName().c_str() : "";
// It is OK to not internationalize this function for v4.00 as
// User names are limited to 7-bit ASCII for v4.00
@ -5699,12 +5703,15 @@ static void set_owner_name(thread_db* tdbb, Record* record, USHORT field_id)
if (!EVL_field(0, record, field_id, &desc1))
{
const Jrd::Attachment* const attachment = tdbb->getAttachment();
const Firebird::MetaName name(attachment->att_user->getUserName());
dsc desc2;
desc2.makeText((USHORT) name.length(), CS_METADATA, (UCHAR*) name.c_str());
MOV_move(tdbb, &desc2, &desc1);
record->clearNull(field_id);
const Jrd::UserId* const user = tdbb->getAttachment()->att_user;
if (user)
{
const Firebird::MetaName name(user->getUserName());
dsc desc2;
desc2.makeText((USHORT) name.length(), CS_METADATA, (UCHAR*) name.c_str());
MOV_move(tdbb, &desc2, &desc1);
record->clearNull(field_id);
}
}
}