diff --git a/main/filesystem-stats/pom.xml b/main/filesystem-stats/pom.xml
index 8cf146c7d..b3f3daceb 100644
--- a/main/filesystem-stats/pom.xml
+++ b/main/filesystem-stats/pom.xml
@@ -22,10 +22,6 @@
org.cryptomator
filesystem-api
-
- org.cryptomator
- commons
-
diff --git a/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java b/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java
index 71b445192..d295f9abe 100644
--- a/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java
+++ b/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java
@@ -20,20 +20,12 @@ public class StatsFileSystem extends StatsFolder implements FileSystem {
this.written = written;
}
- public long getBytesRead() {
- return read.sum();
+ public long getThenResetBytesRead() {
+ return read.sumThenReset();
}
- public void resetBytesRead() {
- read.reset();
- }
-
- public long getBytesWritten() {
- return written.sum();
- }
-
- public void resetBytesWritten() {
- written.reset();
+ public long getThenResetBytesWritten() {
+ return written.sumThenReset();
}
}
diff --git a/main/filesystem-stats/src/test/java/org/cryptomator/filesystem/stats/StatsFileSystemTest.java b/main/filesystem-stats/src/test/java/org/cryptomator/filesystem/stats/StatsFileSystemTest.java
index 7952cdcd2..dfcfb378f 100644
--- a/main/filesystem-stats/src/test/java/org/cryptomator/filesystem/stats/StatsFileSystemTest.java
+++ b/main/filesystem-stats/src/test/java/org/cryptomator/filesystem/stats/StatsFileSystemTest.java
@@ -19,32 +19,24 @@ public class StatsFileSystemTest {
statsFs.folder("foo").create();
File testFile = statsFs.folder("foo").file("bar");
- Assert.assertEquals(0l, statsFs.getBytesRead());
- Assert.assertEquals(0l, statsFs.getBytesWritten());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesRead());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesWritten());
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());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesRead());
+ Assert.assertEquals(15l, statsFs.getThenResetBytesWritten());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesWritten());
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());
+ Assert.assertEquals(3l, statsFs.getThenResetBytesRead());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesRead());
+ Assert.assertEquals(0l, statsFs.getThenResetBytesWritten());
}
}
diff --git a/main/pom.xml b/main/pom.xml
index db5ecf041..5b8fc0b41 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -90,6 +90,11 @@
filesystem-crypto
${project.version}
+
+ org.cryptomator
+ filesystem-stats
+ ${project.version}
+
org.cryptomator
diff --git a/main/ui/pom.xml b/main/ui/pom.xml
index 6cf2d334a..faae1e994 100644
--- a/main/ui/pom.xml
+++ b/main/ui/pom.xml
@@ -34,6 +34,10 @@
org.cryptomator
filesystem-crypto
+
+ org.cryptomator
+ filesystem-stats
+
org.cryptomator
frontend-api
diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java
index 86f25c331..fdb7507c5 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java
@@ -29,6 +29,7 @@ import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
+import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Label;
import javafx.stage.Stage;
@@ -126,7 +127,7 @@ public class UnlockedController extends AbstractFXMLViewController {
// IO Graph
// ****************************************
- private void startIoSampling(final Object sampler) {
+ private void startIoSampling() {
final Series decryptedBytes = new Series<>();
decryptedBytes.setName("decrypted");
final Series encryptedBytes = new Series<>();
@@ -136,7 +137,7 @@ public class UnlockedController extends AbstractFXMLViewController {
ioGraph.getData().add(encryptedBytes);
ioAnimation = new Timeline();
- ioAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(IO_SAMPLING_INTERVAL), new IoSamplingAnimationHandler(sampler, decryptedBytes, encryptedBytes)));
+ ioAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(IO_SAMPLING_INTERVAL), new IoSamplingAnimationHandler(decryptedBytes, encryptedBytes)));
ioAnimation.setCycleCount(Animation.INDEFINITE);
ioAnimation.play();
}
@@ -153,45 +154,41 @@ public class UnlockedController extends AbstractFXMLViewController {
private static final double BYTES_TO_MEGABYTES_FACTOR = 1.0 / IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
private static final double SMOOTHING_FACTOR = 0.3;
private static final long EFFECTIVELY_ZERO = 100000; // 100kb
- private final Object sampler;
private final Series decryptedBytes;
private final Series encryptedBytes;
- private final int step = 0;
- private final long oldDecBytes = 0;
- private final long oldEncBytes = 0;
+ private int step = 0;
+ private long oldDecBytes = 0;
+ private long oldEncBytes = 0;
- public IoSamplingAnimationHandler(Object sampler, Series decryptedBytes, Series encryptedBytes) {
- this.sampler = sampler;
+ public IoSamplingAnimationHandler(Series decryptedBytes, Series encryptedBytes) {
this.decryptedBytes = decryptedBytes;
this.encryptedBytes = encryptedBytes;
}
@Override
public void handle(ActionEvent event) {
- /*
- * step++;
- *
- * final long decBytes = sampler.pollDecryptedBytes(true);
- * final double smoothedDecBytes = oldDecBytes + SMOOTHING_FACTOR * (decBytes - oldDecBytes);
- * final double smoothedDecMb = smoothedDecBytes * BYTES_TO_MEGABYTES_FACTOR;
- * oldDecBytes = smoothedDecBytes > EFFECTIVELY_ZERO ? (long) smoothedDecBytes : 0l;
- * decryptedBytes.getData().add(new Data(step, smoothedDecMb));
- * if (decryptedBytes.getData().size() > IO_SAMPLING_STEPS) {
- * decryptedBytes.getData().remove(0);
- * }
- *
- * final long encBytes = sampler.pollEncryptedBytes(true);
- * final double smoothedEncBytes = oldEncBytes + SMOOTHING_FACTOR * (encBytes - oldEncBytes);
- * final double smoothedEncMb = smoothedEncBytes * BYTES_TO_MEGABYTES_FACTOR;
- * oldEncBytes = smoothedEncBytes > EFFECTIVELY_ZERO ? (long) smoothedEncBytes : 0l;
- * encryptedBytes.getData().add(new Data(step, smoothedEncMb));
- * if (encryptedBytes.getData().size() > IO_SAMPLING_STEPS) {
- * encryptedBytes.getData().remove(0);
- * }
- *
- * xAxis.setLowerBound(step - IO_SAMPLING_STEPS);
- * xAxis.setUpperBound(step);
- */
+ step++;
+
+ final long decBytes = vault.pollBytesRead();
+ final double smoothedDecBytes = oldDecBytes + SMOOTHING_FACTOR * (decBytes - oldDecBytes);
+ final double smoothedDecMb = smoothedDecBytes * BYTES_TO_MEGABYTES_FACTOR;
+ oldDecBytes = smoothedDecBytes > EFFECTIVELY_ZERO ? (long) smoothedDecBytes : 0l;
+ decryptedBytes.getData().add(new Data(step, smoothedDecMb));
+ if (decryptedBytes.getData().size() > IO_SAMPLING_STEPS) {
+ decryptedBytes.getData().remove(0);
+ }
+
+ final long encBytes = vault.pollBytesWritten();
+ final double smoothedEncBytes = oldEncBytes + SMOOTHING_FACTOR * (encBytes - oldEncBytes);
+ final double smoothedEncMb = smoothedEncBytes * BYTES_TO_MEGABYTES_FACTOR;
+ oldEncBytes = smoothedEncBytes > EFFECTIVELY_ZERO ? (long) smoothedEncBytes : 0l;
+ encryptedBytes.getData().add(new Data(step, smoothedEncMb));
+ if (encryptedBytes.getData().size() > IO_SAMPLING_STEPS) {
+ encryptedBytes.getData().remove(0);
+ }
+
+ xAxis.setLowerBound(step - IO_SAMPLING_STEPS);
+ xAxis.setUpperBound(step);
}
}
@@ -214,15 +211,9 @@ public class UnlockedController extends AbstractFXMLViewController {
}
});
- // sample crypto-throughput:
- /*
- * stopIoSampling();
- * if (vault.getCryptor() instanceof CryptorIOSampling) {
- * startIoSampling((CryptorIOSampling) vault.getCryptor());
- * } else {
- * ioGraph.setVisible(false);
- * }
- */
+ // (re)start throughput statistics:
+ stopIoSampling();
+ startIoSampling();
}
public LockListener getListener() {
diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
index 8b7984fe3..8c555737b 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
@@ -21,6 +21,7 @@ import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate;
import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory;
import org.cryptomator.filesystem.nio.NioFileSystem;
+import org.cryptomator.filesystem.stats.StatsFileSystem;
import org.cryptomator.frontend.CommandFailedException;
import org.cryptomator.frontend.Frontend;
import org.cryptomator.frontend.Frontend.MountParam;
@@ -42,7 +43,6 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
private static final long serialVersionUID = 3754487289683599469L;
- @Deprecated
public static final String VAULT_FILE_EXTENSION = ".cryptomator";
@Deprecated
@@ -58,6 +58,7 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
private String mountName;
private Character winDriveLetter;
+ private Optional statsFileSystem = Optional.empty();
private DeferredClosable filesystemFrontend = DeferredClosable.empty();
/**
@@ -76,14 +77,10 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
}
}
- public boolean isValidVaultDirectory() {
- return Files.isDirectory(path) && path.getFileName().toString().endsWith(VAULT_FILE_EXTENSION);
- }
-
- public boolean containsMasterKey() throws IOException {
- final Path masterKeyPath = path.resolve(VAULT_MASTERKEY_FILE);
- return Files.isRegularFile(masterKeyPath);
- }
+ /*
+ * ******************************************************************************
+ * Commands
+ ********************************************************************************/
public void create(CharSequence passphrase) throws IOException {
try {
@@ -110,10 +107,12 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
try {
FileSystem fs = NioFileSystem.rootedAt(path);
FileSystem cryptoFs = cryptoFileSystemFactory.unlockExisting(fs, passphrase, this);
+ StatsFileSystem statsFs = new StatsFileSystem(cryptoFs);
+ statsFileSystem = Optional.of(statsFs);
String contextPath = StringUtils.prependIfMissing(mountName, "/");
- Frontend frontend = frontendFactory.get().create(cryptoFs, contextPath);
+ Frontend frontend = frontendFactory.get().create(statsFs, contextPath);
filesystemFrontend = closer.closeLater(frontend);
- setUnlocked(true);
+ unlocked.set(true);
} catch (UncheckedIOException e) {
throw new FrontendCreationFailedException(e);
}
@@ -121,7 +120,8 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
public synchronized void deactivateFrontend() {
filesystemFrontend.close();
- setUnlocked(false);
+ statsFileSystem = Optional.empty();
+ unlocked.set(false);
}
private Map> getMountParams() {
@@ -150,7 +150,10 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
Optionals.ifPresent(filesystemFrontend.get(), Frontend::unmount);
}
- /* Delegate Methods */
+ /*
+ * ******************************************************************************
+ * Delegate methods
+ ********************************************************************************/
@Override
public void authenticationFailed(String cleartextPath) {
@@ -162,7 +165,10 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
return namesOfResourcesWithInvalidMac.contains(cleartextPath);
}
- /* Getter/Setter */
+ /*
+ * ******************************************************************************
+ * Getter/Setter
+ ********************************************************************************/
public Path getPath() {
return path;
@@ -175,6 +181,15 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
return StringUtils.removeEnd(path.getFileName().toString(), VAULT_FILE_EXTENSION);
}
+ public boolean isValidVaultDirectory() {
+ return Files.isDirectory(path) && path.getFileName().toString().endsWith(VAULT_FILE_EXTENSION);
+ }
+
+ public boolean containsMasterKey() throws IOException {
+ final Path masterKeyPath = path.resolve(VAULT_MASTERKEY_FILE);
+ return Files.isRegularFile(masterKeyPath);
+ }
+
public ObjectProperty unlockedProperty() {
return unlocked;
}
@@ -183,10 +198,6 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
return unlocked.get();
}
- public void setUnlocked(boolean unlocked) {
- this.unlocked.set(unlocked);
- }
-
public ObservableList getNamesOfResourcesWithInvalidMac() {
return namesOfResourcesWithInvalidMac;
}
@@ -195,6 +206,14 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
return whitelistedResourcesWithInvalidMac;
}
+ public long pollBytesRead() {
+ return statsFileSystem.map(StatsFileSystem::getThenResetBytesRead).orElse(0l);
+ }
+
+ public long pollBytesWritten() {
+ return statsFileSystem.map(StatsFileSystem::getThenResetBytesWritten).orElse(0l);
+ }
+
/**
* Tries to form a similar string using the regular latin alphabet.
*
@@ -247,7 +266,10 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
this.winDriveLetter = winDriveLetter;
}
- /* hashcode/equals */
+ /*
+ * ******************************************************************************
+ * Hashcode / Equals
+ ********************************************************************************/
@Override
public int hashCode() {