commit f18e5ec63aaad242b709da701895571cc44c8b94 Author: sam marshall Date: Mon Sep 16 17:08:29 2013 +0100 More fixes to zip stuff diff --git a/lib/filestorage/zip_packer.php b/lib/filestorage/zip_packer.php index 175a552..fd9d003 100644 --- a/lib/filestorage/zip_packer.php +++ b/lib/filestorage/zip_packer.php @@ -36,6 +36,20 @@ require_once("$CFG->libdir/filestorage/zip_archive.php"); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class zip_packer extends file_packer { + /** + * @var int Start of processing or last time archive was reopened. + */ + protected $opentime; + + /** + * @var string Path of current archive. + */ + protected $archivepath; + + /** + * @var int After building a zip for this many seconds, finalise changes. + */ + const ARCHIVE_ACTIONS_TIME_LIMIT = 10; /** * Zip files and store the result in file storage. @@ -87,6 +101,42 @@ class zip_packer extends file_packer { } /** + * + * @param zip_archive $ziparch + * @return bool True if archive is OK, false if an error has occurred + */ + protected function before_archive_action(zip_archive $ziparch) { + $now = $this->get_current_time(); + if ($now < $this->opentime + self::ARCHIVE_ACTIONS_TIME_LIMIT) { + return true; + } + + // Close archive and clear action count. +print_object(date('H:i:s') . ': CLOSING ARCHIVE'); flush(); + $result = $ziparch->close(); + if (!$result) { + return false; + } + + // Record reopen time. Note that this is NOT the same as $now because + // it might take ages to do the close call. + $this->opentime = time(); + +print_object(date('H:i:s') . ': REOPENING ARCHIVE (close took ' . ($this->opentime - $now) . 's)'); flush(); + // Reopen archive. + return $ziparch->open($this->archivefile, file_archive::OPEN); + } + + /** + * Gets current time. Wrapper around time() so we can unit-test. + * + * @return int Current time + */ + protected function get_current_time() { + return time(); + } + + /** * Zip files and store the result in os file. * * @param array $files array with zip paths as keys (archivepath=>ospathname or archivepath=>stored_file or archivepath=>array('content_as_string')) @@ -101,6 +151,8 @@ class zip_packer extends file_packer { if (!$ziparch->open($archivefile, file_archive::OVERWRITE)) { return false; } + $this->archivefile = $archivefile; + $this->opentime = time(); $abort = false; foreach ($files as $archivepath => $file) { @@ -132,6 +184,7 @@ class zip_packer extends file_packer { } else if (is_array($file)) { $content = reset($file); + $this->before_archive_action($ziparch); if (!$ziparch->add_file_from_string($archivepath, $content)) { debugging("Can not zip '$archivepath' file", DEBUG_DEVELOPER); if (!$ignoreinvalidfiles) { @@ -174,6 +227,9 @@ class zip_packer extends file_packer { * @return bool success */ private function archive_stored($ziparch, $archivepath, $file, file_progress $progress = null) { + if (!$this->before_archive_action($ziparch)) { + return false; + } $result = $file->archive_file($ziparch, $archivepath); if (!$result) { return false; @@ -217,6 +273,10 @@ class zip_packer extends file_packer { */ private function archive_pathname($ziparch, $archivepath, $file, file_progress $progress = null) { + // Record archive action (if required). + if (!$this->before_archive_action($ziparch)) { + return false; + } // Record progress each time this function is called. if ($progress) { $progress->progress();