I/O statistics filesystem layer

This commit is contained in:
Sebastian Stenzel
2016-01-28 20:49:32 +01:00
parent 4059f99fd5
commit 6af4ee08f7
8 changed files with 269 additions and 0 deletions

1
main/filesystem-stats/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target/

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
This file is licensed under the terms of the MIT license.
See the LICENSE.txt file for more info.
Contributors:
Sebastian Stenzel - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>0.11.0-SNAPSHOT</version>
</parent>
<artifactId>filesystem-stats</artifactId>
<name>Cryptomator filesystem: Throughput statistics</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,49 @@
package org.cryptomator.filesystem.stats;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.util.function.Consumer;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
import org.cryptomator.filesystem.delegating.DelegatingFile;
import org.cryptomator.filesystem.delegating.DelegatingReadableFile;
import org.cryptomator.filesystem.delegating.DelegatingWritableFile;
public class StatsFile extends DelegatingFile<StatsFolder> {
private final Consumer<Long> readCounter;
private final Consumer<Long> writeCounter;
public StatsFile(StatsFolder parent, File delegate, Consumer<Long> readCounter, Consumer<Long> writeCounter) {
super(parent, delegate);
this.readCounter = readCounter;
this.writeCounter = writeCounter;
}
@Override
public ReadableFile openReadable() throws UncheckedIOException {
return new DelegatingReadableFile(delegate.openReadable()) {
@Override
public int read(ByteBuffer target) throws UncheckedIOException {
int num = super.read(target);
readCounter.accept((long) num);
return num;
}
};
}
@Override
public WritableFile openWritable() throws UncheckedIOException {
return new DelegatingWritableFile(delegate.openWritable()) {
@Override
public int write(ByteBuffer source) throws UncheckedIOException {
int num = super.write(source);
writeCounter.accept((long) num);
return num;
}
};
}
}

View File

@@ -0,0 +1,39 @@
package org.cryptomator.filesystem.stats;
import java.util.concurrent.atomic.LongAdder;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
public class StatsFileSystem extends StatsFolder implements FileSystem {
private final LongAdder read;
private final LongAdder written;
public StatsFileSystem(Folder root) {
this(root, new LongAdder(), new LongAdder());
}
private StatsFileSystem(Folder root, LongAdder read, LongAdder written) {
super(null, root, read::add, written::add);
this.read = read;
this.written = written;
}
public long getBytesRead() {
return read.sum();
}
public void resetBytesRead() {
read.reset();
}
public long getBytesWritten() {
return written.sum();
}
public void resetBytesWritten() {
written.reset();
}
}

View File

@@ -0,0 +1,30 @@
package org.cryptomator.filesystem.stats;
import java.util.function.Consumer;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFolder;
public class StatsFolder extends DelegatingFolder<StatsFolder, StatsFile> {
private final Consumer<Long> readCounter;
private final Consumer<Long> writeCounter;
public StatsFolder(StatsFolder parent, Folder delegate, Consumer<Long> readCounter, Consumer<Long> writeCounter) {
super(parent, delegate);
this.readCounter = readCounter;
this.writeCounter = writeCounter;
}
@Override
protected StatsFile newFile(File delegate) {
return new StatsFile(this, delegate, readCounter, writeCounter);
}
@Override
protected StatsFolder newFolder(Folder delegate) {
return new StatsFolder(this, delegate, readCounter, writeCounter);
}
}

View File

@@ -0,0 +1,50 @@
package org.cryptomator.filesystem.stats;
import java.nio.ByteBuffer;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
import org.cryptomator.filesystem.inmem.InMemoryFileSystem;
import org.junit.Assert;
import org.junit.Test;
public class StatsFileSystemTest {
@Test
public void testReadAndWriteCounters() {
FileSystem underlyingFs = new InMemoryFileSystem();
StatsFileSystem statsFs = new StatsFileSystem(underlyingFs);
statsFs.folder("foo").create();
File testFile = statsFs.folder("foo").file("bar");
Assert.assertEquals(0l, statsFs.getBytesRead());
Assert.assertEquals(0l, statsFs.getBytesWritten());
try (WritableFile w = testFile.openWritable()) {
w.write(ByteBuffer.allocate(15));
}
Assert.assertEquals(0l, statsFs.getBytesRead());
Assert.assertEquals(15l, statsFs.getBytesWritten());
statsFs.resetBytesWritten();
Assert.assertEquals(0l, statsFs.getBytesRead());
Assert.assertEquals(0l, statsFs.getBytesWritten());
try (ReadableFile r = testFile.openReadable()) {
r.read(ByteBuffer.allocate(3));
}
Assert.assertEquals(3l, statsFs.getBytesRead());
Assert.assertEquals(0l, statsFs.getBytesWritten());
statsFs.resetBytesRead();
Assert.assertEquals(0l, statsFs.getBytesRead());
Assert.assertEquals(0l, statsFs.getBytesWritten());
}
}

View File

@@ -0,0 +1,50 @@
package org.cryptomator.filesystem.stats;
import java.nio.ByteBuffer;
import java.util.function.Consumer;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
import org.junit.Test;
import org.mockito.Mockito;
public class StatsFileTest {
@Test
public void testStatsDuringRead() {
ReadableFile readable = Mockito.mock(ReadableFile.class);
File file = Mockito.mock(File.class);
Mockito.when(file.openReadable()).thenReturn(readable);
@SuppressWarnings("unchecked")
Consumer<Long> readCounter = Mockito.mock(Consumer.class);
File statsFile = new StatsFile(null, file, readCounter, null);
Mockito.when(readable.read(Mockito.any())).thenReturn(123);
try (ReadableFile r = statsFile.openReadable()) {
r.read(ByteBuffer.allocate(0));
}
Mockito.verify(readCounter).accept(123l);
}
@Test
public void testStatsDuringWrite() {
WritableFile writable = Mockito.mock(WritableFile.class);
File file = Mockito.mock(File.class);
Mockito.when(file.openWritable()).thenReturn(writable);
@SuppressWarnings("unchecked")
Consumer<Long> writeCounter = Mockito.mock(Consumer.class);
File statsFile = new StatsFile(null, file, null, writeCounter);
Mockito.when(writable.write(Mockito.any())).thenReturn(123);
try (WritableFile w = statsFile.openWritable()) {
w.write(ByteBuffer.allocate(0));
}
Mockito.verify(writeCounter).accept(123l);
}
}

View File

@@ -253,6 +253,7 @@
<module>filesystem-nio</module>
<module>filesystem-nameshortening</module>
<module>filesystem-crypto</module>
<module>filesystem-stats</module>
<module>filesystem-invariants-tests</module>
<module>frontend-api</module>
<module>frontend-webdav</module>