Merge pull request #1586 from owncloud/filecache_mtime

Emulate touch() for backends that don't support it
This commit is contained in:
Thomas Müller 2013-05-21 15:17:08 -07:00
commit 4bb6ac3aa7
9 changed files with 85 additions and 15 deletions

View File

@ -280,6 +280,14 @@
<length>4</length>
</field>
<field>
<name>storage_mtime</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>encrypted</name>
<type>integer</type>

View File

@ -107,7 +107,7 @@ class Cache {
$params = array($file);
}
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` ' . $where);
$result = $query->execute($params);
$data = $result->fetchRow();
@ -126,6 +126,9 @@ class Cache {
$data['storage'] = $this->storageId;
$data['mimetype'] = $this->getMimetype($data['mimetype']);
$data['mimepart'] = $this->getMimetype($data['mimepart']);
if ($data['storage_mtime'] == 0) {
$data['storage_mtime'] = $data['mtime'];
}
}
return $data;
@ -141,13 +144,16 @@ class Cache {
$fileId = $this->getId($folder);
if ($fileId > -1) {
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC');
$result = $query->execute(array($fileId));
$files = $result->fetchAll();
foreach ($files as &$file) {
$file['mimetype'] = $this->getMimetype($file['mimetype']);
$file['mimepart'] = $this->getMimetype($file['mimepart']);
if ($file['storage_mtime'] == 0) {
$file['storage_mtime'] = $file['mtime'];
}
}
return $files;
} else {
@ -224,7 +230,7 @@ class Cache {
* @return array
*/
function buildParts(array $data) {
$fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag');
$fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted', 'etag');
$params = array();
$queryParts = array();
foreach ($data as $name => $value) {
@ -236,6 +242,11 @@ class Cache {
$params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/')));
$queryParts[] = '`mimepart`';
$value = $this->getMimetypeId($value);
} elseif ($name === 'storage_mtime') {
if (!isset($data['mtime'])) {
$params[] = $value;
$queryParts[] = '`mtime`';
}
}
$params[] = $value;
$queryParts[] = '`' . $name . '`';

View File

@ -51,6 +51,7 @@ class Scanner {
$data['size'] = $this->storage->filesize($path);
}
$data['etag'] = $this->storage->getETag($path);
$data['storage_mtime'] = $data['mtime'];
return $data;
}

View File

@ -43,7 +43,7 @@ class Watcher {
*/
public function checkUpdate($path) {
$cachedEntry = $this->cache->get($path);
if ($this->storage->hasUpdated($path, $cachedEntry['mtime'])) {
if ($this->storage->hasUpdated($path, $cachedEntry['storage_mtime'])) {
if ($this->storage->is_dir($path)) {
$this->scanner->scan($path, Scanner::SCAN_SHALLOW);
} else {

View File

@ -251,8 +251,11 @@ class View {
if (!$this->file_exists($path)) {
$hooks[] = 'write';
}
return $this->basicOperation('touch', $path, $hooks, $mtime);
$result = $this->basicOperation('touch', $path, $hooks, $mtime);
if (!$result) { //if native touch fails, we emulate it by changing the mtime in the cache
$this->putFileInfo($path, array('mtime' => $mtime));
}
return true;
}
public function file_get_contents($path) {

View File

@ -77,7 +77,7 @@ class OC_Util {
public static function getVersion() {
// hint: We only can count up. Reset minor/patchlevel when
// updating major/minor version number.
return array(5, 80, 02);
return array(5, 80, 03);
}
/**

View File

@ -211,6 +211,23 @@ class Cache extends \PHPUnit_Framework_TestCase {
$this->assertEquals(array($storageId, 'foo'), \OC\Files\Cache\Cache::getById($id));
}
function testStorageMTime() {
$data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
$this->cache->put('foo', $data);
$cachedData = $this->cache->get('foo');
$this->assertEquals($data['mtime'], $cachedData['storage_mtime']);//if no storage_mtime is saved, mtime should be used
$this->cache->put('foo', array('storage_mtime' => 30));//when setting storage_mtime, mtime is also set
$cachedData = $this->cache->get('foo');
$this->assertEquals(30, $cachedData['storage_mtime']);
$this->assertEquals(30, $cachedData['mtime']);
$this->cache->put('foo', array('mtime' => 25));//setting mtime does not change storage_mtime
$cachedData = $this->cache->get('foo');
$this->assertEquals(30, $cachedData['storage_mtime']);
$this->assertEquals(25, $cachedData['mtime']);
}
function testLongId() {
$storage = new LongId(array());
$cache = $storage->getCache();

View File

@ -35,7 +35,7 @@ class Watcher extends \PHPUnit_Framework_TestCase {
$updater = $storage->getWatcher();
//set the mtime to the past so it can detect an mtime change
$cache->put('', array('mtime' => 10));
$cache->put('', array('storage_mtime' => 10));
$this->assertTrue($cache->inCache('folder/bar.txt'));
$this->assertTrue($cache->inCache('folder/bar2.txt'));
@ -47,14 +47,14 @@ class Watcher extends \PHPUnit_Framework_TestCase {
$cachedData = $cache->get('bar.test');
$this->assertEquals(3, $cachedData['size']);
$cache->put('bar.test', array('mtime' => 10));
$cache->put('bar.test', array('storage_mtime' => 10));
$storage->file_put_contents('bar.test', 'test data');
$updater->checkUpdate('bar.test');
$cachedData = $cache->get('bar.test');
$this->assertEquals(9, $cachedData['size']);
$cache->put('folder', array('mtime' => 10));
$cache->put('folder', array('storage_mtime' => 10));
$storage->unlink('folder/bar2.txt');
$updater->checkUpdate('folder');
@ -69,7 +69,7 @@ class Watcher extends \PHPUnit_Framework_TestCase {
$updater = $storage->getWatcher();
//set the mtime to the past so it can detect an mtime change
$cache->put('', array('mtime' => 10));
$cache->put('', array('storage_mtime' => 10));
$storage->unlink('foo.txt');
$storage->rename('folder', 'foo.txt');
@ -85,7 +85,7 @@ class Watcher extends \PHPUnit_Framework_TestCase {
$updater = $storage->getWatcher();
//set the mtime to the past so it can detect an mtime change
$cache->put('foo.txt', array('mtime' => 10));
$cache->put('foo.txt', array('storage_mtime' => 10));
$storage->unlink('foo.txt');
$storage->rename('folder', 'foo.txt');

View File

@ -7,6 +7,12 @@
namespace Test\Files;
class TemporaryNoTouch extends \OC\Files\Storage\Temporary {
public function touch($path, $mtime = null) {
return false;
}
}
class View extends \PHPUnit_Framework_TestCase {
/**
* @var \OC\Files\Storage\Storage[] $storages;
@ -220,7 +226,7 @@ class View extends \PHPUnit_Framework_TestCase {
$cachedData = $rootView->getFileInfo('foo.txt');
$this->assertEquals(16, $cachedData['size']);
$rootView->putFileInfo('foo.txt', array('mtime' => 10));
$rootView->putFileInfo('foo.txt', array('storage_mtime' => 10));
$storage1->file_put_contents('foo.txt', 'foo');
clearstatcache();
@ -228,12 +234,36 @@ class View extends \PHPUnit_Framework_TestCase {
$this->assertEquals(3, $cachedData['size']);
}
function testTouch() {
$storage = $this->getTestStorage(true, '\Test\Files\TemporaryNoTouch');
\OC\Files\Filesystem::mount($storage, array(), '/');
$rootView = new \OC\Files\View('');
$oldCachedData = $rootView->getFileInfo('foo.txt');
$rootView->touch('foo.txt', 500);
$cachedData = $rootView->getFileInfo('foo.txt');
$this->assertEquals(500, $cachedData['mtime']);
$this->assertEquals($oldCachedData['storage_mtime'], $cachedData['storage_mtime']);
$rootView->putFileInfo('foo.txt', array('storage_mtime' => 1000)); //make sure the watcher detects the change
$rootView->file_put_contents('foo.txt', 'asd');
$cachedData = $rootView->getFileInfo('foo.txt');
$this->assertGreaterThanOrEqual($cachedData['mtime'], $oldCachedData['mtime']);
$this->assertEquals($cachedData['storage_mtime'], $cachedData['mtime']);
}
/**
* @param bool $scan
* @return \OC\Files\Storage\Storage
*/
private function getTestStorage($scan = true) {
$storage = new \OC\Files\Storage\Temporary(array());
private function getTestStorage($scan = true, $class = '\OC\Files\Storage\Temporary') {
/**
* @var \OC\Files\Storage\Storage $storage
*/
$storage = new $class(array());
$textData = "dummy file data\n";
$imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png');
$storage->mkdir('folder');