예제 #1
0
// end deletion.
// Handle download link
if (pb_backupbuddy::_GET('downloadlink_file') != '') {
    $downloadSettings = $settings;
    $downloadSettings['directory'] = $remotePath;
    $link = pb_backupbuddy_destination_live::getFileURL($downloadSettings, base64_decode(pb_backupbuddy::_GET('downloadlink_file')));
    pb_backupbuddy::alert('You may download this backup (' . base64_decode(pb_backupbuddy::_GET('downloadlink_file')) . ') with <a href="' . $link . '">this link</a>. The link is valid for one hour.');
    echo '<br>';
}
// end download link.
$marker = null;
if ('' != pb_backupbuddy::_GET('marker')) {
    // Jump to specific spot.
    $marker = base64_decode(urldecode(pb_backupbuddy::_GET('marker')));
}
$files = pb_backupbuddy_destination_live::listFiles($settings, $remotePath, $marker);
if (!is_array($files)) {
    pb_backupbuddy::alert('Error #892329b: ' . $files);
    die;
}
/*
echo '<pre>';
print_r( $files );
echo '</pre>';
*/
$backup_list_temp = array();
foreach ((array) $files as $file) {
    $last_modified = strtotime($file['LastModified']);
    while (isset($backup_list_temp[$last_modified])) {
        $last_modified += 0.1;
        // Add .1 repeatedly until timestamp is free.
예제 #2
0
 private static function _step_audit_remote_files($marker = null, $runningCount = 0)
 {
     if (time() - self::$_state['stats']['last_file_audit_finish'] < self::TIME_BETWEEN_FILE_AUDIT) {
         pb_backupbuddy::status('details', 'Not enough time has passed since last file audit. Skipping for now. Minimum time: `' . self::TIME_BETWEEN_FILE_AUDIT . '` secs. Last ran ago: `' . (time() - self::$_state['stats']['last_file_audit_finish']) . '` secs.');
         return true;
     }
     $deleteBatchSize = 100;
     // Delete files in batches of this many files via deleteObjects via deleteFiles().
     $serialDir = 'wp-content/uploads/backupbuddy_temp/SERIAL/';
     // Include trailing slash.
     $serialDirLen = strlen($serialDir);
     if (false === self::_load_state()) {
         return false;
     }
     if (false === self::_load_catalog()) {
         return false;
     }
     if (false === self::_load_tables()) {
         return false;
     }
     $destination_settings = self::get_destination_settings();
     require_once pb_backupbuddy::plugin_path() . '/destinations/live/init.php';
     if (null == $marker) {
         // Only reset if NOT chunking (first pass). Was cause of a bug first few weeks of release resulting in process restarting after hitting 100% if audit step chunked.
         self::$_state['stats']['last_file_audit_start'] = microtime(true);
         // Audit start time.
     }
     self::$_stateObj->save();
     $loopCount = 0;
     $loopStart = microtime(true);
     $keepLooping = true;
     $totalListed = 0;
     $totalTables = 0;
     $serialSkips = 0;
     $filesDeleted = 0;
     $tablesDeleted = 0;
     $last_save = microtime(true);
     while (true === $keepLooping) {
         $loopCount++;
         pb_backupbuddy::status('details', 'Listing files starting at marker `' . $marker . '`.');
         $files = pb_backupbuddy_destination_live::listFiles($destination_settings, $remotePath = '', $marker);
         if (!is_array($files)) {
             $error = 'Error #3279327: One or more errors encountered attempting to list remote files for auditing. Details: `' . print_r($files, true) . '`.';
             pb_backupbuddy::status('error', $error);
             backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $error);
             self::$_state['step']['last_status'] = 'Error: Unable to list remote files for audit.';
             return false;
         }
         pb_backupbuddy::status('details', 'Listed `' . count($files) . '` files.');
         $totalListed += count($files);
         // Iterate through all remote files.
         $pendingDelete = array();
         $filesDeletedThisRound = 0;
         foreach ($files as $file) {
             // Skip all files in the SERIAL directory with underscore. Audit the rest.
             if (substr($file['Key'], 0, $serialDirLen) == $serialDir) {
                 $totalTables++;
                 $basename = basename($file['Key']);
                 // Ignore underscore-prefixed live db data. Do not audit these. Skip.
                 if ('_' == substr($basename, 0, 1)) {
                     $serialSkips++;
                     continue;
                 }
                 // Ignore backupbuddy_dat.php metadata file and importbuddy.php files in database folder.
                 if ('backupbuddy_dat.php' == $basename || 'importbuddy.php' == $basename) {
                     continue;
                 }
                 // Verify no unexpected extra .sql files exist.
                 if (pb_backupbuddy::$options['log_level'] == '3') {
                     // Full logging enabled.
                     pb_backupbuddy::status('details', 'Auditing remotely found table (shown due to log level): `' . $basename . '`.');
                 }
                 $table_name = str_replace('.sql', '', $basename);
                 if (!isset(self::$_tables[$table_name])) {
                     pb_backupbuddy::status('details', 'Deleting unexpectedly remotely found table file: `' . $basename . '`.');
                     if (true !== ($delete_result = pb_backupbuddy_destination_live::deleteFile($destination_settings, array($file['Key'])))) {
                         pb_backupbuddy::status('error', 'Error #329030923: Unable to delete remote file. See log above for details. Details: `' . $deleteResult . '`.');
                     } else {
                         pb_backupbuddy::status('details', 'Deleted remote database file `' . $file['Key'] . '`.');
                         $tablesDeleted++;
                     }
                 }
                 continue;
             }
             if (!isset(self::$_catalog['/' . $file['Key']])) {
                 // Remotely stored file not found in local catalog. Delete remote.
                 $pendingDelete[] = $file['Key'];
                 // Process deletions.
                 if (count($pendingDelete) >= $deleteBatchSize) {
                     if (true !== ($delete_result = pb_backupbuddy_destination_live::deleteFile($destination_settings, $pendingDelete))) {
                         pb_backupbuddy::status('error', 'Error #4397347934: Unable to delete one or more remote files. See log above for details. Details: `' . print_r($delete_result, true) . '`. Clearing pendingDelete var for next batch.');
                     } else {
                         pb_backupbuddy::status('details', 'Deleted batch of `' . count($pendingDelete) . '` remote files. Cleaning pendingDelete var for next batch.');
                         $filesDeleted += count($pendingDelete);
                         $filesDeletedThisRound += count($pendingDelete);
                     }
                     $pendingDelete = array();
                 }
             } else {
                 // Remotely stored file found in local catalog. Updated verified audit timestamp.
                 // Update 'v' key (for verified) with current timestamp to show it is verified as being on remote server.
                 self::$_catalog['/' . $file['Key']]['v'] = microtime(true);
             }
         }
         // Process any remaining deletions.
         if (count($pendingDelete) > 0) {
             if (true !== ($delete_result = pb_backupbuddy_destination_live::deleteFile($destination_settings, $pendingDelete))) {
                 pb_backupbuddy::status('error', 'Error #373262793: Unable to delete one or more remote files. See log above for details. Details: `' . $deleteResult . '`. Clearing pendingDelete var for next batch.');
             } else {
                 pb_backupbuddy::status('details', 'Deleted batch of `' . count($pendingDelete) . '` remote files.');
                 $filesDeleted += count($pendingDelete);
             }
             unset($pendingDelete);
         }
         pb_backupbuddy::status('details', 'Deleted `' . $filesDeletedThisRound . '` total files this round out of `' . count($files) . '` listed. Looped `' . $loopCount . '` times.');
         // See if it's time to save 'v' key changes so far.
         if (time() - $last_save > self::SAVE_SIGNATURES_EVERY_X_SECONDS) {
             self::$_catalogObj->save();
             //self::$_stateObj->save();
             $last_save = microtime(true);
         }
         $filesListedMinusSkips = $totalListed - $serialSkips;
         $total_files = $filesListedMinusSkips - $filesDeleted;
         $totalTablesMinusSkips = $totalTables - $serialSkips;
         // If files retrieves is >= to the list limit then there may be more files. Set marker and chunk.
         if (count($files) < $destination_settings['max_filelist_keys']) {
             // No more files remain.
             $keepLooping = false;
             self::$_catalogObj->save();
             self::$_state['stats']['last_file_audit_finish'] = microtime(true);
             // Audit finish time.
             $runningCount += $total_files - $totalTablesMinusSkips;
             pb_backupbuddy::status('details', 'No more files to check. Deleted `' . $filesDeleted . '` out of listed `' . $totalListed . '` (`' . $filesListedMinusSkips . '` files, Deleted `' . $tablesDeleted . '` tables out of `' . $totalTablesMinusSkips . '` total tables. `' . $serialSkips . '` skipped database/serial dir). `' . $total_files . '` files+tables.sql files after deletions. Files running count: `' . $runningCount . '`.');
             if ($runningCount < self::$_state['stats']['files_total_count']) {
                 $message = 'Attention! Remote storage lists fewer files (' . $runningCount . ') than expected (' . self::$_state['stats']['files_total_count'] . '). More files may be pending transfer. Deleted: `' . $filesDeletedThisRound . '`.';
                 pb_backupbuddy::status('error', $message);
                 backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $message);
             }
             return true;
         } else {
             // More files MAY remain.
             pb_backupbuddy::status('details', 'More files remain to check. Deleted `' . $filesDeleted . '` total files this round so far. Files running count: `' . ($runningCount + $total_files - $totalTablesMinusSkips) . '`.');
             $marker = end($files);
             $marker = $marker['Key'];
             reset($files);
             // Do we have enough time to proceed or do we need to chunk?
             $time_elapsed = microtime(true) - pb_backupbuddy::$start_time;
             $time_remaining = $destination_settings['max_time'] - ($time_elapsed + self::TIME_WIGGLE_ROOM);
             // Estimated time remaining before PHP times out. Unit: seconds.
             $averageTimePerLoop = (microtime(true) - $loopStart) / $loopCount;
             pb_backupbuddy::status('details', 'Time elapsed: `' . $time_elapsed . '`, estimated remaining: `' . $time_remaining . '`, average time needed per loop: `' . $averageTimePerLoop . '`. Max time setting: `' . $destination_settings['max_time'] . '`.');
             if ($averageTimePerLoop >= $time_remaining) {
                 // Not enough time for another loop. Chunk.
                 $keepLooping = false;
                 self::$_catalogObj->save();
                 $runningCount += $total_files - $totalTablesMinusSkips;
                 pb_backupbuddy::status('details', 'Running out of time processing file audit. Took `' . (microtime(true) - $loopStart) . '` seconds to delete `' . $filesDeleted . '` out of listed `' . $totalListed . '` (`' . $filesListedMinusSkips . '` files, Deleted `' . $tablesDeleted . '` tables out of `' . $totalTablesMinusSkips . '` total tables. `' . $serialSkips . '` skipped database/serial dir). `' . ($filesListedMinusSkips - $filesDeleted) . '` files after deletions. Starting next at `' . $marker . '`.  Files running count: `' . $runningCount . '`.');
                 return array('Auditing remote files', array($marker, $runningCount));
             } else {
                 // Proceed looping in this PHP page load...
                 $keepLooping = true;
             }
         }
         // end if more files may remain.
     }
     // End while.
     // Made it here so we finished.
     self::$_catalogObj->save();
     self::$_state['stats']['last_file_audit_finish'] = microtime(true);
     // Audit finish time.
     // If not all files have uploaded, skip snapshot for now.
     if (self::$_state['stats']['files_pending_send'] > 0 || self::$_state['stats']['tables_pending_send'] > 0) {
         pb_backupbuddy::status('details', '`' . self::$_state['stats']['files_pending_send'] . '` files and `' . self::$_state['stats']['tables_pending_send'] . '` database tables are still pending transfer. Waiting for transfers to finish before creating Snapshot.');
         self::$_state['stats']['wait_on_transfers_start'] = microtime(true);
         backupbuddy_live::queue_step($step = 'wait_on_transfers', $args = array(), $skip_run_now = true);
         return true;
     }
     return true;
 }