-
-
Save simonwelsh/ce75f7a627a15c3aec44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
function latest_base_lsn() { | |
exec('grep -H to_lsn /root/backup/base/*/xtrabackup_checkpoints', $options); | |
if (!$options) { | |
return null; | |
} | |
$options = array_map(function($opt) { | |
preg_match('#/(\d+)/.+= (\d+)#', $opt, $matches); | |
return array('date' => $matches[1], 'lsn' => $matches[2]); | |
}, $options); | |
usort($options, function($a, $b) { | |
if ($b['lsn'] === $a['lsn']) { | |
return $b['date'] - $a['date']; | |
} | |
return $b['lsn'] - $a['lsn']; | |
}); | |
return $options[0]; | |
} | |
function get_next_lsn($current, $date) { | |
$dir = '/root/backup/increment/' . $current . '-' . $date; | |
assert(file_exists($dir) && is_dir($dir)); | |
$file = $dir . '/xtrabackup_checkpoints'; | |
assert(file_exists($file)); | |
$settings = parse_ini_file($file); | |
assert($settings['from_lsn'] == $current); | |
return $settings['to_lsn']; | |
} | |
function available_increments() { | |
$increments = array(); | |
$dir = dir('/root/backup/increment'); | |
while (false !== ($file = $dir->read())) { | |
if (preg_match('#^(\d+)-(\d{14})$#', $file, $match)) { | |
$date = $match[2]; | |
$lsn = $match[1]; | |
if (!isset($increments[$lsn]) || $increments[$lsn] < $date) { | |
$next = get_next_lsn($lsn, $date); | |
if ($next == $lsn) { | |
// Skip empty incremental backups | |
continue; | |
} | |
$increments[$lsn] = array('date' => $date, 'next' => $next); | |
} | |
} | |
} | |
$dir->close(); | |
ksort($increments, SORT_NUMERIC); | |
return $increments; | |
} | |
function run_script($script) { | |
$script = escapeshellarg($script); | |
$command = "ssh root@localhost $script"; | |
$ret = system($command, $code); | |
return array($ret, $code); | |
} | |
function prep_stream() { | |
$script = <<<SCRIPT | |
mkdir /tmp/restore | |
if [ $? -ne 0 ] | |
then | |
exit 1 | |
fi | |
#service mysql stop | |
#rm -rf /var/lib/mysql/* | |
SCRIPT; | |
list(, $code) = run_script($script); | |
return !$code; | |
$script = escapeshellarg($script); | |
$command = "ssh root@localhost $script"; | |
$ret = system($command, $var); | |
return !$var; | |
} | |
function cleanup() { | |
$script = <<<SCRIPT | |
rm -rf /tmp/restore | |
SCRIPT; | |
run_script($script); | |
} | |
function stream($path, $last, $base = false) { | |
echo "Will stream $path"; | |
if ($base) echo " as base"; | |
if ($last) echo " and finish preparing\n"; | |
else echo " and do a partial prepare\n"; | |
} | |
function restore() { | |
echo "Restoring.\n"; | |
} | |
$base = latest_base_lsn(); | |
if (!$base) { | |
echo 'No backups found.'; | |
exit(1); | |
} | |
$increments = available_increments(); | |
$toStream = array(); | |
$lsn = $base['lsn']; | |
while (isset($increments[$lsn])) { | |
$inc = $increments[$lsn]; | |
$toStream[] = '/root/backup/increment/' . $lsn . '-' . $inc['date']; | |
$lsn = $inc['next']; | |
} | |
if (!prep_stream()) { | |
echo 'Unable to prepare for restore. '; | |
echo "Is another restore happening?\n"; | |
exit(1); | |
} | |
// stream the base | |
stream('/root/backup/base/' . $base['date'], !$toStream, true); | |
// Stream everything else | |
while ($toStream) { | |
$path = array_shift($toStream); | |
stream($path, !$toStream); | |
} | |
// Do the restore | |
restore(); | |
// Cleanup | |
cleanup(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment