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

1. Cleanup:

- moved Attachment constructor (big enough) into .cpp file
 - avoid use of dbb in Database::get() and getUserInfo()
2. Complete fix for CORE-1726 - SecurityDatabase::init() is now not Database, but Attachment counted.
This commit is contained in:
alexpeshkoff 2008-02-10 16:38:30 +00:00
parent 11c47581ab
commit c3e1830e12
2 changed files with 140 additions and 74 deletions

View File

@ -252,6 +252,7 @@ namespace
Firebird::status_exception::raise(isc_bad_svc_handle, 0);
}
class DatabaseContextHolder : public Jrd::ContextPoolHolder
{
public:
@ -282,6 +283,35 @@ namespace
thread_db* tdbb;
};
// shuts SecurityDatabase in case of errors during attach or create
// when attachment is created, control is passed to it using clear
class SecurityInitHolder
{
public:
SecurityInitHolder()
: shutdown(true)
{
SecurityDatabase::initialize();
}
void clear()
{
shutdown = false;
}
~SecurityInitHolder()
{
if (shutdown)
{
SecurityDatabase::shutdown();
}
}
private:
bool shutdown;
};
} // anonymous
#ifdef WIN_NT
@ -425,6 +455,7 @@ public:
bool dpb_no_db_triggers;
bool dpb_gbak_attach;
bool dpb_trusted_role;
ULONG dpb_flags; // to OR'd with dbb_flags
// here begin compound objects
// for constructor to work properly dpb_sys_user_name
@ -499,7 +530,7 @@ static ISC_STATUS rollback(ISC_STATUS*, jrd_tra**, const bool);
static void shutdown_database(Database*, const bool);
static void strip_quotes(Firebird::string&);
static void purge_attachment(thread_db*, ISC_STATUS*, Attachment*, const bool);
static void getUserInfo(Database*, UserId&, const DatabaseOptions&);
static void getUserInfo(UserId&, const DatabaseOptions&);
//____________________________________________________________
//
@ -626,7 +657,8 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
**************************************/
ThreadContextHolder tdbb(user_status);
if (*handle) {
if (*handle)
{
return handle_error(user_status, isc_bad_db_handle);
}
@ -645,15 +677,32 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
expanded_name = _expanded_filename;
}
UserId userId;
DatabaseOptions options;
bool invalid_client_SQL_dialect = false;
SecurityInitHolder siHolder;
try {
// Process database parameter block
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
// Ccheck for correct credentials supplied
getUserInfo(userId, options);
}
catch (const Firebird::Exception& e)
{
e.stuff_exception(user_status);
return user_status[1];
}
// Check database against conf file.
const vdnResult vdn = verify_database_name(expanded_name, user_status);
if (!is_alias && vdn == vdnFail)
{
return user_status[1];
}
}
// Unless we're already attached, do some initialization
Database* dbb = init(tdbb, user_status, expanded_name, true);
if (!dbb) {
dbMutexUnlock();
@ -674,15 +723,6 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
try {
// Process database parameter block
bool invalid_client_SQL_dialect = false;
DatabaseOptions options;
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
// First check for correct credentials supplied
UserId userId;
getUserInfo(dbb, userId, options);
#ifndef NO_NFS
// Don't check nfs if single user
if (!options.dpb_single_user)
@ -696,7 +736,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
}
}
/* If database to be opened is SecurityDatabase, then only
/* If database to be opened is security database, then only
gsec or SecurityDatabase may open it. This protects from use
of old gsec to write wrong password hashes into it. */
if (vdn == vdnSecurity && !options.dpb_gsec_attach && !options.dpb_sec_attach)
@ -775,8 +815,19 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
attachment->att_flags |= ATT_lck_init_done;
if (dbb->dbb_filename.empty())
{
#if defined(DEV_BUILD) && defined(SUPERSERVER)
// make sure we do not reopen same DB twice
for (Database* d=databases; d; d = d->dbb_next)
{
if (d->dbb_filename == expanded_name)
{
Firebird::fatal_exception::raise(("Attempt to reopen " + expanded_name).c_str());
}
}
#endif
first = true;
dbb->dbb_filename = expanded_name;
dbb->dbb_flags |= options.dpb_flags;
// NS: Use alias as database ID only if accessing database using file name is not possible.
//
@ -835,6 +886,14 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
INI_update_database();
*/
}
else
{
if (dbb->dbb_flags & options.dpb_flags != options.dpb_flags)
{
// looks like someone tries to attach incompatibly
Firebird::status_exception::raise(isc_bad_dpb_content, 0);
}
}
// Attachments to a ReadOnly database need NOT do garbage collection
if (dbb->dbb_flags & DBB_read_only) {
@ -1267,6 +1326,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
return unwindAttach(ex, user_status, tdbb, attachment, dbb);
}
siHolder.clear();
return FB_SUCCESS;
}
@ -1620,6 +1680,27 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
expanded_name = _expanded_filename;
}
UserId userId;
DatabaseOptions options;
SecurityInitHolder siHolder;
try {
// Process database parameter block
bool invalid_client_SQL_dialect = false;
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
if (!invalid_client_SQL_dialect && options.dpb_sql_dialect == 99) {
options.dpb_sql_dialect = 0;
}
// Ccheck for correct credentials supplied
getUserInfo(userId, options);
}
catch (const Firebird::Exception& e)
{
e.stuff_exception(user_status);
return user_status[1];
}
// Check database against conf file.
const vdnResult vdn = verify_database_name(expanded_name, user_status);
if (!is_alias && vdn == vdnFail)
@ -1636,7 +1717,7 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
tdbb->setDatabase(dbb);
DatabaseContextHolder dbbHolder(tdbb);
dbb->dbb_flags |= DBB_being_opened;
dbb->dbb_flags |= (DBB_being_opened | options.dpb_flags);
ISC_STATUS* const status = user_status;
Attachment* attachment = NULL;
@ -1645,18 +1726,6 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
try {
// Process database parameter block
bool invalid_client_SQL_dialect = false;
DatabaseOptions options;
options.get(dpb, dpb_length, invalid_client_SQL_dialect);
if (!invalid_client_SQL_dialect && options.dpb_sql_dialect == 99) {
options.dpb_sql_dialect = 0;
}
// First check for correct credentials supplied
UserId userId;
getUserInfo(dbb, userId, options);
#ifndef NO_NFS
// Don't check nfs if single user
if (!options.dpb_single_user)
@ -1919,6 +1988,7 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
return unwindAttach(ex, user_status, tdbb, attachment, dbb);
}
siHolder.clear();
return FB_SUCCESS;
}
@ -2052,32 +2122,34 @@ ISC_STATUS GDS_DETACH(ISC_STATUS* user_status, Attachment** handle)
Attachment* attachment = *handle;
validateHandle(tdbb, attachment);
DatabaseContextHolder dbbHolder(tdbb);
{ // holder scope
DatabaseContextHolder dbbHolder(tdbb);
Database* dbb = tdbb->getDatabase();
Database* dbb = tdbb->getDatabase();
// if this is the last attachment, mark dbb as not in use
if (dbb->dbb_attachments == attachment &&
!attachment->att_next &&
!(dbb->dbb_flags & DBB_being_opened))
{
dbb->dbb_flags |= DBB_not_in_use;
}
// if this is the last attachment, mark dbb as not in use
if (dbb->dbb_attachments == attachment &&
!attachment->att_next &&
!(dbb->dbb_flags & DBB_being_opened))
{
dbb->dbb_flags |= DBB_not_in_use;
}
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
LOG_call(log_detach, *handle);
LOG_call(log_statistics, dbb->dbb_reads, dbb->dbb_writes,
dbb->dbb_max_memory);
LOG_call(log_detach, *handle);
LOG_call(log_statistics, dbb->dbb_reads, dbb->dbb_writes,
dbb->dbb_max_memory);
#endif
// Purge attachment, don't rollback open transactions
// Purge attachment, don't rollback open transactions
attachment->att_flags |= ATT_cancel_disable;
purge_attachment(tdbb, user_status, attachment, false);
attachment->att_flags |= ATT_cancel_disable;
*handle = NULL;
}
purge_attachment(tdbb, user_status, attachment, false);
*handle = NULL;
SecurityDatabase::shutdown();
}
catch (const Firebird::Exception& ex) {
Database* dbb = tdbb->getDatabase();
@ -4353,8 +4425,6 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
**************************************/
SSHORT num_old_files = 0;
Database* dbb = GET_DBB();
ULONG page_cache_size = Config::getDefaultDbCachePages();
if (page_cache_size < MIN_PAGE_BUFFERS)
page_cache_size = MIN_PAGE_BUFFERS;
@ -4460,7 +4530,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
case isc_dpb_verify:
dpb_verify = (USHORT) rdr.getInt();
if (dpb_verify & isc_dpb_ignore)
dbb->dbb_flags |= DBB_damaged;
dpb_flags |= DBB_damaged;
break;
case isc_dpb_trace:
@ -4469,7 +4539,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
case isc_dpb_damaged:
if (rdr.getInt() & 1)
dbb->dbb_flags |= DBB_damaged;
dpb_flags |= DBB_damaged;
break;
case isc_dpb_enable_journal:
@ -4643,7 +4713,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
case isc_dpb_sec_attach:
dpb_sec_attach = rdr.getInt() != 0;
dpb_buffers = 50;
dbb->dbb_flags |= DBB_security_db;
dpb_flags |= DBB_security_db;
break;
case isc_dpb_gbak_attach:
@ -4936,8 +5006,6 @@ static Database* init(thread_db* tdbb,
INTL_init(tdbb);
SecurityDatabase::initialize();
return dbb;
} // try
@ -5137,7 +5205,7 @@ static void detachLocksFromAttachment(Attachment* attachment)
}
Jrd::Attachment::~Attachment()
Attachment::~Attachment()
{
// For normal attachments that happens release_attachment(),
// but for special ones like GC should be done also in dtor -
@ -5149,6 +5217,23 @@ Jrd::Attachment::~Attachment()
}
Attachment::Attachment(Database* dbb) :
att_database(dbb),
att_lock_owner_id(Database::getLockOwnerId()),
att_lc_messages(*dbb->dbb_permanent),
att_working_directory(*dbb->dbb_permanent),
att_filename(*dbb->dbb_permanent),
att_context_vars(*dbb->dbb_permanent),
att_network_protocol(*dbb->dbb_permanent),
att_remote_address(*dbb->dbb_permanent),
att_remote_process(*dbb->dbb_permanent)
#ifndef SUPERSERVER
, att_dsql_cache(*dbb->dbb_permanent)
#endif
{
}
static ISC_STATUS rollback(ISC_STATUS* user_status,
jrd_tra** tra_handle,
const bool retaining_flag)
@ -5368,8 +5453,6 @@ static void shutdown_database(Database* dbb, const bool release_pools)
tdbb->setDatabase(NULL);
Database::deleteDbb(dbb);
}
SecurityDatabase::shutdown();
}
@ -6135,10 +6218,8 @@ bool Attachment::locksmith() const
@param options
**/
static void getUserInfo(Database* dbb, UserId& user, const DatabaseOptions& options)
static void getUserInfo(UserId& user, const DatabaseOptions& options)
{
Database::Checkout dcoHolder(dbb);
int id = -1, group = -1; // CVC: This var contained trash
int node_id = 0;
Firebird::string name;

View File

@ -681,22 +681,7 @@ struct DSqlCacheItem
class Attachment : public pool_alloc<type_att>
{
public:
explicit Attachment(Database* dbb) :
att_database(dbb),
att_lock_owner_id(Database::getLockOwnerId()),
att_lc_messages(*dbb->dbb_permanent),
att_working_directory(*dbb->dbb_permanent),
att_filename(*dbb->dbb_permanent),
att_context_vars(*dbb->dbb_permanent),
att_network_protocol(*dbb->dbb_permanent),
att_remote_address(*dbb->dbb_permanent),
att_remote_process(*dbb->dbb_permanent)
#ifndef SUPERSERVER
, att_dsql_cache(*dbb->dbb_permanent)
#endif
{
}
explicit Attachment(Database* dbb);
~Attachment();
/* Attachment()