cap the number of entries we cache in smb's statcache

This commit is contained in:
Robin Appelman 2016-01-12 13:14:04 +01:00
parent 0c0829fbc7
commit d8d6368dd7
4 changed files with 163 additions and 2 deletions

View File

@ -35,6 +35,7 @@ use Icewind\SMB\NativeServer;
use Icewind\SMB\Server;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory;
use OC\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
class SMB extends Common {
@ -48,10 +49,15 @@ class SMB extends Common {
*/
protected $share;
/**
* @var string
*/
protected $root;
/**
* @var \Icewind\SMB\FileInfo[]
*/
protected $statCache = array();
protected $statCache;
public function __construct($params) {
if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
@ -72,6 +78,7 @@ class SMB extends Common {
} else {
throw new \Exception('Invalid configuration');
}
$this->statCache = new CappedMemoryCache();
}
/**

87
lib/private/cache/cappedmemorycache.php vendored Normal file
View File

@ -0,0 +1,87 @@
<?php
/**
* @author Robin Appelman <icewind@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Cache;
use OCP\ICache;
/**
* In-memory cache with a capacity limit to keep memory usage in check
*
* Uses a simple FIFO expiry mechanism
*/
class CappedMemoryCache implements ICache, \ArrayAccess {
private $capacity;
private $cache = [];
public function __construct($capacity = 512) {
$this->capacity = $capacity;
}
public function hasKey($key) {
return isset($this->cache[$key]);
}
public function get($key) {
return isset($this->cache[$key]) ? $this->cache[$key] : null;
}
public function set($key, $value, $ttl = 0) {
$this->cache[$key] = $value;
$this->garbageCollect();
}
public function remove($key) {
unset($this->cache[$key]);
return true;
}
public function clear($prefix = '') {
$this->cache = [];
return true;
}
public function offsetExists($offset) {
return $this->hasKey($offset);
}
public function offsetGet($offset) {
return $this->get($offset);
}
public function offsetSet($offset, $value) {
$this->set($offset, $value);
}
public function offsetUnset($offset) {
$this->remove($offset);
}
private function garbageCollect() {
while (count($this->cache) > $this->capacity) {
reset($this->cache);
$key = key($this->cache);
$this->remove($key);
}
}
}

View File

@ -8,7 +8,7 @@
abstract class Test_Cache extends \Test\TestCase {
/**
* @var \OC\Cache cache;
* @var \OCP\ICache cache;
*/
protected $instance;

67
tests/lib/cache/cappedmemorycache.php vendored Normal file
View File

@ -0,0 +1,67 @@
<?php
/**
* ownCloud
*
* @author Robin Appelman
* @copyright 2016 Robin Appelman icewind@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\Cache;
/**
* Class FileCache
*
* @group DB
*
* @package Test\Cache
*/
class CappedMemoryCache extends \Test_Cache {
public function setUp() {
parent::setUp();
$this->instance = new \OC\Cache\CappedMemoryCache();
}
public function testSetOverCap() {
$instance = new \OC\Cache\CappedMemoryCache(3);
$instance->set('1', 'a');
$instance->set('2', 'b');
$instance->set('3', 'c');
$instance->set('4', 'd');
$instance->set('5', 'e');
$this->assertFalse($instance->hasKey('1'));
$this->assertFalse($instance->hasKey('2'));
$this->assertTrue($instance->hasKey('3'));
$this->assertTrue($instance->hasKey('4'));
$this->assertTrue($instance->hasKey('5'));
}
function testClear() {
$value = 'ipsum lorum';
$this->instance->set('1_value1', $value);
$this->instance->set('1_value2', $value);
$this->instance->set('2_value1', $value);
$this->instance->set('3_value1', $value);
$this->assertTrue($this->instance->clear());
$this->assertFalse($this->instance->hasKey('1_value1'));
$this->assertFalse($this->instance->hasKey('1_value2'));
$this->assertFalse($this->instance->hasKey('2_value1'));
$this->assertFalse($this->instance->hasKey('3_value1'));
}
}