Skip to content

Commit

Permalink
MDL-34290 repository_equella: do not download files when not needed
Browse files Browse the repository at this point in the history
repository_equella::get_file_by_reference respects request timeouts, downloads only images (for thumbnail generation),
does not use cache_file class (content is cached in moodle filepool if needed);
also repository_equella has counter of unsuccessfull connect attempts and do not perform any more if 3 failed
(within one request)
  • Loading branch information
marinaglancy committed Aug 29, 2012
1 parent a5fe04b commit 120300f
Showing 1 changed file with 74 additions and 16 deletions.
90 changes: 74 additions & 16 deletions repository/equella/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,49 @@ public function get_file_reference($source) {
return $source;
}

/**
* Counts the number of failed connections.
*
* If we received the connection timeout more than 3 times in a row, we don't attemt to
* connect to the server any more during this request.
*
* This function is used by {@link repository_equella::get_file_by_reference()} that
* synchronises the file size of referenced files.
*
* @param int $errno omit if we just want to know the return value, the last curl_errno otherwise
* @return bool true if we had less than 3 failed connections, false if no more connections
* attempts recommended
*/
private function connection_result($errno = null) {
static $countfailures = array();
$sess = sesskey();
if (!array_key_exists($sess, $countfailures)) {
$countfailures[$sess] = 0;
}
if ($errno !== null) {
if ($errno == 0) {
// reset count of failed connections
$countfailures[$sess] = 0;
} else if ($errno == 7 /*CURLE_COULDNT_CONNECT*/ || $errno == 9 /*CURLE_REMOTE_ACCESS_DENIED*/) {
// problems with server
$countfailures[$sess]++;
}
}
return ($countfailures[$sess] < 3);
}

/**
* Decide whether or not the file should be synced
*
* @param stored_file $storedfile
* @return bool
*/
public function sync_individual_file(stored_file $storedfile) {
// if we had several unsuccessfull attempts to connect to server - do not try any more
return $this->connection_result();
}


/**
* Download a file, this function can be overridden by subclass. {@link curl}
*
Expand Down Expand Up @@ -155,35 +198,50 @@ public function get_file($reference, $filename = '') {

/**
* Returns information about file in this repository by reference
* {@link repository::get_file_reference()}
* {@link repository::get_file()}
*
* If the file is an image we download the contents and save it in our filesystem
* so we can generate thumbnails. Otherwise we just request the file size.
* Returns null if file not found or can not be accessed
*
* @param stdClass $reference file reference db record
* @return null|stdClass containing attribute 'filepath'
* @return stdClass|null contains one of the following:
* - 'filesize' (for non-image files or files we failed to retrieve fully because of timeout)
* - 'filepath' (for image files that we retrieived and saved)
*/
public function get_file_by_reference($reference) {
$ref = unserialize(base64_decode($reference->reference));
$url = $this->appendtoken($ref->url);

if (!$url) {
global $USER;
$ref = @unserialize(base64_decode($reference->reference));
if (!isset($ref->url) || !($url = $this->appendtoken($ref->url))) {
// Occurs when the user isn't known..
return null;
}

// We use this cache to get the correct file size.
$cachedfilepath = cache_file::get($url, array('ttl' => 0));
if ($cachedfilepath === false) {
// Cache the file.
$path = $this->get_file($url);
$cachedfilepath = cache_file::create_from_file($url, $path['path']);
$return = null;
$cookiepathname = $this->prepare_file($USER->id. '_'. uniqid('', true). '.cookie');
$c = new curl(array('cookie' => $cookiepathname));
if (file_extension_in_typegroup($ref->filename, 'web_image')) {
$path = $this->prepare_file('');
$result = $c->download_one($url, null, array('filepath' => $path, 'followlocation' => true, 'timeout' => self::SYNCIMAGE_TIMEOUT));
if ($result === true) {
$return = (object)array('filepath' => $path);
}
} else {
$result = $c->head($url, array('followlocation' => true, 'timeout' => self::SYNCFILE_TIMEOUT));
}
// Delete cookie jar.
if (file_exists($cookiepathname)) {
unlink($cookiepathname);
}

if ($cachedfilepath && is_readable($cachedfilepath)) {
return (object)array('filepath' => $cachedfilepath);
$this->connection_result($c->get_errno());
$curlinfo = $c->get_info();
if ($return === null && isset($curlinfo['http_code']) && $curlinfo['http_code'] == 200
&& array_key_exists('download_content_length', $curlinfo)
&& $curlinfo['download_content_length'] >= 0) {
// we received a correct header and at least can tell the file size
$return = (object)array('filesize' => $curlinfo['download_content_length']);
}
return null;
return $return;
}

/**
Expand Down

0 comments on commit 120300f

Please sign in to comment.