support for RFC 4331: DAV:quota-available-bytes and DAV:quota-used-bytes

references #97; quota calculation in NIO filesystem still missing
This commit is contained in:
Sebastian Stenzel
2016-02-23 18:13:19 +01:00
parent 95b5f4c765
commit 7cb435e517
14 changed files with 158 additions and 15 deletions

View File

@@ -23,4 +23,8 @@ public interface FileSystem extends Folder {
return Optional.empty();
}
Optional<Long> quotaUsedBytes();
Optional<Long> quotaAvailableBytes();
}

View File

@@ -0,0 +1,22 @@
package org.cryptomator.filesystem.delegating;
import java.util.Optional;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
public interface DelegatingFileSystem extends FileSystem {
Folder getDelegate();
@Override
default Optional<Long> quotaUsedBytes() {
return getDelegate().fileSystem().quotaUsedBytes();
}
@Override
default Optional<Long> quotaAvailableBytes() {
return getDelegate().fileSystem().quotaAvailableBytes();
}
}

View File

@@ -0,0 +1,32 @@
package org.cryptomator.filesystem.delegating;
import java.util.Optional;
import org.cryptomator.filesystem.FileSystem;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class DelegatingFileSystemTest {
@Test
public void testQuotaAvailableBytes() {
FileSystem mockFs = Mockito.mock(FileSystem.class);
Mockito.when(mockFs.fileSystem()).thenReturn(mockFs);
Mockito.when(mockFs.quotaAvailableBytes()).thenReturn(Optional.of(42l));
DelegatingFileSystem delegatingFs = TestDelegatingFileSystem.withRoot(mockFs);
Assert.assertEquals(mockFs.quotaAvailableBytes(), delegatingFs.quotaAvailableBytes());
}
@Test
public void testQuotaUsedBytes() {
FileSystem mockFs = Mockito.mock(FileSystem.class);
Mockito.when(mockFs.fileSystem()).thenReturn(mockFs);
Mockito.when(mockFs.quotaUsedBytes()).thenReturn(Optional.of(23l));
DelegatingFileSystem delegatingFs = TestDelegatingFileSystem.withRoot(mockFs);
Assert.assertEquals(mockFs.quotaUsedBytes(), delegatingFs.quotaUsedBytes());
}
}

View File

