1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-15 01:04:37 +02:00

More work on restore ownership code.

This commit is contained in:
David Steele
2014-12-30 15:41:43 -05:00
parent 46ba3a18df
commit 0805055d4b
2 changed files with 44 additions and 22 deletions

View File

@ -726,7 +726,7 @@ sub remove
my $bRemoved = true; my $bRemoved = true;
# Set operation and debug strings # Set operation and debug strings
my $strOperation = OP_FILE_EXISTS; my $strOperation = OP_FILE_REMOVE;
my $strDebug = "${strPathType}:${strPathOp}"; my $strDebug = "${strPathType}:${strPathOp}";
&log(DEBUG, "${strOperation}: ${strDebug}"); &log(DEBUG, "${strOperation}: ${strDebug}");

View File

@ -38,7 +38,7 @@ sub new
# Initialize variables # Initialize variables
$self->{strDbClusterPath} = $strDbClusterPath; $self->{strDbClusterPath} = $strDbClusterPath;
$self->{oFile} = $oFile; $self->{oFile} = $oFile;
$self->{thread_total} = defined($iThreadTotal) ? $iThreadTotal : 1; $self->{iThreadTotal} = defined($iThreadTotal) ? $iThreadTotal : 1;
$self->{bForce} = $bForce; $self->{bForce} = $bForce;
$self->{oRemapRef} = $oRemapRef; $self->{oRemapRef} = $oRemapRef;
@ -70,14 +70,17 @@ sub manifest_ownership_test
my %oOwnerHash = (); my %oOwnerHash = ();
# Create hash for each type and owner to be checked # Create hash for each type and owner to be checked
my %oFileTypeHash = ('path' => true, 'link' => true, 'file' => true); my $strDefaultUser = getpwuid($<);
my %oOwnerTypeHash = ('user' => getpwuid($<), 'group' => getgrgid($()); my $strDefaultGroup = getgrgid($();
# Loop through all backup paths my %oFileTypeHash = ('path' => true, 'link' => true, 'file' => true);
foreach my $strPathKey (sort(keys ${$oManifestRef}{'backup:path'})) my %oOwnerTypeHash = ('user' => $strDefaultUser, 'group' => $strDefaultGroup);
# Loop through owner types
foreach my $strOwnerType (sort (keys %oOwnerTypeHash))
{ {
# Loop through owner types # Loop through all backup paths
foreach my $strOwnerType (sort (keys %oOwnerHash)) foreach my $strPathKey (sort(keys ${$oManifestRef}{'backup:path'}))
{ {
# Loop through types # Loop through types
foreach my $strFileType (sort (keys %oFileTypeHash)) foreach my $strFileType (sort (keys %oFileTypeHash))
@ -115,13 +118,13 @@ sub manifest_ownership_test
} }
} }
} }
}
# Output warning for any invalid owners # Output warning for any invalid owners
foreach my $strOwner (sort (keys $oOwnerHash{$strOwnerType})) foreach my $strOwner (sort (keys $oOwnerHash{$strOwnerType}))
{ {
&log(WARN, "${strOwnerType} ${strOwner} " . ($< == 0 ? "does not exist" : "cannot be set") . &log(WARN, "${strOwnerType} ${strOwner} " . ($< == 0 ? "does not exist" : "cannot be set") .
", changed to $oOwnerTypeHash{$strOwnerType}"); ", changed to $oOwnerTypeHash{$strOwnerType}");
}
} }
} }
} }
@ -148,6 +151,17 @@ sub manifest_load
# 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);
# If backup is latest then set it equal to backup label, else verify that requested backup and label match
if ($self->{strBackupPath} eq PATH_LATEST)
{
$self->{strBackupPath} = ${$oManifestRef}{'backup'}{label};
}
elsif ($self->{strBackupPath} ne ${$oManifestRef}{'backup'}{label})
{
confess &log(ASSERT, "request backup $self->{strBackupPath} and label ${$oManifestRef}{'backup'}{label} do not match " .
" - this indicates some sort of corruption (at the very least paths have been renamed.");
}
# If tablespaces have been remapped, update the manifest # If tablespaces have been remapped, update the manifest
if (defined($self->{oRemapRef})) if (defined($self->{oRemapRef}))
{ {
@ -297,8 +311,8 @@ sub clean
# Else delete a file/link # Else delete a file/link
else else
{ {
&log(DEBUG, "removing file ${strFile}"); &log(DEBUG, "removing file/link ${strFile}");
unlink($strFile) or confess &log(ERROR, "unable to delete file ${strFile}"); unlink($strFile) or confess &log(ERROR, "unable to delete file/link ${strFile}");
} }
} }
} }
@ -330,8 +344,11 @@ sub build
} }
# Create the Path # Create the Path
$self->{oFile}->path_create(PATH_DB_ABSOLUTE, "${strPath}/${strName}", if (!$self->{oFile}->exists(PATH_DB_ABSOLUTE, "${strPath}/${strName}"))
${$oManifestRef}{"${strPathKey}:path"}{$strName}{permission}); {
$self->{oFile}->path_create(PATH_DB_ABSOLUTE, "${strPath}/${strName}",
${$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
@ -399,7 +416,7 @@ sub restore
# Create threads to process the thread queues # Create threads to process the thread queues
my $oThreadGroup = new BackRest::ThreadGroup(); my $oThreadGroup = new BackRest::ThreadGroup();
for (my $iThreadIdx = 0; $iThreadIdx < $self->{thread_total}; $iThreadIdx++) for (my $iThreadIdx = 0; $iThreadIdx < $self->{iThreadTotal}; $iThreadIdx++)
{ {
$oThreadGroup->add(threads->create(\&restore_thread, $self, $iThreadIdx, \@oyRestoreQueue, \%oManifest)); $oThreadGroup->add(threads->create(\&restore_thread, $self, $iThreadIdx, \@oyRestoreQueue, \%oManifest));
} }
@ -423,11 +440,11 @@ sub restore_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((@{$oyRestoreQueueRef} / $self->{thread_total}) * $iThreadIdx); my $iQueueStartIdx = int((@{$oyRestoreQueueRef} / $self->{iThreadTotal}) * $iThreadIdx);
my $iQueueIdx = $iQueueStartIdx; my $iQueueIdx = $iQueueStartIdx;
# Set source compression # Set source compression
my $bSourceCompression = ${$oManifestRef}{'backup:option'}{compress} eq 'y'; my $bSourceCompression = ${$oManifestRef}{'backup:option'}{compress} eq 'y' ? true : false;
# 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();};
@ -447,6 +464,10 @@ sub restore_thread
$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
# If the file is a reference to a previous backup and hardlinks are off, then fetch it from that backup
my $strReference = ${$oManifestRef}{'backup:option'}{hardlink} eq 'y' ? undef :
${$oManifestRef}{$strSection}{$strName}{reference};
# Generate destination file name # Generate destination file name
my $strDestinationFile = $oFileThread->path_get(PATH_DB_ABSOLUTE, "${strDestinationPath}/${strName}"); my $strDestinationFile = $oFileThread->path_get(PATH_DB_ABSOLUTE, "${strDestinationPath}/${strName}");
@ -486,7 +507,8 @@ 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, (defined($strReference) ? $strReference : $self->{strBackupPath}) .
"/${strSourcePath}/${strName}" .
($bSourceCompression ? '.' . $oFileThread->{strCompressExtension} : ''), ($bSourceCompression ? '.' . $oFileThread->{strCompressExtension} : ''),
PATH_DB_ABSOLUTE, $strDestinationFile, PATH_DB_ABSOLUTE, $strDestinationFile,
$bSourceCompression, # Source is compressed based on backup settings $bSourceCompression, # Source is compressed based on backup settings