Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>tags/v24.0.0beta1
@@ -121,7 +121,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider { | |||
if (!isset($config['arguments']['bucket'])) { | |||
$config['arguments']['bucket'] = ''; | |||
} | |||
$mapper = new \OC\Files\ObjectStore\Mapper($user); | |||
$mapper = new \OC\Files\ObjectStore\Mapper($user, $this->config); | |||
$numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64; | |||
$config['arguments']['bucket'] .= $mapper->getBucket($numBuckets); | |||
@@ -22,6 +22,7 @@ | |||
*/ | |||
namespace OC\Files\ObjectStore; | |||
use OCP\IConfig; | |||
use OCP\IUser; | |||
/** | |||
@@ -35,13 +36,18 @@ class Mapper { | |||
/** @var IUser */ | |||
private $user; | |||
/** @var IConfig */ | |||
private $config; | |||
/** | |||
* Mapper constructor. | |||
* | |||
* @param IUser $user | |||
* @param IConfig $config | |||
*/ | |||
public function __construct(IUser $user) { | |||
public function __construct(IUser $user, IConfig $config) { | |||
$this->user = $user; | |||
$this->config = $config; | |||
} | |||
/** | |||
@@ -49,8 +55,15 @@ class Mapper { | |||
* @return string | |||
*/ | |||
public function getBucket($numBuckets = 64) { | |||
// Get the bucket config and shift if provided. | |||
// Allow us to prevent writing in old filled buckets | |||
$config = $this->config->getSystemValue('objectstore_multibucket'); | |||
$minBucket = is_array($config) && isset($config['arguments']['min_bucket']) | |||
? (int)$config['arguments']['min_bucket'] | |||
: 0; | |||
$hash = md5($this->user->getUID()); | |||
$num = hexdec(substr($hash, 0, 4)); | |||
return (string)($num % $numBuckets); | |||
return (string)(($num % ($numBuckets - $minBucket)) + $minBucket); | |||
} | |||
} |
@@ -54,7 +54,7 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { | |||
} | |||
public function testMultiBucket() { | |||
$this->config->expects($this->once()) | |||
$this->config->expects($this->exactly(2)) | |||
->method('getSystemValue') | |||
->with($this->equalTo('objectstore_multibucket'), '') | |||
->willReturn([ | |||
@@ -98,9 +98,9 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { | |||
} | |||
public function testMultiBucketWithPrefix() { | |||
$this->config->expects($this->once()) | |||
$this->config->expects($this->exactly(2)) | |||
->method('getSystemValue') | |||
->with($this->equalTo('objectstore_multibucket'), '') | |||
->with('objectstore_multibucket') | |||
->willReturn([ | |||
'class' => 'Test\Files\Mount\FakeObjectStore', | |||
'arguments' => [ | |||
@@ -147,7 +147,7 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { | |||
public function testMultiBucketBucketAlreadySet() { | |||
$this->config->expects($this->once()) | |||
->method('getSystemValue') | |||
->with($this->equalTo('objectstore_multibucket'), '') | |||
->with('objectstore_multibucket') | |||
->willReturn([ | |||
'class' => 'Test\Files\Mount\FakeObjectStore', | |||
'arguments' => [ | |||
@@ -185,9 +185,9 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { | |||
} | |||
public function testMultiBucketConfigFirst() { | |||
$this->config->expects($this->once()) | |||
$this->config->expects($this->exactly(2)) | |||
->method('getSystemValue') | |||
->with($this->equalTo('objectstore_multibucket')) | |||
->with('objectstore_multibucket') | |||
->willReturn([ | |||
'class' => 'Test\Files\Mount\FakeObjectStore', | |||
]); |
@@ -22,17 +22,37 @@ | |||
namespace Test\Files\ObjectStore; | |||
use OC\Files\ObjectStore\Mapper; | |||
use OCP\IConfig; | |||
use OCP\IUser; | |||
class MapperTest extends \Test\TestCase { | |||
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject */ | |||
private $user; | |||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ | |||
private $config; | |||
/** @var Mapper */ | |||
private $mapper; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
$this->user = $this->createMock(IUser::class); | |||
$this->config = $this->createMock(IConfig::class); | |||
$this->mapper = new Mapper($this->user, $this->config); | |||
} | |||
public function dataGetBucket() { | |||
return [ | |||
['user', 64, '17'], | |||
['USER', 64, '0'], | |||
['bc0e8b52-a66c-1035-90c6-d9663bda9e3f', 64, '56'], | |||
['user', 8, '1'], | |||
['user', 2, '1'], | |||
['USER', 2, '0'], | |||
['user', 64, 0, '17'], | |||
['USER', 64, 0, '0'], | |||
['bc0e8b52-a66c-1035-90c6-d9663bda9e3f', 64, 0, '56'], | |||
['user', 8, 0, '1'], | |||
['user', 2, 0, '1'], | |||
['USER', 2, 0, '0'], | |||
['user', 128, 64, '81'], | |||
]; | |||
} | |||
@@ -42,13 +62,17 @@ class MapperTest extends \Test\TestCase { | |||
* @param int $numBuckets | |||
* @param string $expectedBucket | |||
*/ | |||
public function testGetBucket($username, $numBuckets, $expectedBucket) { | |||
$user = $this->createMock(IUser::class); | |||
$user->method('getUID') | |||
public function testGetBucket($username, $numBuckets, $bucketShift, $expectedBucket) { | |||
$this->user->expects($this->once()) | |||
->method('getUID') | |||
->willReturn($username); | |||
$mapper = new Mapper($user); | |||
$this->config->expects($this->once()) | |||
->method('getSystemValue') | |||
->with('objectstore_multibucket') | |||
->willReturn(['arguments' => ['min_bucket' => $bucketShift]]); | |||
$this->assertSame($expectedBucket, $mapper->getBucket($numBuckets)); | |||
$result = $this->mapper->getBucket($numBuckets); | |||
$this->assertEquals($expectedBucket, $result); | |||
} | |||
} |