@@ -1,9 +1,8 @@
package org.cryptomator.filesystem.delegating;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
class TestDelegatingFileSystem extends TestDelegatingFolder implements FileSystem {
class TestDelegatingFileSystem extends TestDelegatingFolder implements DelegatingFileSystem {
private TestDelegatingFileSystem(Folder delegate) {
super(null, delegate);
@@ -13,4 +12,9 @@ class TestDelegatingFileSystem extends TestDelegatingFolder implements FileSyste
return new TestDelegatingFileSystem(delegate);
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -8,13 +8,18 @@
*******************************************************************************/
package org.cryptomator.filesystem.blockaligned;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
class BlockAlignedFileSystem extends BlockAlignedFolder implements FileSystem {
class BlockAlignedFileSystem extends BlockAlignedFolder implements DelegatingFileSystem {
public BlockAlignedFileSystem(Folder delegate, int blockSize) {
super(null, delegate, blockSize);
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -55,6 +55,16 @@ class CryptoFileSystem extends CryptoFolder implements FileSystem {
return physicalRoot.folder(DATA_ROOT_DIR);
}
@Override
public Optional<Long> quotaUsedBytes() {
return physicalRoot.fileSystem().quotaUsedBytes();
}
@Override
public Optional<Long> quotaAvailableBytes() {
return physicalRoot.fileSystem().quotaAvailableBytes();
}
@Override
public Optional<CryptoFolder> parent() {
return Optional.empty();

View File

@@ -39,4 +39,16 @@ public class InMemoryFileSystem extends InMemoryFolder implements FileSystem {
return "/";
}
@Override
public Optional<Long> quotaUsedBytes() {
long used = Runtime.getRuntime().totalMemory();
return Optional.of(used);
}
@Override
public Optional<Long> quotaAvailableBytes() {
long available = Runtime.getRuntime().freeMemory();
return Optional.of(available);
}
}

View File

@@ -10,14 +10,19 @@ package org.cryptomator.filesystem.blacklisting;
import java.util.function.Predicate;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
class BlacklistingFileSystem extends BlacklistingFolder implements FileSystem {
class BlacklistingFileSystem extends BlacklistingFolder implements DelegatingFileSystem {
public BlacklistingFileSystem(Folder root, Predicate<Node> hiddenNodes) {
super(null, root, hiddenNodes);
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -8,14 +8,19 @@
*******************************************************************************/
package org.cryptomator.filesystem.shortening;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
public class ShorteningFileSystem extends ShorteningFolder implements FileSystem {
public class ShorteningFileSystem extends ShorteningFolder implements DelegatingFileSystem {
public ShorteningFileSystem(Folder root, Folder metadataRoot, int threshold) {
super(null, root, "", new FilenameShortener(metadataRoot, threshold));
create();
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -16,4 +16,16 @@ public class NioFileSystem extends NioFolder implements FileSystem {
create();
}
@Override
public Optional<Long> quotaUsedBytes() {
// TODO du -sh
return Optional.empty();
}
@Override
public Optional<Long> quotaAvailableBytes() {
// TODO df -lh
return Optional.empty();
}
}

View File

@@ -10,10 +10,10 @@ package org.cryptomator.filesystem.stats;
import java.util.concurrent.atomic.LongAdder;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
public class StatsFileSystem extends StatsFolder implements FileSystem {
public class StatsFileSystem extends StatsFolder implements DelegatingFileSystem {
private final LongAdder read;
private final LongAdder written;
@@ -36,4 +36,9 @@ public class StatsFileSystem extends StatsFolder implements FileSystem {
return written.sumThenReset();
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -9,10 +9,10 @@
package org.cryptomator.filesystem.jackrabbit;
import org.apache.jackrabbit.webdav.DavLocatorFactory;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
class FileSystemLocator extends FolderLocator implements FileSystem {
class FileSystemLocator extends FolderLocator implements DelegatingFileSystem {
public FileSystemLocator(DavLocatorFactory factory, String prefix, Folder delegate) {
super(factory, prefix, null, delegate);
@@ -28,4 +28,9 @@ class FileSystemLocator extends FolderLocator implements FileSystem {
return "/";
}
@Override
public Folder getDelegate() {
return delegate;
}
}

View File

@@ -17,6 +17,7 @@ import java.time.Instant;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceIterator;
@@ -26,6 +27,7 @@ import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.io.InputContext;
import org.apache.jackrabbit.webdav.io.OutputContext;
import org.apache.jackrabbit.webdav.lock.LockManager;
import org.apache.jackrabbit.webdav.property.DavProperty;
import org.apache.jackrabbit.webdav.property.DavPropertyName;
import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
import org.apache.jackrabbit.webdav.property.ResourceType;
@@ -39,6 +41,9 @@ import com.google.common.io.ByteStreams;
class DavFolder extends DavNode<FolderLocator> {
private static final DavPropertyName PROPERTY_QUOTA_AVAILABLE = DavPropertyName.create("quota-available-bytes");
private static final DavPropertyName PROPERTY_QUOTA_USED = DavPropertyName.create("quota-used-bytes");
public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, FolderLocator folder) {
super(factory, lockManager, session, folder);
properties.add(new ResourceType(ResourceType.COLLECTION));
@@ -173,7 +178,7 @@ class DavFolder extends DavNode<FolderLocator> {
@Override
protected void setModificationTime(Instant instant) {
// TODO Auto-generated method stub
node.setLastModified(instant);
}
@Override
@@ -181,4 +186,20 @@ class DavFolder extends DavNode<FolderLocator> {
node.setCreationTime(instant);
}
@Override
public DavPropertyName[] getPropertyNames() {
return ArrayUtils.addAll(super.getPropertyNames(), PROPERTY_QUOTA_AVAILABLE, PROPERTY_QUOTA_USED);
}
@Override
public DavProperty<?> getProperty(DavPropertyName name) {
if (PROPERTY_QUOTA_AVAILABLE.equals(name)) {
return node.fileSystem().quotaAvailableBytes().map(numBytes -> new DefaultDavProperty<Long>(name, numBytes)).orElse(null);
} else if (PROPERTY_QUOTA_USED.equals(name)) {
return node.fileSystem().quotaUsedBytes().map(numBytes -> new DefaultDavProperty<Long>(name, numBytes)).orElse(null);
} else {
return super.getProperty(name);
}
}
}

View File

@@ -20,6 +20,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavSession;
@@ -40,8 +41,8 @@ import org.cryptomator.filesystem.jackrabbit.FileSystemResourceLocator;
abstract class DavNode<T extends FileSystemResourceLocator> implements DavResource {
private static final String DAV_COMPLIANCE_CLASSES = "1, 2";
private static final String[] DAV_CREATIONDATE_PROPNAMES = {DavPropertyName.CREATIONDATE.getName(), "Win32CreationTime"};
private static final String[] DAV_MODIFIEDDATE_PROPNAMES = {DavPropertyName.GETLASTMODIFIED.getName(), "Win32LastModifiedTime"};
private static final String[] DAV_CREATIONDATE_PROPNAMES = {DavConstants.PROPERTY_CREATIONDATE, "Win32CreationTime"};
private static final String[] DAV_MODIFIEDDATE_PROPNAMES = {DavConstants.PROPERTY_GETLASTMODIFIED, "Win32LastModifiedTime"};
protected final FilesystemResourceFactory factory;
protected final LockManager lockManager;