diff --git a/src/storage/file_io.c b/src/storage/file_io.c index dbeb9eb734..873c49e8bc 100644 --- a/src/storage/file_io.c +++ b/src/storage/file_io.c @@ -10196,7 +10196,8 @@ fileio_decompress_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION int fileio_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION * session_p, char *to_vol_label_p, char *verbose_to_vol_label_p, char *prev_vol_label_p, FILEIO_RESTORE_PAGE_BITMAP * page_bitmap, - bool is_remember_pages) + bool is_remember_pages, bool & is_prev_vol_header_restored, + FILEIO_UNLINKED_VOLINFO_MAP & unlinked_volinfo) { int next_page_id = 0; INT64 total_nbytes = 0; @@ -10382,7 +10383,7 @@ fileio_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION * session_ goto error; } - if (volid != LOG_DBFIRST_VOLID) + if (volid != LOG_DBFIRST_VOLID && is_prev_vol_header_restored) { VOLID prev_volid; int prev_vdes; @@ -10403,7 +10404,42 @@ fileio_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION * session_ } fileio_dismount (thread_p, prev_vdes); + + if (unlinked_volinfo.count (volid)) + { + // The volume headers of both previous and current volumes are in the full or big incremental backup volumes. + // Therefore, the link between the two volumes is naturally established during the restoration process. + // So, there is no need to explicitly set it. + unlinked_volinfo.erase (volid); + + _er_log_debug (ARG_FILE_LINE, "RESTOREDB: [UNSAVE UNLINK] [lv%d] volid=%d, vol=%s, prev_vol=%s\n", + session_p->dbfile.level, volid, to_vol_label_p, prev_vol_label_p); + } } + + if (incremental_includes_volume_header == true) + { + if (volid != LOG_DBFIRST_VOLID && is_prev_vol_header_restored == false) + { + _er_log_debug (ARG_FILE_LINE, "RESTOREDB: [FOUND UNLINK] [lv%d] volid=%d, vol=%s, prev_vol=%s\n", + session_p->dbfile.level, volid, to_vol_label_p, prev_vol_label_p); + + if (!unlinked_volinfo.count (volid)) + { + unlinked_volinfo[volid] = + std::make_pair (std::string (to_vol_label_p), std::string (prev_vol_label_p)); + + _er_log_debug (ARG_FILE_LINE, "RESTOREDB: [SAVE UNLINK] [lv%d] volid=%d, vol=%s, prev_vol=%s\n", + session_p->dbfile.level, volid, to_vol_label_p, prev_vol_label_p); + } + } + } + + is_prev_vol_header_restored = true; + } + else + { + is_prev_vol_header_restored = false; } /* save current volname */ diff --git a/src/storage/file_io.h b/src/storage/file_io.h index 9856fe5fec..4ba731e326 100644 --- a/src/storage/file_io.h +++ b/src/storage/file_io.h @@ -42,6 +42,7 @@ #include #include +#include #define NULL_VOLDES (-1) /* Value of a null (invalid) vol descriptor */ @@ -451,6 +452,10 @@ struct flush_stats unsigned int num_tokens; }; +// *INDENT-OFF* +using FILEIO_UNLINKED_VOLINFO_MAP = std::map >; +// *INDENT-ON* + extern int fileio_open (const char *vlabel, int flags, int mode); extern void fileio_close (int vdes); extern int fileio_format (THREAD_ENTRY * thread_p, const char *db_fullname, const char *vlabel, VOLID volid, @@ -569,7 +574,8 @@ extern int fileio_get_next_restore_file (THREAD_ENTRY * thread_p, FILEIO_BACKUP_ VOLID * volid); extern int fileio_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION * session, char *to_vlabel, char *verbose_to_vlabel, char *prev_vlabel, FILEIO_RESTORE_PAGE_BITMAP * page_bitmap, - bool remember_pages); + bool remember_pages, bool & is_prev_vheader_restored, + FILEIO_UNLINKED_VOLINFO_MAP & unlinked_vol_info); extern int fileio_skip_restore_volume (THREAD_ENTRY * thread_p, FILEIO_BACKUP_SESSION * session); extern const char *fileio_get_zip_method_string (FILEIO_ZIP_METHOD zip_method); extern const char *fileio_get_zip_level_string (FILEIO_ZIP_LEVEL zip_level); diff --git a/src/transaction/log_page_buffer.c b/src/transaction/log_page_buffer.c index 9819e8ea7c..50212e7d55 100644 --- a/src/transaction/log_page_buffer.c +++ b/src/transaction/log_page_buffer.c @@ -8064,6 +8064,9 @@ logpb_restore (THREAD_ENTRY * thread_p, const char *db_fullname, const char *log REL_COMPATIBILITY compat; int dummy; + bool is_prev_volheader_restored = false; + FILEIO_UNLINKED_VOLINFO_MAP unlinked_volinfo; + try_level = (FILEIO_BACKUP_LEVEL) r_args->level; start_level = try_level; @@ -8301,6 +8304,8 @@ logpb_restore (THREAD_ENTRY * thread_p, const char *db_fullname, const char *log case LOG_DBVOLINFO_VOLID: case LOG_DBLOG_ARCHIVE_VOLID: + is_prev_volheader_restored = false; + /* We can only take the most recent information, and we do not want to overwrite it with out of data * information from earlier backups. This is because we are applying the restoration in reverse time * order. */ @@ -8354,7 +8359,7 @@ logpb_restore (THREAD_ENTRY * thread_p, const char *db_fullname, const char *log success = fileio_restore_volume (thread_p, session, volume_name_p, verbose_to_volname, prev_volname, page_bitmap, - remember_pages); + remember_pages, is_prev_volheader_restored, unlinked_volinfo); if (success != NO_ERROR) { @@ -8439,6 +8444,39 @@ logpb_restore (THREAD_ENTRY * thread_p, const char *db_fullname, const char *log try_level = (FILEIO_BACKUP_LEVEL) (try_level - 1); } + // Incremental backup volumes often do not include volume header pages. + // Accordingly, it is necessary to set unlinked volumes after all volume header pages are restored. + // *INDENT-OFF* + for (const auto &unlinked_itr : unlinked_volinfo) + { + VOLID prev_volid, volid; + int prev_vdes; + const char *prev_volname, *volname; + + volid = unlinked_itr.first; + volname = unlinked_itr.second.first.c_str(); + prev_volname = unlinked_itr.second.second.c_str(); + + prev_volid = fileio_find_previous_perm_volume (thread_p, volid); + prev_vdes = fileio_mount (thread_p, NULL, prev_volname, prev_volid, false, false); + if (prev_vdes == NULL_VOLDES) + { + goto error; + } + + if (disk_set_link (thread_p, prev_volid, volid, volname, false, DISK_FLUSH_AND_INVALIDATE) != NO_ERROR) + { + fileio_dismount (thread_p, prev_vdes); + goto error; + } + + fileio_dismount (thread_p, prev_vdes); + + _er_log_debug (ARG_FILE_LINE, "RESTOREDB: [FIXED UNLINK] volid=%d, vol=%s, prev_vol=%s", volid, volname, + prev_volname); + } + // *INDENT-ON* + /* make bkvinf file */ nopath_name = fileio_get_base_file_name (db_fullname); fileio_make_backup_volume_info_name (from_volbackup, logpath, nopath_name);