You've already forked pgbackrest
							
							
				mirror of
				https://github.com/pgbackrest/pgbackrest.git
				synced 2025-10-30 23:37:45 +02:00 
			
		
		
		
	Restore can now remap base/tablespace locations.
Made Restore more modular.
This commit is contained in:
		| @@ -441,6 +441,7 @@ if (operation_get() eq OP_RESTORE) | |||||||
|     ( |     ( | ||||||
|         config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH), |         config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH), | ||||||
|         undef, |         undef, | ||||||
|  |         param_get(PARAM_REMAP), | ||||||
|         $oFile, |         $oFile, | ||||||
|         4, |         4, | ||||||
|         param_get(PARAM_FORCE) |         param_get(PARAM_FORCE) | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ our @EXPORT = qw(config_load config_key_load operation_get operation_set param_g | |||||||
|  |  | ||||||
|                  BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR |                  BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR | ||||||
|  |  | ||||||
|                  PARAM_CONFIG PARAM_STANZA PARAM_TYPE PARAM_NO_START_STOP PARAM_FORCE PARAM_VERSION PARAM_HELP |                  PARAM_CONFIG PARAM_STANZA PARAM_TYPE PARAM_REMAP PARAM_NO_START_STOP PARAM_FORCE PARAM_VERSION PARAM_HELP | ||||||
|                  PARAM_TEST PARAM_TEST_DELAY PARAM_TEST_NO_FORK |                  PARAM_TEST PARAM_TEST_DELAY PARAM_TEST_NO_FORK | ||||||
|  |  | ||||||
|                  CONFIG_SECTION_COMMAND CONFIG_SECTION_COMMAND_OPTION CONFIG_SECTION_LOG CONFIG_SECTION_BACKUP |                  CONFIG_SECTION_COMMAND CONFIG_SECTION_COMMAND_OPTION CONFIG_SECTION_LOG CONFIG_SECTION_BACKUP | ||||||
| @@ -86,6 +86,7 @@ use constant | |||||||
|     PARAM_STANZA          => 'stanza', |     PARAM_STANZA          => 'stanza', | ||||||
|     PARAM_TYPE            => 'type', |     PARAM_TYPE            => 'type', | ||||||
|     PARAM_NO_START_STOP   => 'no-start-stop', |     PARAM_NO_START_STOP   => 'no-start-stop', | ||||||
|  |     PARAM_REMAP           => 'remap', | ||||||
|     PARAM_FORCE           => 'force', |     PARAM_FORCE           => 'force', | ||||||
|     PARAM_VERSION         => 'version', |     PARAM_VERSION         => 'version', | ||||||
|     PARAM_HELP            => 'help', |     PARAM_HELP            => 'help', | ||||||
| @@ -162,8 +163,8 @@ sub config_load | |||||||
|     param_set(PARAM_TEST_DELAY, 5);        # Seconds to delay after a test point (default is not enough for manual tests) |     param_set(PARAM_TEST_DELAY, 5);        # Seconds to delay after a test point (default is not enough for manual tests) | ||||||
|  |  | ||||||
|     # Get command line parameters |     # Get command line parameters | ||||||
|     GetOptions (\%oParam, PARAM_CONFIG . '=s', PARAM_STANZA . '=s', PARAM_TYPE . '=s', PARAM_NO_START_STOP, PARAM_FORCE, |     GetOptions (\%oParam, PARAM_CONFIG . '=s', PARAM_STANZA . '=s', PARAM_TYPE . '=s', PARAM_REMAP . '=s%', PARAM_NO_START_STOP, | ||||||
|                           PARAM_VERSION, PARAM_HELP, |                           PARAM_FORCE, PARAM_VERSION, PARAM_HELP, | ||||||
|                           PARAM_TEST, PARAM_TEST_DELAY . '=s', PARAM_TEST_NO_FORK) |                           PARAM_TEST, PARAM_TEST_DELAY . '=s', PARAM_TEST_NO_FORK) | ||||||
|         or pod2usage(2); |         or pod2usage(2); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ sub new | |||||||
|     my $class = shift;              # Class name |     my $class = shift;              # Class name | ||||||
|     my $strDbClusterPath = shift;   # Database cluster path |     my $strDbClusterPath = shift;   # Database cluster path | ||||||
|     my $strBackupPath = shift;      # Backup to restore |     my $strBackupPath = shift;      # Backup to restore | ||||||
|  |     my $oRemapRef = shift;          # Tablespace remaps | ||||||
|     my $oFile = shift;              # Default file object |     my $oFile = shift;              # Default file object | ||||||
|     my $iThreadTotal = shift;       # Total threads to run for restore |     my $iThreadTotal = shift;       # Total threads to run for restore | ||||||
|     my $bForce = shift;             # Force the restore even if files are present |     my $bForce = shift;             # Force the restore even if files are present | ||||||
| @@ -39,6 +40,7 @@ sub new | |||||||
|     $self->{oFile} = $oFile; |     $self->{oFile} = $oFile; | ||||||
|     $self->{thread_total} = $iThreadTotal; |     $self->{thread_total} = $iThreadTotal; | ||||||
|     $self->{bForce} = $bForce; |     $self->{bForce} = $bForce; | ||||||
|  |     $self->{oRemapRef} = $oRemapRef; | ||||||
|  |  | ||||||
|     # If backup path is not specified then default to latest |     # If backup path is not specified then default to latest | ||||||
|     if (defined($strBackupPath)) |     if (defined($strBackupPath)) | ||||||
| @@ -54,22 +56,14 @@ sub new | |||||||
| } | } | ||||||
|  |  | ||||||
| #################################################################################################################################### | #################################################################################################################################### | ||||||
| # RESTORE | # MANIFEST_LOAD | ||||||
| # | # | ||||||
| # Takes a backup and restores it back to the original or a remapped location. | # Loads the backup manifest and performs requested tablespace remaps. | ||||||
| #################################################################################################################################### | #################################################################################################################################### | ||||||
| sub restore | sub manifest_load | ||||||
| { | { | ||||||
|     my $self = shift;       # Class hash |     my $self = shift;           # Class hash | ||||||
|  |     my $oManifestRef = shift;   # Backup manifest | ||||||
|     # Make sure that Postgres is not running |  | ||||||
|     if ($self->{oFile}->exists(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_POSTMASTER_PID)) |  | ||||||
|     { |  | ||||||
|         confess &log(ERROR, 'unable to restore while Postgres is running'); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     # Make sure the backup path is valid and load the manifest |  | ||||||
|     my %oManifest; |  | ||||||
|  |  | ||||||
|     if ($self->{oFile}->exists(PATH_BACKUP_CLUSTER, $self->{strBackupPath})) |     if ($self->{oFile}->exists(PATH_BACKUP_CLUSTER, $self->{strBackupPath})) | ||||||
|     { |     { | ||||||
| @@ -78,39 +72,81 @@ sub restore | |||||||
|                              PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST); |                              PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST); | ||||||
|  |  | ||||||
|          # Load the manifest into a hash |          # Load the manifest into a hash | ||||||
|          ini_load($self->{oFile}->path_get(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST), \%oManifest); |          ini_load($self->{oFile}->path_get(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST), $oManifestRef); | ||||||
|  |  | ||||||
|          # Remove the manifest now that it is in memory |          # Remove the manifest now that it is in memory | ||||||
|          $self->{oFile}->remove(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST); |          $self->{oFile}->remove(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_MANIFEST); | ||||||
|  |  | ||||||
|          # Set source compression |          # If tablespaces have been remapped, update the manifest | ||||||
|          if ($oManifest{'backup:option'}{compress} eq 'y') |          if (defined($self->{oRemapRef})) | ||||||
|          { |          { | ||||||
|              $self->{bSourceCompressed} = true; |              foreach my $strPathKey (sort(keys $self->{oRemapRef})) | ||||||
|  |              { | ||||||
|  |                  my $strRemapPath = ${$self->{oRemapRef}}{$strPathKey}; | ||||||
|  |  | ||||||
|  |                  if ($strPathKey eq 'base') | ||||||
|  |                  { | ||||||
|  |                      &log(INFO, "remapping base to ${strRemapPath}"); | ||||||
|  |                      ${$oManifestRef}{'backup:path'}{$strPathKey} = $strRemapPath; | ||||||
|  |                  } | ||||||
|  |                  else | ||||||
|  |                  { | ||||||
|  |                      # If the tablespace beigns with prefix 'tablespace:' then strip the prefix.  This only needs to be used in | ||||||
|  |                      # the case that there is a tablespace called 'base' | ||||||
|  |                      if (index($strPathKey, 'tablespace:') == 0) | ||||||
|  |                      { | ||||||
|  |                          $strPathKey = substr($strPathKey, length('tablespace:')); | ||||||
|  |                      } | ||||||
|  |  | ||||||
|  |                      # Make sure that the tablespace exists in the manifest | ||||||
|  |                      if (!defined(${$oManifestRef}{'backup:tablespace'}{$strPathKey})) | ||||||
|  |                      { | ||||||
|  |                          confess &log(ERROR, "cannot remap invalid tablespace ${strPathKey} to ${strRemapPath}"); | ||||||
|  |                      } | ||||||
|  |  | ||||||
|  |                      # Remap the tablespace in the manifest | ||||||
|  |                      &log(INFO, "remapping tablespace to ${strRemapPath}"); | ||||||
|  |  | ||||||
|  |                      my $strTablespaceLink = ${$oManifestRef}{'backup:tablespace'}{$strPathKey}{link}; | ||||||
|  |  | ||||||
|  |                      ${$oManifestRef}{'backup:path'}{"tablespace:${strPathKey}"} = $strRemapPath; | ||||||
|  |                      ${$oManifestRef}{'backup:tablespace'}{$strPathKey}{path} = $strRemapPath; | ||||||
|  |                      ${$oManifestRef}{'base:link'}{"pg_tblspc/${strTablespaceLink}"}{link_destination} = $strRemapPath; | ||||||
|  |                  } | ||||||
|  |              } | ||||||
|          } |          } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         confess &log(ERROR, 'backup ' . $self->{strBackupPath} . ' does not exist'); |         confess &log(ERROR, 'backup ' . $self->{strBackupPath} . ' does not exist'); | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|     # Declare thread queues that will be used to process files | #################################################################################################################################### | ||||||
|     my @oyRestoreQueue; | # CLEAN | ||||||
|  | # | ||||||
|  | # Checks that the restore paths are empty, or if --force was used then it cleans files/paths/links from the restore directories that | ||||||
|  | # are not present in the manifest. | ||||||
|  | #################################################################################################################################### | ||||||
|  | sub clean | ||||||
|  | { | ||||||
|  |     my $self = shift;               # Class hash | ||||||
|  |     my $oManifestRef = shift;       # Backup manifest | ||||||
|  |  | ||||||
|     # Check each restore directory in the manifest and make sure that it exists and is empty. |     # Check each restore directory in the manifest and make sure that it exists and is empty. | ||||||
|     # The --force option can be used to override the empty requirement. |     # The --force option can be used to override the empty requirement. | ||||||
|     foreach my $strPathKey (sort(keys $oManifest{'backup:path'})) |     foreach my $strPathKey (sort(keys ${$oManifestRef}{'backup:path'})) | ||||||
|     { |     { | ||||||
|         my $strPath = $oManifest{'backup:path'}{$strPathKey}; |         my $strPath = ${$oManifestRef}{'backup:path'}{$strPathKey}; | ||||||
|  |  | ||||||
|         &log(INFO, "processing db path ${strPath}"); |         &log(INFO, "checking/cleaning db path ${strPath}"); | ||||||
|  |  | ||||||
|         if (!$self->{oFile}->exists(PATH_DB_ABSOLUTE,  $strPath)) |         if (!$self->{oFile}->exists(PATH_DB_ABSOLUTE,  $strPath)) | ||||||
|         { |         { | ||||||
|             confess &log(ERROR, "required db path '${strPath}' does not exist"); |             confess &log(ERROR, "required db path '${strPath}' does not exist"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         # Load path manifest so it can be compared to delete files/paths/links that are not in the backup |         # Load path manifest so it can be compared to deleted files/paths/links that are not in the backup | ||||||
|         my %oPathManifest; |         my %oPathManifest; | ||||||
|         $self->{oFile}->manifest(PATH_DB_ABSOLUTE, $strPath, \%oPathManifest); |         $self->{oFile}->manifest(PATH_DB_ABSOLUTE, $strPath, \%oPathManifest); | ||||||
|  |  | ||||||
| @@ -143,9 +179,9 @@ sub restore | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             # Check to see if the file/path/link exists in the manifest |             # Check to see if the file/path/link exists in the manifest | ||||||
|             if (defined($oManifest{"${strPathKey}:${strType}"}{$strName})) |             if (defined(${$oManifestRef}{"${strPathKey}:${strType}"}{$strName})) | ||||||
|             { |             { | ||||||
|                 my $strMode = $oManifest{"${strPathKey}:${strType}"}{$strName}{permission}; |                 my $strMode = ${$oManifestRef}{"${strPathKey}:${strType}"}{$strName}{permission}; | ||||||
|  |  | ||||||
|                 # If file/path mode does not match, fix it |                 # If file/path mode does not match, fix it | ||||||
|                 if ($strType ne 'link' && $strMode ne $oPathManifest{name}{$strName}{permission}) |                 if ($strType ne 'link' && $strMode ne $oPathManifest{name}{$strName}{permission}) | ||||||
| @@ -156,8 +192,8 @@ sub restore | |||||||
|                         or confess 'unable to set mode ${strMode} for ${strFile}'; |                         or confess 'unable to set mode ${strMode} for ${strFile}'; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 my $strUser = $oManifest{"${strPathKey}:${strType}"}{$strName}{user}; |                 my $strUser = ${$oManifestRef}{"${strPathKey}:${strType}"}{$strName}{user}; | ||||||
|                 my $strGroup = $oManifest{"${strPathKey}:${strType}"}{$strName}{group}; |                 my $strGroup = ${$oManifestRef}{"${strPathKey}:${strType}"}{$strName}{group}; | ||||||
|  |  | ||||||
|                 # If ownership does not match, fix it |                 # If ownership does not match, fix it | ||||||
|                 if ($strUser ne $oPathManifest{name}{$strName}{user} || |                 if ($strUser ne $oPathManifest{name}{$strName}{user} || | ||||||
| @@ -169,7 +205,7 @@ sub restore | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 # If a link does not have the same destination, then delete it (it will be recreated later) |                 # If a link does not have the same destination, then delete it (it will be recreated later) | ||||||
|                 if ($strType eq 'link' && $oManifest{"${strPathKey}:${strType}"}{$strName}{link_destination} ne |                 if ($strType eq 'link' && ${$oManifestRef}{"${strPathKey}:${strType}"}{$strName}{link_destination} ne | ||||||
|                     $oPathManifest{name}{$strName}{link_destination}) |                     $oPathManifest{name}{$strName}{link_destination}) | ||||||
|                 { |                 { | ||||||
|                     &log(DEBUG, "removing link ${strFile} - destination changed"); |                     &log(DEBUG, "removing link ${strFile} - destination changed"); | ||||||
| @@ -193,9 +229,26 @@ sub restore | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #################################################################################################################################### | ||||||
|  | # BUILD | ||||||
|  | # | ||||||
|  | # Creates missing paths and links and corrects ownership/mode on existing paths and links. | ||||||
|  | #################################################################################################################################### | ||||||
|  | sub build | ||||||
|  | { | ||||||
|  |     my $self = shift;               # Class hash | ||||||
|  |     my $oManifestRef = shift;       # Backup manifest | ||||||
|  |  | ||||||
|  |     # Build paths/links in each restore path | ||||||
|  |     foreach my $strPathKey (sort(keys ${$oManifestRef}{'backup:path'})) | ||||||
|  |     { | ||||||
|  |         my $strPath = ${$oManifestRef}{'backup:path'}{$strPathKey}; | ||||||
|  |  | ||||||
|         # Create all paths in the manifest that do not already exist |         # Create all paths in the manifest that do not already exist | ||||||
|         foreach my $strName (sort (keys $oManifest{"${strPathKey}:path"})) |         foreach my $strName (sort (keys ${$oManifestRef}{"${strPathKey}:path"})) | ||||||
|         { |         { | ||||||
|             # Skip the root path |             # Skip the root path | ||||||
|             if ($strName eq '.') |             if ($strName eq '.') | ||||||
| @@ -205,23 +258,55 @@ sub restore | |||||||
|  |  | ||||||
|             # Create the Path |             # Create the Path | ||||||
|             $self->{oFile}->path_create(PATH_DB_ABSOLUTE, "${strPath}/${strName}", |             $self->{oFile}->path_create(PATH_DB_ABSOLUTE, "${strPath}/${strName}", | ||||||
|                                         $oManifest{"${strPathKey}:path"}{$strName}{permission}); |                                         ${$oManifestRef}{"${strPathKey}:path"}{$strName}{permission}); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         # Create all links in the manifest that do not already exist |         # Create all links in the manifest that do not already exist | ||||||
|         if (defined($oManifest{"${strPathKey}:link"})) |         if (defined(${$oManifestRef}{"${strPathKey}:link"})) | ||||||
|         { |         { | ||||||
|             foreach my $strName (sort (keys $oManifest{"${strPathKey}:link"})) |             foreach my $strName (sort (keys ${$oManifestRef}{"${strPathKey}:link"})) | ||||||
|             { |             { | ||||||
|                 if (!$self->{oFile}->exists(PATH_DB_ABSOLUTE, "${strPath}/${strName}")) |                 if (!$self->{oFile}->exists(PATH_DB_ABSOLUTE, "${strPath}/${strName}")) | ||||||
|                 { |                 { | ||||||
|                     $self->{oFile}->link_create(PATH_DB_ABSOLUTE, $oManifest{"${strPathKey}:link"}{$strName}{link_destination}, |                     $self->{oFile}->link_create(PATH_DB_ABSOLUTE, | ||||||
|  |                                                 ${$oManifestRef}{"${strPathKey}:link"}{$strName}{link_destination}, | ||||||
|                                                 PATH_DB_ABSOLUTE, "${strPath}/${strName}"); |                                                 PATH_DB_ABSOLUTE, "${strPath}/${strName}"); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|         # Assign the files in each path to a thread queue | #################################################################################################################################### | ||||||
|  | # RESTORE | ||||||
|  | # | ||||||
|  | # Takes a backup and restores it back to the original or a remapped location. | ||||||
|  | #################################################################################################################################### | ||||||
|  | sub restore | ||||||
|  | { | ||||||
|  |     my $self = shift;       # Class hash | ||||||
|  |  | ||||||
|  |     # Make sure that Postgres is not running | ||||||
|  |     if ($self->{oFile}->exists(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/' . FILE_POSTMASTER_PID)) | ||||||
|  |     { | ||||||
|  |         confess &log(ERROR, 'unable to restore while Postgres is running'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     # Make sure the backup path is valid and load the manifest | ||||||
|  |     my %oManifest; | ||||||
|  |     $self->manifest_load(\%oManifest); | ||||||
|  |  | ||||||
|  |     # Clean the restore paths | ||||||
|  |     $self->clean(\%oManifest); | ||||||
|  |  | ||||||
|  |     # Build paths/links in the restore paths | ||||||
|  |     $self->build(\%oManifest); | ||||||
|  |  | ||||||
|  |     # Assign the files in each path to a thread queue | ||||||
|  |     my @oyRestoreQueue; | ||||||
|  |  | ||||||
|  |     foreach my $strPathKey (sort(keys $oManifest{'backup:path'})) | ||||||
|  |     { | ||||||
|         if (defined($oManifest{"${strPathKey}:file"})) |         if (defined($oManifest{"${strPathKey}:file"})) | ||||||
|         { |         { | ||||||
|             $oyRestoreQueue[@oyRestoreQueue] = Thread::Queue->new(); |             $oyRestoreQueue[@oyRestoreQueue] = Thread::Queue->new(); | ||||||
| @@ -255,27 +340,30 @@ sub restore_thread | |||||||
| { | { | ||||||
|     my $self = shift;               # Class hash |     my $self = shift;               # Class hash | ||||||
|     my $iThreadIdx = shift;         # Defines the index of this thread |     my $iThreadIdx = shift;         # Defines the index of this thread | ||||||
|     my @oyRestoreQueue = @{+shift}; # Restore queues |     my $oyRestoreQueueRef = shift;  # Restore queues | ||||||
|     my %oManifest = %{+shift};      # Backup manifest |     my $oManifestRef = shift;       # Backup manifest | ||||||
|  |  | ||||||
|     my $iDirection = $iThreadIdx % 2 == 0 ? 1 : -1;         # Size of files currently copied by this thread |     my $iDirection = $iThreadIdx % 2 == 0 ? 1 : -1;         # Size of files currently copied by this thread | ||||||
|     my $oFileThread = $self->{oFile}->clone($iThreadIdx);   # Thread local file object |     my $oFileThread = $self->{oFile}->clone($iThreadIdx);   # Thread local file object | ||||||
|  |  | ||||||
|     # Initialize the starting and current queue index based in the total number of threads in relation to this thread |     # Initialize the starting and current queue index based in the total number of threads in relation to this thread | ||||||
|     my $iQueueStartIdx = int((@oyRestoreQueue / $self->{thread_total}) * $iThreadIdx); |     my $iQueueStartIdx = int((@{$oyRestoreQueueRef} / $self->{thread_total}) * $iThreadIdx); | ||||||
|     my $iQueueIdx = $iQueueStartIdx; |     my $iQueueIdx = $iQueueStartIdx; | ||||||
|  |  | ||||||
|  |     # Set source compression | ||||||
|  |     my $bSourceCompression = ${$oManifestRef}{'backup:option'}{compress} eq 'y'; | ||||||
|  |  | ||||||
|     # When a KILL signal is received, immediately abort |     # When a KILL signal is received, immediately abort | ||||||
|     $SIG{'KILL'} = sub {threads->exit();}; |     $SIG{'KILL'} = sub {threads->exit();}; | ||||||
|  |  | ||||||
|     # Loop through all the queues to restore files (exit when the original queue is reached |     # Loop through all the queues to restore files (exit when the original queue is reached | ||||||
|     do |     do | ||||||
|     { |     { | ||||||
|         while (my $strMessage = $oyRestoreQueue[$iQueueIdx]->dequeue()) |         while (my $strMessage = ${$oyRestoreQueueRef}[$iQueueIdx]->dequeue()) | ||||||
|         { |         { | ||||||
|             my $strSourcePath = (split(/\|/, $strMessage))[0];                  # Source path from backup |             my $strSourcePath = (split(/\|/, $strMessage))[0];                  # Source path from backup | ||||||
|             my $strSection = "${strSourcePath}:file";                           # Backup section with file info |             my $strSection = "${strSourcePath}:file";                           # Backup section with file info | ||||||
|             my $strDestinationPath = $oManifest{'backup:path'}{$strSourcePath}; # Destination path stored in manifest |             my $strDestinationPath = ${$oManifestRef}{'backup:path'}{$strSourcePath}; # Destination path stored in manifest | ||||||
|             $strSourcePath =~ s/\:/\//g;                                        # Replace : with / in source path |             $strSourcePath =~ s/\:/\//g;                                        # Replace : with / in source path | ||||||
|             my $strName = (split(/\|/, $strMessage))[1];                        # Name of file to be restored |             my $strName = (split(/\|/, $strMessage))[1];                        # Name of file to be restored | ||||||
|  |  | ||||||
| @@ -283,7 +371,7 @@ sub restore_thread | |||||||
|             my $strDestinationFile = $oFileThread->path_get(PATH_DB_ABSOLUTE, "${strDestinationPath}/${strName}"); |             my $strDestinationFile = $oFileThread->path_get(PATH_DB_ABSOLUTE, "${strDestinationPath}/${strName}"); | ||||||
|  |  | ||||||
|             # If checksum is set the destination file already exists, try a checksum before copying |             # If checksum is set the destination file already exists, try a checksum before copying | ||||||
|             my $strChecksum = $oManifest{$strSection}{$strName}{checksum}; |             my $strChecksum = ${$oManifestRef}{$strSection}{$strName}{checksum}; | ||||||
|  |  | ||||||
|             if ($oFileThread->exists(PATH_DB_ABSOLUTE, $strDestinationFile)) |             if ($oFileThread->exists(PATH_DB_ABSOLUTE, $strDestinationFile)) | ||||||
|             { |             { | ||||||
| @@ -298,12 +386,12 @@ sub restore_thread | |||||||
|  |  | ||||||
|             # Copy the file from the backup to the database |             # Copy the file from the backup to the database | ||||||
|             $oFileThread->copy(PATH_BACKUP_CLUSTER, $self->{strBackupPath} . "/${strSourcePath}/${strName}" . |             $oFileThread->copy(PATH_BACKUP_CLUSTER, $self->{strBackupPath} . "/${strSourcePath}/${strName}" . | ||||||
|                                ($self->{bSourceCompressed} ? '.' . $oFileThread->{strCompressExtension} : ''), |                                ($bSourceCompression ? '.' . $oFileThread->{strCompressExtension} : ''), | ||||||
|                                PATH_DB_ABSOLUTE, $strDestinationFile, |                                PATH_DB_ABSOLUTE, $strDestinationFile, | ||||||
|                                $self->{bSourceCompressed},   # Source is compressed based on backup settings |                                $bSourceCompression,   # Source is compressed based on backup settings | ||||||
|                                undef, undef, |                                undef, undef, | ||||||
|                                $oManifest{$strSection}{$strName}{modification_time}, |                                ${$oManifestRef}{$strSection}{$strName}{modification_time}, | ||||||
|                                $oManifest{$strSection}{$strName}{permission}); |                                ${$oManifestRef}{$strSection}{$strName}{permission}); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         # Even number threads move up when they have finished a queue, odd numbered threads move down |         # Even number threads move up when they have finished a queue, odd numbered threads move down | ||||||
| @@ -312,9 +400,9 @@ sub restore_thread | |||||||
|         # Reset the queue index when it goes over or under the number of queues |         # Reset the queue index when it goes over or under the number of queues | ||||||
|         if ($iQueueIdx < 0) |         if ($iQueueIdx < 0) | ||||||
|         { |         { | ||||||
|             $iQueueIdx = @oyRestoreQueue - 1; |             $iQueueIdx = @{$oyRestoreQueueRef} - 1; | ||||||
|         } |         } | ||||||
|         elsif ($iQueueIdx >= @oyRestoreQueue) |         elsif ($iQueueIdx >= @{$oyRestoreQueueRef}) | ||||||
|         { |         { | ||||||
|             $iQueueIdx = 0; |             $iQueueIdx = 0; | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user