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

Fixed CORE-1124.

This commit is contained in:
dimitr 2007-02-09 08:11:35 +00:00
parent 19df9afe07
commit 367a315eec

View File

@ -185,7 +185,7 @@ private:
ISC_STATUS_ARRAY status; /* status vector */ ISC_STATUS_ARRAY status; /* status vector */
isc_db_handle newdb; /* database handle */ isc_db_handle newdb; /* database handle */
isc_tr_handle trans; /* transaction handle */ isc_tr_handle trans; /* transaction handle */
Firebird::PathName database; Firebird::PathName database;
Firebird::string username; Firebird::string username;
Firebird::string password; Firebird::string password;
@ -194,25 +194,25 @@ private:
Firebird::PathName bakname; Firebird::PathName bakname;
FILE_HANDLE dbase; FILE_HANDLE dbase;
FILE_HANDLE backup; FILE_HANDLE backup;
// IO functions // IO functions
size_t read_file(FILE_HANDLE &file, void *buffer, size_t bufsize); size_t read_file(FILE_HANDLE &file, void *buffer, size_t bufsize);
void write_file(FILE_HANDLE &file, void *buffer, size_t bufsize); void write_file(FILE_HANDLE &file, void *buffer, size_t bufsize);
void seek_file(FILE_HANDLE &file, SINT64 pos); void seek_file(FILE_HANDLE &file, SINT64 pos);
static void pr_error(const ISC_STATUS* status, const char* operation); static void pr_error(const ISC_STATUS* status, const char* operation);
void internal_lock_database(); void internal_lock_database();
void internal_unlock_database(); void internal_unlock_database();
void attach_database(); void attach_database();
void detach_database(); void detach_database();
// Create/open database and backup // Create/open database and backup
void open_database_write(); void open_database_write();
void open_database_scan(); void open_database_scan();
void create_database(); void create_database();
void close_database(); void close_database();
void open_backup_scan(); void open_backup_scan();
void create_backup(); void create_backup();
void close_backup(); void close_backup();
@ -433,7 +433,7 @@ void nbackup::attach_database()
b_error::raise("Username or password is too long"); b_error::raise("Username or password is too long");
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1); Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
if (!username.isEmpty()) { if (!username.isEmpty()) {
dpb.insertString(isc_dpb_user_name, username); dpb.insertString(isc_dpb_user_name, username);
} }
@ -525,7 +525,7 @@ void nbackup::backup_database(int level, const char* fname)
XSQLDA *out_sqlda = (XSQLDA*)out_sqlda_data; XSQLDA *out_sqlda = (XSQLDA*)out_sqlda_data;
out_sqlda->version = SQLDA_VERSION1; out_sqlda->version = SQLDA_VERSION1;
out_sqlda->sqln = 2; out_sqlda->sqln = 2;
isc_stmt_handle stmt = 0; isc_stmt_handle stmt = 0;
if (isc_dsql_allocate_statement(status, &newdb, &stmt)) if (isc_dsql_allocate_statement(status, &newdb, &stmt))
pr_error(status, "allocate statement"); pr_error(status, "allocate statement");
@ -545,7 +545,7 @@ void nbackup::backup_database(int level, const char* fname)
out_sqlda->sqlvar[1].sqldata = (char*)&prev_scn; out_sqlda->sqlvar[1].sqldata = (char*)&prev_scn;
if (isc_dsql_execute(status, &trans, &stmt, 1, NULL)) if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
pr_error(status, "execute history query"); pr_error(status, "execute history query");
switch (isc_dsql_fetch(status, &stmt, 1, out_sqlda)) { switch (isc_dsql_fetch(status, &stmt, 1, out_sqlda)) {
case 100: /* No more records available */ case 100: /* No more records available */
b_error::raise("Cannot find record for database \"%s\" backup level %d " b_error::raise("Cannot find record for database \"%s\" backup level %d "
@ -562,14 +562,14 @@ void nbackup::backup_database(int level, const char* fname)
if (isc_commit_transaction(status, &trans)) if (isc_commit_transaction(status, &trans))
pr_error(status, "commit history query"); pr_error(status, "commit history query");
} }
// Lock database for backup // Lock database for backup
internal_lock_database(); internal_lock_database();
database_locked = true; database_locked = true;
time_t _time = time(NULL); time_t _time = time(NULL);
const struct tm *today = localtime(&_time); const struct tm *today = localtime(&_time);
if (fname) if (fname)
bakname = fname; bakname = fname;
else { else {
@ -589,20 +589,20 @@ void nbackup::backup_database(int level, const char* fname)
// used directly after fixup. Incremenal backups of other levels are // used directly after fixup. Incremenal backups of other levels are
// consisted of header followed by page data. Each page is preceded // consisted of header followed by page data. Each page is preceded
// by 4-byte integer page number // by 4-byte integer page number
// Actual IO is optimized to get maximum performance // Actual IO is optimized to get maximum performance
// from the IO subsystem while taking as little CPU time as possible // from the IO subsystem while taking as little CPU time as possible
// NOTE: this is still possible to improve performance by implementing // NOTE: this is still possible to improve performance by implementing
// version using asynchronous unbuffered IO on NT series of OS. // version using asynchronous unbuffered IO on NT series of OS.
// But this task is for another day. 02 Aug 2003, Nickolay Samofatov. // But this task is for another day. 02 Aug 2003, Nickolay Samofatov.
// Create backup file and open database file // Create backup file and open database file
create_backup(); create_backup();
delete_backup = true; delete_backup = true;
open_database_scan(); open_database_scan();
// Read database header // Read database header
char unaligned_header_buffer[SECTOR_ALIGNMENT * 2]; char unaligned_header_buffer[SECTOR_ALIGNMENT * 2];
@ -616,7 +616,7 @@ void nbackup::backup_database(int level, const char* fname)
b_error::raise("Internal error. Database file is not locked. Flags are %d", b_error::raise("Internal error. Database file is not locked. Flags are %d",
header->hdr_flags); header->hdr_flags);
} }
Firebird::Array<UCHAR> unaligned_page_buffer; Firebird::Array<UCHAR> unaligned_page_buffer;
page_buff = reinterpret_cast<Ods::pag*>( page_buff = reinterpret_cast<Ods::pag*>(
FB_ALIGN( FB_ALIGN(
@ -625,12 +625,12 @@ void nbackup::backup_database(int level, const char* fname)
SECTOR_ALIGNMENT SECTOR_ALIGNMENT
) )
); );
seek_file(dbase, 0); seek_file(dbase, 0);
if (read_file(dbase, page_buff, header->hdr_page_size) != header->hdr_page_size) if (read_file(dbase, page_buff, header->hdr_page_size) != header->hdr_page_size)
b_error::raise("Unexpected end of file when reading header of database file (stage 2)"); b_error::raise("Unexpected end of file when reading header of database file (stage 2)");
FB_GUID backup_guid; FB_GUID backup_guid;
bool guid_found = false; bool guid_found = false;
const UCHAR* p = reinterpret_cast<Ods::header_page*>(page_buff)->hdr_data; const UCHAR* p = reinterpret_cast<Ods::header_page*>(page_buff)->hdr_data;
@ -648,11 +648,10 @@ void nbackup::backup_database(int level, const char* fname)
} }
break; break;
} }
if (!guid_found) if (!guid_found)
b_error::raise("Internal error. Cannot get backup guid clumplet"); b_error::raise("Internal error. Cannot get backup guid clumplet");
// Write data to backup file // Write data to backup file
ULONG backup_scn = header->hdr_header.pag_scn - 1; ULONG backup_scn = header->hdr_header.pag_scn - 1;
if (level) { if (level) {
@ -667,7 +666,7 @@ void nbackup::backup_database(int level, const char* fname)
bh.prev_scn = prev_scn; bh.prev_scn = prev_scn;
write_file(backup, &bh, sizeof(bh)); write_file(backup, &bh, sizeof(bh));
} }
ULONG curPage = 0; ULONG curPage = 0;
while (true) { while (true) {
if (curPage && page_buff->pag_scn > backup_scn) if (curPage && page_buff->pag_scn > backup_scn)
@ -691,9 +690,9 @@ void nbackup::backup_database(int level, const char* fname)
} }
close_database(); close_database();
close_backup(); close_backup();
delete_backup = false; // Backup file is consistent. No need to delete it delete_backup = false; // Backup file is consistent. No need to delete it
// Write about successful backup to backup history table // Write about successful backup to backup history table
if (isc_start_transaction(status, &trans, 1, &newdb, 0, NULL)) if (isc_start_transaction(status, &trans, 1, &newdb, 0, NULL))
pr_error(status, "start transaction"); pr_error(status, "start transaction");
@ -736,7 +735,7 @@ void nbackup::backup_database(int level, const char* fname)
pr_error(status, "execute history insert"); pr_error(status, "execute history insert");
if (isc_commit_transaction(status, &trans)) if (isc_commit_transaction(status, &trans))
pr_error(status, "commit history insert"); pr_error(status, "commit history insert");
} }
catch (const Firebird::Exception&) { catch (const Firebird::Exception&) {
if (delete_backup) if (delete_backup)
@ -786,16 +785,15 @@ void nbackup::restore_database(int filecount, const char* const* files)
return; return;
} }
try { try {
open_backup_scan(); #ifdef WIN_NT
if (curLevel)
#endif
open_backup_scan();
break; break;
} }
catch (const Firebird::Exception& e) { catch (const Firebird::Exception& e) {
printf("%s\n", e.what()); printf("%s\n", e.what());
} }
#ifdef WIN_NT
if (curLevel)
close_backup();
#endif
} }
} }
else { else {
@ -813,7 +811,7 @@ void nbackup::restore_database(int filecount, const char* const* files)
open_backup_scan(); open_backup_scan();
} }
} }
if (curLevel) { if (curLevel) {
inc_header bakheader; inc_header bakheader;
if (read_file(backup, &bakheader, sizeof(bakheader)) != sizeof(bakheader)) if (read_file(backup, &bakheader, sizeof(bakheader)) != sizeof(bakheader))
@ -873,12 +871,12 @@ void nbackup::restore_database(int filecount, const char* const* files)
if (read_file(dbase, &header, sizeof(header)) != sizeof(header)) if (read_file(dbase, &header, sizeof(header)) != sizeof(header))
b_error::raise("Unexpected end of file when reading restored database header"); b_error::raise("Unexpected end of file when reading restored database header");
page_buffer = FB_NEW(*getDefaultMemoryPool()) UCHAR[header.hdr_page_size]; page_buffer = FB_NEW(*getDefaultMemoryPool()) UCHAR[header.hdr_page_size];
seek_file(dbase, 0); seek_file(dbase, 0);
if (read_file(dbase, page_buffer, header.hdr_page_size) != header.hdr_page_size) if (read_file(dbase, page_buffer, header.hdr_page_size) != header.hdr_page_size)
b_error::raise("Unexpected end of file when reading header of restored database file (stage 2)"); b_error::raise("Unexpected end of file when reading header of restored database file (stage 2)");
bool guid_found = false; bool guid_found = false;
const UCHAR* p = reinterpret_cast<Ods::header_page*>(page_buffer)->hdr_data; const UCHAR* p = reinterpret_cast<Ods::header_page*>(page_buffer)->hdr_data;
while (true) { while (true) {
@ -900,7 +898,10 @@ void nbackup::restore_database(int filecount, const char* const* files)
// We are likely to have normal database here // We are likely to have normal database here
delete_database = false; delete_database = false;
} }
close_backup(); #ifdef WIN_NT
if (curLevel)
#endif
close_backup();
curLevel++; curLevel++;
} }
} }
@ -928,7 +929,7 @@ int main( int argc, char *argv[] )
const char* const* backup_files = NULL; const char* const* backup_files = NULL;
int level; int level;
int filecount; int filecount;
try { try {
// Read global command line parameters // Read global command line parameters
for (char** argp = argv + 1; argp < end; argp++) { for (char** argp = argv + 1; argp < end; argp++) {
@ -1028,7 +1029,7 @@ int main( int argc, char *argv[] )
break; break;
} }
} }
switch (op) { switch (op) {
case nbNone: case nbNone:
usage(); usage();
@ -1059,7 +1060,6 @@ int main( int argc, char *argv[] )
// It must have been printed out. No need to repeat the task // It must have been printed out. No need to repeat the task
return EXIT_ERROR; return EXIT_ERROR;
} }
return EXIT_OK; return EXIT_OK;
} }