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

Implement new shutdown modes (single-user and full shutdown). Tested on Linux/AMD64 CS and SS

This commit is contained in:
skidder 2004-02-25 01:50:40 +00:00
parent 5ede51a093
commit 2c4fe73bd4
23 changed files with 700 additions and 309 deletions

Binary file not shown.

View File

@ -1080,6 +1080,8 @@ C --
PARAMETER (GDS__wal_backup_err = 335544833)
INTEGER*4 GDS__invalid_cursor_state
PARAMETER (GDS__invalid_cursor_state = 335544834)
INTEGER*4 GDS__bad_shutdown_mode
PARAMETER (GDS__bad_shutdown_mode = 335544835)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -547,6 +547,7 @@ const
gds_wrong_backup_state = 335544832;
gds_wal_backup_err = 335544833;
gds_invalid_cursor_state = 335544834;
gds_bad_shutdown_mode = 335544835;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;

View File

@ -24,7 +24,7 @@
//
//____________________________________________________________
//
// $Id: alice.cpp,v 1.50 2004-02-20 06:42:27 robocop Exp $
// $Id: alice.cpp,v 1.51 2004-02-25 01:50:10 skidder Exp $
//
// 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
// conditionals, as the engine now fully supports
@ -345,6 +345,28 @@ int common_main(int argc,
}
switches |= table->in_sw_value;
if ((table->in_sw_value & (sw_shut | sw_online)) && (argc > 1)) {
ALICE_down_case(*argv, string, sizeof(string));
bool found = false;
if ((found = (strcmp(string, "normal") == 0)))
tdgbl->ALICE_data.ua_shutdown_mode = SHUT_NORMAL;
else
if ((found = (strcmp(string, "multi") == 0)))
tdgbl->ALICE_data.ua_shutdown_mode = SHUT_MULTI;
else
if ((found = (strcmp(string, "single") == 0)))
tdgbl->ALICE_data.ua_shutdown_mode = SHUT_SINGLE;
else
if ((found = (strcmp(string, "full") == 0)))
tdgbl->ALICE_data.ua_shutdown_mode = SHUT_FULL;
// Consume argument only if we identified mode
// Let's hope that database with names of modes above are unusual
if (found) {
argv++;
argc--;
}
}
if (table->in_sw_value & sw_begin_log) {
if (--argc <= 0) {
ALICE_error(5); // msg 5: replay log pathname required

View File

@ -49,6 +49,14 @@ enum val_errors {
MAX_VAL_ERRORS = 8
};
enum alice_shut_mode {
SHUT_DEFAULT = 0,
SHUT_NORMAL = 1,
SHUT_MULTI = 2,
SHUT_SINGLE = 3,
SHUT_FULL = 4
};
typedef struct user_action
{
ULONG ua_switches;
@ -65,6 +73,7 @@ typedef struct user_action
SLONG ua_val_errors[MAX_VAL_ERRORS];
TEXT ua_log_file[MAXPATHLEN];
USHORT ua_db_SQL_dialect;
alice_shut_mode ua_shutdown_mode;
} *USER_ACTION;

View File

@ -24,7 +24,7 @@
//
//____________________________________________________________
//
// $Id: exe.cpp,v 1.28 2004-02-20 06:42:27 robocop Exp $
// $Id: exe.cpp,v 1.29 2004-02-25 01:50:10 skidder Exp $
//
// 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
// conditionals, as the engine now fully supports
@ -104,9 +104,14 @@ int EXE_action(const TEXT* database, const ULONG switches)
tdgbl->service_blk->svc_started();
if (tdgbl->status[1])
if (tdgbl->status[1] &&
// Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected.
(tdgbl->status[1] != isc_shutdown || !(switches & sw_shut) || tdgbl->ALICE_data.ua_shutdown_mode != SHUT_FULL)
)
{
error = true;
}
if (tdgbl->status[2] == isc_arg_warning)
ALICE_print_status(tdgbl->status);
@ -276,6 +281,22 @@ static USHORT build_dpb(UCHAR* dpb, const ULONG switches)
*dpb2 |= isc_dpb_shut_force;
else if (switches & sw_tran)
*dpb2 |= isc_dpb_shut_transaction;
switch(tdgbl->ALICE_data.ua_shutdown_mode) {
case SHUT_NORMAL:
*dpb2 |= isc_dpb_shut_normal;
break;
case SHUT_SINGLE:
*dpb2 |= isc_dpb_shut_single;
break;
case SHUT_MULTI:
*dpb2 |= isc_dpb_shut_multi;
break;
case SHUT_FULL:
*dpb2 |= isc_dpb_shut_full;
break;
default:
break;
}
dpb2++;
*dpb2++ = isc_dpb_shutdown_delay;
*dpb2++ = 2; // Build room for shutdown delay
@ -287,7 +308,25 @@ static USHORT build_dpb(UCHAR* dpb, const ULONG switches)
}
else if (switches & sw_online) {
*dpb2++ = isc_dpb_online;
*dpb2++ = 0;
*dpb2++ = 1;
*dpb2 = 0;
switch(tdgbl->ALICE_data.ua_shutdown_mode) {
case SHUT_NORMAL:
*dpb2 |= isc_dpb_shut_normal;
break;
case SHUT_SINGLE:
*dpb2 |= isc_dpb_shut_single;
break;
case SHUT_MULTI:
*dpb2 |= isc_dpb_shut_multi;
break;
case SHUT_FULL:
*dpb2 |= isc_dpb_shut_full;
break;
default:
break;
}
dpb2++;
}
else if (switches & sw_disable) {
*dpb2++ = isc_dpb_disable_wal;

View File

@ -24,7 +24,7 @@
* 2003.08.17 Claudio Valderrama: Fix SF Bug #750659.
*/
/*
$Id: restore.epp,v 1.68 2004-02-24 05:34:26 robocop Exp $
$Id: restore.epp,v 1.69 2004-02-25 01:50:12 skidder Exp $
*/
#include "firebird.h"
@ -1002,10 +1002,11 @@ void create_database (const TEXT* file_name)
else
*d++ = (UCHAR) SQL_DIALECT_V5;
// start database up shut down
// start database up shut down,
// use single-user mode to avoid conflicts during restore process
*d++ = (UCHAR) isc_dpb_shutdown;
*d++ = 1;
*d++ = (UCHAR) isc_dpb_shut_attachment;
*d++ = 1;
*d++ = (UCHAR) isc_dpb_shut_attachment | isc_dpb_shut_single;
*d++ = (UCHAR) isc_dpb_shutdown_delay;
*d++ = 2;
*d++ = 0;

View File

@ -557,6 +557,7 @@ const SLONG gds_conf_access_denied = 335544831L;
const SLONG gds_wrong_backup_state = 335544832L;
const SLONG gds_wal_backup_err = 335544833L;
const SLONG gds_invalid_cursor_state = 335544834L;
const SLONG gds_bad_shutdown_mode = 335544835L;
const SLONG gds_gfix_db_name = 335740929L;
const SLONG gds_gfix_invalid_sw = 335740930L;
const SLONG gds_gfix_incmp_sw = 335740932L;
@ -759,7 +760,7 @@ const SLONG gds_gstat_unexpected_eof = 336920580L;
const SLONG gds_gstat_open_err = 336920605L;
const SLONG gds_gstat_read_err = 336920606L;
const SLONG gds_gstat_sysmemex = 336920607L;
const SLONG gds_err_max = 716L;
const SLONG gds_err_max = 717L;
#else /* c definitions */
@ -1297,6 +1298,7 @@ const SLONG gds_err_max = 716L;
#define gds__wrong_backup_state 335544832L
#define gds__wal_backup_err 335544833L
#define gds__invalid_cursor_state 335544834L
#define gds__bad_shutdown_mode 335544835L
#define gds__gfix_db_name 335740929L
#define gds__gfix_invalid_sw 335740930L
#define gds__gfix_incmp_sw 335740932L
@ -1499,7 +1501,7 @@ const SLONG gds_err_max = 716L;
#define gds__gstat_open_err 336920605L
#define gds__gstat_read_err 336920606L
#define gds__gstat_sysmemex 336920607L
#define gds_err_max 716
#define gds_err_max 717
#endif

View File

@ -536,6 +536,7 @@ static const struct {
{"wrong_backup_state", 335544832},
{"wal_backup_err", 335544833},
{"invalid_cursor_state", 335544834},
{"bad_shutdown_mode", 335544835},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -569,6 +569,7 @@ const SLONG isc_conf_access_denied = 335544831L;
const SLONG isc_wrong_backup_state = 335544832L;
const SLONG isc_wal_backup_err = 335544833L;
const SLONG isc_invalid_cursor_state = 335544834L;
const SLONG isc_bad_shutdown_mode = 335544835L;
const SLONG isc_gfix_db_name = 335740929L;
const SLONG isc_gfix_invalid_sw = 335740930L;
const SLONG isc_gfix_incmp_sw = 335740932L;
@ -771,7 +772,7 @@ const SLONG isc_gstat_unexpected_eof = 336920580L;
const SLONG isc_gstat_open_err = 336920605L;
const SLONG isc_gstat_read_err = 336920606L;
const SLONG isc_gstat_sysmemex = 336920607L;
const SLONG isc_err_max = 716;
const SLONG isc_err_max = 717;
#else /* c definitions */
@ -1310,6 +1311,7 @@ const SLONG isc_err_max = 716;
#define isc_wrong_backup_state 335544832L
#define isc_wal_backup_err 335544833L
#define isc_invalid_cursor_state 335544834L
#define isc_bad_shutdown_mode 335544835L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -1512,7 +1514,7 @@ const SLONG isc_err_max = 716;
#define isc_gstat_open_err 336920605L
#define isc_gstat_read_err 336920606L
#define isc_gstat_sysmemex 336920607L
#define isc_err_max 716
#define isc_err_max 717
#endif

View File

@ -534,207 +534,208 @@ static const SCHAR * const messages[] = {
"Cannot change difference file name while database is in backup mode", /* 512, wrong_backup_state */
"Physical backup is not allowed while Write-Ahead Log is in use", /* 513, wal_backup_err */
"Invalid cursor state: %s", /* 514, invalid_cursor_state */
"data base file name (%s) already given", /* 515, gfix_db_name */
"invalid switch %s", /* 516, gfix_invalid_sw */
"incompatible switch combination", /* 517, gfix_incmp_sw */
"replay log pathname required", /* 518, gfix_replay_req */
"number of page buffers for cache required", /* 519, gfix_pgbuf_req */
"numeric value required", /* 520, gfix_val_req */
"positive numeric value required", /* 521, gfix_pval_req */
"number of transactions per sweep required", /* 522, gfix_trn_req */
"\"full\" or \"reserve\" required", /* 523, gfix_full_req */
"user name required", /* 524, gfix_usrname_req */
"password required", /* 525, gfix_pass_req */
"subsystem name", /* 526, gfix_subs_name */
"\"wal\" required", /* 527, gfix_wal_req */
"number of seconds required", /* 528, gfix_sec_req */
"numeric value between 0 and 32767 inclusive required", /* 529, gfix_nval_req */
"must specify type of shutdown", /* 530, gfix_type_shut */
"please retry, specifying an option", /* 531, gfix_retry */
"please retry, giving a database name", /* 532, gfix_retry_db */
"internal block exceeds maximum size", /* 533, gfix_exceed_max */
"corrupt pool", /* 534, gfix_corrupt_pool */
"virtual memory exhausted", /* 535, gfix_mem_exhausted */
"bad pool id", /* 536, gfix_bad_pool */
"Transaction state %d not in valid range.", /* 537, gfix_trn_not_valid */
"unexpected end of input", /* 538, gfix_unexp_eoi */
"failed to reconnect to a transaction in database %s", /* 539, gfix_recon_fail */
"Transaction description item unknown", /* 540, gfix_trn_unknown */
"\"read_only\" or \"read_write\" required", /* 541, gfix_mode_req */
" -sql_dialect set database dialect n", /* 542, gfix_opt_SQL_dialect */
"Cannot SELECT RDB$DB_KEY from a stored procedure.", /* 543, dsql_dbkey_from_non_table */
"Precision 10 to 18 changed from DOUBLE PRECISION in SQL dialect 1 to 64-bit scaled integer in SQL dialect 3", /* 544, dsql_transitional_numeric */
"Use of %s expression that returns different results in dialect 1 and dialect 3", /* 545, dsql_dialect_warning_expr */
"Database SQL dialect %d does not support reference to %s datatype", /* 546, sql_db_dialect_dtype_unsupport */
"DB dialect %d and client dialect %d conflict with respect to numeric precision %d.", /* 547, isc_sql_dialect_conflict_num */
"WARNING: Numeric literal %s is interpreted as a floating-point", /* 548, dsql_warning_number_ambiguous */
"value in SQL dialect 1, but as an exact numeric value in SQL dialect 3.", /* 549, dsql_warning_number_ambiguous1 */
"WARNING: NUMERIC and DECIMAL fields with precision 10 or greater are stored", /* 550, dsql_warn_precision_ambiguous */
"as approximate floating-point values in SQL dialect 1, but as 64-bit", /* 551, dsql_warn_precision_ambiguous1 */
"integers in SQL dialect 3.", /* 552, dsql_warn_precision_ambiguous2 */
"Ambiguous field name between %s and %s", /* 553, dsql_ambiguous_field_name */
"External function should have return position between 1 and %d", /* 554, dsql_udf_return_pos_err */
"Label %s %s in the current scope", /* 555, dsql_invalid_label */
"Datatypes %sare not comparable in expression %s", /* 556, dsql_datatypes_not_comparable */
"SQL role %s does not exist", /* 557, dyn_role_does_not_exist */
"user %s has no grant admin option on SQL role %s", /* 558, dyn_no_grant_admin_opt */
"user %s is not a member of SQL role %s", /* 559, dyn_user_not_role_member */
"%s is not the owner of SQL role %s", /* 560, dyn_delete_role_failed */
"%s is a SQL role and not a user", /* 561, dyn_grant_role_to_user */
"user name %s could not be used for SQL role", /* 562, dyn_inv_sql_role_name */
"SQL role %s already exists", /* 563, dyn_dup_sql_role */
"keyword %s can not be used as a SQL role name", /* 564, dyn_kywd_spec_for_role */
"SQL roles are not supported in on older versions of the database. A backup and restore of the database is required.", /* 565, dyn_roles_not_supported */
"Cannot rename domain %s to %s. A domain with that name already exists.", /* 566, dyn_domain_name_exists */
"Cannot rename column %s to %s. A column with that name already exists in table %s.", /* 567, dyn_field_name_exists */
"Column %s from table %s is referenced in %s", /* 568, dyn_dependency_exists */
"Cannot change datatype for column %s. Changing datatype is not supported for BLOB or ARRAY columns.", /* 569, dyn_dtype_invalid */
"New size specified for column %s must be at least %d characters.", /* 570, dyn_char_fld_too_small */
"Cannot change datatype for %s. Conversion from base type %s to %s is not supported.", /* 571, dyn_invalid_dtype_conversion */
"Cannot change datatype for column %s from a character type to a non-character type.", /* 572, dyn_dtype_conv_invalid */
"Zero length identifiers are not allowed", /* 573, dyn_zero_len_id */
"found unknown switch", /* 574, gbak_unknown_switch */
"page size parameter missing", /* 575, gbak_page_size_missing */
"Page size specified (%ld) greater than limit (8192 bytes)", /* 576, gbak_page_size_toobig */
"redirect location for output is not specified", /* 577, gbak_redir_ouput_missing */
"conflicting switches for backup/restore", /* 578, gbak_switches_conflict */
"device type %s not known", /* 579, gbak_unknown_device */
"protection is not there yet", /* 580, gbak_no_protection */
"page size is allowed only on restore or create", /* 581, gbak_page_size_not_allowed */
"multiple sources or destinations specified", /* 582, gbak_multi_source_dest */
"requires both input and output filenames", /* 583, gbak_filename_missing */
"input and output have the same name. Disallowed.", /* 584, gbak_dup_inout_names */
"expected page size, encountered \"%s\"", /* 585, gbak_inv_page_size */
"REPLACE specified, but the first file %s is a database", /* 586, gbak_db_specified */
"database %s already exists. To replace it, use the -R switch", /* 587, gbak_db_exists */
"device type not specified", /* 588, gbak_unk_device */
"gds_$blob_info failed", /* 589, gbak_blob_info_failed */
"do not understand BLOB INFO item %ld", /* 590, gbak_unk_blob_item */
"gds_$get_segment failed", /* 591, gbak_get_seg_failed */
"gds_$close_blob failed", /* 592, gbak_close_blob_failed */
"gds_$open_blob failed", /* 593, gbak_open_blob_failed */
"Failed in put_blr_gen_id", /* 594, gbak_put_blr_gen_id_failed */
"data type %ld not understood", /* 595, gbak_unk_type */
"gds_$compile_request failed", /* 596, gbak_comp_req_failed */
"gds_$start_request failed", /* 597, gbak_start_req_failed */
" gds_$receive failed", /* 598, gbak_rec_failed */
"gds_$release_request failed", /* 599, gbak_rel_req_failed */
" gds_$database_info failed", /* 600, gbak_db_info_failed */
"Expected database description record", /* 601, gbak_no_db_desc */
"failed to create database %s", /* 602, gbak_db_create_failed */
"RESTORE: decompression length error", /* 603, gbak_decomp_len_error */
"cannot find table %s", /* 604, gbak_tbl_missing */
"Cannot find column for BLOB", /* 605, gbak_blob_col_missing */
"gds_$create_blob failed", /* 606, gbak_create_blob_failed */
"gds_$put_segment failed", /* 607, gbak_put_seg_failed */
"expected record length", /* 608, gbak_rec_len_exp */
"wrong length record, expected %ld encountered %ld", /* 609, gbak_inv_rec_len */
"expected data attribute", /* 610, gbak_exp_data_type */
"Failed in store_blr_gen_id", /* 611, gbak_gen_id_failed */
"do not recognize record type %ld", /* 612, gbak_unk_rec_type */
"Expected backup version 1, 2, or 3. Found %ld", /* 613, gbak_inv_bkup_ver */
"expected backup description record", /* 614, gbak_missing_bkup_desc */
"string truncated", /* 615, gbak_string_trunc */
" warning -- record could not be restored", /* 616, gbak_cant_rest_record */
"gds_$send failed", /* 617, gbak_send_failed */
"no table name for data", /* 618, gbak_no_tbl_name */
"unexpected end of file on backup file", /* 619, gbak_unexp_eof */
"database format %ld is too old to restore to", /* 620, gbak_db_format_too_old */
"array dimension for column %s is invalid", /* 621, gbak_inv_array_dim */
"Expected XDR record length", /* 622, gbak_xdr_len_expected */
"cannot open backup file %s", /* 623, gbak_open_bkup_error */
"cannot open status and error output file %s", /* 624, gbak_open_error */
"blocking factor parameter missing", /* 625, gbak_missing_block_fac */
"expected blocking factor, encountered \"%s\"", /* 626, gbak_inv_block_fac */
"a blocking factor may not be used in conjunction with device CT", /* 627, gbak_block_fac_specified */
"user name parameter missing", /* 628, gbak_missing_username */
"password parameter missing", /* 629, gbak_missing_password */
" missing parameter for the number of bytes to be skipped", /* 630, gbak_missing_skipped_bytes */
"expected number of bytes to be skipped, encountered \"%s\"", /* 631, gbak_inv_skipped_bytes */
"Bad attribute for RDB$CHARACTER_SETS", /* 632, gbak_err_restore_charset */
"Bad attribute for RDB$COLLATIONS", /* 633, gbak_err_restore_collation */
"Unexpected I/O error while reading from backup file", /* 634, gbak_read_error */
"Unexpected I/O error while writing to backup file", /* 635, gbak_write_error */
"could not drop database %s (database might be in use)", /* 636, gbak_db_in_use */
"System memory exhausted", /* 637, gbak_sysmemex */
"Bad attributes for restoring SQL role", /* 638, gbak_restore_role_failed */
"SQL role parameter missing", /* 639, gbak_role_op_missing */
"page buffers parameter missing", /* 640, gbak_page_buffers_missing */
"expected page buffers, encountered \"%s\"", /* 641, gbak_page_buffers_wrong_param */
"page buffers is allowed only on restore or create", /* 642, gbak_page_buffers_restore */
"size specification either missing or incorrect for file %s", /* 643, gbak_inv_size */
"file %s out of sequence", /* 644, gbak_file_outof_sequence */
"can't join -- one of the files missing", /* 645, gbak_join_file_missing */
" standard input is not supported when using join operation", /* 646, gbak_stdin_not_supptd */
"standard output is not supported when using split operation", /* 647, gbak_stdout_not_supptd */
"backup file %s might be corrupt", /* 648, gbak_bkup_corrupt */
"database file specification missing", /* 649, gbak_unk_db_file_spec */
"can't write a header record to file %s", /* 650, gbak_hdr_write_failed */
"free disk space exhausted", /* 651, gbak_disk_space_ex */
"file size given (%d) is less than minimum allowed (%d)", /* 652, gbak_size_lt_min */
"service name parameter missing", /* 653, gbak_svc_name_missing */
"Cannot restore over current database, must be SYSDBA or owner of the existing database.", /* 654, gbak_not_ownr */
"\"read_only\" or \"read_write\" required", /* 655, gbak_mode_req */
"just data ignore all constraints etc.", /* 656, gbak_just_data */
"restoring data only ignoring foreign key, unique, not null & other constraints", /* 657, gbak_data_only */
"unable to open database", /* 658, gsec_cant_open_db */
"error in switch specifications", /* 659, gsec_switches_error */
"no operation specified", /* 660, gsec_no_op_spec */
"no user name specified", /* 661, gsec_no_usr_name */
"add record error", /* 662, gsec_err_add */
"modify record error", /* 663, gsec_err_modify */
"find/modify record error", /* 664, gsec_err_find_mod */
"record not found for user: %s", /* 665, gsec_err_rec_not_found */
"delete record error", /* 666, gsec_err_delete */
"find/delete record error", /* 667, gsec_err_find_del */
"find/display record error", /* 668, gsec_err_find_disp */
"invalid parameter, no switch defined", /* 669, gsec_inv_param */
"operation already specified", /* 670, gsec_op_specified */
"password already specified", /* 671, gsec_pw_specified */
"uid already specified", /* 672, gsec_uid_specified */
"gid already specified", /* 673, gsec_gid_specified */
"project already specified", /* 674, gsec_proj_specified */
"organization already specified", /* 675, gsec_org_specified */
"first name already specified", /* 676, gsec_fname_specified */
"middle name already specified", /* 677, gsec_mname_specified */
"last name already specified", /* 678, gsec_lname_specified */
"invalid switch specified", /* 679, gsec_inv_switch */
"ambiguous switch specified", /* 680, gsec_amb_switch */
"no operation specified for parameters", /* 681, gsec_no_op_specified */
"no parameters allowed for this operation", /* 682, gsec_params_not_allowed */
"incompatible switches specified", /* 683, gsec_incompat_switch */
"Invalid user name (maximum 31 bytes allowed)", /* 684, gsec_inv_username */
"Warning - maximum 8 significant bytes of password used", /* 685, gsec_inv_pw_length */
"database already specified", /* 686, gsec_db_specified */
"database administrator name already specified", /* 687, gsec_db_admin_specified */
"database administrator password already specified", /* 688, gsec_db_admin_pw_specified */
"SQL role name already specified", /* 689, gsec_sql_role_specified */
"The license file does not exist or could not be opened for read", /* 690, license_no_file */
"operation already specified", /* 691, license_op_specified */
"no operation specified", /* 692, license_op_missing */
"invalid switch", /* 693, license_inv_switch */
"invalid switch combination", /* 694, license_inv_switch_combo */
"illegal operation/switch combination", /* 695, license_inv_op_combo */
"ambiguous switch", /* 696, license_amb_switch */
"invalid parameter, no switch specified", /* 697, license_inv_parameter */
"switch does not take any parameter", /* 698, license_param_specified */
"switch requires a parameter", /* 699, license_param_req */
"syntax error in command line", /* 700, license_syntx_error */
"The certificate was not added. A duplicate ID exists in the license file.", /* 701, license_dup_id */
"The certificate was not added. Invalid certificate ID / Key combination.", /* 702, license_inv_id_key */
"The certificate was not removed. The key does not exist or corresponds to a temporary evaluation license.", /* 703, license_err_remove */
"An error occurred updating the license file. Operation cancelled.", /* 704, license_err_update */
"The certificate could not be validated based on the information given. Please recheck the ID and key information.", /* 705, license_err_convert */
"Operation failed. An unknown error occurred.", /* 706, license_err_unk */
"Add license operation failed, KEY: %s ID: %s", /* 707, license_svc_err_add */
"Remove license operation failed, KEY: %s", /* 708, license_svc_err_remove */
"The evaluation license has already been used on this server. You need to purchase a non-evaluation license.", /* 709, license_eval_exists */
"found unknown switch", /* 710, gstat_unknown_switch */
"please retry, giving a database name", /* 711, gstat_retry */
"Wrong ODS version, expected %d, encountered %d", /* 712, gstat_wrong_ods */
"Unexpected end of database file.", /* 713, gstat_unexpected_eof */
"Can't open database file %s", /* 714, gstat_open_err */
"Can't read a database page", /* 715, gstat_read_err */
"System memory exhausted", /* 716, gstat_sysmemex */
"Target shutdown mode is invalid for database \"%s\"", /* 515, bad_shutdown_mode */
"data base file name (%s) already given", /* 516, gfix_db_name */
"invalid switch %s", /* 517, gfix_invalid_sw */
"incompatible switch combination", /* 518, gfix_incmp_sw */
"replay log pathname required", /* 519, gfix_replay_req */
"number of page buffers for cache required", /* 520, gfix_pgbuf_req */
"numeric value required", /* 521, gfix_val_req */
"positive numeric value required", /* 522, gfix_pval_req */
"number of transactions per sweep required", /* 523, gfix_trn_req */
"\"full\" or \"reserve\" required", /* 524, gfix_full_req */
"user name required", /* 525, gfix_usrname_req */
"password required", /* 526, gfix_pass_req */
"subsystem name", /* 527, gfix_subs_name */
"\"wal\" required", /* 528, gfix_wal_req */
"number of seconds required", /* 529, gfix_sec_req */
"numeric value between 0 and 32767 inclusive required", /* 530, gfix_nval_req */
"must specify type of shutdown", /* 531, gfix_type_shut */
"please retry, specifying an option", /* 532, gfix_retry */
"please retry, giving a database name", /* 533, gfix_retry_db */
"internal block exceeds maximum size", /* 534, gfix_exceed_max */
"corrupt pool", /* 535, gfix_corrupt_pool */
"virtual memory exhausted", /* 536, gfix_mem_exhausted */
"bad pool id", /* 537, gfix_bad_pool */
"Transaction state %d not in valid range.", /* 538, gfix_trn_not_valid */
"unexpected end of input", /* 539, gfix_unexp_eoi */
"failed to reconnect to a transaction in database %s", /* 540, gfix_recon_fail */
"Transaction description item unknown", /* 541, gfix_trn_unknown */
"\"read_only\" or \"read_write\" required", /* 542, gfix_mode_req */
" -sql_dialect set database dialect n", /* 543, gfix_opt_SQL_dialect */
"Cannot SELECT RDB$DB_KEY from a stored procedure.", /* 544, dsql_dbkey_from_non_table */
"Precision 10 to 18 changed from DOUBLE PRECISION in SQL dialect 1 to 64-bit scaled integer in SQL dialect 3", /* 545, dsql_transitional_numeric */
"Use of %s expression that returns different results in dialect 1 and dialect 3", /* 546, dsql_dialect_warning_expr */
"Database SQL dialect %d does not support reference to %s datatype", /* 547, sql_db_dialect_dtype_unsupport */
"DB dialect %d and client dialect %d conflict with respect to numeric precision %d.", /* 548, isc_sql_dialect_conflict_num */
"WARNING: Numeric literal %s is interpreted as a floating-point", /* 549, dsql_warning_number_ambiguous */
"value in SQL dialect 1, but as an exact numeric value in SQL dialect 3.", /* 550, dsql_warning_number_ambiguous1 */
"WARNING: NUMERIC and DECIMAL fields with precision 10 or greater are stored", /* 551, dsql_warn_precision_ambiguous */
"as approximate floating-point values in SQL dialect 1, but as 64-bit", /* 552, dsql_warn_precision_ambiguous1 */
"integers in SQL dialect 3.", /* 553, dsql_warn_precision_ambiguous2 */
"Ambiguous field name between %s and %s", /* 554, dsql_ambiguous_field_name */
"External function should have return position between 1 and %d", /* 555, dsql_udf_return_pos_err */
"Label %s %s in the current scope", /* 556, dsql_invalid_label */
"Datatypes %sare not comparable in expression %s", /* 557, dsql_datatypes_not_comparable */
"SQL role %s does not exist", /* 558, dyn_role_does_not_exist */
"user %s has no grant admin option on SQL role %s", /* 559, dyn_no_grant_admin_opt */
"user %s is not a member of SQL role %s", /* 560, dyn_user_not_role_member */
"%s is not the owner of SQL role %s", /* 561, dyn_delete_role_failed */
"%s is a SQL role and not a user", /* 562, dyn_grant_role_to_user */
"user name %s could not be used for SQL role", /* 563, dyn_inv_sql_role_name */
"SQL role %s already exists", /* 564, dyn_dup_sql_role */
"keyword %s can not be used as a SQL role name", /* 565, dyn_kywd_spec_for_role */
"SQL roles are not supported in on older versions of the database. A backup and restore of the database is required.", /* 566, dyn_roles_not_supported */
"Cannot rename domain %s to %s. A domain with that name already exists.", /* 567, dyn_domain_name_exists */
"Cannot rename column %s to %s. A column with that name already exists in table %s.", /* 568, dyn_field_name_exists */
"Column %s from table %s is referenced in %s", /* 569, dyn_dependency_exists */
"Cannot change datatype for column %s. Changing datatype is not supported for BLOB or ARRAY columns.", /* 570, dyn_dtype_invalid */
"New size specified for column %s must be at least %d characters.", /* 571, dyn_char_fld_too_small */
"Cannot change datatype for %s. Conversion from base type %s to %s is not supported.", /* 572, dyn_invalid_dtype_conversion */
"Cannot change datatype for column %s from a character type to a non-character type.", /* 573, dyn_dtype_conv_invalid */
"Zero length identifiers are not allowed", /* 574, dyn_zero_len_id */
"found unknown switch", /* 575, gbak_unknown_switch */
"page size parameter missing", /* 576, gbak_page_size_missing */
"Page size specified (%ld) greater than limit (8192 bytes)", /* 577, gbak_page_size_toobig */
"redirect location for output is not specified", /* 578, gbak_redir_ouput_missing */
"conflicting switches for backup/restore", /* 579, gbak_switches_conflict */
"device type %s not known", /* 580, gbak_unknown_device */
"protection is not there yet", /* 581, gbak_no_protection */
"page size is allowed only on restore or create", /* 582, gbak_page_size_not_allowed */
"multiple sources or destinations specified", /* 583, gbak_multi_source_dest */
"requires both input and output filenames", /* 584, gbak_filename_missing */
"input and output have the same name. Disallowed.", /* 585, gbak_dup_inout_names */
"expected page size, encountered \"%s\"", /* 586, gbak_inv_page_size */
"REPLACE specified, but the first file %s is a database", /* 587, gbak_db_specified */
"database %s already exists. To replace it, use the -R switch", /* 588, gbak_db_exists */
"device type not specified", /* 589, gbak_unk_device */
"gds_$blob_info failed", /* 590, gbak_blob_info_failed */
"do not understand BLOB INFO item %ld", /* 591, gbak_unk_blob_item */
"gds_$get_segment failed", /* 592, gbak_get_seg_failed */
"gds_$close_blob failed", /* 593, gbak_close_blob_failed */
"gds_$open_blob failed", /* 594, gbak_open_blob_failed */
"Failed in put_blr_gen_id", /* 595, gbak_put_blr_gen_id_failed */
"data type %ld not understood", /* 596, gbak_unk_type */
"gds_$compile_request failed", /* 597, gbak_comp_req_failed */
"gds_$start_request failed", /* 598, gbak_start_req_failed */
" gds_$receive failed", /* 599, gbak_rec_failed */
"gds_$release_request failed", /* 600, gbak_rel_req_failed */
" gds_$database_info failed", /* 601, gbak_db_info_failed */
"Expected database description record", /* 602, gbak_no_db_desc */
"failed to create database %s", /* 603, gbak_db_create_failed */
"RESTORE: decompression length error", /* 604, gbak_decomp_len_error */
"cannot find table %s", /* 605, gbak_tbl_missing */
"Cannot find column for BLOB", /* 606, gbak_blob_col_missing */
"gds_$create_blob failed", /* 607, gbak_create_blob_failed */
"gds_$put_segment failed", /* 608, gbak_put_seg_failed */
"expected record length", /* 609, gbak_rec_len_exp */
"wrong length record, expected %ld encountered %ld", /* 610, gbak_inv_rec_len */
"expected data attribute", /* 611, gbak_exp_data_type */
"Failed in store_blr_gen_id", /* 612, gbak_gen_id_failed */
"do not recognize record type %ld", /* 613, gbak_unk_rec_type */
"Expected backup version 1, 2, or 3. Found %ld", /* 614, gbak_inv_bkup_ver */
"expected backup description record", /* 615, gbak_missing_bkup_desc */
"string truncated", /* 616, gbak_string_trunc */
" warning -- record could not be restored", /* 617, gbak_cant_rest_record */
"gds_$send failed", /* 618, gbak_send_failed */
"no table name for data", /* 619, gbak_no_tbl_name */
"unexpected end of file on backup file", /* 620, gbak_unexp_eof */
"database format %ld is too old to restore to", /* 621, gbak_db_format_too_old */
"array dimension for column %s is invalid", /* 622, gbak_inv_array_dim */
"Expected XDR record length", /* 623, gbak_xdr_len_expected */
"cannot open backup file %s", /* 624, gbak_open_bkup_error */
"cannot open status and error output file %s", /* 625, gbak_open_error */
"blocking factor parameter missing", /* 626, gbak_missing_block_fac */
"expected blocking factor, encountered \"%s\"", /* 627, gbak_inv_block_fac */
"a blocking factor may not be used in conjunction with device CT", /* 628, gbak_block_fac_specified */
"user name parameter missing", /* 629, gbak_missing_username */
"password parameter missing", /* 630, gbak_missing_password */
" missing parameter for the number of bytes to be skipped", /* 631, gbak_missing_skipped_bytes */
"expected number of bytes to be skipped, encountered \"%s\"", /* 632, gbak_inv_skipped_bytes */
"Bad attribute for RDB$CHARACTER_SETS", /* 633, gbak_err_restore_charset */
"Bad attribute for RDB$COLLATIONS", /* 634, gbak_err_restore_collation */
"Unexpected I/O error while reading from backup file", /* 635, gbak_read_error */
"Unexpected I/O error while writing to backup file", /* 636, gbak_write_error */
"could not drop database %s (database might be in use)", /* 637, gbak_db_in_use */
"System memory exhausted", /* 638, gbak_sysmemex */
"Bad attributes for restoring SQL role", /* 639, gbak_restore_role_failed */
"SQL role parameter missing", /* 640, gbak_role_op_missing */
"page buffers parameter missing", /* 641, gbak_page_buffers_missing */
"expected page buffers, encountered \"%s\"", /* 642, gbak_page_buffers_wrong_param */
"page buffers is allowed only on restore or create", /* 643, gbak_page_buffers_restore */
"size specification either missing or incorrect for file %s", /* 644, gbak_inv_size */
"file %s out of sequence", /* 645, gbak_file_outof_sequence */
"can't join -- one of the files missing", /* 646, gbak_join_file_missing */
" standard input is not supported when using join operation", /* 647, gbak_stdin_not_supptd */
"standard output is not supported when using split operation", /* 648, gbak_stdout_not_supptd */
"backup file %s might be corrupt", /* 649, gbak_bkup_corrupt */
"database file specification missing", /* 650, gbak_unk_db_file_spec */
"can't write a header record to file %s", /* 651, gbak_hdr_write_failed */
"free disk space exhausted", /* 652, gbak_disk_space_ex */
"file size given (%d) is less than minimum allowed (%d)", /* 653, gbak_size_lt_min */
"service name parameter missing", /* 654, gbak_svc_name_missing */
"Cannot restore over current database, must be SYSDBA or owner of the existing database.", /* 655, gbak_not_ownr */
"\"read_only\" or \"read_write\" required", /* 656, gbak_mode_req */
"just data ignore all constraints etc.", /* 657, gbak_just_data */
"restoring data only ignoring foreign key, unique, not null & other constraints", /* 658, gbak_data_only */
"unable to open database", /* 659, gsec_cant_open_db */
"error in switch specifications", /* 660, gsec_switches_error */
"no operation specified", /* 661, gsec_no_op_spec */
"no user name specified", /* 662, gsec_no_usr_name */
"add record error", /* 663, gsec_err_add */
"modify record error", /* 664, gsec_err_modify */
"find/modify record error", /* 665, gsec_err_find_mod */
"record not found for user: %s", /* 666, gsec_err_rec_not_found */
"delete record error", /* 667, gsec_err_delete */
"find/delete record error", /* 668, gsec_err_find_del */
"find/display record error", /* 669, gsec_err_find_disp */
"invalid parameter, no switch defined", /* 670, gsec_inv_param */
"operation already specified", /* 671, gsec_op_specified */
"password already specified", /* 672, gsec_pw_specified */
"uid already specified", /* 673, gsec_uid_specified */
"gid already specified", /* 674, gsec_gid_specified */
"project already specified", /* 675, gsec_proj_specified */
"organization already specified", /* 676, gsec_org_specified */
"first name already specified", /* 677, gsec_fname_specified */
"middle name already specified", /* 678, gsec_mname_specified */
"last name already specified", /* 679, gsec_lname_specified */
"invalid switch specified", /* 680, gsec_inv_switch */
"ambiguous switch specified", /* 681, gsec_amb_switch */
"no operation specified for parameters", /* 682, gsec_no_op_specified */
"no parameters allowed for this operation", /* 683, gsec_params_not_allowed */
"incompatible switches specified", /* 684, gsec_incompat_switch */
"Invalid user name (maximum 31 bytes allowed)", /* 685, gsec_inv_username */
"Warning - maximum 8 significant bytes of password used", /* 686, gsec_inv_pw_length */
"database already specified", /* 687, gsec_db_specified */
"database administrator name already specified", /* 688, gsec_db_admin_specified */
"database administrator password already specified", /* 689, gsec_db_admin_pw_specified */
"SQL role name already specified", /* 690, gsec_sql_role_specified */
"The license file does not exist or could not be opened for read", /* 691, license_no_file */
"operation already specified", /* 692, license_op_specified */
"no operation specified", /* 693, license_op_missing */
"invalid switch", /* 694, license_inv_switch */
"invalid switch combination", /* 695, license_inv_switch_combo */
"illegal operation/switch combination", /* 696, license_inv_op_combo */
"ambiguous switch", /* 697, license_amb_switch */
"invalid parameter, no switch specified", /* 698, license_inv_parameter */
"switch does not take any parameter", /* 699, license_param_specified */
"switch requires a parameter", /* 700, license_param_req */
"syntax error in command line", /* 701, license_syntx_error */
"The certificate was not added. A duplicate ID exists in the license file.", /* 702, license_dup_id */
"The certificate was not added. Invalid certificate ID / Key combination.", /* 703, license_inv_id_key */
"The certificate was not removed. The key does not exist or corresponds to a temporary evaluation license.", /* 704, license_err_remove */
"An error occurred updating the license file. Operation cancelled.", /* 705, license_err_update */
"The certificate could not be validated based on the information given. Please recheck the ID and key information.", /* 706, license_err_convert */
"Operation failed. An unknown error occurred.", /* 707, license_err_unk */
"Add license operation failed, KEY: %s ID: %s", /* 708, license_svc_err_add */
"Remove license operation failed, KEY: %s", /* 709, license_svc_err_remove */
"The evaluation license has already been used on this server. You need to purchase a non-evaluation license.", /* 710, license_eval_exists */
"found unknown switch", /* 711, gstat_unknown_switch */
"please retry, giving a database name", /* 712, gstat_retry */
"Wrong ODS version, expected %d, encountered %d", /* 713, gstat_wrong_ods */
"Unexpected end of database file.", /* 714, gstat_unexpected_eof */
"Can't open database file %s", /* 715, gstat_open_err */
"Can't read a database page", /* 716, gstat_read_err */
"System memory exhausted", /* 717, gstat_sysmemex */
0 /* Null entry to terminate list */
};

View File

@ -735,4 +735,5 @@ static SLONG user_codes[] = {
0,
0,
0,
0,
};

View File

@ -533,6 +533,7 @@ static const SSHORT gds__sql_code [] = {
-904 /* 512 wrong_backup_state */,
-904 /* 513 wal_backup_err */,
-902 /* 514 invalid_cursor_state */,
-901 /* 515 bad_shutdown_mode */,
-901 /* 1 gfix_db_name */,
-901 /* 2 gfix_invalid_sw */,
-901 /* 4 gfix_incmp_sw */,

View File

@ -452,7 +452,7 @@ if (dbb->dbb_use_count)
/* If we are supposed to be exclusive, stay exclusive */
if (dbb->dbb_flags & DBB_exclusive) {
if ((dbb->dbb_flags & DBB_exclusive) || (dbb->dbb_ast_flags & DBB_shutdown_single)) {
RESTORE_THREAD_DATA;
return 0;
}
@ -787,7 +787,7 @@ PAG CCH_fetch(TDBB tdbb,
WIN* window,
USHORT lock_type,
SSHORT page_type,
SHORT checksum, SSHORT latch_wait, bool read_shadow)
SSHORT checksum, SSHORT latch_wait, bool read_shadow)
{
/**************************************
*
@ -2263,7 +2263,7 @@ void CCH_release_exclusive(TDBB tdbb)
* Release exclusive access to database.
*
**************************************/
SET_TDBB(tdbb);
SET_TDBB(tdbb);
DBB dbb = tdbb->tdbb_database;
dbb->dbb_flags &= ~DBB_exclusive;

View File

@ -33,7 +33,7 @@
*
*/
/*
$Id: ibase.h,v 1.68 2004-02-02 11:01:34 robocop Exp $
$Id: ibase.h,v 1.69 2004-02-25 01:50:34 skidder Exp $
*/
#ifndef JRD_IBASE_H
@ -1341,10 +1341,17 @@ int ISC_EXPORT isc_get_client_minor_version ();
/* isc_dpb_shutdown specific flags */
/***********************************/
#define isc_dpb_shut_cache 1
#define isc_dpb_shut_attachment 2
#define isc_dpb_shut_transaction 4
#define isc_dpb_shut_force 8
#define isc_dpb_shut_cache 0x1
#define isc_dpb_shut_attachment 0x2
#define isc_dpb_shut_transaction 0x4
#define isc_dpb_shut_force 0x8
#define isc_dpb_shut_mode_mask 0x70
#define isc_dpb_shut_default 0x0
#define isc_dpb_shut_normal 0x10
#define isc_dpb_shut_multi 0x20
#define isc_dpb_shut_single 0x30
#define isc_dpb_shut_full 0x40
/**************************************/
/* Bit assignments in RDB$SYSTEM_FLAG */

View File

@ -989,7 +989,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
#endif
if (options.dpb_shutdown || options.dpb_online)
if (options.dpb_shutdown)
{
/* By releasing the DBB_MUTX_init_fini mutex here, we would be allowing
other threads to proceed with their detachments, so that shutdown does
@ -1001,7 +1001,41 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
#endif
JRD_SS_MUTEX_UNLOCK;
if (!SHUT_database
(dbb, options.dpb_shutdown, options.dpb_shutdown_delay)) {
(dbb, options.dpb_shutdown, options.dpb_shutdown_delay))
{
JRD_SS_MUTEX_LOCK;
#if defined(V4_THREADING) && !defined(SUPERSERVER)
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
#endif
if (user_status[1] != FB_SUCCESS)
ERR_punt();
else
ERR_post(isc_no_priv,
isc_arg_string, "shutdown or online",
isc_arg_string, "database",
isc_arg_string,
ERR_string(file_name, file_length),
0);
}
JRD_SS_MUTEX_LOCK;
#if defined(V4_THREADING) && !defined(SUPERSERVER)
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
#endif
}
if (options.dpb_online)
{
/* By releasing the DBB_MUTX_init_fini mutex here, we would be allowing
other threads to proceed with their detachments, so that shutdown does
not timeout for exclusive access and other threads don't have to wait
behind shutdown */
#if defined(V4_THREADING) && !defined(SUPERSERVER)
V4_JRD_MUTEX_UNLOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
#endif
JRD_SS_MUTEX_UNLOCK;
if (!SHUT_online(dbb, options.dpb_online))
{
JRD_SS_MUTEX_LOCK;
#if defined(V4_THREADING) && !defined(SUPERSERVER)
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
@ -1052,11 +1086,30 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
ERR_string(file_name, file_length), 0);
}
if (dbb->dbb_ast_flags & DBB_shutdown &&
!(attachment->att_user->usr_flags & (USR_locksmith | USR_owner)))
{
ERR_post(isc_shutdown, isc_arg_string,
ERR_string(file_name, file_length), 0);
if (dbb->dbb_ast_flags & DBB_shutdown) {
// Allow only SYSDBA/owner to access database that is shut down
bool allow_access = attachment->att_user->usr_flags & (USR_locksmith | USR_owner);
// Handle special shutdown modes
if (allow_access) {
if (dbb->dbb_ast_flags & DBB_shutdown_full) {
// Full shutdown. Deny access always
allow_access = false;
}
else if (dbb->dbb_ast_flags & DBB_shutdown_single) {
// Single user maintenance. Allow access only if we were able to take exclusive lock
// Note that logic below this exclusive lock differs for SS and CS builds:
// - CS keeps PW database lock from releasing in AST in single-user maintenance mode
// - for SS this code effectively checks that no other attachments are present
// at call point, ATT_exclusive bit is released just before this procedure exits
// Things are done this way to handle return to online mode nicely.
allow_access = CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD);
}
}
if (!allow_access) {
// Note we throw exception here when entering full-shutdown mode
ERR_post(isc_shutdown, isc_arg_string,
ERR_string(file_name, file_length), 0);
}
}
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
@ -1917,7 +1970,12 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
INI_format(attachment->att_user->usr_user_name, options.dpb_set_db_charset);
if (options.dpb_shutdown || options.dpb_online) {
// There is no point to move database online at database creation since it is online by default.
// We do not allow to create database that is fully shut down.
if (options.dpb_online || (options.dpb_shutdown & isc_dpb_shut_mode_mask) == isc_dpb_shut_full)
ERR_post(isc_bad_shutdown_mode, isc_arg_string, ERR_string(file_name, file_length), 0);
if (options.dpb_shutdown) {
/* By releasing the DBB_MUTX_init_fini mutex here, we would be allowing
other threads to proceed with their detachments, so that shutdown does
not timeout for exclusive access and other threads don't have to wait
@ -1941,7 +1999,7 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
#endif
}
if (options.dpb_sweep_interval != -1) {
PAG_sweep_interval(options.dpb_sweep_interval);
dbb->dbb_sweep_interval = options.dpb_sweep_interval;
@ -4587,8 +4645,9 @@ static ISC_STATUS check_database(TDBB tdbb, ATT attachment, ISC_STATUS * user_st
}
if (attachment->att_flags & ATT_shutdown ||
(dbb->dbb_ast_flags & DBB_shutdown &&
!(attachment->att_user->usr_flags & (USR_locksmith | USR_owner))))
((dbb->dbb_ast_flags & DBB_shutdown) &&
((dbb->dbb_ast_flags & DBB_shutdown_full) ||
!(attachment->att_user->usr_flags & (USR_locksmith | USR_owner)))))
{
tdbb->tdbb_status_vector = ptr = user_status;
*ptr++ = isc_arg_gds;
@ -5187,6 +5246,9 @@ static void get_options(const UCHAR* dpb,
case isc_dpb_shutdown:
options->dpb_shutdown = (USHORT) get_parameter(&p);
// Enforce default
if ((options->dpb_shutdown & isc_dpb_shut_mode_mask) == isc_dpb_shut_default)
options->dpb_shutdown |= isc_dpb_shut_multi;
break;
case isc_dpb_shutdown_delay:
@ -5194,9 +5256,10 @@ static void get_options(const UCHAR* dpb,
break;
case isc_dpb_online:
options->dpb_online = TRUE;
l = *p++;
p += l;
options->dpb_online = (USHORT) get_parameter(&p);
// Enforce default
if ((options->dpb_online & isc_dpb_shut_mode_mask) == isc_dpb_shut_default)
options->dpb_online |= isc_dpb_shut_normal;
break;
case isc_dpb_reserved:

View File

@ -88,6 +88,16 @@
#include "../include/fb_blk.h"
/* Shutdown lock data */
typedef union {
struct {
SSHORT flag;
SSHORT delay;
} data_items;
SLONG data_long;
} SDATA;
/* the database block, the topmost block in the metadata
cache for a database */
@ -305,6 +315,8 @@ typedef dbb* DBB;
#define DBB_shut_tran 0x20L // no new transactions accepted
#define DBB_shut_force 0x40L // forced shutdown in progress
#define DBB_shutdown_locks 0x80L // Database locks release by shutdown
#define DBB_shutdown_full 0x100L // Database fully shut down
#define DBB_shutdown_single 0x200L // Database is in single-user maintenance mode
//
// Database attachments

View File

@ -365,11 +365,18 @@ struct header_page {
#define hdr_no_checksums 0x10 /* 16 don't calculate checksums */
#define hdr_no_reserve 0x20 /* 32 don't reserve space for versions */
#define hdr_disable_cache 0x40 /* 64 disable using shared cache file */
#define hdr_shutdown 0x80 /* 128 database is shutdown */
//#define hdr_shutdown 0x80 /* 128 database is shutdown */
#define hdr_SQL_dialect_3 0x100 /* 256 database SQL dialect 3 */
#define hdr_read_only 0x200 /* 512 Database in ReadOnly. If not set, DB is RW */
/* backup status mask */
#define hdr_backup_mask 0xC00
/* backup status mask - see bit values in nbak.h */
#define hdr_backup_mask 0xC00
#define hdr_shutdown_mask 0x1080
// Values for shutdown mask
#define hdr_shutdown_none 0x0
#define hdr_shutdown_multi 0x80
#define hdr_shutdown_full 0x1000
#define hdr_shutdown_single 0x1080
/*
typedef struct sfd {

View File

@ -290,7 +290,13 @@ jrd_file* PIO_create(DBB dbb, const TEXT* string, SSHORT length, bool overwrite)
TEXT expanded_name[256]; // Shouldn't it be MAXPATHLEN?
length = PIO_expand(string, length, expanded_name);
jrd_file* file = setup_file(dbb, expanded_name, length, desc);
jrd_file *file;
try {
file = setup_file(dbb, expanded_name, length, desc);
} catch(const std::exception&) {
close(desc);
throw;
}
return file;
}
@ -661,7 +667,14 @@ jrd_file* PIO_open(DBB dbb,
}
#endif /* SUPPORT_RAW_DEVICES */
return setup_file(dbb, string, length, desc);
jrd_file *file;
try {
file = setup_file(dbb, string, length, desc);
} catch(const std::exception&) {
close(desc);
throw;
}
return file;
}
@ -1012,7 +1025,35 @@ static jrd_file* setup_file(DBB dbb, const TEXT* file_name, USHORT file_length,
dbb->dbb_flags |= DBB_exclusive;
if (!LCK_lock(NULL, lock, LCK_EX, LCK_NO_WAIT)) {
dbb->dbb_flags &= ~DBB_exclusive;
LCK_lock(NULL, lock, LCK_SW, LCK_WAIT);
TDBB tdbb = 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);
try {
dbb->dbb_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_string, ERR_string (file_name, file_length),
isc_arg_gds, isc_io_read_err,
isc_arg_unix, errno, 0);
if ((reinterpret_cast<header_page*>(header_page_buffer)->hdr_flags & hdr_shutdown_mask) == hdr_shutdown_single)
ERR_post(isc_shutdown, isc_arg_string, ERR_string(file_name, file_length), 0);
dbb->dbb_file = NULL; // Will be set again later by the caller
} catch(const std::exception&) {
delete dbb->dbb_lock;
dbb->dbb_lock = NULL;
delete file;
dbb->dbb_file = NULL; // Will be set again later by the caller
throw;
}
}
}
return file;
@ -1317,8 +1358,8 @@ raw_devices_unlink_database (
for (i = 0; i < IO_RETRY; i++)
{
const ssize_t bytes = write (desc, header, sizeof(header);
if (bytes) == sizeof(header))
const ssize_t bytes = write (desc, header, sizeof(header));
if (bytes == sizeof(header))
break;
if (bytes == -1 && SYSCALL_INTERRUPTED(errno))
continue;

View File

@ -1102,8 +1102,13 @@ if (header->hdr_implementation && header->hdr_implementation != CLASS)
if (header->hdr_flags & hdr_no_reserve)
dbb->dbb_flags |= DBB_no_reserve;
if (header->hdr_flags & hdr_shutdown)
if (header->hdr_flags & hdr_shutdown_mask) {
dbb->dbb_ast_flags |= DBB_shutdown;
if ((header->hdr_flags & hdr_shutdown_mask) == hdr_shutdown_full)
dbb->dbb_ast_flags |= DBB_shutdown_full;
else if ((header->hdr_flags & hdr_shutdown_mask) == hdr_shutdown_single)
dbb->dbb_ast_flags |= DBB_shutdown_single;
}
if (temp_buffer)
gds__free(temp_buffer);

View File

@ -39,23 +39,17 @@
#include "../jrd/thd_proto.h"
#include "../jrd/tra_proto.h"
/* Shutdown lock data */
typedef union {
struct {
SSHORT flag;
SSHORT delay;
} data_items;
SLONG data_long;
} SDATA;
#define SHUT_WAIT_TIME 5
// Define this to true if you need to allow no-op behavior when requested shutdown mode
// matches current. Logic of jrd8_create_database may need attention in this case too
#define IGNORE_SAME_MODE false
static bool notify_shutdown(DBB, SSHORT, SSHORT);
static bool shutdown_locks(DBB);
static bool shutdown_locks(DBB, SSHORT);
BOOLEAN SHUT_blocking_ast(DBB dbb)
bool SHUT_blocking_ast(DBB dbb)
{
/**************************************
*
@ -75,21 +69,36 @@ BOOLEAN SHUT_blocking_ast(DBB dbb)
/* Database shutdown has been cancelled. */
if (!flag) {
// Delay of -1 means we're going online
if (delay == -1) {
dbb->dbb_ast_flags &=
~(DBB_shut_attach | DBB_shut_tran | DBB_shut_force |
DBB_shutdown);
DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full);
switch (flag & isc_dpb_shut_mode_mask) {
case isc_dpb_shut_normal:
break;
case isc_dpb_shut_multi:
dbb->dbb_ast_flags |= DBB_shutdown;
break;
case isc_dpb_shut_single:
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single;
break;
case isc_dpb_shut_full:
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full;
break;
}
dbb->dbb_shutdown_delay = 0;
for (att* attachment = dbb->dbb_attachments; attachment;
attachment = attachment->att_next)
{
attachment->att_flags &= ~ATT_shutdown_notify;
}
return FALSE;
return false;
}
if (flag & isc_dpb_shut_force && !delay)
return shutdown_locks(dbb);
if ((flag & isc_dpb_shut_force) && !delay)
return shutdown_locks(dbb, flag);
else {
if (flag & isc_dpb_shut_attachment)
dbb->dbb_ast_flags |= DBB_shut_attach;
@ -98,12 +107,124 @@ BOOLEAN SHUT_blocking_ast(DBB dbb)
if (flag & isc_dpb_shut_transaction)
dbb->dbb_ast_flags |= DBB_shut_tran;
dbb->dbb_shutdown_delay = delay;
return FALSE;
return false;
}
}
bool bad_mode(bool ignore) {
if (!ignore) {
TDBB tdbb = GET_THREAD_DATA;
ISC_STATUS* status = tdbb->tdbb_status_vector;
*status++ = isc_arg_gds;
*status++ = isc_bad_shutdown_mode;
*status++ = isc_arg_string;
*status++ = (ISC_STATUS) ERR_cstring(reinterpret_cast<TEXT*>(tdbb->tdbb_database->dbb_filename->str_data));
*status++ = isc_arg_end;
}
return ignore;
}
BOOLEAN SHUT_database(DBB dbb, SSHORT flag, SSHORT delay)
bool SHUT_online(DBB dbb, SSHORT flag)
{
/**************************************
*
* S H U T _ o n l i n e
*
**************************************
*
* Functional description
* Move database to "more online" state
*
**************************************/
TDBB tdbb = GET_THREAD_DATA;
att* attachment = tdbb->tdbb_attachment;
/* Only platform's user locksmith can shutdown or bring online
a database. */
if (!(attachment->att_user->usr_flags & (USR_locksmith | USR_owner))) {
return false;
}
// Check if requested shutdown mode is valid
int shut_mode = flag & isc_dpb_shut_mode_mask;
switch(shut_mode) {
case isc_dpb_shut_normal:
if (!(dbb->dbb_ast_flags & DBB_shutdown))
return bad_mode(IGNORE_SAME_MODE); // normal -> normal
break;
case isc_dpb_shut_multi:
if (!(dbb->dbb_ast_flags & DBB_shutdown))
return bad_mode(false); // normal -> multi
if (!(dbb->dbb_ast_flags & DBB_shutdown_full) &&
!(dbb->dbb_ast_flags & DBB_shutdown_single))
{
return bad_mode(IGNORE_SAME_MODE); // multi -> multi
}
break;
case isc_dpb_shut_single:
if (dbb->dbb_ast_flags & DBB_shutdown_single)
return bad_mode(IGNORE_SAME_MODE); //single -> single
if (!(dbb->dbb_ast_flags & DBB_shutdown_full))
return bad_mode(false); // !full -> single
break;
case isc_dpb_shut_full:
if (dbb->dbb_ast_flags & DBB_shutdown_full)
{
return bad_mode(IGNORE_SAME_MODE); // full -> full
}
return bad_mode(false);
default: // isc_dpb_shut_full
return bad_mode(false); // unexpected mode
}
try {
/* Clear shutdown flag on database header page */
WIN window(HEADER_PAGE);
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window);
// Set appropriate shutdown mode in database header
header->hdr_flags &= ~hdr_shutdown_mask;
switch(shut_mode) {
case isc_dpb_shut_normal:
break;
case isc_dpb_shut_multi:
header->hdr_flags |= hdr_shutdown_multi;
break;
case isc_dpb_shut_single:
header->hdr_flags |= hdr_shutdown_single;
break;
case isc_dpb_shut_full:
header->hdr_flags |= hdr_shutdown_full;
break;
}
CCH_RELEASE(tdbb, &window);
/* Notify existing database clients that a currently
scheduled shutdown is cancelled. */
if (notify_shutdown(dbb, shut_mode, -1))
CCH_release_exclusive(tdbb);
/* Notify local attachments */
SHUT_blocking_ast(dbb);
} // try
catch (const std::exception&) {
return false;
}
return true;
}
bool SHUT_database(DBB dbb, SSHORT flag, SSHORT delay)
{
/**************************************
*
@ -115,45 +236,54 @@ BOOLEAN SHUT_database(DBB dbb, SSHORT flag, SSHORT delay)
* Schedule database for shutdown
*
**************************************/
TDBB tdbb;
ATT attachment;
SSHORT timeout, exclusive;
TDBB tdbb = GET_THREAD_DATA;
att* attachment = tdbb->tdbb_attachment;
tdbb = GET_THREAD_DATA;
attachment = tdbb->tdbb_attachment;
/* Only platform's user locksmith can shutdown or bring online
a database. */
if (!(attachment->att_user->usr_flags & (USR_locksmith | USR_owner))) {
return FALSE;
return false;
}
// Check if requested shutdown mode is valid
// Note that if we are already in requested mode we just return true.
// This is required to ensure backward compatible behavior (gbak relies on that,
// user-written scripts may rely on this behaviour too)
int shut_mode = flag & isc_dpb_shut_mode_mask;
switch(shut_mode) {
case isc_dpb_shut_full:
if (dbb->dbb_ast_flags & DBB_shutdown_full) return bad_mode(IGNORE_SAME_MODE);
break;
case isc_dpb_shut_multi:
if ((dbb->dbb_ast_flags & DBB_shutdown_full) ||
(dbb->dbb_ast_flags & DBB_shutdown_single))
{
return bad_mode(false);
}
if (dbb->dbb_ast_flags & DBB_shutdown)
return bad_mode(IGNORE_SAME_MODE);
break;
case isc_dpb_shut_single:
if (dbb->dbb_ast_flags & DBB_shutdown_full)
return bad_mode(false);
if (dbb->dbb_ast_flags & DBB_shutdown_single)
return bad_mode(IGNORE_SAME_MODE);
break;
case isc_dpb_shut_normal:
if (!(dbb->dbb_ast_flags & DBB_shutdown))
return bad_mode(IGNORE_SAME_MODE);
return bad_mode(false);
default:
return bad_mode(false); // unexpected mode
}
try {
/* If shutdown flag is zero then bring database online */
if (!flag)
{
/* Clear shutdown flag on database header page */
WIN window(HEADER_PAGE);
header_page* header =
(header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window);
header->hdr_flags &= ~hdr_shutdown;
CCH_RELEASE(tdbb, &window);
/* Notify existing database clients that a currently
scheduled shutdown is cancelled. */
if (notify_shutdown(dbb, 0, 0))
CCH_release_exclusive(tdbb);
/* Notify local attachments */
SHUT_blocking_ast(dbb);
return TRUE;
}
attachment->att_flags |= ATT_shutdown_manager;
--dbb->dbb_use_count;
@ -202,8 +332,13 @@ BOOLEAN SHUT_database(DBB dbb, SSHORT flag, SSHORT delay)
}
dbb->dbb_ast_flags |= DBB_shutdown;
dbb->dbb_ast_flags &= ~(DBB_shutdown_single | DBB_shutdown_full);
if (flag & isc_dpb_shut_single)
dbb->dbb_ast_flags |= DBB_shutdown_single;
else if (flag & isc_dpb_shut_full)
dbb->dbb_ast_flags |= DBB_shutdown_full;
if (!exclusive && flag & isc_dpb_shut_force) {
if (!exclusive && (flag & isc_dpb_shut_force)) {
// TMN: Ugly counting!
while (!notify_shutdown(dbb, flag, 0));
}
@ -214,20 +349,34 @@ BOOLEAN SHUT_database(DBB dbb, SSHORT flag, SSHORT delay)
header_page* header =
(header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window);
header->hdr_flags |= hdr_shutdown;
// Set appropriate shutdown mode in database header
header->hdr_flags &= ~hdr_shutdown_mask;
switch(flag & isc_dpb_shut_mode_mask) {
case isc_dpb_shut_normal:
break;
case isc_dpb_shut_multi:
header->hdr_flags |= hdr_shutdown_multi;
break;
case isc_dpb_shut_single:
header->hdr_flags |= hdr_shutdown_single;
break;
case isc_dpb_shut_full:
header->hdr_flags |= hdr_shutdown_full;
break;
}
CCH_RELEASE(tdbb, &window);
CCH_release_exclusive(tdbb);
} // try
catch (const std::exception&) {
return FALSE;
return false;
}
return TRUE;
return true;
}
BOOLEAN SHUT_init(DBB dbb)
bool SHUT_init(DBB dbb)
{
/**************************************
*
@ -271,11 +420,11 @@ static bool notify_shutdown(DBB dbb, SSHORT flag, SSHORT delay)
/* Send blocking ASTs to database users */
if (CCH_exclusive(tdbb, LCK_PW, ((SSHORT) - SHUT_WAIT_TIME)) && flag) {
return shutdown_locks(dbb);
if (CCH_exclusive(tdbb, LCK_PW, ((SSHORT) - SHUT_WAIT_TIME)) && (delay != -1)) {
return shutdown_locks(dbb, flag);
}
if ((flag & isc_dpb_shut_force) && !delay) {
return shutdown_locks(dbb);
return shutdown_locks(dbb, flag);
}
if ((flag & isc_dpb_shut_transaction) &&
!(TRA_active_transactions(tdbb, dbb)))
@ -287,7 +436,7 @@ static bool notify_shutdown(DBB dbb, SSHORT flag, SSHORT delay)
}
static bool shutdown_locks(DBB dbb)
static bool shutdown_locks(DBB dbb, SSHORT flag)
{
/**************************************
*
@ -304,7 +453,19 @@ static bool shutdown_locks(DBB dbb)
/* Mark database and all active attachments as shutdown. */
dbb->dbb_ast_flags |= DBB_shutdown;
dbb->dbb_ast_flags &= ~(DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full);
switch (flag & isc_dpb_shut_mode_mask) {
case isc_dpb_shut_multi:
dbb->dbb_ast_flags |= DBB_shutdown;
break;
case isc_dpb_shut_single:
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single;
break;
case isc_dpb_shut_full:
dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full;
break;
}
att* attachment;

View File

@ -26,9 +26,10 @@
class dbb;
BOOLEAN SHUT_blocking_ast(dbb*);
BOOLEAN SHUT_database(dbb*, SSHORT, SSHORT);
BOOLEAN SHUT_init(dbb*);
bool SHUT_blocking_ast(dbb*);
bool SHUT_online(dbb*, SSHORT);
bool SHUT_database(dbb*, SSHORT, SSHORT);
bool SHUT_init(dbb*);
#endif // JRD_SHUT_PROTO_H

View File

@ -164,10 +164,22 @@ void PPG_print_header(const header_page* header, SLONG page,
FPRINTF(outfile, "active shadow");
}
if (flags & hdr_shutdown) {
if ((flags & hdr_shutdown_mask) == hdr_shutdown_multi) {
if (flag_count++)
FPRINTF(outfile, ", ");
FPRINTF(outfile, "database shutdown");
FPRINTF(outfile, "multi-user maintenance");
}
if ((flags & hdr_shutdown_mask) == hdr_shutdown_single) {
if (flag_count++)
FPRINTF(outfile, ", ");
FPRINTF(outfile, "single-user maintenance");
}
if ((flags & hdr_shutdown_mask) == hdr_shutdown_full) {
if (flag_count++)
FPRINTF(outfile, ", ");
FPRINTF(outfile, "full shutdown");
}
if (flags & hdr_read_only) {