mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-07-20 15:02:58 +00:00
"lock" deduplication
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
package org.cryptomator.ui.common;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.common.vaults.Volume;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
@FxApplicationScoped
|
||||
public class VaultService {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VaultService.class);
|
||||
|
||||
private final ExecutorService executorService;
|
||||
|
||||
@Inject
|
||||
public VaultService(ExecutorService executorService) {
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks a vault in a background thread.
|
||||
*
|
||||
* @param vault The vault to lock
|
||||
* @param forced Whether to attempt a forced lock
|
||||
*/
|
||||
public void lock(Vault vault, boolean forced) {
|
||||
Task<Void> task = createLockTask(vault, forced);
|
||||
task.setOnSucceeded(evt -> LOG.info("Locked {}", vault.getDisplayableName()));
|
||||
task.setOnFailed(evt -> LOG.error("Failed to lock vault " + vault.getDisplayableName(), evt.getSource().getException()));
|
||||
executorService.execute(task);
|
||||
}
|
||||
|
||||
public void lockAll(Collection<Vault> vaults, boolean forced) {
|
||||
Service<Void> service = createLockAllService(vaults, forced);
|
||||
service.setOnFailed(evt -> LOG.error("Failed to lock vault", evt.getSource().getException()));
|
||||
service.setExecutor(executorService);
|
||||
service.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates but doesn't start a lock-all service that can be run on a background thread.
|
||||
*
|
||||
* @param vaults The list of vaults to be locked. Must not be concurrently modified
|
||||
* @param forced Whether to attempt a forced lock
|
||||
* @return Service that tries to lock all given vaults
|
||||
*/
|
||||
public Service<Void> createLockAllService(Collection<Vault> vaults, boolean forced) {
|
||||
Iterator<Vault> iter = vaults.iterator();
|
||||
return new ScheduledService<>() {
|
||||
|
||||
@Override
|
||||
protected Task<Void> createTask() {
|
||||
assert Platform.isFxApplicationThread();
|
||||
if (iter.hasNext()) {
|
||||
return createLockTask(iter.next(), forced);
|
||||
} else {
|
||||
// This should be unreachable code, since iter is only accessed on the FX App Thread.
|
||||
// But if quitting the application takes longer for any reason, this service should shut down properly
|
||||
reset();
|
||||
return createNoopTask();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates but doesn't start a lock task that can be run on a background thread.
|
||||
*
|
||||
* @param vault The vault to lock
|
||||
* @param forced Whether to attempt a forced lock
|
||||
* @return Task that tries to lock the given vault
|
||||
*/
|
||||
public Task<Void> createLockTask(Vault vault, boolean forced) {
|
||||
return new Task<>() {
|
||||
@Override
|
||||
protected Void call() throws Volume.VolumeException {
|
||||
vault.lock(forced);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduled() {
|
||||
vault.setState(VaultState.PROCESSING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
vault.setState(VaultState.LOCKED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void failed() {
|
||||
vault.setState(VaultState.UNLOCKED);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Task<Void> createNoopTask() {
|
||||
return new Task<>() {
|
||||
@Override
|
||||
protected Void call() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+6
-15
@@ -8,6 +8,7 @@ import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.common.vaults.Volume;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.Tasks;
|
||||
import org.cryptomator.ui.common.VaultService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,12 +21,12 @@ public class VaultDetailUnlockedController implements FxController {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VaultDetailUnlockedController.class);
|
||||
|
||||
private final ReadOnlyObjectProperty<Vault> vault;
|
||||
private final ExecutorService executor;
|
||||
private final VaultService vaultService;
|
||||
|
||||
@Inject
|
||||
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, ExecutorService executor) {
|
||||
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, VaultService vaultService) {
|
||||
this.vault = vault;
|
||||
this.executor = executor;
|
||||
this.vaultService = vaultService;
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -39,18 +40,8 @@ public class VaultDetailUnlockedController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void lock() {
|
||||
Vault v = vault.get();
|
||||
v.setState(VaultState.PROCESSING);
|
||||
Tasks.create(() -> {
|
||||
v.lock(false);
|
||||
}).onSuccess(() -> {
|
||||
LOG.trace("Regular unmount succeeded.");
|
||||
v.setState(VaultState.LOCKED);
|
||||
}).onError(Exception.class, e -> {
|
||||
v.setState(VaultState.UNLOCKED);
|
||||
LOG.error("Regular unmount failed.", e);
|
||||
// TODO
|
||||
}).runOnce(executor);
|
||||
vaultService.lock(vault.get(), false);
|
||||
// TODO count lock attempts, and allow forced lock
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package org.cryptomator.ui.quit;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.common.vaults.Volume;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.VaultService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -19,7 +16,6 @@ import javax.inject.Inject;
|
||||
import java.awt.desktop.QuitResponse;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
@QuitScoped
|
||||
@@ -31,14 +27,16 @@ public class QuitController implements FxController {
|
||||
private final QuitResponse response;
|
||||
private final ObservableList<Vault> unlockedVaults;
|
||||
private final ExecutorService executor;
|
||||
private final VaultService vaultService;
|
||||
public Button lockAndQuitButton;
|
||||
|
||||
@Inject
|
||||
QuitController(@QuitWindow Stage window, QuitResponse response, ObservableList<Vault> vaults, ExecutorService executor) {
|
||||
QuitController(@QuitWindow Stage window, QuitResponse response, ObservableList<Vault> vaults, ExecutorService executor, VaultService vaultService) {
|
||||
this.window = window;
|
||||
this.response = response;
|
||||
this.unlockedVaults = vaults.filtered(Vault::isUnlocked);
|
||||
this.executor = executor;
|
||||
this.vaultService = vaultService;
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -52,11 +50,11 @@ public class QuitController implements FxController {
|
||||
public void lockAndQuit() {
|
||||
lockAndQuitButton.setDisable(true);
|
||||
lockAndQuitButton.setContentDisplay(ContentDisplay.LEFT);
|
||||
|
||||
Iterator<Vault> toBeLocked = List.copyOf(unlockedVaults).iterator();
|
||||
ScheduledService<Void> lockAllService = new LockAllVaultsService(executor, toBeLocked);
|
||||
|
||||
Service<Void> lockAllService = vaultService.createLockAllService(List.copyOf(unlockedVaults), false);
|
||||
|
||||
lockAllService.setOnSucceeded(evt -> {
|
||||
if (!toBeLocked.hasNext()) {
|
||||
if (unlockedVaults.isEmpty()) {
|
||||
window.close();
|
||||
response.performQuit();
|
||||
}
|
||||
@@ -71,65 +69,4 @@ public class QuitController implements FxController {
|
||||
lockAllService.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vault The vault to lock
|
||||
* @return Task that tries to lock the given vault gracefully.
|
||||
*/
|
||||
private Task<Void> createGracefulLockTask(Vault vault) {
|
||||
Task task = new Task<Void>() {
|
||||
@Override
|
||||
protected Void call() throws Volume.VolumeException {
|
||||
vault.lock(false);
|
||||
LOG.info("Locked {}", vault.getDisplayableName());
|
||||
return null;
|
||||
}
|
||||
};
|
||||
task.setOnScheduled(evt -> {
|
||||
vault.setState(VaultState.PROCESSING);
|
||||
});
|
||||
task.setOnSucceeded(evt -> {
|
||||
vault.setState(VaultState.LOCKED);
|
||||
});
|
||||
task.setOnFailed(evt -> {
|
||||
LOG.warn("Failed to lock vault", vault);
|
||||
});
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Task that succeeds immediately
|
||||
*/
|
||||
private Task<Void> createNoopTask() {
|
||||
return new Task<>() {
|
||||
@Override
|
||||
protected Void call() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class LockAllVaultsService extends ScheduledService<Void> {
|
||||
|
||||
private final Iterator<Vault> vaultsToLock;
|
||||
|
||||
public LockAllVaultsService(Executor executor, Iterator<Vault> vaultsToLock) {
|
||||
this.vaultsToLock = vaultsToLock;
|
||||
setExecutor(executor);
|
||||
setRestartOnFailure(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<Void> createTask() {
|
||||
assert Platform.isFxApplicationThread();
|
||||
if (vaultsToLock.hasNext()) {
|
||||
return createGracefulLockTask(vaultsToLock.next());
|
||||
} else {
|
||||
// This should be unreachable code, since vaultsToLock is only accessed on the FX App Thread.
|
||||
// But if quitting the application takes longer for any reason, this service should shut down properly
|
||||
reset();
|
||||
return createNoopTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user