mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:43:03 +01:00
1) Fixed the layering, as dbb_lock shouldn't belong to PIO.
2) Passed tdbb to some engine routines that were dealing with TLS. 3) Got rid of fil_length and some minor cleanup.
This commit is contained in:
parent
cd10fbee3b
commit
609f466ad3
@ -400,7 +400,7 @@ int DatabaseSnapshot::blockingAst(void* ast_object)
|
||||
DatabaseSnapshot::DatabaseSnapshot(thread_db* tdbb, MemoryPool& pool)
|
||||
: snapshot(pool), idMap(pool), idCounter(0)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
|
@ -475,7 +475,7 @@ int INF_database_info(const SCHAR* items,
|
||||
case isc_info_forced_writes:
|
||||
if (!header_refreshed)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
header_refreshed = true;
|
||||
}
|
||||
*p++ = (dbb->dbb_flags & DBB_force_write) ? 1 : 0;
|
||||
@ -737,7 +737,7 @@ int INF_database_info(const SCHAR* items,
|
||||
case isc_info_oldest_transaction:
|
||||
if (!header_refreshed)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
header_refreshed = true;
|
||||
}
|
||||
length = INF_convert(dbb->dbb_oldest_transaction, buffer);
|
||||
@ -746,7 +746,7 @@ int INF_database_info(const SCHAR* items,
|
||||
case isc_info_oldest_active:
|
||||
if (!header_refreshed)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
header_refreshed = true;
|
||||
}
|
||||
length = INF_convert(dbb->dbb_oldest_active, buffer);
|
||||
@ -755,7 +755,7 @@ int INF_database_info(const SCHAR* items,
|
||||
case isc_info_oldest_snapshot:
|
||||
if (!header_refreshed)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
header_refreshed = true;
|
||||
}
|
||||
length = INF_convert(dbb->dbb_oldest_snapshot, buffer);
|
||||
@ -764,7 +764,7 @@ int INF_database_info(const SCHAR* items,
|
||||
case isc_info_next_transaction:
|
||||
if (!header_refreshed)
|
||||
{
|
||||
PAG_header(true);
|
||||
PAG_header(tdbb, true);
|
||||
header_refreshed = true;
|
||||
}
|
||||
length = INF_convert(dbb->dbb_next_transaction, buffer);
|
||||
|
@ -537,7 +537,7 @@ USHORT INI_get_trig_flags(const TEXT* trig_name)
|
||||
}
|
||||
|
||||
|
||||
void INI_init()
|
||||
void INI_init(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -552,8 +552,8 @@ void INI_init()
|
||||
* format descriptor.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
const int* fld;
|
||||
@ -614,7 +614,7 @@ void INI_init()
|
||||
}
|
||||
|
||||
|
||||
void INI_init2()
|
||||
void INI_init2(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -628,8 +628,8 @@ void INI_init2()
|
||||
* the database when it was created.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
const USHORT major_version = dbb->dbb_ods_version;
|
||||
const USHORT minor_original = dbb->dbb_minor_original;
|
||||
|
@ -30,8 +30,8 @@ namespace Jrd {
|
||||
|
||||
void INI_format(const TEXT*, const TEXT*);
|
||||
USHORT INI_get_trig_flags(const TEXT*);
|
||||
void INI_init();
|
||||
void INI_init2();
|
||||
void INI_init(Jrd::thread_db*);
|
||||
void INI_init2(Jrd::thread_db*);
|
||||
|
||||
#endif // JRD_INI_PROTO_H
|
||||
|
||||
|
211
src/jrd/jrd.cpp
211
src/jrd/jrd.cpp
@ -450,7 +450,7 @@ static void commit(thread_db*, jrd_tra*, const bool);
|
||||
static bool drop_files(const jrd_file*);
|
||||
static void find_intl_charset(thread_db*, Attachment*, const DatabaseOptions*);
|
||||
static jrd_tra* find_transaction(thread_db*, ISC_STATUS);
|
||||
static void init_database_locks(thread_db*, Database*);
|
||||
static void init_database_locks(thread_db*);
|
||||
static ISC_STATUS handle_error(ISC_STATUS*, ISC_STATUS);
|
||||
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction);
|
||||
static void verify_request_synchronization(jrd_req*& request, SSHORT level);
|
||||
@ -770,8 +770,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, "direct",
|
||||
isc_arg_string, "security database",
|
||||
isc_arg_string,
|
||||
ERR_string(file_name),
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
@ -788,8 +787,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, "encryption",
|
||||
isc_arg_string, "database",
|
||||
isc_arg_string,
|
||||
ERR_string(file_name),
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
@ -873,14 +871,19 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags |= DBB_lck_init_done;
|
||||
|
||||
INI_init();
|
||||
INI_init(tdbb);
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
pageSpace->file = PIO_open(dbb, expanded_name, file_name, false);
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb);
|
||||
|
||||
SHUT_init(tdbb);
|
||||
PAG_header_init();
|
||||
INI_init2();
|
||||
PAG_init();
|
||||
PAG_header_init(tdbb);
|
||||
INI_init2(tdbb);
|
||||
PAG_init(tdbb);
|
||||
|
||||
if (options.dpb_set_page_buffers) {
|
||||
#ifdef SUPERSERVER
|
||||
// Here we do not let anyone except SYSDBA (like DBO) to change dbb_page_buffers,
|
||||
@ -890,17 +893,15 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
#endif
|
||||
dbb->dbb_page_buffers = options.dpb_page_buffers;
|
||||
}
|
||||
CCH_init(tdbb, options.dpb_buffers);
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb, dbb);
|
||||
CCH_init(tdbb, options.dpb_buffers);
|
||||
|
||||
// Initialize backup difference subsystem. This must be done before WAL and shadowing
|
||||
// is enabled because nbackup it is a lower level subsystem
|
||||
dbb->dbb_backup_manager = FB_NEW(*dbb->dbb_permanent) BackupManager(tdbb, dbb, nbak_state_unknown);
|
||||
|
||||
PAG_init2(0);
|
||||
PAG_header(false);
|
||||
PAG_init2(tdbb, 0);
|
||||
PAG_header(tdbb, false);
|
||||
|
||||
// initialize shadowing as soon as the database is ready for it
|
||||
// but before any real work is done
|
||||
@ -921,9 +922,9 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
}
|
||||
|
||||
if (options.dpb_disable_wal) {
|
||||
ERR_post(isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string,
|
||||
ERR_string(file_name),
|
||||
ERR_post(isc_lock_timeout,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
@ -943,7 +944,8 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
ERR_post(isc_inv_client_dialect_specified, isc_arg_number,
|
||||
options.dpb_sql_dialect,
|
||||
isc_arg_gds, isc_valid_client_dialects,
|
||||
isc_arg_string, "1, 2 or 3", isc_arg_end);
|
||||
isc_arg_string, "1, 2 or 3",
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
if (userId.usr_sql_role_name.hasData())
|
||||
@ -1083,16 +1085,14 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
CCH_exclusive_attachment(tdbb, LCK_none, LCK_WAIT);
|
||||
if (attachment->att_flags & ATT_shutdown) {
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown) {
|
||||
ERR_post(isc_shutdown, isc_arg_string,
|
||||
ERR_string(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutdown, isc_arg_string, ERR_string(file_name), isc_arg_end);
|
||||
}
|
||||
else {
|
||||
ERR_post(isc_att_shutdown);
|
||||
}
|
||||
}
|
||||
if (!attachment_succeeded) {
|
||||
ERR_post(isc_shutdown, isc_arg_string,
|
||||
ERR_string(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutdown, isc_arg_string, ERR_string(file_name), isc_arg_end);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1101,8 +1101,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
if (dbb->dbb_ast_flags & (DBB_shut_attach | DBB_shut_tran))
|
||||
{
|
||||
ERR_post(isc_shutinprog, isc_arg_string,
|
||||
ERR_string(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutinprog, isc_arg_string, ERR_string(file_name), isc_arg_end);
|
||||
}
|
||||
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown) {
|
||||
@ -1126,8 +1125,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
}
|
||||
if (!allow_access) {
|
||||
// Note we throw exception here when entering full-shutdown mode
|
||||
ERR_post(isc_shutdown, isc_arg_string,
|
||||
ERR_string(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutdown, isc_arg_string, ERR_string(file_name), isc_arg_end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1152,9 +1150,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
}
|
||||
|
||||
if (options.dpb_journal.hasData()) {
|
||||
ERR_post(isc_bad_dpb_content,
|
||||
isc_arg_gds, isc_cant_start_journal,
|
||||
isc_arg_end);
|
||||
ERR_post(isc_bad_dpb_content, isc_arg_gds, isc_cant_start_journal, isc_arg_end);
|
||||
}
|
||||
|
||||
if (options.dpb_wal_action)
|
||||
@ -1223,9 +1219,9 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
if (options.dpb_set_db_readonly) {
|
||||
validateAccess(attachment);
|
||||
if (!CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD)) {
|
||||
ERR_post(isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string,
|
||||
ERR_string(file_name),
|
||||
ERR_post(isc_lock_timeout,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
PAG_set_db_readonly(dbb, options.dpb_db_readonly);
|
||||
@ -1792,10 +1788,12 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
dbb->dbb_flags |= DBB_DB_SQL_dialect_3;
|
||||
break;
|
||||
default:
|
||||
ERR_post(isc_database_create_failed, isc_arg_string,
|
||||
expanded_name.c_str(), isc_arg_gds, isc_inv_dialect_specified,
|
||||
isc_arg_number, options.dpb_sql_dialect, isc_arg_gds,
|
||||
isc_valid_db_dialects, isc_arg_string, "1 and 3", isc_arg_end);
|
||||
ERR_post(isc_database_create_failed,
|
||||
isc_arg_string, ERR_string(expanded_name),
|
||||
isc_arg_gds, isc_inv_dialect_specified,
|
||||
isc_arg_number, options.dpb_sql_dialect,
|
||||
isc_arg_gds, isc_valid_db_dialects,
|
||||
isc_arg_string, "1 and 3", isc_arg_end);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1826,8 +1824,8 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
dbb->dbb_flags |= DBB_lck_init_done;
|
||||
|
||||
INI_init();
|
||||
PAG_init();
|
||||
INI_init(tdbb);
|
||||
PAG_init(tdbb);
|
||||
initing_security = true;
|
||||
|
||||
SCL_init(true, userId, tdbb);
|
||||
@ -1866,39 +1864,39 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
if (allow_overwrite)
|
||||
{
|
||||
// file is a database and the user (SYSDBA or owner) has right to overwrite
|
||||
pageSpace->file =
|
||||
PIO_create(dbb, expanded_name, options.dpb_overwrite, false, false);
|
||||
pageSpace->file = PIO_create(dbb, expanded_name, options.dpb_overwrite, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, "overwrite",
|
||||
isc_arg_string, "database",
|
||||
isc_arg_string,
|
||||
ERR_cstring(expanded_name.c_str()), isc_arg_end);
|
||||
isc_arg_string, "overwrite",
|
||||
isc_arg_string, "database",
|
||||
isc_arg_string, ERR_string(expanded_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
const jrd_file* first_dbb_file = pageSpace->file;
|
||||
const jrd_file* const first_dbb_file = pageSpace->file;
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb);
|
||||
|
||||
if (options.dpb_set_page_buffers)
|
||||
dbb->dbb_page_buffers = options.dpb_page_buffers;
|
||||
CCH_init(tdbb, options.dpb_buffers);
|
||||
|
||||
// Initialize locks
|
||||
init_database_locks(tdbb, dbb);
|
||||
CCH_init(tdbb, options.dpb_buffers);
|
||||
|
||||
// Initialize backup difference subsystem. This must be done before WAL and shadowing
|
||||
// is enabled because nbackup it is a lower level subsystem
|
||||
dbb->dbb_backup_manager = FB_NEW(*dbb->dbb_permanent) BackupManager(tdbb, dbb, nbak_state_normal);
|
||||
|
||||
dbb->dbb_backup_manager->dbCreating = true;
|
||||
PAG_format_header();
|
||||
INI_init2();
|
||||
PAG_format_log();
|
||||
PAG_format_header(tdbb);
|
||||
INI_init2(tdbb);
|
||||
PAG_format_log(tdbb);
|
||||
PAG_format_pip(tdbb, *pageSpace);
|
||||
|
||||
if (options.dpb_set_page_buffers)
|
||||
@ -1922,8 +1920,8 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, "shutdown or online",
|
||||
isc_arg_string, "database",
|
||||
isc_arg_string,
|
||||
ERR_string(file_name), isc_arg_end);
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1946,12 +1944,12 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
if (options.dpb_set_db_readonly) {
|
||||
if (!CCH_exclusive (tdbb, LCK_EX, WAIT_PERIOD))
|
||||
ERR_post (isc_lock_timeout, isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string,
|
||||
ERR_string (file_name),
|
||||
isc_arg_end);
|
||||
ERR_post(isc_lock_timeout,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, ERR_string(file_name),
|
||||
isc_arg_end);
|
||||
|
||||
PAG_set_db_readonly (dbb, options.dpb_db_readonly);
|
||||
PAG_set_db_readonly(dbb, options.dpb_db_readonly);
|
||||
}
|
||||
|
||||
PAG_attachment_id(tdbb);
|
||||
@ -1963,8 +1961,7 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
find_intl_charset(tdbb, attachment, &options);
|
||||
|
||||
#ifdef WIN_NT
|
||||
dbb->dbb_filename.assign(first_dbb_file->fil_string,
|
||||
first_dbb_file->fil_length);
|
||||
dbb->dbb_filename.assign(first_dbb_file->fil_string);
|
||||
#else
|
||||
dbb->dbb_filename = expanded_name;
|
||||
#endif
|
||||
@ -2166,17 +2163,18 @@ ISC_STATUS GDS_DROP_DATABASE(ISC_STATUS* user_status, Attachment** handle)
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, "drop",
|
||||
isc_arg_string, "database",
|
||||
isc_arg_string, ERR_cstring(file_name), isc_arg_end);
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
if (attachment->att_flags & ATT_shutdown)
|
||||
{
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown)
|
||||
{
|
||||
ERR_post(isc_shutdown, isc_arg_string,
|
||||
ERR_cstring(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutdown, isc_arg_string, ERR_cstring(file_name), isc_arg_end);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
ERR_post(isc_att_shutdown, isc_arg_end);
|
||||
}
|
||||
}
|
||||
@ -2185,14 +2183,17 @@ ISC_STATUS GDS_DROP_DATABASE(ISC_STATUS* user_status, Attachment** handle)
|
||||
{
|
||||
ERR_post(isc_lock_timeout,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, ERR_cstring(file_name), isc_arg_end);
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
// Check if same process has more attachments
|
||||
|
||||
if (dbb->dbb_attachments && dbb->dbb_attachments->att_next) {
|
||||
ERR_post(isc_no_meta_update, isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, "DATABASE", isc_arg_end);
|
||||
ERR_post(isc_no_meta_update,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, "DATABASE",
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
// Forced release of all transactions
|
||||
@ -3838,8 +3839,7 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
||||
const PathName& file_name = attachment->att_filename;
|
||||
if (punt) {
|
||||
CCH_unwind(tdbb, false);
|
||||
ERR_post(isc_shutdown, isc_arg_string,
|
||||
ERR_cstring(file_name), isc_arg_end);
|
||||
ERR_post(isc_shutdown, isc_arg_string, ERR_cstring(file_name), isc_arg_end);
|
||||
}
|
||||
else {
|
||||
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
||||
@ -4204,9 +4204,9 @@ static void find_intl_charset(thread_db* tdbb, Attachment* attachment, const Dat
|
||||
{
|
||||
// Report an error - we can't do what user has requested
|
||||
ERR_post(isc_bad_dpb_content,
|
||||
isc_arg_gds, isc_charset_not_found,
|
||||
isc_arg_string, ERR_cstring(options->dpb_lc_ctype),
|
||||
isc_arg_end);
|
||||
isc_arg_gds, isc_charset_not_found,
|
||||
isc_arg_string, ERR_cstring(options->dpb_lc_ctype),
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4390,7 +4390,8 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
// Just in case there WAS a customer using this unsupported
|
||||
// feature - post an error when they try to access it in 4.0
|
||||
ERR_post(isc_uns_ext, isc_arg_gds, isc_random,
|
||||
isc_arg_string, "Encryption not supported", isc_arg_end);
|
||||
isc_arg_string, "Encryption not supported",
|
||||
isc_arg_end);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -4650,8 +4651,10 @@ static Database* init(thread_db* tdbb,
|
||||
if (attach_flag)
|
||||
return dbb;
|
||||
|
||||
ERR_post(isc_no_meta_update, isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, "DATABASE", isc_arg_end);
|
||||
ERR_post(isc_no_meta_update,
|
||||
isc_arg_gds, isc_obj_in_use,
|
||||
isc_arg_string, "DATABASE",
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -4730,7 +4733,7 @@ static Database* init(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
static void init_database_locks(thread_db* tdbb, Database* dbb)
|
||||
static void init_database_locks(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -4739,16 +4742,63 @@ static void init_database_locks(thread_db* tdbb, Database* dbb)
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Initialize secondary database locks.
|
||||
* Initialize database locks.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
fb_assert(dbb);
|
||||
// Main database lock
|
||||
|
||||
PageSpace* const pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
fb_assert(pageSpace && pageSpace->file);
|
||||
|
||||
UCharBuffer file_id;
|
||||
PIO_get_unique_file_id(pageSpace->file, file_id);
|
||||
size_t key_length = file_id.getCount();
|
||||
|
||||
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, key_length) Lock;
|
||||
dbb->dbb_lock = lock;
|
||||
lock->lck_type = LCK_database;
|
||||
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
|
||||
lock->lck_object = dbb;
|
||||
lock->lck_length = key_length;
|
||||
lock->lck_dbb = dbb;
|
||||
lock->lck_ast = CCH_down_grade_dbb;
|
||||
memcpy(lock->lck_key.lck_string, file_id.begin(), key_length);
|
||||
|
||||
// Try to get an exclusive lock on database.
|
||||
// If this fails, insist on at least a shared lock.
|
||||
|
||||
dbb->dbb_flags |= DBB_exclusive;
|
||||
if (!LCK_lock(tdbb, lock, LCK_EX, LCK_NO_WAIT))
|
||||
{
|
||||
dbb->dbb_flags &= ~DBB_exclusive;
|
||||
|
||||
while (!LCK_lock(tdbb, lock, LCK_SW, -1))
|
||||
{
|
||||
tdbb->tdbb_status_vector[0] = 0; // Clean status vector from lock manager error code
|
||||
|
||||
// If we are in a single-threaded maintenance mode then clean up and stop waiting
|
||||
SCHAR spare_memory[MIN_PAGE_SIZE * 2];
|
||||
SCHAR* header_page_buffer = (SCHAR*) FB_ALIGN((IPTR) spare_memory, MIN_PAGE_SIZE);
|
||||
Ods::header_page* header_page = reinterpret_cast<Ods::header_page*>(header_page_buffer);
|
||||
|
||||
PIO_header(dbb, header_page_buffer, MIN_PAGE_SIZE);
|
||||
|
||||
if ((header_page->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single)
|
||||
{
|
||||
ERR_post(isc_shutdown,
|
||||
isc_arg_string, ERR_cstring(pageSpace->file->fil_string),
|
||||
isc_arg_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock shared by all dbb owners, used to signal other processes
|
||||
// to dump their monitoring data and synchronize operations
|
||||
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
|
||||
|
||||
lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
|
||||
dbb->dbb_monitor_lock = lock;
|
||||
lock->lck_type = LCK_monitor;
|
||||
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
|
||||
@ -4760,7 +4810,8 @@ static void init_database_locks(thread_db* tdbb, Database* dbb)
|
||||
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);
|
||||
|
||||
// Lock that identifies a dbb instance
|
||||
const size_t key_length = sizeof(FB_GUID);
|
||||
|
||||
key_length = sizeof(FB_GUID);
|
||||
lock = FB_NEW_RPT(*dbb->dbb_permanent, key_length) Lock();
|
||||
dbb->dbb_instance_lock = lock;
|
||||
lock->lck_type = LCK_instance;
|
||||
|
@ -50,7 +50,6 @@ public:
|
||||
//int *fil_trace; /* Trace file, if any */
|
||||
Firebird::Mutex fil_mutex;
|
||||
USHORT fil_flags;
|
||||
USHORT fil_length; /* Length of expanded file name */
|
||||
SCHAR fil_string[1]; /* Expanded file name */
|
||||
};
|
||||
|
||||
@ -84,7 +83,6 @@ public:
|
||||
void* fil_io_events[MAX_FILE_IO]; /* Overlapped I/O events */
|
||||
#endif
|
||||
USHORT fil_flags;
|
||||
USHORT fil_length; /* Length of expanded file name */
|
||||
SCHAR fil_string[1]; /* Expanded file name */
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,7 @@ void PIO_extend(Jrd::Database*, Jrd::jrd_file*, const ULONG, const USHORT);
|
||||
void PIO_flush(Jrd::Database*, Jrd::jrd_file*);
|
||||
void PIO_force_write(Jrd::jrd_file*, const bool, const bool);
|
||||
ULONG PIO_get_number_of_pages(const Jrd::jrd_file*, const USHORT);
|
||||
void PIO_get_unique_file_id(const Jrd::jrd_file*, Firebird::UCharBuffer&);
|
||||
void PIO_header(Jrd::Database*, SCHAR*, int);
|
||||
USHORT PIO_init_data(Jrd::Database*, Jrd::jrd_file*, ISC_STATUS*, ULONG, USHORT);
|
||||
Jrd::jrd_file* PIO_open(Jrd::Database*, const Firebird::PathName&,
|
||||
|
@ -117,7 +117,7 @@ using namespace Firebird;
|
||||
// that can successfully change BOTH O_DIRECT and O_SYNC using fcntl()
|
||||
|
||||
static jrd_file* seek_file(jrd_file*, BufferDesc*, FB_UINT64*, ISC_STATUS*);
|
||||
static jrd_file* setup_file(Database*, const PathName&, int);
|
||||
static jrd_file* setup_file(Database*, const PathName&, int, bool);
|
||||
static bool unix_error(const TEXT*, const jrd_file*, ISC_STATUS, ISC_STATUS*);
|
||||
#if !(defined HAVE_PREAD && defined HAVE_PWRITE)
|
||||
static SLONG pread(int, SCHAR *, SLONG, SLONG);
|
||||
@ -273,17 +273,8 @@ jrd_file* PIO_create(Database* dbb, const PathName& file_name,
|
||||
|
||||
PathName expanded_name(file_name);
|
||||
ISC_expand_filename(expanded_name, false);
|
||||
jrd_file* file;
|
||||
try
|
||||
{
|
||||
file = setup_file(dbb, expanded_name, desc);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
close(desc);
|
||||
throw;
|
||||
}
|
||||
return file;
|
||||
|
||||
return setup_file(dbb, expanded_name, desc, false);
|
||||
}
|
||||
|
||||
|
||||
@ -381,9 +372,9 @@ void PIO_force_write(jrd_file* file, const bool forcedWrites, const bool notUseF
|
||||
{
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string, "fcntl() SYNC/DIRECT",
|
||||
isc_arg_cstring, file->fil_length,
|
||||
ERR_string(file->fil_string, file->fil_length), isc_arg_gds,
|
||||
isc_io_access_err, isc_arg_unix, errno, isc_arg_end);
|
||||
isc_arg_string, ERR_cstring(file->fil_string),
|
||||
isc_arg_gds, isc_io_access_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
#else //FCNTL_BROKEN
|
||||
maybeCloseFile(file->fil_desc);
|
||||
@ -392,8 +383,9 @@ void PIO_force_write(jrd_file* file, const bool forcedWrites, const bool notUseF
|
||||
if (file->fil_desc == -1)
|
||||
{
|
||||
ERR_post(isc_io_error, isc_arg_string, "re open() for SYNC/DIRECT",
|
||||
isc_arg_cstring, file->fil_length, ERR_string(file->fil_string, file->fil_length),
|
||||
isc_arg_gds, isc_io_open_err, isc_arg_unix, errno, isc_arg_end);
|
||||
isc_arg_string, ERR_cstring(file->fil_string),
|
||||
isc_arg_gds, isc_io_open_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
#endif //FCNTL_BROKEN
|
||||
|
||||
@ -442,6 +434,32 @@ length = statistics.st_blocks * statistics.st_blksize;
|
||||
}
|
||||
|
||||
|
||||
void PIO_get_unique_file_id(const Jrd::jrd_file* file, UCharBuffer& id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P I O _ g e t _ u n i q u e _ f i l e _ i d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Return a binary string that uniquely identifies the file.
|
||||
*
|
||||
**************************************/
|
||||
struct stat statistics;
|
||||
fstat(file->fil_desc, &statistics);
|
||||
|
||||
const size_t len1 = sizeof(statistics.st_dev);
|
||||
const size_t len2 = sizeof(statistics.st_ino);
|
||||
|
||||
UCHAR* p = id.getBuffer(len1 + len2);
|
||||
|
||||
memcpy(p, &statistics.st_dev, len1);
|
||||
p += len1;
|
||||
memcpy(p, &statistics.st_ino, len2);
|
||||
}
|
||||
|
||||
|
||||
void PIO_header(Database* dbb, SCHAR * address, int length)
|
||||
{
|
||||
/**************************************
|
||||
@ -601,7 +619,7 @@ jrd_file* PIO_open(Database* dbb,
|
||||
if (desc == -1) {
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string, "open",
|
||||
isc_arg_cstring, file_name.length(), ERR_cstring(file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_open_err, isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
/* If this is the primary file, set Database flag to indicate that it is
|
||||
@ -627,24 +645,13 @@ jrd_file* PIO_open(Database* dbb,
|
||||
{
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "open",
|
||||
isc_arg_cstring, file_name.length(),
|
||||
ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_open_err,
|
||||
isc_arg_unix, ENOENT, isc_arg_end);
|
||||
}
|
||||
#endif /* SUPPORT_RAW_DEVICES */
|
||||
|
||||
jrd_file *file;
|
||||
try {
|
||||
file = setup_file(dbb, string, desc);
|
||||
if (readOnly)
|
||||
file->fil_flags |= FIL_readonly;
|
||||
}
|
||||
catch (const Exception&) {
|
||||
close(desc);
|
||||
throw;
|
||||
}
|
||||
return file;
|
||||
return setup_file(dbb, string, desc, readOnly);
|
||||
}
|
||||
|
||||
|
||||
@ -891,7 +898,10 @@ static void maybeCloseFile(int& desc)
|
||||
}
|
||||
|
||||
|
||||
static jrd_file* setup_file(Database* dbb, const PathName& file_name, int desc)
|
||||
static jrd_file* setup_file(Database* dbb,
|
||||
const PathName& file_name,
|
||||
int desc,
|
||||
bool read_only)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -903,88 +913,26 @@ static jrd_file* setup_file(Database* dbb, const PathName& file_name, int desc)
|
||||
* Set up file and lock blocks for a file.
|
||||
*
|
||||
**************************************/
|
||||
jrd_file* file = NULL;
|
||||
|
||||
/* Allocate file block and copy file name string */
|
||||
try
|
||||
{
|
||||
file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||
file->fil_desc = desc;
|
||||
file->fil_max_page = MAX_ULONG;
|
||||
strcpy(file->fil_string, file_name.c_str());
|
||||
|
||||
jrd_file* file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||
file->fil_desc = desc;
|
||||
file->fil_max_page = MAX_ULONG;
|
||||
file->fil_length = file_name.length();
|
||||
strcpy(file->fil_string, file_name.c_str());
|
||||
|
||||
/* If this isn't the primary file, we're done */
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
if (pageSpace && pageSpace->file)
|
||||
return file;
|
||||
|
||||
/* Build unique lock string for file and construct lock block */
|
||||
|
||||
struct stat statistics;
|
||||
fstat(desc, &statistics);
|
||||
UCHAR lock_string[32];
|
||||
UCHAR* p = lock_string;
|
||||
|
||||
USHORT l = sizeof(statistics.st_dev);
|
||||
memcpy(p, &statistics.st_dev, l);
|
||||
p += l;
|
||||
|
||||
l = sizeof(statistics.st_ino);
|
||||
memcpy(p, &statistics.st_ino, l);
|
||||
p += l;
|
||||
|
||||
l = p - lock_string;
|
||||
fb_assert(l <= sizeof(lock_string)); // In case we add more information.
|
||||
|
||||
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, l) Lock();
|
||||
dbb->dbb_lock = lock;
|
||||
lock->lck_type = LCK_database;
|
||||
lock->lck_owner_handle = LCK_get_owner_handle(NULL, lock->lck_type);
|
||||
lock->lck_object = dbb;
|
||||
lock->lck_length = l;
|
||||
lock->lck_dbb = dbb;
|
||||
lock->lck_ast = CCH_down_grade_dbb;
|
||||
memcpy(lock->lck_key.lck_string, lock_string, l);
|
||||
|
||||
/* Try to get an exclusive lock on database. If this fails, insist
|
||||
on at least a shared lock */
|
||||
|
||||
dbb->dbb_flags |= DBB_exclusive;
|
||||
if (!LCK_lock(NULL, lock, LCK_EX, LCK_NO_WAIT)) {
|
||||
dbb->dbb_flags &= ~DBB_exclusive;
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
while (!LCK_lock(tdbb, lock, LCK_SW, -1)) {
|
||||
tdbb->tdbb_status_vector[0] = 0; // Clean status vector from lock manager error code
|
||||
// If we are in a single-threaded maintenance mode then clean up and stop waiting
|
||||
SCHAR spare_memory[MIN_PAGE_SIZE * 2];
|
||||
SCHAR *header_page_buffer = (SCHAR*) FB_ALIGN((IPTR)spare_memory, MIN_PAGE_SIZE);
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
try {
|
||||
pageSpace->file = file;
|
||||
PIO_header(dbb, header_page_buffer, MIN_PAGE_SIZE);
|
||||
/* Rewind file pointer */
|
||||
if (lseek (file->fil_desc, LSEEK_OFFSET_CAST 0, 0) == (off_t)-1)
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "lseek",
|
||||
isc_arg_cstring, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
if ((reinterpret_cast<Ods::header_page*>(header_page_buffer)->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single)
|
||||
ERR_post(isc_shutdown, isc_arg_cstring, file_name.length(), ERR_cstring(file_name), isc_arg_end);
|
||||
pageSpace->file = NULL; // Will be set again later by the caller
|
||||
}
|
||||
catch (const Exception&) {
|
||||
delete dbb->dbb_lock;
|
||||
dbb->dbb_lock = NULL;
|
||||
delete file;
|
||||
pageSpace->file = NULL; // Will be set again later by the caller
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (read_only)
|
||||
file->fil_flags |= FIL_readonly;
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
close(desc);
|
||||
delete file;
|
||||
throw;
|
||||
}
|
||||
|
||||
fb_assert(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -1011,7 +959,7 @@ static bool unix_error(const TEXT* string,
|
||||
*status++ = isc_arg_string;
|
||||
*status++ = (ISC_STATUS) string; // pointer to ISC_STATUS!!!
|
||||
*status++ = isc_arg_string;
|
||||
*status++ = (ISC_STATUS)(U_IPTR) ERR_string(file->fil_string, file->fil_length);
|
||||
*status++ = (ISC_STATUS)(U_IPTR) ERR_cstring(file->fil_string);
|
||||
*status++ = isc_arg_gds;
|
||||
*status++ = operation;
|
||||
*status++ = isc_arg_unix;
|
||||
@ -1023,8 +971,7 @@ static bool unix_error(const TEXT* string,
|
||||
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string, string,
|
||||
isc_arg_string, ERR_string(file->fil_string,
|
||||
file->fil_length),
|
||||
isc_arg_string, ERR_cstring(file->fil_string),
|
||||
isc_arg_gds, operation,
|
||||
isc_arg_unix, errno,
|
||||
isc_arg_end);
|
||||
@ -1180,7 +1127,7 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name)
|
||||
if (desc == -1)
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "raw_devices_validate_database",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
|
||||
@ -1189,7 +1136,7 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name)
|
||||
if (lseek (desc, LSEEK_OFFSET_CAST 0, 0) == (off_t) -1)
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "lseek",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
const ssize_t bytes = read (desc, header, sizeof(header));
|
||||
@ -1198,14 +1145,14 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name)
|
||||
if (bytes == -1 && !SYSCALL_INTERRUPTED(errno))
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "read",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "read_retry",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
|
||||
@ -1214,7 +1161,7 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name)
|
||||
if (lseek (desc, LSEEK_OFFSET_CAST 0, 0) == (off_t)-1)
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "lseek",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_read_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
|
||||
@ -1256,7 +1203,7 @@ static int raw_devices_unlink_database(const PathName& file_name)
|
||||
if (!SYSCALL_INTERRUPTED(errno))
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "open",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_open_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
@ -1272,7 +1219,7 @@ static int raw_devices_unlink_database(const PathName& file_name)
|
||||
continue;
|
||||
ERR_post (isc_io_error,
|
||||
isc_arg_string, "write",
|
||||
isc_arg_string, file_name.length(), ERR_cstring (file_name),
|
||||
isc_arg_string, ERR_cstring(file_name),
|
||||
isc_arg_gds, isc_io_write_err,
|
||||
isc_arg_unix, errno, isc_arg_end);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ static void release_io_event(jrd_file*, OVERLAPPED*);
|
||||
#endif
|
||||
static bool maybe_close_file(HANDLE&);
|
||||
static jrd_file* seek_file(jrd_file*, BufferDesc*, ISC_STATUS*, OVERLAPPED*, OVERLAPPED**);
|
||||
static jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE);
|
||||
static jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE, bool);
|
||||
static bool nt_error(TEXT*, const jrd_file*, ISC_STATUS, ISC_STATUS*);
|
||||
|
||||
#ifdef SUPERSERVER_V2
|
||||
@ -229,7 +229,7 @@ jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string,
|
||||
{
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string, "CreateFile (create)",
|
||||
isc_arg_cstring, string.length(), ERR_cstring(string),
|
||||
isc_arg_string, ERR_cstring(string),
|
||||
isc_arg_gds, isc_io_create_err, isc_arg_win32, GetLastError(),
|
||||
0);
|
||||
}
|
||||
@ -239,16 +239,8 @@ jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string,
|
||||
|
||||
Firebird::PathName workspace(string);
|
||||
ISC_expand_filename(workspace, false);
|
||||
jrd_file *file;
|
||||
try {
|
||||
file = setup_file(dbb, workspace, desc);
|
||||
}
|
||||
catch (const Firebird::Exception&) {
|
||||
CloseHandle(desc);
|
||||
throw;
|
||||
}
|
||||
|
||||
return file;
|
||||
return setup_file(dbb, workspace, desc, false);
|
||||
}
|
||||
|
||||
|
||||
@ -385,9 +377,8 @@ void PIO_force_write(jrd_file* file, const bool forceWrite, const bool notUseFSC
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string,
|
||||
"CreateFile (force write)",
|
||||
isc_arg_cstring,
|
||||
file->fil_length,
|
||||
ERR_string(file->fil_string, file->fil_length),
|
||||
isc_arg_string,
|
||||
ERR_cstring(file->fil_string),
|
||||
isc_arg_gds, isc_io_access_err,
|
||||
isc_arg_win32,
|
||||
GetLastError(),
|
||||
@ -591,8 +582,7 @@ jrd_file* PIO_open(Database* dbb,
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string,
|
||||
"CreateFile (open)",
|
||||
isc_arg_cstring,
|
||||
file_name.length(),
|
||||
isc_arg_string,
|
||||
ERR_cstring(file_name),
|
||||
isc_arg_gds,
|
||||
isc_io_open_err, isc_arg_win32, GetLastError(), 0);
|
||||
@ -610,18 +600,7 @@ jrd_file* PIO_open(Database* dbb,
|
||||
}
|
||||
}
|
||||
|
||||
jrd_file *file;
|
||||
try {
|
||||
file = setup_file(dbb, string, desc);
|
||||
|
||||
if (readOnly)
|
||||
file->fil_flags |= FIL_readonly;
|
||||
}
|
||||
catch (const Firebird::Exception&) {
|
||||
CloseHandle(desc);
|
||||
throw;
|
||||
}
|
||||
return file;
|
||||
return setup_file(dbb, string, desc, readOnly);
|
||||
}
|
||||
|
||||
|
||||
@ -933,6 +912,39 @@ ULONG PIO_get_number_of_pages(const jrd_file* file, const USHORT pagesize)
|
||||
}
|
||||
|
||||
|
||||
void PIO_get_unique_file_id(const Jrd::jrd_file* file, Firebird::UCharBuffer& id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P I O _ g e t _ u n i q u e _ f i l e _ i d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Return a binary string that uniquely identifies the file.
|
||||
*
|
||||
**************************************/
|
||||
BY_HANDLE_FILE_INFORMATION file_info;
|
||||
GetFileInformationByHandle(file->fil_desc, &file_info);
|
||||
|
||||
// The identifier is [nFileIndexHigh, nFileIndexLow]
|
||||
// MSDN says: After a process opens a file, the identifier is constant until
|
||||
// the file is closed. An application can use this identifier and the
|
||||
// volume serial number to determine whether two handles refer to the same file.
|
||||
const size_t len1 = sizeof(file_info.dwVolumeSerialNumber);
|
||||
const size_t len2 = sizeof(file_info.nFileIndexHigh);
|
||||
const size_t len3 = sizeof(file_info.nFileIndexLow);
|
||||
|
||||
UCHAR* p = id.getBuffer(len1 + len2 + len3);
|
||||
|
||||
memcpy(p, &file_info.dwVolumeSerialNumber, len1);
|
||||
p += len1;
|
||||
memcpy(p, &file_info.nFileIndexHigh, len2);
|
||||
p += len2;
|
||||
memcpy(p, &file_info.nFileIndexLow, len3);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPERSERVER_V2
|
||||
static void release_io_event(jrd_file* file, OVERLAPPED* overlapped)
|
||||
{
|
||||
@ -1034,9 +1046,10 @@ static jrd_file* seek_file(jrd_file* file,
|
||||
}
|
||||
|
||||
|
||||
static jrd_file* setup_file(Database* dbb,
|
||||
const Firebird::PathName& file_name,
|
||||
HANDLE desc)
|
||||
static jrd_file* setup_file(Database* dbb,
|
||||
const Firebird::PathName& file_name,
|
||||
HANDLE desc,
|
||||
bool read_only)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1048,95 +1061,37 @@ static jrd_file* setup_file(Database* dbb,
|
||||
* Set up file and lock blocks for a file.
|
||||
*
|
||||
**************************************/
|
||||
jrd_file* file = NULL;
|
||||
|
||||
/* Allocate file block and copy file name string */
|
||||
|
||||
jrd_file* file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||
file->fil_desc = desc;
|
||||
file->fil_max_page = MAX_ULONG;
|
||||
file->fil_length = file_name.length();
|
||||
strcpy(file->fil_string, file_name.c_str());
|
||||
try
|
||||
{
|
||||
file = FB_NEW_RPT(*dbb->dbb_permanent, file_name.length() + 1) jrd_file();
|
||||
file->fil_desc = desc;
|
||||
file->fil_max_page = MAX_ULONG;
|
||||
strcpy(file->fil_string, file_name.c_str());
|
||||
#ifdef SUPERSERVER_V2
|
||||
memset(file->fil_io_events, 0, MAX_FILE_IO * sizeof(void*));
|
||||
memset(file->fil_io_events, 0, MAX_FILE_IO * sizeof(void*));
|
||||
#endif
|
||||
|
||||
/* If this isn't the primary file, we're done */
|
||||
if (read_only)
|
||||
file->fil_flags |= FIL_readonly;
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
if (pageSpace && pageSpace->file)
|
||||
return file;
|
||||
// If this isn't the primary file, we're done
|
||||
|
||||
/* Build unique lock string for file and construct lock block */
|
||||
const PageSpace* const pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
if (pageSpace && pageSpace->file)
|
||||
return file;
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION file_info;
|
||||
GetFileInformationByHandle(desc, &file_info);
|
||||
UCHAR lock_string[32];
|
||||
UCHAR* p = lock_string;
|
||||
|
||||
// The identifier is [nFileIndexHigh, nFileIndexLow]
|
||||
// MSDN says: After a process opens a file, the identifier is constant until
|
||||
// the file is closed. An application can use this identifier and the
|
||||
// volume serial number to determine whether two handles refer to the same file.
|
||||
size_t l = sizeof(file_info.dwVolumeSerialNumber);
|
||||
memcpy(p, &file_info.dwVolumeSerialNumber, l);
|
||||
p += l;
|
||||
|
||||
l = sizeof(file_info.nFileIndexHigh);
|
||||
memcpy(p, &file_info.nFileIndexHigh, l);
|
||||
p += l;
|
||||
|
||||
l = sizeof(file_info.nFileIndexLow);
|
||||
memcpy(p, &file_info.nFileIndexLow, l);
|
||||
p += l;
|
||||
|
||||
// We know p only was incremented, so can use safely size_t instead of ptrdiff_t
|
||||
l = p - lock_string;
|
||||
fb_assert(l <= sizeof(lock_string)); // In case we continue adding information.
|
||||
|
||||
file->fil_ext_lock = FB_NEW(*dbb->dbb_permanent) Firebird::RWLock();
|
||||
|
||||
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, l) Lock;
|
||||
dbb->dbb_lock = lock;
|
||||
lock->lck_type = LCK_database;
|
||||
lock->lck_owner_handle = LCK_get_owner_handle(NULL, lock->lck_type);
|
||||
lock->lck_object = dbb;
|
||||
lock->lck_length = l;
|
||||
lock->lck_dbb = dbb;
|
||||
lock->lck_ast = CCH_down_grade_dbb;
|
||||
memcpy(lock->lck_key.lck_string, lock_string, l);
|
||||
|
||||
/* Try to get an exclusive lock on database. If this fails, insist
|
||||
on at least a shared lock */
|
||||
|
||||
dbb->dbb_flags |= DBB_exclusive;
|
||||
if (!LCK_lock(NULL, lock, LCK_EX, LCK_NO_WAIT)) {
|
||||
dbb->dbb_flags &= ~DBB_exclusive;
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
while (!LCK_lock(tdbb, lock, LCK_SW, -1)) {
|
||||
tdbb->tdbb_status_vector[0] = 0; // Clean status vector from lock manager error code
|
||||
// If we are in a single-threaded maintenance mode then clean up and stop waiting
|
||||
SCHAR spare_memory[MIN_PAGE_SIZE * 2];
|
||||
SCHAR *header_page_buffer = (SCHAR*) FB_ALIGN((IPTR)spare_memory, MIN_PAGE_SIZE);
|
||||
|
||||
pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
try {
|
||||
pageSpace->file = file;
|
||||
PIO_header(dbb, header_page_buffer, MIN_PAGE_SIZE);
|
||||
if ((reinterpret_cast<Ods::header_page*>(header_page_buffer)->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single)
|
||||
ERR_post(isc_shutdown, isc_arg_cstring, file_name.length(), ERR_cstring(file_name), 0);
|
||||
pageSpace->file = NULL; // Will be set again later by the caller
|
||||
}
|
||||
catch (const Firebird::Exception&) {
|
||||
delete dbb->dbb_lock;
|
||||
dbb->dbb_lock = NULL;
|
||||
delete file;
|
||||
pageSpace->file = NULL; // Will be set again later by the caller
|
||||
throw;
|
||||
}
|
||||
}
|
||||
file->fil_ext_lock = FB_NEW(*dbb->dbb_permanent) Firebird::RWLock();
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
CloseHandle(desc);
|
||||
delete file;
|
||||
throw;
|
||||
}
|
||||
|
||||
fb_assert(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -1185,8 +1140,7 @@ static bool nt_error(TEXT* string,
|
||||
*status_vector++ = isc_arg_string;
|
||||
*status_vector++ = (ISC_STATUS) string;
|
||||
*status_vector++ = isc_arg_string;
|
||||
*status_vector++ =
|
||||
(ISC_STATUS)(U_IPTR) ERR_string(file->fil_string, file->fil_length);
|
||||
*status_vector++ = (ISC_STATUS)(U_IPTR) ERR_cstring(file->fil_string);
|
||||
*status_vector++ = isc_arg_gds;
|
||||
*status_vector++ = operation;
|
||||
*status_vector++ = isc_arg_win32;
|
||||
@ -1197,7 +1151,7 @@ static bool nt_error(TEXT* string,
|
||||
|
||||
ERR_post(isc_io_error,
|
||||
isc_arg_string, string,
|
||||
isc_arg_string, ERR_string(file->fil_string, file->fil_length),
|
||||
isc_arg_string, ERR_cstring(file->fil_string),
|
||||
isc_arg_gds, operation, isc_arg_win32, GetLastError(), 0);
|
||||
|
||||
return true;
|
||||
|
@ -1041,7 +1041,7 @@ int PAG_delete_clump_entry(SLONG page_num, USHORT type)
|
||||
}
|
||||
|
||||
|
||||
void PAG_format_header()
|
||||
void PAG_format_header(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1053,8 +1053,8 @@ void PAG_format_header()
|
||||
* Create the header page for a new file.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
/* Initialize header page */
|
||||
@ -1091,7 +1091,7 @@ void PAG_format_header()
|
||||
|
||||
// CVC: This function is mostly obsolete. Ann requested to keep it and the code that calls it.
|
||||
// We won't read the log, anyway.
|
||||
void PAG_format_log()
|
||||
void PAG_format_log(thread_db* tdbb)
|
||||
{
|
||||
/***********************************************
|
||||
*
|
||||
@ -1104,7 +1104,7 @@ void PAG_format_log()
|
||||
* Set all parameters to 0
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
WIN window(LOG_PAGE_NUMBER);
|
||||
log_info_page* logp = (log_info_page*) CCH_fake(tdbb, &window, 1);
|
||||
@ -1207,7 +1207,7 @@ bool PAG_get_clump(SLONG page_num, USHORT type, USHORT* inout_len, UCHAR* entry)
|
||||
}
|
||||
|
||||
|
||||
void PAG_header(bool info)
|
||||
void PAG_header(thread_db* tdbb, bool info)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1220,8 +1220,8 @@ void PAG_header(bool info)
|
||||
* Done through the page cache.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
fb_assert(attachment);
|
||||
@ -1332,7 +1332,7 @@ void PAG_header(bool info)
|
||||
}
|
||||
|
||||
|
||||
void PAG_header_init()
|
||||
void PAG_header_init(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1347,10 +1347,10 @@ void PAG_header_init()
|
||||
* Done using a physical page read.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
fb_assert(attachment);
|
||||
|
||||
// Allocate a spare buffer which is large enough,
|
||||
@ -1434,7 +1434,7 @@ void PAG_header_init()
|
||||
}
|
||||
|
||||
|
||||
void PAG_init()
|
||||
void PAG_init(thread_db* tdbb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1446,8 +1446,8 @@ void PAG_init()
|
||||
* Initialize stuff for page handling.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
PageManager& pageMgr = dbb->dbb_page_manager;
|
||||
@ -1518,7 +1518,7 @@ void PAG_init()
|
||||
}
|
||||
|
||||
|
||||
void PAG_init2(USHORT shadow_number)
|
||||
void PAG_init2(thread_db* tdbb, USHORT shadow_number)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1531,8 +1531,8 @@ void PAG_init2(USHORT shadow_number)
|
||||
* search for additional files.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
SET_TDBB(tdbb);
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
ISC_STATUS* status = tdbb->tdbb_status_vector;
|
||||
|
||||
/* allocate a spare buffer which is large enough,
|
||||
|
@ -44,14 +44,14 @@ int PAG_replace_entry_first(Ods::header_page*, USHORT, USHORT, const UCHAR*);
|
||||
Ods::pag* PAG_allocate(Jrd::win *);
|
||||
SLONG PAG_attachment_id(Jrd::thread_db*);
|
||||
int PAG_delete_clump_entry(SLONG, USHORT);
|
||||
void PAG_format_header();
|
||||
void PAG_format_log();
|
||||
void PAG_format_header(Jrd::thread_db*);
|
||||
void PAG_format_log(Jrd::thread_db*);
|
||||
void PAG_format_pip(Jrd::thread_db*, Jrd::PageSpace& pageSpace);
|
||||
bool PAG_get_clump(SLONG, USHORT, USHORT*, UCHAR*);
|
||||
void PAG_header(bool);
|
||||
void PAG_header_init();
|
||||
void PAG_init();
|
||||
void PAG_init2(USHORT);
|
||||
void PAG_header(Jrd::thread_db*, bool);
|
||||
void PAG_header_init(Jrd::thread_db*);
|
||||
void PAG_init(Jrd::thread_db*);
|
||||
void PAG_init2(Jrd::thread_db*, USHORT);
|
||||
SLONG PAG_last_page();
|
||||
void PAG_release_page(const Jrd::PageNumber&, const Jrd::PageNumber&);
|
||||
void PAG_set_force_write(Jrd::Database*, bool);
|
||||
|
@ -132,7 +132,6 @@ int QATEST_entrypoint(ULONG * function, void *arg1, void *arg2, void *arg3)
|
||||
* These entrypoints are *NOT* designed for customer use!
|
||||
*
|
||||
**************************************/
|
||||
char filename[MAXPATHLEN];
|
||||
Shadow* shadow;
|
||||
#ifdef WIN_NT
|
||||
HANDLE desc;
|
||||
@ -159,23 +158,19 @@ int QATEST_entrypoint(ULONG * function, void *arg1, void *arg2, void *arg3)
|
||||
return -1;
|
||||
|
||||
#ifdef WIN_NT
|
||||
|
||||
desc =
|
||||
(HANDLE) ((file->fil_flags & FIL_force_write) ?
|
||||
file->fil_force_write_desc : file->fil_desc);
|
||||
|
||||
CloseHandle(desc);
|
||||
desc = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
close(file->fil_desc);
|
||||
#endif
|
||||
strncpy((char *) filename, file->fil_string, file->fil_length);
|
||||
filename[file->fil_length] = 0;
|
||||
|
||||
#ifdef WIN_NT
|
||||
DeleteFile(filename);
|
||||
DeleteFile(file->fil_string);
|
||||
#else
|
||||
unlink(filename);
|
||||
unlink(file->fil_string);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@ -184,29 +179,27 @@ int QATEST_entrypoint(ULONG * function, void *arg1, void *arg2, void *arg3)
|
||||
/* Close & delete specified shadow file */
|
||||
|
||||
tdbb = JRD_get_thread_data();
|
||||
|
||||
if (!(shadow = dbb->dbb_shadow))
|
||||
return -1;
|
||||
|
||||
for (; shadow; shadow = shadow->sdw_next)
|
||||
if (shadow->sdw_number == *(ULONG *) arg1) {
|
||||
#ifdef WIN_NT
|
||||
|
||||
desc =
|
||||
(HANDLE) ((shadow->sdw_file->fil_flags & FIL_force_write) ?
|
||||
shadow->sdw_file->fil_force_write_desc :
|
||||
shadow->sdw_file->fil_desc);
|
||||
|
||||
CloseHandle(desc);
|
||||
desc = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
close(shadow->sdw_file->fil_desc);
|
||||
#endif
|
||||
strncpy((char *) filename, shadow->sdw_file->fil_string,
|
||||
shadow->sdw_file->fil_length);
|
||||
filename[shadow->sdw_file->fil_length] = 0;
|
||||
|
||||
#ifdef WIN_NT
|
||||
DeleteFile(filename);
|
||||
DeleteFile(shadow->sdw_file->fil_string);
|
||||
#else
|
||||
unlink(filename);
|
||||
unlink(shadow->sdw_file->fil_string);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1057,7 +1057,8 @@ void SDW_start(const TEXT* file_name,
|
||||
|
||||
/* get the ancillary files and reset the error environment */
|
||||
|
||||
PAG_init2(shadow_number);
|
||||
PAG_init2(tdbb, shadow_number);
|
||||
|
||||
if (spare_buffer)
|
||||
delete[] spare_buffer;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user