Added I/O stats (work in progress)

This commit is contained in:
Sebastian Stenzel
2019-08-27 15:50:15 +02:00
parent 71e414ae5c
commit f4ee8d0a15
14 changed files with 189 additions and 44 deletions
@@ -48,7 +48,7 @@ import java.util.function.Predicate;
@PerVault
public class Vault {
public static final Predicate<Vault> NOT_LOCKED = hasState(State.LOCKED).negate();
public static final Predicate<Vault> NOT_LOCKED = hasState(VaultState.LOCKED).negate();
private static final Logger LOG = LoggerFactory.getLogger(Vault.class);
private static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
@@ -56,8 +56,9 @@ public class Vault {
private final VaultSettings vaultSettings;
private final Provider<Volume> volumeProvider;
private final StringBinding defaultMountFlags;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem = new AtomicReference<>();
private final ObjectProperty<State> state = new SimpleObjectProperty<State>(State.LOCKED);
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final ObjectProperty<VaultState> state ;
private final VaultStats stats;
private final ObjectProperty<Path> accessPoint = new SimpleObjectProperty<>(Path.of(""));
private final StringBinding displayableName;
private final StringBinding displayablePath;
@@ -67,16 +68,14 @@ public class Vault {
private Volume volume;
public enum State {
LOCKED, PROCESSING, UNLOCKED
}
@Inject
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags) {
Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, ObjectProperty<VaultState> state, VaultStats stats) {
this.vaultSettings = vaultSettings;
this.volumeProvider = volumeProvider;
this.defaultMountFlags = defaultMountFlags;
this.cryptoFileSystem = cryptoFileSystem;
this.state = state;
this.stats = stats;
this.displayableName = Bindings.createStringBinding(this::getDisplayableName, vaultSettings.path());
this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());
this.locked = Bindings.createBooleanBinding(this::isLocked, state);
@@ -166,7 +165,7 @@ public class Vault {
volume.reveal();
}
public static Predicate<Vault> hasState(State state) {
public static Predicate<Vault> hasState(VaultState state) {
return vault -> {
return vault.getState() == state;
};
@@ -176,15 +175,15 @@ public class Vault {
// Observable Properties
// *******************************************************************************
public ObjectProperty<State> stateProperty() {
public ObjectProperty<VaultState> stateProperty() {
return state;
}
public State getState() {
public VaultState getState() {
return state.get();
}
public void setState(State value) {
public void setState(VaultState value) {
state.setValue(value);
}
@@ -193,7 +192,7 @@ public class Vault {
}
public boolean isLocked() {
return state.get() == State.LOCKED;
return state.get() == VaultState.LOCKED;
}
public BooleanBinding processingProperty() {
@@ -201,7 +200,7 @@ public class Vault {
}
public boolean isProcessing() {
return state.get() == State.PROCESSING;
return state.get() == VaultState.PROCESSING;
}
public BooleanBinding unlockedProperty() {
@@ -209,7 +208,7 @@ public class Vault {
}
public boolean isUnlocked() {
return state.get() == State.UNLOCKED;
return state.get() == VaultState.UNLOCKED;
}
public StringBinding displayableNameProperty() {
@@ -230,7 +229,7 @@ public class Vault {
}
private void setAccessPoint(Observable obs) {
if (this.getState() == State.UNLOCKED) {
if (this.getState() == VaultState.UNLOCKED) {
accessPoint.setValue(volume.getMountPointSafe().get());
} else {
accessPoint.setValue(Path.of(""));
@@ -256,6 +255,10 @@ public class Vault {
// Getter/Setter
// *******************************************************************************/
public VaultStats getStats() {
return stats;
}
public Observable[] observables() {
return new Observable[]{state};
}
@@ -8,18 +8,18 @@ package org.cryptomator.common.vaults;
import dagger.Module;
import dagger.Provides;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.settings.VolumeImpl;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,12 +27,25 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;
@Module
public class VaultModule {
private static final Logger LOG = LoggerFactory.getLogger(VaultModule.class);
@Provides
@PerVault
public AtomicReference<CryptoFileSystem> provideCryptoFileSystemReference() {
return new AtomicReference<>();
}
@Provides
@PerVault
public ObjectProperty<VaultState> provideVaultState() {
return new SimpleObjectProperty<>(VaultState.LOCKED);
}
@Provides
public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) {
VolumeImpl preferredImpl = settings.preferredVolumeImpl().get();
@@ -0,0 +1,6 @@
package org.cryptomator.common.vaults;
public enum VaultState {
LOCKED, PROCESSING, UNLOCKED;
}
@@ -0,0 +1,102 @@
package org.cryptomator.common.vaults;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
@PerVault
public class VaultStats {
private static final Logger LOG = LoggerFactory.getLogger(VaultStats.class);
private final AtomicReference<CryptoFileSystem> fs;
private final ObjectProperty<VaultState> state;
private final ScheduledService<Optional<CryptoFileSystemStats>> updateService;
private final LongProperty bytesPerSecondRead = new SimpleLongProperty();
private final LongProperty bytesPerSecondWritten = new SimpleLongProperty();
@Inject
VaultStats(AtomicReference<CryptoFileSystem> fs, ObjectProperty<VaultState> state, ExecutorService executor) {
this.fs = fs;
this.state = state;
this.updateService = new UpdateStatsService();
updateService.setExecutor(executor);
updateService.setPeriod(Duration.seconds(1));
state.addListener(this::vaultStateChanged);
}
private void vaultStateChanged(@SuppressWarnings("unused") Observable observable) {
switch (state.get()) {
case UNLOCKED:
assert fs.get() != null;
LOG.debug("start recording stats");
updateService.start();
break;
case LOCKED:
LOG.debug("stop recording stats");
updateService.cancel();
break;
default:
break;
}
}
private void updateStats(Optional<CryptoFileSystemStats> stats) {
assert Platform.isFxApplicationThread();
bytesPerSecondRead.set(stats.map(CryptoFileSystemStats::pollBytesRead).orElse(0l));
bytesPerSecondWritten.set(stats.map(CryptoFileSystemStats::pollBytesWritten).orElse(0l));
}
private class UpdateStatsService extends ScheduledService<Optional<CryptoFileSystemStats>> {
@Override
protected Task<Optional<CryptoFileSystemStats>> createTask() {
return new Task<>() {
@Override
protected Optional<CryptoFileSystemStats> call() {
return Optional.ofNullable(fs.get()).map(CryptoFileSystem::getStats);
}
};
}
@Override
protected void succeeded() {
assert getValue() != null;
updateStats(getValue());
super.succeeded();
}
}
/* Observables */
public LongProperty bytesPerSecondReadProperty() {
return bytesPerSecondRead;
}
public long getBytesPerSecondRead() {
return bytesPerSecondRead.get();
}
public LongProperty bytesPerSecondWrittenProperty() {
return bytesPerSecondWritten;
}
public long getBytesPerSecondWritten() {
return bytesPerSecondWritten.get();
}
}