Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
try to grab the appdata folder directly without going trough the whol…
…e tree

Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Dec 6, 2018
commit 740ea0d30e8ed8967e5d940b971e8854812c627d
88 changes: 63 additions & 25 deletions lib/private/Files/AppData/AppData.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace OC\Files\AppData;

use OC\Cache\CappedMemoryCache;
use OC\Files\SimpleFS\SimpleFolder;
use OCP\Files\IAppData;
use OCP\Files\IRootFolder;
Expand All @@ -48,6 +49,9 @@ class AppData implements IAppData {
/** @var Folder */
private $folder;

/** @var (ISimpleFolder|NotFoundException)[]|CappedMemoryCache */
private $folders;

/**
* AppData constructor.
*
Expand All @@ -62,6 +66,32 @@ public function __construct(IRootFolder $rootFolder,
$this->rootFolder = $rootFolder;
$this->config = $systemConfig;
$this->appId = $appId;
$this->folders = new CappedMemoryCache();
}

private function getAppDataFolderName() {
$instanceId = $this->config->getValue('instanceid', null);
if ($instanceId === null) {
throw new \RuntimeException('no instance id!');
}

return 'appdata_' . $instanceId;
}

private function getAppDataRootFolder(): Folder {
$name = $this->getAppDataFolderName();

try {
/** @var Folder $node */
$node = $this->rootFolder->get($name);
return $node;
} catch (NotFoundException $e) {
try {
return $this->rootFolder->newFolder($name);
} catch (NotPermittedException $e) {
throw new \RuntimeException('Could not get appdata folder');
}
}
}

/**
Expand All @@ -70,56 +100,64 @@ public function __construct(IRootFolder $rootFolder,
*/
private function getAppDataFolder(): Folder {
if ($this->folder === null) {
$instanceId = $this->config->getValue('instanceid', null);
if ($instanceId === null) {
throw new \RuntimeException('no instance id!');
}

$name = 'appdata_' . $instanceId;
$name = $this->getAppDataFolderName();

try {
$appDataFolder = $this->rootFolder->get($name);
$this->folder = $this->rootFolder->get($name . '/' . $this->appId);
} catch (NotFoundException $e) {
try {
$appDataFolder = $this->rootFolder->newFolder($name);
} catch (NotPermittedException $e) {
throw new \RuntimeException('Could not get appdata folder');
}
}
$appDataRootFolder = $this->getAppDataRootFolder();

try {
$appDataFolder = $appDataFolder->get($this->appId);
} catch (NotFoundException $e) {
try {
$appDataFolder = $appDataFolder->newFolder($this->appId);
} catch (NotPermittedException $e) {
throw new \RuntimeException('Could not get appdata folder for ' . $this->appId);
$this->folder = $appDataRootFolder->get($this->appId);
} catch (NotFoundException $e) {
try {
$this->folder = $appDataRootFolder->newFolder($this->appId);
} catch (NotPermittedException $e) {
throw new \RuntimeException('Could not get appdata folder for ' . $this->appId);
}
}
}

$this->folder = $appDataFolder;
}

return $this->folder;
}

public function getFolder(string $name): ISimpleFolder {
$node = $this->getAppDataFolder()->get($name);
$key = $this->appId . '/' . $name;
if ($cachedFolder = $this->folders->get($key)) {
if ($cachedFolder instanceof \Exception) {
throw $cachedFolder;
} else {
return $cachedFolder;
}
}
try {
$path = $this->getAppDataFolderName() . '/' . $this->appId . '/' . $name;
$node = $this->rootFolder->get($path);
} catch (NotFoundException $e) {
$this->folders->set($key, $e);
throw $e;
}

/** @var Folder $node */
return new SimpleFolder($node);
$folder = new SimpleFolder($node);
$this->folders->set($key, $folder);
return $folder;
}

public function newFolder(string $name): ISimpleFolder {
$key = $this->appId . '/' . $name;
$folder = $this->getAppDataFolder()->newFolder($name);

return new SimpleFolder($folder);
$simpleFolder = new SimpleFolder($folder);
$this->folders->set($key, $simpleFolder);
return $simpleFolder;
}

public function getDirectoryListing(): array {
$listing = $this->getAppDataFolder()->getDirectoryListing();

$fileListing = array_map(function(Node $folder) {
$fileListing = array_map(function (Node $folder) {
if ($folder instanceof Folder) {
return new SimpleFolder($folder);
}
Expand Down
7 changes: 6 additions & 1 deletion lib/private/Files/AppData/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Factory {
/** @var SystemConfig */
private $config;

private $folders = [];

public function __construct(IRootFolder $rootFolder,
SystemConfig $systemConfig) {

Expand All @@ -46,6 +48,9 @@ public function __construct(IRootFolder $rootFolder,
* @return AppData
*/
public function get(string $appId): AppData {
return new AppData($this->rootFolder, $this->config, $appId);
if (!isset($this->folders[$appId])) {
$this->folders[$appId] = new AppData($this->rootFolder, $this->config, $appId);
}
return $this->folders[$appId];
}
}
24 changes: 7 additions & 17 deletions tests/lib/Files/AppData/AppDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,39 +55,30 @@ public function setUp() {
}

private function setupAppFolder() {
$dataFolder = $this->createMock(Folder::class);
$appFolder = $this->createMock(Folder::class);

$this->rootFolder->expects($this->once())
->method('get')
->with($this->equalTo('appdata_iid'))
->willReturn($dataFolder);
$dataFolder->expects($this->once())
$this->rootFolder->expects($this->any())
->method('get')
->with($this->equalTo('myApp'))
->with($this->equalTo('appdata_iid/myApp'))
->willReturn($appFolder);

return [$dataFolder, $appFolder];
return $appFolder;
}

public function testGetFolder() {
$folders = $this->setupAppFolder();
$appFolder = $folders[1];

$folder = $this->createMock(Folder::class);

$appFolder->expects($this->once())
$this->rootFolder->expects($this->once())
->method('get')
->with($this->equalTo('folder'))
->with($this->equalTo('appdata_iid/myApp/folder'))
->willReturn($folder);

$result = $this->appData->getFolder('folder');
$this->assertInstanceOf(ISimpleFolder::class, $result);
}

public function testNewFolder() {
$folders = $this->setupAppFolder();
$appFolder = $folders[1];
$appFolder = $this->setupAppFolder();

$folder = $this->createMock(Folder::class);

Expand All @@ -101,8 +92,7 @@ public function testNewFolder() {
}

public function testGetDirectoryListing() {
$folders = $this->setupAppFolder();
$appFolder = $folders[1];
$appFolder = $this->setupAppFolder();

$file = $this->createMock(File::class);
$folder = $this->createMock(Folder::class);
Expand Down