mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 09:20:39 +01:00
Applied initial patch from red-soft
This commit is contained in:
parent
08746df97e
commit
fa0bae17e2
@ -2548,6 +2548,8 @@ C --
|
||||
PARAMETER (GDS__nbackup_user_stop = 337117257)
|
||||
INTEGER*4 GDS__nbackup_deco_parse
|
||||
PARAMETER (GDS__nbackup_deco_parse = 337117259)
|
||||
INTEGER*4 GDS__nbackup_lostrec_guid_db
|
||||
PARAMETER (GDS__nbackup_lostrec_guid_db = 337117261)
|
||||
INTEGER*4 GDS__trace_conflict_acts
|
||||
PARAMETER (GDS__trace_conflict_acts = 337182750)
|
||||
INTEGER*4 GDS__trace_act_notfound
|
||||
|
@ -2543,6 +2543,8 @@ const
|
||||
gds_nbackup_user_stop = 337117257;
|
||||
isc_nbackup_deco_parse = 337117259;
|
||||
gds_nbackup_deco_parse = 337117259;
|
||||
isc_nbackup_lostrec_guid_db = 337117261;
|
||||
gds_nbackup_lostrec_guid_db = 337117261;
|
||||
isc_trace_conflict_acts = 337182750;
|
||||
gds_trace_conflict_acts = 337182750;
|
||||
isc_trace_act_notfound = 337182751;
|
||||
|
@ -436,6 +436,7 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
|
||||
case isc_spb_nbk_file:
|
||||
case isc_spb_nbk_direct:
|
||||
case isc_spb_dbname:
|
||||
case isc_spb_nbk_guid:
|
||||
return StringSpb;
|
||||
case isc_spb_nbk_level:
|
||||
case isc_spb_options:
|
||||
|
@ -556,7 +556,9 @@
|
||||
#define isc_spb_nbk_level 5
|
||||
#define isc_spb_nbk_file 6
|
||||
#define isc_spb_nbk_direct 7
|
||||
#define isc_spb_nbk_guid 8
|
||||
#define isc_spb_nbk_no_triggers 0x01
|
||||
#define isc_spb_nbk_inplace 0x02
|
||||
|
||||
/***************************************
|
||||
* Parameters for isc_action_svc_trace *
|
||||
|
@ -1270,6 +1270,7 @@ static const struct {
|
||||
{"nbackup_switchd_parameter", 337117255},
|
||||
{"nbackup_user_stop", 337117257},
|
||||
{"nbackup_deco_parse", 337117259},
|
||||
{"nbackup_lostrec_guid_db", 337117261},
|
||||
{"trace_conflict_acts", 337182750},
|
||||
{"trace_act_notfound", 337182751},
|
||||
{"trace_switch_once", 337182752},
|
||||
|
@ -1304,6 +1304,7 @@ const ISC_STATUS isc_nbackup_lostguid_l0bk = 337117251L;
|
||||
const ISC_STATUS isc_nbackup_switchd_parameter = 337117255L;
|
||||
const ISC_STATUS isc_nbackup_user_stop = 337117257L;
|
||||
const ISC_STATUS isc_nbackup_deco_parse = 337117259L;
|
||||
const ISC_STATUS isc_nbackup_lostrec_guid_db = 337117261L;
|
||||
const ISC_STATUS isc_trace_conflict_acts = 337182750L;
|
||||
const ISC_STATUS isc_trace_act_notfound = 337182751L;
|
||||
const ISC_STATUS isc_trace_switch_once = 337182752L;
|
||||
@ -1315,7 +1316,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1259;
|
||||
const ISC_STATUS isc_err_max = 1260;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2589,6 +2590,7 @@ const ISC_STATUS isc_err_max = 1259;
|
||||
#define isc_nbackup_switchd_parameter 337117255L
|
||||
#define isc_nbackup_user_stop 337117257L
|
||||
#define isc_nbackup_deco_parse 337117259L
|
||||
#define isc_nbackup_lostrec_guid_db 337117261L
|
||||
#define isc_trace_conflict_acts 337182750L
|
||||
#define isc_trace_act_notfound 337182751L
|
||||
#define isc_trace_switch_once 337182752L
|
||||
@ -2600,7 +2602,7 @@ const ISC_STATUS isc_err_max = 1259;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1259
|
||||
#define isc_err_max 1260
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1273,6 +1273,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{337117255, "Wrong parameter @1 for switch -D, need ON or OFF"}, /* nbackup_switchd_parameter */
|
||||
{337117257, "Terminated due to user request"}, /* nbackup_user_stop */
|
||||
{337117259, "Too complex decompress command (> @1 arguments)"}, /* nbackup_deco_parse */
|
||||
{337117261, "Cannot find record for database \"@1\" backup GUID @2 in the backup history"}, /* nbackup_lostrec_guid_db */
|
||||
{337182750, "conflicting actions \"@1\" and \"@2\" found"}, /* trace_conflict_acts */
|
||||
{337182751, "action switch not found"}, /* trace_act_notfound */
|
||||
{337182752, "switch \"@1\" must be set only once"}, /* trace_switch_once */
|
||||
|
@ -1269,6 +1269,7 @@ static const struct {
|
||||
{337117255, -901}, /* 71 nbackup_switchd_parameter */
|
||||
{337117257, -901}, /* 73 nbackup_user_stop */
|
||||
{337117259, -901}, /* 75 nbackup_deco_parse */
|
||||
{337117261, -901}, /* 77 nbackup_lostrec_guid_db */
|
||||
{337182750, -901}, /* 30 trace_conflict_acts */
|
||||
{337182751, -901}, /* 31 trace_act_notfound */
|
||||
{337182752, -901}, /* 32 trace_switch_once */
|
||||
|
@ -1269,6 +1269,7 @@ static const struct {
|
||||
{337117255, "00000"}, // 71 nbackup_switchd_parameter
|
||||
{337117257, "08006"}, // 73 nbackup_user_stop
|
||||
{337117259, "54023"}, // 75 nbackup_deco_parse
|
||||
{337117261, "00000"}, // 77 nbackup_lostrec_guid_db
|
||||
{337182750, "00000"}, // 30 trace_conflict_acts
|
||||
{337182751, "00000"}, // 31 trace_act_notfound
|
||||
{337182752, "00000"}, // 32 trace_switch_once
|
||||
|
@ -2530,7 +2530,7 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
|
||||
string burp_database, burp_backup;
|
||||
int burp_options = 0;
|
||||
|
||||
string nbk_database, nbk_file;
|
||||
string nbk_database, nbk_file, nbk_guid;
|
||||
int nbk_level = -1;
|
||||
|
||||
bool val_database = false;
|
||||
@ -2556,13 +2556,22 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
|
||||
break;
|
||||
|
||||
case isc_spb_nbk_level:
|
||||
if (nbk_level >= 0)
|
||||
if (nbk_level >= 0 || nbk_guid.hasData())
|
||||
{
|
||||
(Arg::Gds(isc_unexp_spb_form) << Arg::Str("only one isc_spb_nbk_level")).raise();
|
||||
(Arg::Gds(isc_unexp_spb_form) << Arg::Str("only one isc_spb_nbk_level or isc_spb_nbk_guid")).raise();
|
||||
}
|
||||
nbk_level = spb.getInt();
|
||||
break;
|
||||
|
||||
case isc_spb_nbk_guid:
|
||||
if (nbk_level >= 0 || nbk_guid.hasData())
|
||||
{
|
||||
(Arg::Gds(isc_unexp_spb_form) <<
|
||||
Arg::Str("only one isc_spb_nbk_level or isc_spb_nbk_guid")).raise();
|
||||
}
|
||||
get_action_svc_string(spb, nbk_guid);
|
||||
break;
|
||||
|
||||
case isc_spb_nbk_file:
|
||||
if (nbk_file.hasData() && svc_action != isc_action_svc_nrest)
|
||||
{
|
||||
@ -2980,13 +2989,18 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
|
||||
}
|
||||
if (svc_action == isc_action_svc_nbak)
|
||||
{
|
||||
if (nbk_level < 0)
|
||||
if (nbk_level < 0 && nbk_guid.isEmpty())
|
||||
{
|
||||
(Arg::Gds(isc_missing_required_spb) << Arg::Str("isc_spb_nbk_level")).raise();
|
||||
(Arg::Gds(isc_missing_required_spb) << Arg::Str("isc_spb_nbk_level or isc_spb_nbk_guid")).raise();
|
||||
}
|
||||
string temp;
|
||||
temp.printf("%d ", nbk_level);
|
||||
switches += temp;
|
||||
if (nbk_level >= 0)
|
||||
{
|
||||
string temp;
|
||||
temp.printf("%d ", nbk_level);
|
||||
switches += temp;
|
||||
}
|
||||
else
|
||||
switches += nbk_guid;
|
||||
}
|
||||
switches += nbk_database;
|
||||
switches += nbk_file;
|
||||
|
@ -18,7 +18,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
|
||||
('2015-01-07 18:01:51', 'GSTAT', 21, 58)
|
||||
('2013-12-19 17:31:31', 'FBSVCMGR', 22, 58)
|
||||
('2009-07-18 12:12:12', 'UTL', 23, 2)
|
||||
('2015-01-07 18:01:51', 'NBACKUP', 24, 77)
|
||||
('2016-03-20 15:30:00', 'NBACKUP', 24, 80)
|
||||
('2009-07-20 07:55:48', 'FBTRACEMGR', 25, 41)
|
||||
('2015-07-27 00:00:00', 'JAYBIRD', 26, 1)
|
||||
stop
|
||||
|
@ -3296,7 +3296,7 @@ Analyzing database pages ...', NULL, NULL);
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 8, NULL, ' -L(OCK) <database> Lock database for filesystem copy', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 9, NULL, ' -UN(LOCK) <database> Unlock previously locked database', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 10, NULL, ' -F(IXUP) <database> Fixup database after filesystem copy', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 11, NULL, ' -B(ACKUP) <level> <db> [<file>] Create incremental backup', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 11, NULL, ' -B(ACKUP) <level>|<GUID> <db> [<file>] Create incremental backup', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 12, NULL, ' -R(ESTORE) <db> [<file0> [<file1>...]] Restore incremental backup', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 13, NULL, ' -U(SER) <user> User name', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 14, NULL, ' -P(ASSWORD) <password> Password', NULL, NULL)
|
||||
@ -3362,6 +3362,9 @@ Analyzing database pages ...', NULL, NULL);
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 74, NULL, ' -DE(COMPRESS) <command> Command to extract archives during restore', NULL, NULL)
|
||||
('nbackup_deco_parse', 'NBackup::open_backup_scan', 'nbackup.cpp', NULL, 24, 75, NULL, 'Too complex decompress command (> @1 arguments)', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 76, NULL, ' -RO(LE) <role> SQL role name', NULL, NULL)
|
||||
('nbackup_lostrec_guid_db', 'NBackup::backup_database', 'nbackup.cpp', NULL, 24, 77, NULL, 'Cannot find record for database "@1" backup GUID @2 in the backup history', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 78, NULL, ' -I Restore incremental backup(s) to existing database', NULL, NULL)
|
||||
(NULL, 'usage', 'nbackup.cpp', NULL, 24, 79, NULL, ' -I option could corrupt the database that has changed since previous restore', NULL, NULL)
|
||||
-- FBTRACEMGR
|
||||
-- All messages use the new format.
|
||||
(NULL, 'usage', 'TraceCmdLine.cpp', NULL, 25, 1, NULL, 'Firebird Trace Manager version @1', NULL, NULL)
|
||||
|
@ -1268,6 +1268,7 @@ COMMIT WORK;
|
||||
(-901, '00', '000', 24, 71, 'nbackup_switchd_parameter', NULL, NULL)
|
||||
(-901, '08', '006', 24, 73, 'nbackup_user_stop', NULL, NULL)
|
||||
(-901, '54', '023', 24, 75, 'nbackup_deco_parse', NULL, NULL)
|
||||
(-901, '00', '000', 24, 77, 'nbackup_lostrec_guid_db', NULL, NULL)
|
||||
-- FBTRACEMGR
|
||||
(-901, '00', '000', 25, 30, 'trace_conflict_acts', NULL, NULL)
|
||||
(-901, '00', '000', 25, 31, 'trace_act_notfound', NULL, NULL)
|
||||
|
@ -483,6 +483,7 @@ const SvcSwitches nbackOptions[] =
|
||||
{"dbname", putStringArgument, 0, isc_spb_dbname, 0},
|
||||
{"nbk_file", putStringArgument, 0, isc_spb_nbk_file, 0},
|
||||
{"nbk_level", putNumericArgument, 0, isc_spb_nbk_level, 0},
|
||||
{"nbk_guid", putStringArgument, 0, isc_spb_nbk_guid, 0},
|
||||
{"nbk_no_triggers", putOption, 0, isc_spb_nbk_no_triggers, 0},
|
||||
{"nbk_direct", putStringArgument, 0, isc_spb_nbk_direct, 0},
|
||||
{0, 0, 0, 0, 0}
|
||||
@ -492,6 +493,7 @@ const SvcSwitches nrestOptions[] =
|
||||
{
|
||||
{"dbname", putStringArgument, 0, isc_spb_dbname, 0},
|
||||
{"nbk_file", putStringArgument, 0, isc_spb_nbk_file, 0},
|
||||
{"nbk_inplace", putOption, 0, isc_spb_nbk_inplace, 0},
|
||||
{0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -146,7 +146,7 @@ namespace
|
||||
}
|
||||
|
||||
const int mainUsage[] = { 2, 3, 4, 5, 6, 0 };
|
||||
const int notes[] = { 19, 20, 21, 22, 26, 27, 28, 0 };
|
||||
const int notes[] = { 19, 20, 21, 22, 26, 27, 28, 79, 0 };
|
||||
const Switches::in_sw_tab_t* const base = nbackup_action_in_sw_table;
|
||||
|
||||
for (int i = 0; mainUsage[i]; ++i)
|
||||
@ -310,11 +310,11 @@ public:
|
||||
typedef ObjectsArray<PathName> BackupFiles;
|
||||
|
||||
// External calls must clean up resources after themselves
|
||||
void fixup_database();
|
||||
void fixup_database(bool set_readonly = false);
|
||||
void lock_database(bool get_size);
|
||||
void unlock_database();
|
||||
void backup_database(int level, const PathName& fname);
|
||||
void restore_database(const BackupFiles& files);
|
||||
void backup_database(int level, Guid& guid, const PathName& fname);
|
||||
void restore_database(const BackupFiles& files, bool inc_rest = false);
|
||||
|
||||
bool printed() const
|
||||
{
|
||||
@ -359,7 +359,7 @@ private:
|
||||
string to_system(const PathName& from);
|
||||
|
||||
// Create/open database and backup
|
||||
void open_database_write();
|
||||
void open_database_write(bool exclusive = false);
|
||||
void open_database_scan();
|
||||
void create_database();
|
||||
void close_database();
|
||||
@ -450,16 +450,21 @@ void NBackup::seek_file(FILE_HANDLE &file, SINT64 pos)
|
||||
Arg::OsError());
|
||||
}
|
||||
|
||||
void NBackup::open_database_write()
|
||||
void NBackup::open_database_write(bool exclusive)
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
const DWORD shareFlags = exclusive ? FILE_SHARE_READ :
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
|
||||
dbase = CreateFile(dbname.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
shareFlags, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dbase != INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
#else
|
||||
dbase = os_utils::open(dbname.c_str(), O_RDWR | O_LARGEFILE);
|
||||
const int flags = exclusive ? O_EXCL | O_RDWR | O_LARGEFILE :
|
||||
O_RDWR | O_LARGEFILE;
|
||||
|
||||
dbase = open(dbname.c_str(), flags);
|
||||
if (dbase >= 0)
|
||||
return;
|
||||
#endif
|
||||
@ -710,7 +715,7 @@ void NBackup::close_backup()
|
||||
#endif
|
||||
}
|
||||
|
||||
void NBackup::fixup_database()
|
||||
void NBackup::fixup_database(bool set_readonly)
|
||||
{
|
||||
open_database_write();
|
||||
Ods::header_page header;
|
||||
@ -724,6 +729,9 @@ void NBackup::fixup_database()
|
||||
Arg::Num(Ods::hdr_nbak_stalled));
|
||||
}
|
||||
header.hdr_flags = (header.hdr_flags & ~Ods::hdr_backup_mask) | Ods::hdr_nbak_normal;
|
||||
if (set_readonly)
|
||||
header.hdr_flags |= Ods::hdr_read_only;
|
||||
|
||||
seek_file(dbase, 0);
|
||||
write_file(dbase, &header, sizeof(header));
|
||||
close_database();
|
||||
@ -917,13 +925,14 @@ void NBackup::unlock_database()
|
||||
detach_database();
|
||||
}
|
||||
|
||||
void NBackup::backup_database(int level, const PathName& fname)
|
||||
void NBackup::backup_database(int level, Guid& guid, const PathName& fname)
|
||||
{
|
||||
bool database_locked = false;
|
||||
// We set this flag when backup file is in inconsistent state
|
||||
bool delete_backup = false;
|
||||
ULONG prev_scn = 0;
|
||||
char prev_guid[GUID_BUFF_SIZE] = "";
|
||||
char str_guid[GUID_BUFF_SIZE] = "";
|
||||
Ods::pag* page_buff = NULL;
|
||||
attach_database();
|
||||
ULONG page_writes = 0, page_reads = 0;
|
||||
@ -950,6 +959,9 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
// Look for SCN and GUID of previous-level backup in history table
|
||||
if (level)
|
||||
{
|
||||
if (level < 0)
|
||||
GuidToString(str_guid, &guid);
|
||||
|
||||
if (isc_start_transaction(status, &trans, 1, &newdb, 0, NULL))
|
||||
pr_error(status, "start transaction");
|
||||
char out_sqlda_data[XSQLDA_LENGTH(2)];
|
||||
@ -961,10 +973,18 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
if (isc_dsql_allocate_statement(status, &newdb, &stmt))
|
||||
pr_error(status, "allocate statement");
|
||||
char str[200];
|
||||
sprintf(str, "SELECT RDB$GUID, RDB$SCN FROM RDB$BACKUP_HISTORY "
|
||||
"WHERE RDB$BACKUP_ID = "
|
||||
"(SELECT MAX(RDB$BACKUP_ID) FROM RDB$BACKUP_HISTORY "
|
||||
"WHERE RDB$BACKUP_LEVEL = %d)", level - 1);
|
||||
if (level > 0)
|
||||
{
|
||||
sprintf(str, "SELECT RDB$GUID, RDB$SCN FROM RDB$BACKUP_HISTORY "
|
||||
"WHERE RDB$BACKUP_ID = "
|
||||
"(SELECT MAX(RDB$BACKUP_ID) FROM RDB$BACKUP_HISTORY "
|
||||
"WHERE RDB$BACKUP_LEVEL = %d)", level - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(str, "SELECT RDB$GUID, RDB$SCN FROM RDB$BACKUP_HISTORY "
|
||||
"WHERE RDB$GUID = '%s'", str_guid);
|
||||
}
|
||||
if (isc_dsql_prepare(status, &trans, &stmt, 0, str, 1, NULL))
|
||||
pr_error(status, "prepare history query");
|
||||
if (isc_dsql_describe(status, &stmt, 1, out_sqlda))
|
||||
@ -980,8 +1000,13 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
switch (isc_dsql_fetch(status, &stmt, 1, out_sqlda))
|
||||
{
|
||||
case 100: // No more records available
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_lostrec_db) << database.c_str() <<
|
||||
Arg::Num(level - 1));
|
||||
if (level > 0)
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_lostrec_db) << database.c_str() <<
|
||||
Arg::Num(level - 1));
|
||||
else
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_lostrec_guid_db) << database.c_str() <<
|
||||
Arg::Str(str_guid));
|
||||
|
||||
case 0:
|
||||
if (guid_null || scn_null)
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_lostguid_db));
|
||||
@ -1008,9 +1033,18 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
// Let's generate nice new filename
|
||||
PathName begin, fil;
|
||||
PathUtils::splitLastComponent(begin, fil, database);
|
||||
bakname.printf("%s-%d-%04d%02d%02d-%02d%02d.nbk", fil.c_str(), level,
|
||||
today.tm_year + 1900, today.tm_mon + 1, today.tm_mday,
|
||||
today.tm_hour, today.tm_min);
|
||||
if (level >= 0)
|
||||
{
|
||||
bakname.printf("%s-%d-%04d%02d%02d-%02d%02d.nbk", fil.c_str(), level,
|
||||
today.tm_year + 1900, today.tm_mon + 1, today.tm_mday,
|
||||
today.tm_hour, today.tm_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
bakname.printf("%s-%s-%04d%02d%02d-%02d%02d.nbk", fil.c_str(), str_guid,
|
||||
today.tm_year + 1900, today.tm_mon + 1, today.tm_mday,
|
||||
today.tm_hour, today.tm_min);
|
||||
}
|
||||
if (!uSvc->isService())
|
||||
printf("%s", bakname.c_str()); // Print out generated filename for script processing
|
||||
}
|
||||
@ -1100,7 +1134,7 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
inc_header bh;
|
||||
memcpy(bh.signature, backup_signature, sizeof(backup_signature));
|
||||
bh.version = BACKUP_VERSION;
|
||||
bh.level = level;
|
||||
bh.level = level > 0 ? level : 0;
|
||||
bh.backup_guid = backup_guid;
|
||||
StringToGuid(&bh.prev_guid, prev_guid);
|
||||
bh.page_size = header->hdr_page_size;
|
||||
@ -1271,8 +1305,17 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
if (isc_dsql_describe_bind(status, &stmt, 1, in_sqlda))
|
||||
pr_error(status, "bind history insert");
|
||||
short null_flag = 0;
|
||||
in_sqlda->sqlvar[0].sqldata = (char*) &level;
|
||||
in_sqlda->sqlvar[0].sqlind = &null_flag;
|
||||
short null_ind = -1;
|
||||
if (level >= 0)
|
||||
{
|
||||
in_sqlda->sqlvar[0].sqldata = (char*)&level;
|
||||
in_sqlda->sqlvar[0].sqlind = &null_flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_sqlda->sqlvar[0].sqldata = NULL;
|
||||
in_sqlda->sqlvar[0].sqlind = &null_ind;
|
||||
}
|
||||
char temp[GUID_BUFF_SIZE];
|
||||
GuidToString(temp, &backup_guid);
|
||||
in_sqlda->sqlvar[1].sqldata = temp;
|
||||
@ -1334,14 +1377,17 @@ void NBackup::backup_database(int level, const PathName& fname)
|
||||
}
|
||||
}
|
||||
|
||||
void NBackup::restore_database(const BackupFiles& files)
|
||||
void NBackup::restore_database(const BackupFiles& files, bool inc_rest)
|
||||
{
|
||||
// We set this flag when database file is in inconsistent state
|
||||
bool delete_database = false;
|
||||
const int filecount = files.getCount();
|
||||
#ifndef WIN_NT
|
||||
create_database();
|
||||
delete_database = true;
|
||||
if (!inc_rest)
|
||||
{
|
||||
create_database();
|
||||
delete_database = true;
|
||||
}
|
||||
#endif
|
||||
UCHAR *page_buffer = NULL;
|
||||
try {
|
||||
@ -1396,16 +1442,19 @@ void NBackup::restore_database(const BackupFiles& files)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curLevel >= filecount)
|
||||
if (curLevel >= filecount + (inc_rest ? 1 : 0))
|
||||
{
|
||||
close_database();
|
||||
fixup_database();
|
||||
fixup_database(inc_rest);
|
||||
delete[] page_buffer;
|
||||
return;
|
||||
}
|
||||
bakname = files[curLevel];
|
||||
if (!inc_rest || curLevel)
|
||||
bakname = files[curLevel - (inc_rest ? 1 : 0)];
|
||||
#ifdef WIN_NT
|
||||
if (curLevel)
|
||||
#else
|
||||
if (!inc_rest || curLevel)
|
||||
#endif
|
||||
open_backup_scan();
|
||||
}
|
||||
@ -1422,7 +1471,7 @@ void NBackup::restore_database(const BackupFiles& files)
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_unsupvers_incbk) <<
|
||||
Arg::Num(bakheader.version) << bakname.c_str());
|
||||
}
|
||||
if (bakheader.level != curLevel)
|
||||
if (bakheader.level && bakheader.level != curLevel)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_invlevel_incbk) <<
|
||||
Arg::Num(bakheader.level) << bakname.c_str() << Arg::Num(curLevel));
|
||||
@ -1432,7 +1481,8 @@ void NBackup::restore_database(const BackupFiles& files)
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_wrong_orderbk) << bakname.c_str());
|
||||
seek_file(backup, bakheader.page_size);
|
||||
|
||||
delete_database = true;
|
||||
if (!inc_rest)
|
||||
delete_database = true;
|
||||
prev_guid = bakheader.backup_guid;
|
||||
while (true)
|
||||
{
|
||||
@ -1451,28 +1501,34 @@ void NBackup::restore_database(const BackupFiles& files)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inc_rest)
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
if (!CopyFile(bakname.c_str(), dbname.c_str(), TRUE))
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_err_copy) <<
|
||||
dbname.c_str() << bakname.c_str() << Arg::OsError());
|
||||
}
|
||||
checkCtrlC(uSvc);
|
||||
delete_database = true; // database is possibly broken
|
||||
open_database_write();
|
||||
#else
|
||||
// Use relatively small buffer to make use of prefetch and lazy flush
|
||||
char buffer[65536];
|
||||
while (true)
|
||||
{
|
||||
const FB_SIZE_T bytesRead = read_file(backup, buffer, sizeof(buffer));
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
write_file(dbase, buffer, bytesRead);
|
||||
if (!CopyFile(bakname.c_str(), dbname.c_str(), TRUE))
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_nbackup_err_copy) <<
|
||||
dbname.c_str() << bakname.c_str() << Arg::OsError());
|
||||
}
|
||||
checkCtrlC(uSvc);
|
||||
}
|
||||
seek_file(dbase, 0);
|
||||
delete_database = true; // database is possibly broken
|
||||
open_database_write();
|
||||
#else
|
||||
// Use relatively small buffer to make use of prefetch and lazy flush
|
||||
char buffer[65536];
|
||||
while (true)
|
||||
{
|
||||
const FB_SIZE_T bytesRead = read_file(backup, buffer, sizeof(buffer));
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
write_file(dbase, buffer, bytesRead);
|
||||
checkCtrlC(uSvc);
|
||||
}
|
||||
seek_file(dbase, 0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
open_database_write(true);
|
||||
|
||||
// Read database header
|
||||
Ods::header_page header;
|
||||
if (read_file(dbase, &header, sizeof(header)) != sizeof(header))
|
||||
@ -1579,8 +1635,9 @@ void nbackup(UtilSvc* uSvc)
|
||||
false;
|
||||
#endif
|
||||
NBackup::BackupFiles backup_files;
|
||||
int level;
|
||||
bool print_size = false, version = false;
|
||||
int level = -1;
|
||||
Guid guid;
|
||||
bool print_size = false, version = false, inc_rest = false;
|
||||
string onOff;
|
||||
|
||||
const Switches switches(nbackup_action_in_sw_table, FB_NELEM(nbackup_action_in_sw_table),
|
||||
@ -1709,7 +1766,10 @@ void nbackup(UtilSvc* uSvc)
|
||||
if (++itr >= argc)
|
||||
missingParameterForSwitch(uSvc, argv[itr - 1]);
|
||||
|
||||
level = atoi(argv[itr]);
|
||||
if (argv[itr][0] == '{')
|
||||
StringToGuid(&guid, argv[itr]);
|
||||
else
|
||||
level = atoi(argv[itr]);
|
||||
|
||||
if (++itr >= argc)
|
||||
missingParameterForSwitch(uSvc, argv[itr - 2]);
|
||||
@ -1754,6 +1814,10 @@ void nbackup(UtilSvc* uSvc)
|
||||
version = true;
|
||||
break;
|
||||
|
||||
case IN_SW_NBK_INPLACE:
|
||||
inc_rest = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(uSvc, isc_nbackup_unknown_switch, argv[itr]);
|
||||
break;
|
||||
@ -1797,11 +1861,11 @@ void nbackup(UtilSvc* uSvc)
|
||||
break;
|
||||
|
||||
case nbBackup:
|
||||
nbk.backup_database(level, filename);
|
||||
nbk.backup_database(level, guid, filename);
|
||||
break;
|
||||
|
||||
case nbRestore:
|
||||
nbk.restore_database(backup_files);
|
||||
nbk.restore_database(backup_files, inc_rest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -48,12 +48,14 @@ const int IN_SW_NBK_HELP = 12;
|
||||
const int IN_SW_NBK_DIRECT = 13;
|
||||
const int IN_SW_NBK_DECOMPRESS = 14;
|
||||
const int IN_SW_NBK_ROLE = 15;
|
||||
const int IN_SW_NBK_INPLACE = 16;
|
||||
|
||||
|
||||
static const struct Switches::in_sw_tab_t nbackup_in_sw_table [] =
|
||||
{
|
||||
{IN_SW_NBK_NODBTRIG, isc_spb_nbk_no_triggers, "T", 0, 0, 0, false, 0, 1, NULL},
|
||||
{IN_SW_NBK_DIRECT, isc_spb_nbk_direct, "DIRECT", 0, 0, 0, false, 0, 1, NULL},
|
||||
{IN_SW_NBK_INPLACE, isc_spb_nbk_inplace, "I", 0, 0, 0, false, 0, 1, NULL},
|
||||
{IN_SW_NBK_0, 0, NULL, 0, 0, 0, false, 0, 0, NULL} // End of List
|
||||
};
|
||||
|
||||
@ -68,6 +70,7 @@ static const struct Switches::in_sw_tab_t nbackup_action_in_sw_table [] =
|
||||
{IN_SW_NBK_BACKUP, isc_action_svc_nbak, "BACKUP", 0, 0, 0, false, 11, 1, NULL, nboExclusive},
|
||||
{IN_SW_NBK_RESTORE, isc_action_svc_nrest, "RESTORE", 0, 0, 0, false, 12, 1, NULL, nboExclusive},
|
||||
{IN_SW_NBK_DIRECT, 0, "DIRECT", 0, 0, 0, false, 70, 1, NULL, nboSpecial},
|
||||
{IN_SW_NBK_INPLACE, 0, "I", 0, 0, 0, false, 78, 1, NULL, nboSpecial},
|
||||
{IN_SW_NBK_SIZE, 0, "SIZE", 0, 0, 0, false, 17, 1, NULL, nboSpecial},
|
||||
{IN_SW_NBK_DECOMPRESS, 0, "DECOMPRESS", 0, 0, 0, false, 74, 2, NULL, nboSpecial},
|
||||
{IN_SW_NBK_NODBTRIG, 0, "T", 0, 0, 0, false, 0, 1, NULL, nboGeneral},
|
||||
|
Loading…
Reference in New Issue
Block a user