Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 59 additions & 9 deletions apps/files_external/lib/Lib/Storage/AmazonS3.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ public function needsPartFile() {
/** @var CappedMemoryCache|Result[] */
private $objectCache;

/** @var CappedMemoryCache|array */
private $filesCache;

public function __construct($parameters) {
parent::__construct($parameters);
$this->parseParams($parameters);
$this->objectCache = new CappedMemoryCache();
$this->filesCache = new CappedMemoryCache();
}

/**
Expand Down Expand Up @@ -94,6 +98,7 @@ private function cleanKey($path) {

private function clearCache() {
$this->objectCache = new CappedMemoryCache();
$this->filesCache = new CappedMemoryCache();
}

private function invalidateCache($key) {
Expand All @@ -105,6 +110,7 @@ private function invalidateCache($key) {
unset($this->objectCache[$existingKey]);
}
}
unset($this->filesCache[$key]);
}

/**
Expand Down Expand Up @@ -301,6 +307,12 @@ public function opendir($path) {
isset($object['Key']) ? $object['Key'] : $object['Prefix']
);
$files[] = $file;

// store this information for later usage
$this->filesCache[$file] = [
'ContentLength' => $object['Size'],
'LastModified' => (string)$object['LastModified'],
];
}
}
}
Expand All @@ -316,20 +328,14 @@ public function stat($path) {
$path = $this->normalizePath($path);

try {
$stat = array();
$stat = [];
if ($this->is_dir($path)) {
//folders don't really exist
$stat['size'] = -1; //unknown
$stat['mtime'] = time() - $this->rescanDelay * 1000;
} else {
$result = $this->headObject($path);

$stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
if (isset($result['Metadata']['lastmodified'])) {
$stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
} else {
$stat['mtime'] = strtotime($result['LastModified']);
}
$stat['size'] = $this->getContentLength($path);
$stat['mtime'] = strtotime($this->getLastModified($path));
}
$stat['atime'] = time();

Expand All @@ -340,6 +346,50 @@ public function stat($path) {
}
}

/**
* Return content length for object
*
* When the information is already present (e.g. opendir has been called before)
* this value is return. Otherwise a headObject is emitted.
*
* @param $path
* @return int|mixed
*/
private function getContentLength($path) {
if (isset($this->filesCache[$path])) {
return $this->filesCache[$path]['ContentLength'];
}

$result = $this->headObject($path);
if (isset($result['ContentLength'])) {
return $result['ContentLength'];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if this would fill in the filesCache from the head response

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about that but headObject has already some internal cache. I think this would just add additional complexity. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough

}

return 0;
}

/**
* Return last modified for object
*
* When the information is already present (e.g. opendir has been called before)
* this value is return. Otherwise a headObject is emitted.
*
* @param $path
* @return mixed|string
*/
private function getLastModified($path) {
if (isset($this->filesCache[$path])) {
return $this->filesCache[$path]['LastModified'];
}

$result = $this->headObject($path);
if (isset($result['LastModified'])) {
return $result['LastModified'];
}

return 'now';
}

public function is_dir($path) {
$path = $this->normalizePath($path);
try {
Expand Down