8
0
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:
hvlad 2016-03-22 10:35:55 +02:00
parent 08746df97e
commit fa0bae17e2
16 changed files with 167 additions and 67 deletions

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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 *

View File

@ -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},

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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;

View 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

View File

@ -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)

View File

@ -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)

View File

@ -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}
};

View File

@ -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;
}
}

View File

@ -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},