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
@@ -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;
}
};
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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());
}
}
@@ -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);
}
}