) getList()).removeListener(listener);
+ }
+}
diff --git a/common/src/main/java/bisq/common/proto/persistable/ThreadedPersistableEnvelope.java b/common/src/main/java/bisq/common/proto/persistable/ThreadedPersistableEnvelope.java
deleted file mode 100644
index 7cee389f07e..00000000000
--- a/common/src/main/java/bisq/common/proto/persistable/ThreadedPersistableEnvelope.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.common.proto.persistable;
-
-import com.google.protobuf.Message;
-
-/**
- * Interface for the outer envelope object persisted to disk, where its serialization
- * during persistence takes place on a separate thread (for performance).
- *
- * To make the serialization thread-safe, all modifications of the object must be
- * synchronized with it. This may be achieved by wrapping such modifications with the
- * provided {@link ThreadedPersistableEnvelope#modifySynchronized(Runnable)} method.
- */
-public interface ThreadedPersistableEnvelope extends PersistableEnvelope {
-
- @Override
- default Message toPersistableMessage() {
- synchronized (this) {
- return toProtoMessage();
- }
- }
-
- default void modifySynchronized(Runnable modifyTask) {
- synchronized (this) {
- modifyTask.run();
- }
- }
-}
diff --git a/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableEnvelope.java b/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableEnvelope.java
deleted file mode 100644
index 1b3a91a8ff6..00000000000
--- a/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableEnvelope.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.common.proto.persistable;
-
-import bisq.common.UserThread;
-
-import com.google.protobuf.Message;
-
-import com.google.common.util.concurrent.Futures;
-
-import java.util.concurrent.FutureTask;
-
-/**
- * Interface for the outer envelope object persisted to disk, where its serialization
- * during persistence is forced to take place on the user thread.
- *
- * To avoid jitter, this should be only be used for small, safely critical stores. Larger
- * or frequently written stores should either implement {@link PersistableEnvelope}
- * directly (where thread-safety isn't needed) or use {@link ThreadedPersistableEnvelope}.
- */
-public interface UserThreadMappedPersistableEnvelope extends PersistableEnvelope {
-
- @Override
- default Message toPersistableMessage() {
- FutureTask toProtoOnUserThread = new FutureTask<>(this::toProtoMessage);
- UserThread.execute(toProtoOnUserThread);
- return Futures.getUnchecked(toProtoOnUserThread);
- }
-}
diff --git a/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableList.java b/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableList.java
deleted file mode 100644
index d9829910b5c..00000000000
--- a/common/src/main/java/bisq/common/proto/persistable/UserThreadMappedPersistableList.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.common.proto.persistable;
-
-import java.util.List;
-
-public abstract class UserThreadMappedPersistableList extends PersistableList
- implements UserThreadMappedPersistableEnvelope {
-
- public UserThreadMappedPersistableList(List list) {
- super(list);
- }
-
- public UserThreadMappedPersistableList() {
- }
-}
diff --git a/common/src/main/java/bisq/common/storage/FileManager.java b/common/src/main/java/bisq/common/storage/FileManager.java
deleted file mode 100644
index fa9b00af89d..00000000000
--- a/common/src/main/java/bisq/common/storage/FileManager.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.common.storage;
-
-import bisq.common.UserThread;
-import bisq.common.proto.persistable.PersistableEnvelope;
-import bisq.common.proto.persistable.PersistenceProtoResolver;
-import bisq.common.util.Utilities;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import java.util.Random;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class FileManager {
- private final File dir;
- private final File storageFile;
- private final ScheduledThreadPoolExecutor executor;
- private final long delay;
- private final Callable saveFileTask;
- private final AtomicReference nextWrite;
- private final PersistenceProtoResolver persistenceProtoResolver;
- private Path usedTempFilePath;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Constructor
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- public FileManager(File dir, File storageFile, long delay, PersistenceProtoResolver persistenceProtoResolver) {
- this.dir = dir;
- this.storageFile = storageFile;
- this.persistenceProtoResolver = persistenceProtoResolver;
- this.nextWrite = new AtomicReference<>(null);
-
- executor = Utilities.getScheduledThreadPoolExecutor("FileManager", 1, 10, 5);
-
- // File must only be accessed from the auto-save executor from now on, to avoid simultaneous access.
- this.delay = delay;
-
- saveFileTask = () -> {
- try {
- Thread.currentThread().setName("Save-file-task-" + new Random().nextInt(10000));
-
- // Atomically take the next object to write and set the value to null so concurrent saveFileTask
- // won't duplicate work.
- T persistable = this.nextWrite.getAndSet(null);
-
- // If null, a concurrent saveFileTask already grabbed the data. Don't duplicate work.
- if (persistable == null)
- return null;
-
- long now = System.currentTimeMillis();
- saveToFile(persistable, dir, storageFile);
- log.debug("Save {} completed in {} msec", storageFile, System.currentTimeMillis() - now);
- } catch (Throwable e) {
- log.error("Error during saveFileTask", e);
- }
- return null;
- };
- Runtime.getRuntime().addShutdownHook(new Thread(() ->
- UserThread.execute(FileManager.this::shutDown), "FileManager.ShutDownHook")
- );
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // API
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- /**
- * Queues up a save in the background. Useful for not very important wallet changes.
- */
- void saveLater(T persistable) {
- saveLater(persistable, delay);
- }
-
- public void saveLater(T persistable, long delayInMilli) {
- // Atomically set the value of the next write. This allows batching of multiple writes of the same data
- // structure if there are multiple calls to saveLater within a given `delayInMillis`.
- this.nextWrite.set(persistable);
-
- // Always schedule a write. It is possible that a previous saveLater was called with a larger `delayInMilli`
- // and we want the lower delay to execute. The saveFileTask handles concurrent operations.
- executor.schedule(saveFileTask, delayInMilli, TimeUnit.MILLISECONDS);
- }
-
- @SuppressWarnings("unchecked")
- public synchronized T read(File file) {
- log.debug("Read from disc: {}", file.getName());
-
- try (final FileInputStream fileInputStream = new FileInputStream(file)) {
- protobuf.PersistableEnvelope persistable = protobuf.PersistableEnvelope.parseDelimitedFrom(fileInputStream);
- return (T) persistenceProtoResolver.fromProto(persistable);
- } catch (Throwable t) {
- String errorMsg = "Exception at proto read: " + t.getMessage() + " file:" + file.getAbsolutePath();
- log.error(errorMsg, t);
- //if(DevEnv.DEV_MODE)
- throw new RuntimeException(errorMsg);
- }
- }
-
- synchronized void removeFile(String fileName) {
- File file = new File(dir, fileName);
- boolean result = file.delete();
- if (!result)
- log.warn("Could not delete file: " + file.toString());
-
- File backupDir = new File(Paths.get(dir.getAbsolutePath(), "backup").toString());
- if (backupDir.exists()) {
- File backupFile = new File(Paths.get(dir.getAbsolutePath(), "backup", fileName).toString());
- if (backupFile.exists()) {
- result = backupFile.delete();
- if (!result)
- log.warn("Could not delete backupFile: " + file.toString());
- }
- }
- }
-
-
- /**
- * Shut down auto-saving.
- */
- private void shutDown() {
- executor.shutdown();
- try {
- executor.awaitTermination(5, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public static void removeAndBackupFile(File dbDir, File storageFile, String fileName, String backupFolderName)
- throws IOException {
- File corruptedBackupDir = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName).toString());
- if (!corruptedBackupDir.exists())
- if (!corruptedBackupDir.mkdir())
- log.warn("make dir failed");
-
- File corruptedFile = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName, fileName).toString());
- if (storageFile.exists()) {
- FileUtil.renameFile(storageFile, corruptedFile);
- }
- }
-
- synchronized void removeAndBackupFile(String fileName) throws IOException {
- removeAndBackupFile(dir, storageFile, fileName, "backup_of_corrupted_data");
- }
-
- synchronized void backupFile(String fileName, int numMaxBackupFiles) {
- FileUtil.rollingBackup(dir, fileName, numMaxBackupFiles);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Private
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- private synchronized void saveToFile(T persistable, File dir, File storageFile) {
- File tempFile = null;
- FileOutputStream fileOutputStream = null;
- PrintWriter printWriter = null;
-
- try {
- log.debug("Write to disc: {}", storageFile.getName());
- protobuf.PersistableEnvelope protoPersistable;
- try {
- protoPersistable = (protobuf.PersistableEnvelope) persistable.toPersistableMessage();
- if (protoPersistable.toByteArray().length == 0)
- log.error("protoPersistable is empty. persistable=" + persistable.getClass().getSimpleName());
- } catch (Throwable e) {
- log.error("Error in saveToFile toProtoMessage: {}, {}", persistable.getClass().getSimpleName(), storageFile);
- e.printStackTrace();
- throw new RuntimeException(e);
- }
-
- if (!dir.exists() && !dir.mkdir())
- log.warn("make dir failed");
-
- tempFile = usedTempFilePath != null
- ? FileUtil.createNewFile(usedTempFilePath)
- : File.createTempFile("temp", null, dir);
- // Don't use a new temp file path each time, as that causes the delete-on-exit hook to leak memory:
- tempFile.deleteOnExit();
-
- fileOutputStream = new FileOutputStream(tempFile);
-
- log.debug("Writing protobuffer class:{} to file:{}", persistable.getClass(), storageFile.getName());
- protoPersistable.writeDelimitedTo(fileOutputStream);
-
- // Attempt to force the bits to hit the disk. In reality the OS or hard disk itself may still decide
- // to not write through to physical media for at least a few seconds, but this is the best we can do.
- fileOutputStream.flush();
- fileOutputStream.getFD().sync();
-
- // Close resources before replacing file with temp file because otherwise it causes problems on windows
- // when rename temp file
- fileOutputStream.close();
-
- FileUtil.renameFile(tempFile, storageFile);
- usedTempFilePath = tempFile.toPath();
- } catch (Throwable t) {
- // If an error occurred, don't attempt to reuse this path again, in case temp file cleanup fails.
- usedTempFilePath = null;
- log.error("Error at saveToFile, storageFile=" + storageFile.toString(), t);
- } finally {
- if (tempFile != null && tempFile.exists()) {
- log.warn("Temp file still exists after failed save. We will delete it now. storageFile=" + storageFile);
- if (!tempFile.delete())
- log.error("Cannot delete temp file.");
- }
-
- try {
- if (fileOutputStream != null)
- fileOutputStream.close();
- if (printWriter != null)
- printWriter.close();
- } catch (IOException e) {
- // We swallow that
- e.printStackTrace();
- log.error("Cannot close resources." + e.getMessage());
- }
- }
- }
-}
diff --git a/common/src/main/java/bisq/common/storage/Storage.java b/common/src/main/java/bisq/common/storage/Storage.java
deleted file mode 100644
index 3521d8c6844..00000000000
--- a/common/src/main/java/bisq/common/storage/Storage.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.common.storage;
-
-import bisq.common.app.DevEnv;
-import bisq.common.config.Config;
-import bisq.common.proto.persistable.PersistableEnvelope;
-import bisq.common.proto.persistable.PersistenceProtoResolver;
-
-import com.google.inject.Inject;
-
-import javax.inject.Named;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Nullable;
-
-import static bisq.common.util.Preconditions.checkDir;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * That class handles the storage of a particular object to disk using Protobuffer.
- *
- * For every data object we write a separate file to minimize the risk of corrupted files in case of inconsistency from newer versions.
- * In case of a corrupted file we backup the old file to a separate directory, so if it holds critical data it might be helpful for recovery.
- *
- * We also backup at first read the file, so we have a valid file form the latest version in case a write operation corrupted the file.
- *
- * The read operation is triggered just at object creation (startup) and is at the moment not executed on a background thread to avoid asynchronous behaviour.
- * As the data are small and it is just one read access the performance penalty is small and might be even worse to create and setup a thread for it.
- *
- * The write operation used a background thread and supports a delayed write to avoid too many repeated write operations.
- */
-public class Storage {
- private static final Logger log = LoggerFactory.getLogger(Storage.class);
-
- private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
-
- private final File dir;
- private FileManager fileManager;
- private File storageFile;
- private T persistable;
- private String fileName;
- private int numMaxBackupFiles = 10;
- private final PersistenceProtoResolver persistenceProtoResolver;
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Constructor
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Inject
- public Storage(@Named(Config.STORAGE_DIR) File dir,
- PersistenceProtoResolver persistenceProtoResolver,
- CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) {
- this.dir = checkDir(dir);
- this.persistenceProtoResolver = persistenceProtoResolver;
- this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler;
- }
-
- @Nullable
- public T getPersisted(String fileName) {
- return getPersisted(new File(dir, fileName));
- }
-
- @Nullable
- public T initAndGetPersistedWithFileName(String fileName, long delay) {
- this.fileName = fileName;
- storageFile = new File(dir, fileName);
- fileManager = new FileManager<>(dir, storageFile, delay, persistenceProtoResolver);
- return getPersisted(storageFile);
- }
-
- @Nullable
- public T initAndGetPersisted(T persistable, long delay) {
- return initAndGetPersisted(persistable, persistable.getClass().getSimpleName(), delay);
- }
-
- @Nullable
- public T initAndGetPersisted(T persistable, String fileName, long delay) {
- this.persistable = persistable;
- this.fileName = fileName;
- storageFile = new File(dir, fileName);
- fileManager = new FileManager<>(dir, storageFile, delay, persistenceProtoResolver);
- return getPersisted(storageFile);
- }
-
- public void queueUpForSave() {
- queueUpForSave(persistable);
- }
-
- public void queueUpForSave(long delayInMilli) {
- queueUpForSave(persistable, delayInMilli);
- }
-
- public void setNumMaxBackupFiles(int numMaxBackupFiles) {
- this.numMaxBackupFiles = numMaxBackupFiles;
- }
-
- // Save delayed and on a background thread
- public void queueUpForSave(T persistable) {
- if (persistable != null) {
- checkNotNull(storageFile, "storageFile = null. Call setupFileStorage before using read/write.");
-
- fileManager.saveLater(persistable);
- } else {
- log.trace("queueUpForSave called but no persistable set");
- }
- }
-
- public void queueUpForSave(T persistable, long delayInMilli) {
- if (persistable != null) {
- checkNotNull(storageFile, "storageFile = null. Call setupFileStorage before using read/write.");
-
- fileManager.saveLater(persistable, delayInMilli);
- } else {
- log.trace("queueUpForSave called but no persistable set");
- }
- }
-
- public void remove(String fileName) {
- fileManager.removeFile(fileName);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Private
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- // We do the file read on the UI thread to avoid problems from multi threading.
- // Data are small and read is done only at startup, so it is no performance issue.
- @Nullable
- private T getPersisted(File storageFile) {
- if (storageFile.exists()) {
- long now = System.currentTimeMillis();
- try {
- T persistedObject = fileManager.read(storageFile);
- log.trace("Read {} completed in {}msec", storageFile, System.currentTimeMillis() - now);
-
- // If we did not get any exception we can be sure the data are consistent so we make a backup
- now = System.currentTimeMillis();
- fileManager.backupFile(fileName, numMaxBackupFiles);
- log.trace("Backup {} completed in {}msec", storageFile, System.currentTimeMillis() - now);
-
- return persistedObject;
- } catch (Throwable t) {
- log.error("We cannot read the persisted data. " +
- "We make a backup and remove the inconsistent file. fileName=" + fileName);
- log.error(t.getMessage());
- try {
- // We keep a backup which might be used for recovery
- removeAndBackupFile(fileName);
- DevEnv.logErrorAndThrowIfDevMode(t.toString());
- } catch (IOException e1) {
- e1.printStackTrace();
- log.error(e1.getMessage());
- // We swallow Exception if backup fails
- }
- if (corruptedDatabaseFilesHandler != null)
- corruptedDatabaseFilesHandler.onFileCorrupted(storageFile.getName());
- }
- }
- return null;
- }
-
- public void removeAndBackupFile(String fileName) throws IOException {
- fileManager.removeAndBackupFile(fileName);
- }
-}
diff --git a/common/src/main/java/bisq/common/taskrunner/Model.java b/common/src/main/java/bisq/common/taskrunner/Model.java
index 514add29490..4a0ead244c3 100644
--- a/common/src/main/java/bisq/common/taskrunner/Model.java
+++ b/common/src/main/java/bisq/common/taskrunner/Model.java
@@ -18,7 +18,5 @@
package bisq.common.taskrunner;
public interface Model {
- void persist();
-
void onComplete();
}
diff --git a/common/src/main/java/bisq/common/taskrunner/TaskRunner.java b/common/src/main/java/bisq/common/taskrunner/TaskRunner.java
index f6f6d12d2bb..d8870b09f48 100644
--- a/common/src/main/java/bisq/common/taskrunner/TaskRunner.java
+++ b/common/src/main/java/bisq/common/taskrunner/TaskRunner.java
@@ -28,7 +28,7 @@
@Slf4j
public class TaskRunner {
- private final Queue> tasks = new LinkedBlockingQueue<>();
+ private final Queue>> tasks = new LinkedBlockingQueue<>();
private final T sharedModel;
private final Class sharedModelClass;
private final ResultHandler resultHandler;
@@ -36,7 +36,7 @@ public class TaskRunner {
private boolean failed = false;
private boolean isCanceled;
- private Class extends Task> currentTask;
+ private Class extends Task> currentTask;
public TaskRunner(T sharedModel, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
@@ -82,7 +82,6 @@ public void cancel() {
}
void handleComplete() {
- sharedModel.persist();
next();
}
diff --git a/common/src/main/java/bisq/common/util/Utilities.java b/common/src/main/java/bisq/common/util/Utilities.java
index 2a65a60cb89..426dcb162ba 100644
--- a/common/src/main/java/bisq/common/util/Utilities.java
+++ b/common/src/main/java/bisq/common/util/Utilities.java
@@ -58,6 +58,7 @@
import java.util.TimeZone;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
@@ -79,7 +80,6 @@
@Slf4j
public class Utilities {
- // TODO check out Jackson lib
public static String objectToJson(Object object) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new AnnotationExclusionStrategy())
@@ -90,12 +90,16 @@ public static String objectToJson(Object object) {
return gson.toJson(object);
}
- public static ListeningExecutorService getSingleThreadExecutor(String name) {
+ public static ExecutorService getSingleThreadExecutor(String name) {
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat(name)
.setDaemon(true)
.build();
- return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(threadFactory));
+ return Executors.newSingleThreadExecutor(threadFactory);
+ }
+
+ public static ListeningExecutorService getSingleThreadListeningExecutor(String name) {
+ return MoreExecutors.listeningDecorator(getSingleThreadExecutor(name));
}
public static ListeningExecutorService getListeningExecutorService(String name,
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java
index 722522cba78..a27c0ade90f 100644
--- a/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java
@@ -22,10 +22,10 @@
import bisq.network.p2p.storage.persistence.MapStoreService;
import bisq.common.config.Config;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
-import javax.inject.Named;
import javax.inject.Inject;
+import javax.inject.Named;
import java.io.File;
@@ -33,8 +33,6 @@
import lombok.extern.slf4j.Slf4j;
-import static com.google.common.base.Preconditions.checkArgument;
-
@Slf4j
public class SignedWitnessStorageService extends MapStoreService {
private static final String FILE_NAME = "SignedWitnessStore";
@@ -46,14 +44,19 @@ public class SignedWitnessStorageService extends MapStoreService persistableNetworkPayloadMapStorage) {
- super(storageDir, persistableNetworkPayloadMapStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
+
@Override
public String getFileName() {
return FILE_NAME;
@@ -78,12 +81,4 @@ public boolean canHandle(PersistableNetworkPayload payload) {
protected SignedWitnessStore createStore() {
return new SignedWitnessStore();
}
-
- @Override
- protected void readStore() {
- super.readStore();
- checkArgument(store instanceof SignedWitnessStore,
- "Store is not instance of SignedWitnessStore. That can happen if the ProtoBuffer " +
- "file got changed. We cleared the data store and recreated it again.");
- }
}
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java
index a1e8372f8e1..d764ed3409b 100644
--- a/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java
@@ -18,7 +18,6 @@
package bisq.core.account.sign;
-import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.persistence.PersistableNetworkPayloadStore;
import com.google.protobuf.Message;
@@ -35,7 +34,7 @@
* definition and provide a hashMap for the domain access.
*/
@Slf4j
-public class SignedWitnessStore extends PersistableNetworkPayloadStore {
+public class SignedWitnessStore extends PersistableNetworkPayloadStore {
SignedWitnessStore() {
}
@@ -46,7 +45,7 @@ public class SignedWitnessStore extends PersistableNetworkPayloadStore {
///////////////////////////////////////////////////////////////////////////////////////////
private SignedWitnessStore(List list) {
- list.forEach(item -> map.put(new P2PDataStorage.ByteArray(item.getHash()), item));
+ super(list);
}
public Message toProtoMessage() {
@@ -68,8 +67,4 @@ public static SignedWitnessStore fromProto(protobuf.SignedWitnessStore proto) {
.map(SignedWitness::fromProto).collect(Collectors.toList());
return new SignedWitnessStore(list);
}
-
- public boolean containsKey(P2PDataStorage.ByteArray hash) {
- return map.containsKey(hash);
- }
}
diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
index bc261e7efe5..93ab89b0f94 100644
--- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
@@ -22,10 +22,10 @@
import bisq.network.p2p.storage.persistence.MapStoreService;
import bisq.common.config.Config;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
-import javax.inject.Named;
import javax.inject.Inject;
+import javax.inject.Named;
import java.io.File;
@@ -33,8 +33,6 @@
import lombok.extern.slf4j.Slf4j;
-import static com.google.common.base.Preconditions.checkArgument;
-
@Slf4j
public class AccountAgeWitnessStorageService extends MapStoreService {
private static final String FILE_NAME = "AccountAgeWitnessStore";
@@ -46,14 +44,19 @@ public class AccountAgeWitnessStorageService extends MapStoreService persistableNetworkPayloadMapStorage) {
- super(storageDir, persistableNetworkPayloadMapStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
+
@Override
public String getFileName() {
return FILE_NAME;
@@ -78,12 +81,4 @@ public boolean canHandle(PersistableNetworkPayload payload) {
protected AccountAgeWitnessStore createStore() {
return new AccountAgeWitnessStore();
}
-
- @Override
- protected void readStore() {
- super.readStore();
- checkArgument(store instanceof AccountAgeWitnessStore,
- "Store is not instance of AccountAgeWitnessStore. That can happen if the ProtoBuffer " +
- "file got changed. We cleared the data store and recreated it again.");
- }
}
diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
index 0da7f9d211d..28661102ded 100644
--- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
@@ -17,7 +17,6 @@
package bisq.core.account.witness;
-import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.persistence.PersistableNetworkPayloadStore;
import com.google.protobuf.Message;
@@ -34,7 +33,7 @@
* definition and provide a hashMap for the domain access.
*/
@Slf4j
-public class AccountAgeWitnessStore extends PersistableNetworkPayloadStore {
+public class AccountAgeWitnessStore extends PersistableNetworkPayloadStore {
AccountAgeWitnessStore() {
}
@@ -45,7 +44,7 @@ public class AccountAgeWitnessStore extends PersistableNetworkPayloadStore {
///////////////////////////////////////////////////////////////////////////////////////////
private AccountAgeWitnessStore(List list) {
- list.forEach(item -> map.put(new P2PDataStorage.ByteArray(item.getHash()), item));
+ super(list);
}
public Message toProtoMessage() {
@@ -67,8 +66,4 @@ public static AccountAgeWitnessStore fromProto(protobuf.AccountAgeWitnessStore p
.map(AccountAgeWitness::fromProto).collect(Collectors.toList());
return new AccountAgeWitnessStore(list);
}
-
- public boolean containsKey(P2PDataStorage.ByteArray hash) {
- return map.containsKey(hash);
- }
}
diff --git a/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java b/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
index 91e6145bf47..4415b4acfa9 100644
--- a/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
+++ b/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
@@ -20,8 +20,8 @@
import bisq.core.user.Preferences;
import bisq.common.config.Config;
-import bisq.common.storage.FileUtil;
-import bisq.common.storage.ResourceNotFoundException;
+import bisq.common.file.FileUtil;
+import bisq.common.file.ResourceNotFoundException;
import bisq.common.util.Utilities;
import javax.inject.Inject;
diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java
index f1376be8d66..8e403b97dc1 100644
--- a/core/src/main/java/bisq/core/app/BisqExecutable.java
+++ b/core/src/main/java/bisq/core/app/BisqExecutable.java
@@ -31,11 +31,11 @@
import bisq.common.UserThread;
import bisq.common.app.AppModule;
-import bisq.common.app.DevEnv;
import bisq.common.config.BisqHelpFormatter;
import bisq.common.config.Config;
import bisq.common.config.ConfigException;
import bisq.common.handlers.ResultHandler;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.setup.CommonSetup;
import bisq.common.setup.GracefulShutDownHandler;
@@ -45,13 +45,18 @@
import com.google.inject.Guice;
import com.google.inject.Injector;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
import lombok.extern.slf4j.Slf4j;
+import javax.annotation.Nullable;
+
@Slf4j
public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSetup.BisqSetupListener, UncaughtExceptionHandler {
- private static final int EXIT_SUCCESS = 0;
- private static final int EXIT_FAILURE = 1;
+ public static final int EXIT_SUCCESS = 0;
+ public static final int EXIT_FAILURE = 1;
private final String fullName;
private final String scriptName;
@@ -127,7 +132,7 @@ protected void onApplicationLaunched() {
CommonSetup.setupUncaughtExceptionHandler(this);
setupGuice();
setupAvoidStandbyMode();
- startApplication();
+ readAllPersisted(this::startApplication);
}
@@ -148,21 +153,30 @@ protected Injector getInjector() {
}
protected void applyInjector() {
- setupPersistedDataHosts(injector);
+ // Subclasses might configure classes with the injector here
}
- protected void setupPersistedDataHosts(Injector injector) {
- try {
- PersistedDataHost.apply(CorePersistedDataHost.getPersistedDataHosts(injector));
- } catch (Throwable t) {
- log.error("Error at PersistedDataHost.apply: {}", t.toString(), t);
- // If we are in dev mode we want to get the exception if some db files are corrupted
- // We need to delay it as the stage is not created yet and so popups would not be shown.
- if (DevEnv.isDevMode())
- UserThread.runAfter(() -> {
- throw t;
- }, 2);
+ protected void readAllPersisted(Runnable completeHandler) {
+ readAllPersisted(null, completeHandler);
+ }
+
+ protected void readAllPersisted(@Nullable List additionalHosts, Runnable completeHandler) {
+ List hosts = CorePersistedDataHost.getPersistedDataHosts(injector);
+ if (additionalHosts != null) {
+ hosts.addAll(additionalHosts);
}
+
+ AtomicInteger remaining = new AtomicInteger(hosts.size());
+ hosts.forEach(e -> {
+ new Thread(() -> {
+ e.readPersisted();
+ remaining.decrementAndGet();
+ if (remaining.get() == 0) {
+ UserThread.execute(completeHandler);
+ }
+
+ }, "BisqExecutable-read-" + e.getClass().getSimpleName()).start();
+ });
}
protected void setupAvoidStandbyMode() {
@@ -199,9 +213,9 @@ public void gracefulShutDown(ResultHandler resultHandler) {
isShutdownInProgress = true;
if (injector == null) {
- log.warn("Shut down called before injector was created");
+ log.info("Shut down called before injector was created");
resultHandler.handleResult();
- System.exit(0);
+ System.exit(EXIT_SUCCESS);
}
try {
@@ -222,11 +236,12 @@ public void gracefulShutDown(ResultHandler resultHandler) {
injector.getInstance(P2PService.class).shutDown(() -> {
log.info("P2PService shutdown completed");
-
module.close(injector);
- resultHandler.handleResult();
- log.info("Graceful shutdown completed. Exiting now.");
- System.exit(0);
+ PersistenceManager.flushAllDataToDisk(() -> {
+ log.info("Graceful shutdown completed. Exiting now.");
+ resultHandler.handleResult();
+ System.exit(EXIT_SUCCESS);
+ });
});
});
walletsSetup.shutDown();
@@ -236,13 +251,20 @@ public void gracefulShutDown(ResultHandler resultHandler) {
// Wait max 20 sec.
UserThread.runAfter(() -> {
log.warn("Timeout triggered resultHandler");
- resultHandler.handleResult();
- System.exit(0);
+ PersistenceManager.flushAllDataToDisk(() -> {
+ log.info("Graceful shutdown resulted in a timeout. Exiting now.");
+ resultHandler.handleResult();
+ System.exit(EXIT_SUCCESS);
+ });
}, 20);
} catch (Throwable t) {
log.error("App shutdown failed with exception {}", t.toString());
t.printStackTrace();
- System.exit(1);
+ PersistenceManager.flushAllDataToDisk(() -> {
+ log.info("Graceful shutdown resulted in an error. Exiting now.");
+ resultHandler.handleResult();
+ System.exit(EXIT_FAILURE);
+ });
}
}
diff --git a/core/src/main/java/bisq/core/app/BisqHeadlessApp.java b/core/src/main/java/bisq/core/app/BisqHeadlessApp.java
index ed17af065eb..71a6ab4e394 100644
--- a/core/src/main/java/bisq/core/app/BisqHeadlessApp.java
+++ b/core/src/main/java/bisq/core/app/BisqHeadlessApp.java
@@ -20,8 +20,8 @@
import bisq.core.trade.TradeManager;
import bisq.common.UserThread;
+import bisq.common.file.CorruptedStorageFileHandler;
import bisq.common.setup.GracefulShutDownHandler;
-import bisq.common.storage.CorruptedDatabaseFilesHandler;
import com.google.inject.Injector;
@@ -33,7 +33,6 @@
@Slf4j
public class BisqHeadlessApp implements HeadlessApp {
- private static final long LOG_MEMORY_PERIOD_MIN = 10;
@Getter
private static Runnable shutDownHandler;
@@ -43,7 +42,7 @@ public class BisqHeadlessApp implements HeadlessApp {
private GracefulShutDownHandler gracefulShutDownHandler;
private boolean shutDownRequested;
protected BisqSetup bisqSetup;
- private CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
+ private CorruptedStorageFileHandler corruptedStorageFileHandler;
private TradeManager tradeManager;
public BisqHeadlessApp() {
@@ -55,7 +54,7 @@ public void startApplication() {
bisqSetup = injector.getInstance(BisqSetup.class);
bisqSetup.addBisqSetupListener(this);
- corruptedDatabaseFilesHandler = injector.getInstance(CorruptedDatabaseFilesHandler.class);
+ corruptedStorageFileHandler = injector.getInstance(CorruptedStorageFileHandler.class);
tradeManager = injector.getInstance(TradeManager.class);
setupHandlers();
@@ -96,8 +95,7 @@ protected void setupHandlers() {
bisqSetup.setOsxKeyLoggerWarningHandler(() -> log.info("setOsxKeyLoggerWarningHandler"));
bisqSetup.setQubesOSInfoHandler(() -> log.info("setQubesOSInfoHandler"));
- //TODO move to bisqSetup
- corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files));
+ corruptedStorageFileHandler.getFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files));
tradeManager.setTakeOfferRequestErrorMessageHandler(errorMessage -> log.error("onTakeOfferRequestErrorMessageHandler"));
}
diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java
index 4bafdc0058d..57a5b00fd61 100644
--- a/core/src/main/java/bisq/core/app/BisqSetup.java
+++ b/core/src/main/java/bisq/core/app/BisqSetup.java
@@ -122,15 +122,12 @@ public class BisqSetup {
public interface BisqSetupListener {
default void onInitP2pNetwork() {
- log.info("onInitP2pNetwork");
}
default void onInitWallet() {
- log.info("onInitWallet");
}
default void onRequestWalletPassword() {
- log.info("onRequestWalletPassword");
}
void onSetupComplete();
@@ -502,6 +499,7 @@ else if (displayTorNetworkSettingsHandler != null)
}, STARTUP_TIMEOUT_MINUTES, TimeUnit.MINUTES);
+ log.info("Init P2P network");
bisqSetupListeners.forEach(BisqSetupListener::onInitP2pNetwork);
p2pNetworkReady = p2PNetworkSetup.init(this::initWallet, displayTorNetworkSettingsHandler);
@@ -530,6 +528,7 @@ else if (displayTorNetworkSettingsHandler != null)
}
private void initWallet() {
+ log.info("Init wallet");
bisqSetupListeners.forEach(BisqSetupListener::onInitWallet);
Runnable walletPasswordHandler = () -> {
log.info("Wallet password required");
diff --git a/core/src/main/java/bisq/core/app/SetupUtils.java b/core/src/main/java/bisq/core/app/SetupUtils.java
index c0b3338dcd5..eb210da5fea 100644
--- a/core/src/main/java/bisq/core/app/SetupUtils.java
+++ b/core/src/main/java/bisq/core/app/SetupUtils.java
@@ -17,65 +17,22 @@
package bisq.core.app;
-import bisq.common.config.BaseCurrencyNetwork;
-
-import bisq.network.crypto.DecryptedDataTuple;
-import bisq.network.crypto.EncryptionService;
-import bisq.network.p2p.peers.keepalive.messages.Ping;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.common.UserThread;
+import bisq.common.config.BaseCurrencyNetwork;
import bisq.common.config.Config;
-import bisq.common.crypto.CryptoException;
-import bisq.common.crypto.KeyRing;
-import bisq.common.crypto.SealedAndSigned;
-import bisq.common.handlers.ResultHandler;
-import bisq.common.proto.ProtobufferException;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import java.util.Date;
-import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SetupUtils {
- public static void checkCryptoSetup(KeyRing keyRing, EncryptionService encryptionService,
- ResultHandler resultHandler, Consumer errorHandler) {
- // We want to test if the client is compiled with the correct crypto provider (BountyCastle)
- // and if the unlimited Strength for cryptographic keys is set.
- // If users compile themselves they might miss that step and then would get an exception in the trade.
- // To avoid that we add a sample encryption and signing here at startup to see if it doesn't cause an exception.
- // See: https://github.com/bisq-network/exchange/blob/master/doc/build.md#7-enable-unlimited-strength-for-cryptographic-keys
- Thread checkCryptoThread = new Thread(() -> {
- try {
- // just use any simple dummy msg
- Ping payload = new Ping(1, 1);
- SealedAndSigned sealedAndSigned = EncryptionService.encryptHybridWithSignature(payload,
- keyRing.getSignatureKeyPair(), keyRing.getPubKeyRing().getEncryptionPubKey());
- DecryptedDataTuple tuple = encryptionService.decryptHybridWithSignature(sealedAndSigned,
- keyRing.getEncryptionKeyPair().getPrivate());
- if (tuple.getNetworkEnvelope() instanceof Ping &&
- ((Ping) tuple.getNetworkEnvelope()).getNonce() == payload.getNonce() &&
- ((Ping) tuple.getNetworkEnvelope()).getLastRoundTripTime() == payload.getLastRoundTripTime()) {
- log.debug("Crypto test succeeded");
-
- UserThread.execute(resultHandler::handleResult);
- } else {
- errorHandler.accept(new CryptoException("Payload not correct after decryption"));
- }
- } catch (CryptoException | ProtobufferException e) {
- log.error(e.toString());
- e.printStackTrace();
- errorHandler.accept(e);
- }
- }, "checkCryptoThread");
- checkCryptoThread.start();
- }
-
public static BooleanProperty readFromResources(P2PDataStorage p2PDataStorage, Config config) {
BooleanProperty result = new SimpleBooleanProperty();
new Thread(() -> {
@@ -86,7 +43,7 @@ public static BooleanProperty readFromResources(P2PDataStorage p2PDataStorage, C
p2PDataStorage.readFromResources(postFix);
log.info("readFromResources took {} ms", (new Date().getTime() - ts));
UserThread.execute(() -> result.set(true));
- }, "readFromResourcesThread").start();
+ }, "BisqSetup-readFromResources").start();
return result;
}
}
diff --git a/core/src/main/java/bisq/core/app/TorSetup.java b/core/src/main/java/bisq/core/app/TorSetup.java
index 946058fd578..b2ff5378b79 100644
--- a/core/src/main/java/bisq/core/app/TorSetup.java
+++ b/core/src/main/java/bisq/core/app/TorSetup.java
@@ -18,8 +18,8 @@
package bisq.core.app;
import bisq.common.config.Config;
+import bisq.common.file.FileUtil;
import bisq.common.handlers.ErrorMessageHandler;
-import bisq.common.storage.FileUtil;
import javax.inject.Inject;
import javax.inject.Named;
@@ -39,7 +39,7 @@
@Slf4j
@Singleton
public class TorSetup {
- private File torDir;
+ private final File torDir;
@Inject
public TorSetup(@Named(Config.TOR_DIR) File torDir) {
diff --git a/core/src/main/java/bisq/core/app/WalletAppSetup.java b/core/src/main/java/bisq/core/app/WalletAppSetup.java
index 3c7c7466c39..74049ae6376 100644
--- a/core/src/main/java/bisq/core/app/WalletAppSetup.java
+++ b/core/src/main/java/bisq/core/app/WalletAppSetup.java
@@ -235,7 +235,7 @@ void setRejectedTxErrorMessageHandler(Consumer rejectedTxErrorMessageHan
}, 1);
});
- tradeManager.getTradesAsObservableList().stream()
+ tradeManager.getObservableList().stream()
.filter(trade -> trade.getOffer() != null)
.forEach(trade -> {
String details = null;
diff --git a/core/src/main/java/bisq/core/app/misc/AppSetup.java b/core/src/main/java/bisq/core/app/misc/AppSetup.java
index 213c2b0a270..88e8b12f15b 100644
--- a/core/src/main/java/bisq/core/app/misc/AppSetup.java
+++ b/core/src/main/java/bisq/core/app/misc/AppSetup.java
@@ -17,13 +17,8 @@
package bisq.core.app.misc;
-import bisq.core.app.SetupUtils;
-
-import bisq.network.crypto.EncryptionService;
-
import bisq.common.app.Version;
import bisq.common.config.Config;
-import bisq.common.crypto.KeyRing;
import javax.inject.Inject;
@@ -31,17 +26,11 @@
@Slf4j
public abstract class AppSetup {
- protected final EncryptionService encryptionService;
- protected final KeyRing keyRing;
protected final Config config;
@Inject
- public AppSetup(EncryptionService encryptionService,
- KeyRing keyRing,
- Config config) {
+ public AppSetup(Config config) {
// we need to reference it so the seed node stores tradeStatistics
- this.encryptionService = encryptionService;
- this.keyRing = keyRing;
this.config = config;
Version.setBaseCryptoNetworkId(this.config.baseCurrencyNetwork.ordinal());
@@ -49,14 +38,8 @@ public AppSetup(EncryptionService encryptionService,
}
public void start() {
- SetupUtils.checkCryptoSetup(keyRing, encryptionService, () -> {
- initPersistedDataHosts();
- initBasicServices();
- }, throwable -> {
- log.error(throwable.getMessage());
- throwable.printStackTrace();
- System.exit(1);
- });
+ initPersistedDataHosts();
+ initBasicServices();
}
abstract void initPersistedDataHosts();
diff --git a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
index 78d5beaf90a..8b2dc545d6c 100644
--- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
+++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
@@ -24,7 +24,6 @@
import bisq.core.filter.FilterManager;
import bisq.core.trade.statistics.TradeStatisticsManager;
-import bisq.network.crypto.EncryptionService;
import bisq.network.p2p.P2PService;
import bisq.network.p2p.P2PServiceListener;
import bisq.network.p2p.network.CloseConnectionReason;
@@ -32,7 +31,6 @@
import bisq.network.p2p.network.ConnectionListener;
import bisq.common.config.Config;
-import bisq.common.crypto.KeyRing;
import bisq.common.proto.persistable.PersistedDataHost;
import javax.inject.Inject;
@@ -56,16 +54,14 @@ public class AppSetupWithP2P extends AppSetup {
protected ArrayList persistedDataHosts;
@Inject
- public AppSetupWithP2P(EncryptionService encryptionService,
- KeyRing keyRing,
- P2PService p2PService,
+ public AppSetupWithP2P(P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService,
FilterManager filterManager,
TorSetup torSetup,
Config config) {
- super(encryptionService, keyRing, config);
+ super(config);
this.p2PService = p2PService;
this.tradeStatisticsManager = tradeStatisticsManager;
this.accountAgeWitnessService = accountAgeWitnessService;
diff --git a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
index 8257e47e5ce..3331906c8dc 100644
--- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
+++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
@@ -30,11 +30,9 @@
import bisq.core.filter.FilterManager;
import bisq.core.trade.statistics.TradeStatisticsManager;
-import bisq.network.crypto.EncryptionService;
import bisq.network.p2p.P2PService;
import bisq.common.config.Config;
-import bisq.common.crypto.KeyRing;
import javax.inject.Inject;
@@ -45,9 +43,7 @@ public class AppSetupWithP2PAndDAO extends AppSetupWithP2P {
private final DaoSetup daoSetup;
@Inject
- public AppSetupWithP2PAndDAO(EncryptionService encryptionService,
- KeyRing keyRing,
- P2PService p2PService,
+ public AppSetupWithP2PAndDAO(P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService,
@@ -61,9 +57,7 @@ public AppSetupWithP2PAndDAO(EncryptionService encryptionService,
MyProofOfBurnListService myProofOfBurnListService,
TorSetup torSetup,
Config config) {
- super(encryptionService,
- keyRing,
- p2PService,
+ super(p2PService,
tradeStatisticsManager,
accountAgeWitnessService,
signedWitnessService,
diff --git a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
index 297c7bf4fd4..8a22a56bcae 100644
--- a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
+++ b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
@@ -32,9 +32,9 @@
import bisq.common.app.DevEnv;
import bisq.common.config.Config;
import bisq.common.handlers.ResultHandler;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.setup.GracefulShutDownHandler;
import bisq.common.util.Profiler;
-import bisq.common.util.RestartUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -42,8 +42,6 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.io.IOException;
-
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -82,16 +80,19 @@ public void onSetupComplete() {
// We don't use the gracefulShutDown implementation of the super class as we have a limited set of modules
@Override
public void gracefulShutDown(ResultHandler resultHandler) {
- log.debug("gracefulShutDown");
+ log.info("gracefulShutDown");
try {
if (injector != null) {
injector.getInstance(ArbitratorManager.class).shutDown();
injector.getInstance(OpenOfferManager.class).shutDown(() -> injector.getInstance(P2PService.class).shutDown(() -> {
injector.getInstance(WalletsSetup.class).shutDownComplete.addListener((ov, o, n) -> {
module.close(injector);
- resultHandler.handleResult();
- log.info("Graceful shutdown completed");
- System.exit(0);
+
+ PersistenceManager.flushAllDataToDisk(() -> {
+ resultHandler.handleResult();
+ log.info("Graceful shutdown completed. Exiting now.");
+ System.exit(BisqExecutable.EXIT_SUCCESS);
+ });
});
injector.getInstance(WalletsSetup.class).shutDown();
injector.getInstance(BtcWalletService.class).shutDown();
@@ -99,19 +100,27 @@ public void gracefulShutDown(ResultHandler resultHandler) {
}));
// we wait max 5 sec.
UserThread.runAfter(() -> {
- resultHandler.handleResult();
- System.exit(0);
+ PersistenceManager.flushAllDataToDisk(() -> {
+ resultHandler.handleResult();
+ log.info("Graceful shutdown caused a timeout. Exiting now.");
+ System.exit(BisqExecutable.EXIT_SUCCESS);
+ });
}, 5);
} else {
UserThread.runAfter(() -> {
resultHandler.handleResult();
- System.exit(0);
+ System.exit(BisqExecutable.EXIT_SUCCESS);
}, 1);
}
} catch (Throwable t) {
log.debug("App shutdown failed with exception");
t.printStackTrace();
- System.exit(1);
+ PersistenceManager.flushAllDataToDisk(() -> {
+ resultHandler.handleResult();
+ log.info("Graceful shutdown resulted in an error. Exiting now.");
+ System.exit(BisqExecutable.EXIT_FAILURE);
+ });
+
}
}
@@ -228,22 +237,4 @@ protected void shutDown(GracefulShutDownHandler gracefulShutDownHandler) {
System.exit(1);
});
}
-
- protected void restart(Config config, GracefulShutDownHandler gracefulShutDownHandler) {
- stopped = true;
- gracefulShutDownHandler.gracefulShutDown(() -> {
- //noinspection finally
- try {
- final String[] tokens = config.appDataDir.getPath().split("_");
- String logPath = "error_" + (tokens.length > 1 ? tokens[tokens.length - 2] : "") + ".log";
- RestartUtil.restartApplication(logPath);
- } catch (IOException e) {
- log.error(e.toString());
- e.printStackTrace();
- } finally {
- log.warn("Shutdown complete");
- System.exit(0);
- }
- });
- }
}
diff --git a/core/src/main/java/bisq/core/btc/Balances.java b/core/src/main/java/bisq/core/btc/Balances.java
index e25352d3036..e162d547075 100644
--- a/core/src/main/java/bisq/core/btc/Balances.java
+++ b/core/src/main/java/bisq/core/btc/Balances.java
@@ -80,7 +80,7 @@ public Balances(TradeManager tradeManager,
public void onAllServicesInitialized() {
openOfferManager.getObservableList().addListener((ListChangeListener) c -> updateBalance());
- tradeManager.getTradesAsObservableList().addListener((ListChangeListener) change -> updateBalance());
+ tradeManager.getObservableList().addListener((ListChangeListener) change -> updateBalance());
refundManager.getDisputesAsObservableList().addListener((ListChangeListener) c -> updateBalance());
btcWalletService.addBalanceListener(new BalanceListener() {
@Override
diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
index d6741af0f57..4827fbc1621 100644
--- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
+++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
@@ -18,9 +18,9 @@
package bisq.core.btc.model;
import bisq.common.config.Config;
+import bisq.common.persistence.PersistenceManager;
+import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
-import bisq.common.storage.Storage;
import com.google.protobuf.Message;
@@ -41,28 +41,28 @@
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
-import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
/**
* The AddressEntries was previously stored as list, now as hashSet. We still keep the old name to reflect the
* associated protobuf message.
*/
-@ToString
@Slf4j
-public final class AddressEntryList implements UserThreadMappedPersistableEnvelope, PersistedDataHost {
- transient private Storage storage;
+public final class AddressEntryList implements PersistableEnvelope, PersistedDataHost {
+ transient private PersistenceManager persistenceManager;
transient private Wallet wallet;
private final Set entrySet = new CopyOnWriteArraySet<>();
@Inject
- public AddressEntryList(Storage storage) {
- this.storage = storage;
+ public AddressEntryList(PersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+
+ this.persistenceManager.initialize(this, PersistenceManager.Source.PRIVATE);
}
@Override
public void readPersisted() {
- AddressEntryList persisted = storage.initAndGetPersisted(this, 50);
+ AddressEntryList persisted = persistenceManager.getPersisted();
if (persisted != null) {
entrySet.clear();
entrySet.addAll(persisted.entrySet);
@@ -164,7 +164,7 @@ public void onWalletReady(Wallet wallet) {
maybeAddNewAddressEntry(tx);
});
- persist();
+ requestPersistence();
}
public ImmutableList getAddressEntriesAsListImmutable() {
@@ -186,7 +186,7 @@ public void addAddressEntry(AddressEntry addressEntry) {
boolean setChangedByAdd = entrySet.add(addressEntry);
if (setChangedByAdd)
- persist();
+ requestPersistence();
}
public void swapToAvailable(AddressEntry addressEntry) {
@@ -194,7 +194,7 @@ public void swapToAvailable(AddressEntry addressEntry) {
boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(),
AddressEntry.Context.AVAILABLE));
if (setChangedByRemove || setChangedByAdd) {
- persist();
+ requestPersistence();
}
}
@@ -205,13 +205,13 @@ public AddressEntry swapAvailableToAddressEntryWithOfferId(AddressEntry addressE
final AddressEntry newAddressEntry = new AddressEntry(addressEntry.getKeyPair(), context, offerId);
boolean setChangedByAdd = entrySet.add(newAddressEntry);
if (setChangedByRemove || setChangedByAdd)
- persist();
+ requestPersistence();
return newAddressEntry;
}
- public void persist() {
- storage.queueUpForSave(50);
+ public void requestPersistence() {
+ persistenceManager.requestPersistence();
}
@@ -235,4 +235,11 @@ private void maybeAddNewAddressEntry(Transaction tx) {
private boolean isAddressNotInEntries(Address address) {
return entrySet.stream().noneMatch(e -> address.equals(e.getAddress()));
}
+
+ @Override
+ public String toString() {
+ return "AddressEntryList{" +
+ ",\n entrySet=" + entrySet +
+ "\n}";
+ }
}
diff --git a/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java b/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java
index e94e65bbea7..650f9297853 100644
--- a/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java
+++ b/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java
@@ -34,11 +34,11 @@
import bisq.common.Timer;
import bisq.common.UserThread;
-import bisq.common.config.Config;
import bisq.common.app.Version;
+import bisq.common.config.Config;
+import bisq.common.file.FileUtil;
import bisq.common.handlers.ExceptionHandler;
import bisq.common.handlers.ResultHandler;
-import bisq.common.storage.FileUtil;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.BlockChain;
diff --git a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java
index 7e2aa0d26ce..b5860e00491 100644
--- a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java
+++ b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java
@@ -118,7 +118,7 @@ void decryptWallet(@NotNull KeyParameter key) {
if (keyPair.isEncrypted())
e.setDeterministicKey(keyPair.decrypt(key));
});
- addressEntryList.persist();
+ addressEntryList.requestPersistence();
}
@Override
@@ -129,7 +129,7 @@ void encryptWallet(KeyCrypterScrypt keyCrypterScrypt, KeyParameter key) {
if (keyPair.isEncrypted())
e.setDeterministicKey(keyPair.encrypt(keyCrypterScrypt, key));
});
- addressEntryList.persist();
+ addressEntryList.requestPersistence();
}
@Override
@@ -700,7 +700,7 @@ public void swapAnyTradeEntryContextToAvailableEntry(String offerId) {
}
public void saveAddressEntryList() {
- addressEntryList.persist();
+ addressEntryList.requestPersistence();
}
public DeterministicKey getMultiSigKeyPair(String tradeId, byte[] pubKey) {
diff --git a/core/src/main/java/bisq/core/dao/DaoFacade.java b/core/src/main/java/bisq/core/dao/DaoFacade.java
index ce52e74e674..f330289ff20 100644
--- a/core/src/main/java/bisq/core/dao/DaoFacade.java
+++ b/core/src/main/java/bisq/core/dao/DaoFacade.java
@@ -54,7 +54,6 @@
import bisq.core.dao.governance.proposal.role.RoleProposalFactory;
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.DaoStateService;
-import bisq.core.dao.state.DaoStateStorageService;
import bisq.core.dao.state.model.blockchain.BaseTx;
import bisq.core.dao.state.model.blockchain.BaseTxOutput;
import bisq.core.dao.state.model.blockchain.Block;
@@ -70,6 +69,7 @@
import bisq.core.dao.state.model.governance.Role;
import bisq.core.dao.state.model.governance.RoleProposal;
import bisq.core.dao.state.model.governance.Vote;
+import bisq.core.dao.state.storage.DaoStateStorageService;
import bisq.asset.Asset;
diff --git a/core/src/main/java/bisq/core/dao/DaoModule.java b/core/src/main/java/bisq/core/dao/DaoModule.java
index ad8f2c30efc..87d5f9e7a00 100644
--- a/core/src/main/java/bisq/core/dao/DaoModule.java
+++ b/core/src/main/java/bisq/core/dao/DaoModule.java
@@ -80,9 +80,9 @@
import bisq.core.dao.node.parser.TxParser;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.DaoStateSnapshotService;
-import bisq.core.dao.state.DaoStateStorageService;
import bisq.core.dao.state.GenesisTxInfo;
import bisq.core.dao.state.model.DaoState;
+import bisq.core.dao.state.storage.DaoStateStorageService;
import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputListService;
import bisq.common.app.AppModule;
diff --git a/core/src/main/java/bisq/core/dao/governance/ballot/BallotListService.java b/core/src/main/java/bisq/core/dao/governance/ballot/BallotListService.java
index 1760ba3f956..cb01694fdf6 100644
--- a/core/src/main/java/bisq/core/dao/governance/ballot/BallotListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/ballot/BallotListService.java
@@ -28,8 +28,8 @@
import bisq.core.dao.state.model.governance.Vote;
import bisq.common.app.DevEnv;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import javax.inject.Inject;
@@ -58,7 +58,7 @@ public interface BallotListChangeListener {
private final ProposalService proposalService;
private final PeriodService periodService;
private final ProposalValidatorProvider validatorProvider;
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final BallotList ballotList = new BallotList();
private final List listeners = new CopyOnWriteArrayList<>();
@@ -67,11 +67,13 @@ public interface BallotListChangeListener {
public BallotListService(ProposalService proposalService,
PeriodService periodService,
ProposalValidatorProvider validatorProvider,
- Storage storage) {
+ PersistenceManager persistenceManager) {
this.proposalService = proposalService;
this.periodService = periodService;
this.validatorProvider = validatorProvider;
- this.storage = storage;
+ this.persistenceManager = persistenceManager;
+
+ this.persistenceManager.initialize(ballotList, PersistenceManager.Source.NETWORK);
}
@@ -93,7 +95,7 @@ private void onChanged(Change extends ProposalPayload> change) {
.map(ProposalPayload::getProposal)
.filter(this::isNewProposal)
.forEach(this::registerProposalAsBallot);
- persist();
+ requestPersistence();
}
}
@@ -129,10 +131,9 @@ public void start() {
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- BallotList persisted = storage.initAndGetPersisted(ballotList, 100);
+ BallotList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- ballotList.clear();
- ballotList.addAll(persisted.getList());
+ ballotList.setAll(persisted.getList());
listeners.forEach(l -> l.onListChanged(ballotList.getList()));
}
}
@@ -145,7 +146,7 @@ public void readPersisted() {
public void setVote(Ballot ballot, @Nullable Vote vote) {
ballot.setVote(vote);
- persist();
+ requestPersistence();
}
public void addListener(BallotListChangeListener listener) {
@@ -170,7 +171,7 @@ public List getValidBallotsOfCycle() {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private void persist() {
- storage.queueUpForSave();
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
index 313fc07d349..be0890b653a 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
@@ -19,7 +19,7 @@
import bisq.core.dao.governance.ConsensusCritical;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import com.google.protobuf.Message;
@@ -33,7 +33,7 @@
* List of my own blind votes. Blind votes received from other voters are stored in the BlindVoteStore.
*/
@EqualsAndHashCode(callSuper = true)
-public class MyBlindVoteList extends UserThreadMappedPersistableList implements ConsensusCritical {
+public class MyBlindVoteList extends PersistableList implements ConsensusCritical {
MyBlindVoteList() {
super();
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteListService.java b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteListService.java
index 62b64f22ada..cc70c4a002e 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteListService.java
@@ -52,8 +52,8 @@
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ExceptionHandler;
import bisq.common.handlers.ResultHandler;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import bisq.common.util.Tuple2;
import bisq.common.util.Utilities;
@@ -99,7 +99,7 @@ public class MyBlindVoteListService implements PersistedDataHost, DaoStateListen
private final DaoStateService daoStateService;
private final PeriodService periodService;
private final WalletsManager walletsManager;
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final BsqWalletService bsqWalletService;
private final BtcWalletService btcWalletService;
private final BallotListService ballotListService;
@@ -119,7 +119,7 @@ public MyBlindVoteListService(P2PService p2PService,
DaoStateService daoStateService,
PeriodService periodService,
WalletsManager walletsManager,
- Storage storage,
+ PersistenceManager persistenceManager,
BsqWalletService bsqWalletService,
BtcWalletService btcWalletService,
BallotListService ballotListService,
@@ -129,13 +129,15 @@ public MyBlindVoteListService(P2PService p2PService,
this.daoStateService = daoStateService;
this.periodService = periodService;
this.walletsManager = walletsManager;
- this.storage = storage;
+ this.persistenceManager = persistenceManager;
this.bsqWalletService = bsqWalletService;
this.btcWalletService = btcWalletService;
this.ballotListService = ballotListService;
this.myVoteListService = myVoteListService;
this.myProposalListService = myProposalListService;
+ this.persistenceManager.initialize(myBlindVoteList, PersistenceManager.Source.PRIVATE);
+
numConnectedPeersListener = (observable, oldValue, newValue) -> maybeRePublishMyBlindVote();
}
@@ -162,10 +164,9 @@ public void start() {
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- MyBlindVoteList persisted = storage.initAndGetPersisted(myBlindVoteList, 100);
+ MyBlindVoteList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- myBlindVoteList.clear();
- myBlindVoteList.addAll(persisted.getList());
+ myBlindVoteList.setAll(persisted.getList());
}
}
}
@@ -403,11 +404,11 @@ private void addToP2PNetwork(BlindVote blindVote, @Nullable ErrorMessageHandler
private void addBlindVoteToList(BlindVote blindVote) {
if (!myBlindVoteList.getList().contains(blindVote)) {
myBlindVoteList.add(blindVote);
- persist();
+ requestPersistence();
}
}
- private void persist() {
- storage.queueUpForSave();
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStorageService.java b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStorageService.java
index 3f4df241c0f..0271fdce7f5 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStorageService.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStorageService.java
@@ -22,10 +22,10 @@
import bisq.network.p2p.storage.persistence.MapStoreService;
import bisq.common.config.Config;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
-import javax.inject.Named;
import javax.inject.Inject;
+import javax.inject.Named;
import java.io.File;
@@ -50,8 +50,8 @@ public class BlindVoteStorageService extends MapStoreService persistableNetworkPayloadMapStorage) {
- super(storageDir, persistableNetworkPayloadMapStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -63,6 +63,11 @@ public String getFileName() {
return FILE_NAME;
}
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
+
@Override
public Map getMap() {
return store.getMap();
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
index 32e5b256b91..41ed5b0368a 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
@@ -17,7 +17,6 @@
package bisq.core.dao.governance.blindvote.storage;
-import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.persistence.PersistableNetworkPayloadStore;
import com.google.protobuf.Message;
@@ -34,8 +33,7 @@
* definition and provide a hashMap for the domain access.
*/
@Slf4j
-public class BlindVoteStore extends PersistableNetworkPayloadStore {
-
+public class BlindVoteStore extends PersistableNetworkPayloadStore {
BlindVoteStore() {
}
@@ -45,7 +43,7 @@ public class BlindVoteStore extends PersistableNetworkPayloadStore {
///////////////////////////////////////////////////////////////////////////////////////////
private BlindVoteStore(List list) {
- list.forEach(item -> map.put(new P2PDataStorage.ByteArray(item.getHash()), item));
+ super(list);
}
public Message toProtoMessage() {
@@ -67,8 +65,4 @@ public static BlindVoteStore fromProto(protobuf.BlindVoteStore proto) {
.map(BlindVotePayload::fromProto).collect(Collectors.toList());
return new BlindVoteStore(list);
}
-
- public boolean containsKey(P2PDataStorage.ByteArray hash) {
- return map.containsKey(hash);
- }
}
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
index 9e705d2642f..2a39f783176 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
@@ -17,7 +17,7 @@
package bisq.core.dao.governance.bond.reputation;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +29,7 @@
* PersistableEnvelope wrapper for list of MyReputations.
*/
@EqualsAndHashCode(callSuper = true)
-public class MyReputationList extends UserThreadMappedPersistableList {
+public class MyReputationList extends PersistableList {
private MyReputationList(List list) {
super(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java
index 85e5477574b..c417b9c61ce 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java
@@ -20,8 +20,8 @@
import bisq.core.dao.DaoSetupService;
import bisq.common.app.DevEnv;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import javax.inject.Inject;
@@ -35,7 +35,7 @@
@Slf4j
public class MyReputationListService implements PersistedDataHost, DaoSetupService {
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final MyReputationList myReputationList = new MyReputationList();
@@ -44,8 +44,9 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
- public MyReputationListService(Storage storage) {
- this.storage = storage;
+ public MyReputationListService(PersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+ persistenceManager.initialize(myReputationList, PersistenceManager.Source.PRIVATE);
}
@@ -56,10 +57,9 @@ public MyReputationListService(Storage storage) {
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- MyReputationList persisted = storage.initAndGetPersisted(myReputationList, 100);
+ MyReputationList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- myReputationList.clear();
- myReputationList.addAll(persisted.getList());
+ myReputationList.setAll(persisted.getList());
}
}
}
@@ -84,7 +84,7 @@ public void start() {
public void addReputation(MyReputation reputation) {
if (!myReputationList.contains(reputation)) {
myReputationList.add(reputation);
- persist();
+ requestPersistence();
}
}
@@ -97,7 +97,7 @@ public List getMyReputationList() {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private void persist() {
- storage.queueUpForSave(20);
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
index c840faf7e60..05610f8dcb8 100644
--- a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
+++ b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
@@ -17,7 +17,7 @@
package bisq.core.dao.governance.myvote;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import com.google.protobuf.Message;
@@ -28,7 +28,7 @@
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
-public class MyVoteList extends UserThreadMappedPersistableList {
+public class MyVoteList extends PersistableList {
MyVoteList() {
super();
diff --git a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteListService.java b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteListService.java
index 8b5a7433c9b..390ee4ee608 100644
--- a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteListService.java
@@ -25,8 +25,8 @@
import bisq.common.app.DevEnv;
import bisq.common.crypto.Encryption;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import bisq.common.util.Tuple2;
import javax.inject.Inject;
@@ -46,7 +46,7 @@
@Slf4j
public class MyVoteListService implements PersistedDataHost {
private final DaoStateService daoStateService;
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final MyVoteList myVoteList = new MyVoteList();
@@ -56,9 +56,11 @@ public class MyVoteListService implements PersistedDataHost {
@Inject
public MyVoteListService(DaoStateService daoStateService,
- Storage storage) {
+ PersistenceManager persistenceManager) {
this.daoStateService = daoStateService;
- this.storage = storage;
+ this.persistenceManager = persistenceManager;
+
+ this.persistenceManager.initialize(myVoteList, PersistenceManager.Source.PRIVATE);
}
@@ -69,10 +71,9 @@ public MyVoteListService(DaoStateService daoStateService,
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- MyVoteList persisted = storage.initAndGetPersisted(myVoteList, 100);
+ MyVoteList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- this.myVoteList.clear();
- this.myVoteList.addAll(persisted.getList());
+ this.myVoteList.setAll(persisted.getList());
}
}
}
@@ -87,13 +88,13 @@ public void createAndAddMyVote(BallotList sortedBallotListForCycle, SecretKey se
MyVote myVote = new MyVote(daoStateService.getChainHeight(), sortedBallotListForCycle, secretKeyBytes, blindVote);
log.info("Add new MyVote to myVotesList list.\nMyVote=" + myVote);
myVoteList.add(myVote);
- persist();
+ requestPersistence();
}
public void applyRevealTxId(MyVote myVote, String voteRevealTxId) {
myVote.setRevealTxId(voteRevealTxId);
log.info("Applied revealTxId to myVote.\nmyVote={}\nvoteRevealTxId={}", myVote, voteRevealTxId);
- persist();
+ requestPersistence();
}
public Tuple2 getMeritAndStakeForProposal(String proposalTxId, MyBlindVoteListService myBlindVoteListService) {
@@ -102,7 +103,7 @@ public Tuple2 getMeritAndStakeForProposal(String proposalTxId, MyBli
List list = new ArrayList<>(myVoteList.getList());
list.sort(Comparator.comparing(MyVote::getDate));
for (MyVote myVote : list) {
- for (Ballot ballot : myVote.getBallotList()) {
+ for (Ballot ballot : myVote.getBallotList().getList()) {
if (ballot.getTxId().equals(proposalTxId)) {
merit = myVote.getMerit(myBlindVoteListService, daoStateService);
stake = myVote.getBlindVote().getStake();
@@ -129,7 +130,7 @@ public List getMyVoteListForCycle() {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private void persist() {
- storage.queueUpForSave();
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
index 0845b4efb74..a1f55c24996 100644
--- a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
+++ b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
@@ -17,7 +17,7 @@
package bisq.core.dao.governance.proofofburn;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +29,7 @@
* PersistableEnvelope wrapper for list of MyProofOfBurn objects.
*/
@EqualsAndHashCode(callSuper = true)
-public class MyProofOfBurnList extends UserThreadMappedPersistableList {
+public class MyProofOfBurnList extends PersistableList {
private MyProofOfBurnList(List list) {
super(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnListService.java b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnListService.java
index 05ea0f973d5..39d8ed5a525 100644
--- a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnListService.java
@@ -20,8 +20,8 @@
import bisq.core.dao.DaoSetupService;
import bisq.common.app.DevEnv;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import javax.inject.Inject;
@@ -35,7 +35,7 @@
@Slf4j
public class MyProofOfBurnListService implements PersistedDataHost, DaoSetupService {
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final MyProofOfBurnList myProofOfBurnList = new MyProofOfBurnList();
@@ -44,8 +44,9 @@ public class MyProofOfBurnListService implements PersistedDataHost, DaoSetupServ
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
- public MyProofOfBurnListService(Storage storage) {
- this.storage = storage;
+ public MyProofOfBurnListService(PersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+ persistenceManager.initialize(myProofOfBurnList, PersistenceManager.Source.PRIVATE);
}
@@ -56,10 +57,9 @@ public MyProofOfBurnListService(Storage storage) {
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- MyProofOfBurnList persisted = storage.initAndGetPersisted(myProofOfBurnList, 100);
+ MyProofOfBurnList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- myProofOfBurnList.clear();
- myProofOfBurnList.addAll(persisted.getList());
+ myProofOfBurnList.setAll(persisted.getList());
}
}
}
@@ -85,7 +85,7 @@ public void start() {
public void addMyProofOfBurn(MyProofOfBurn myProofOfBurn) {
if (!myProofOfBurnList.contains(myProofOfBurn)) {
myProofOfBurnList.add(myProofOfBurn);
- persist();
+ requestPersistence();
}
}
@@ -98,7 +98,7 @@ public List getMyProofOfBurnList() {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private void persist() {
- storage.queueUpForSave(20);
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
index 0729043232c..7ec120d719b 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
@@ -20,7 +20,7 @@
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.state.model.governance.Proposal;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import java.util.ArrayList;
import java.util.List;
@@ -32,7 +32,7 @@
* PersistableEnvelope wrapper for list of proposals. Used in vote consensus, so changes can break consensus!
*/
@EqualsAndHashCode(callSuper = true)
-public class MyProposalList extends UserThreadMappedPersistableList implements ConsensusCritical {
+public class MyProposalList extends PersistableList implements ConsensusCritical {
public MyProposalList(List list) {
super(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
index 9c4ac114e8f..19284a0c042 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
@@ -35,8 +35,8 @@
import bisq.common.crypto.PubKeyRing;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import org.bitcoinj.core.Transaction;
@@ -67,7 +67,7 @@ public interface Listener {
private final DaoStateService daoStateService;
private final PeriodService periodService;
private final WalletsManager walletsManager;
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
private final PublicKey signaturePubKey;
private final MyProposalList myProposalList = new MyProposalList();
@@ -84,13 +84,15 @@ public MyProposalListService(P2PService p2PService,
DaoStateService daoStateService,
PeriodService periodService,
WalletsManager walletsManager,
- Storage storage,
+ PersistenceManager persistenceManager,
PubKeyRing pubKeyRing) {
this.p2PService = p2PService;
this.daoStateService = daoStateService;
this.periodService = periodService;
this.walletsManager = walletsManager;
- this.storage = storage;
+ this.persistenceManager = persistenceManager;
+
+ this.persistenceManager.initialize(myProposalList, PersistenceManager.Source.PRIVATE);
signaturePubKey = pubKeyRing.getSignaturePubKey();
@@ -107,10 +109,9 @@ public MyProposalListService(P2PService p2PService,
@Override
public void readPersisted() {
if (DevEnv.isDaoActivated()) {
- MyProposalList persisted = storage.initAndGetPersisted(myProposalList, 100);
+ MyProposalList persisted = persistenceManager.getPersisted();
if (persisted != null) {
- myProposalList.clear();
- myProposalList.addAll(persisted.getList());
+ myProposalList.setAll(persisted.getList());
listeners.forEach(l -> l.onListChanged(getList()));
}
}
@@ -157,7 +158,7 @@ public void onFailure(TxBroadcastException exception) {
if (!getList().contains(proposal)) {
myProposalList.add(proposal);
listeners.forEach(l -> l.onListChanged(getList()));
- persist();
+ requestPersistence();
}
}
@@ -169,7 +170,7 @@ public boolean remove(Proposal proposal) {
if (myProposalList.remove(proposal)) {
listeners.forEach(l -> l.onListChanged(getList()));
- persist();
+ requestPersistence();
} else {
log.warn("We called remove at a proposal which was not in our list");
}
@@ -234,8 +235,8 @@ private void rePublishMyProposalsOnceWellConnected() {
}
}
- private void persist() {
- storage.queueUpForSave();
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
private boolean canRemoveProposal(Proposal proposal, DaoStateService daoStateService, PeriodService periodService) {
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStorageService.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStorageService.java
index 1cc3dee5eb5..b6f2022201b 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStorageService.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStorageService.java
@@ -22,10 +22,10 @@
import bisq.network.p2p.storage.persistence.MapStoreService;
import bisq.common.config.Config;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
-import javax.inject.Named;
import javax.inject.Inject;
+import javax.inject.Named;
import java.io.File;
@@ -44,8 +44,8 @@ public class ProposalStorageService extends MapStoreService persistableNetworkPayloadMapStorage) {
- super(storageDir, persistableNetworkPayloadMapStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -57,6 +57,11 @@ public String getFileName() {
return FILE_NAME;
}
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
+
@Override
public Map getMap() {
return store.getMap();
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
index 6652362d14a..23c9b3732ed 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
@@ -17,7 +17,6 @@
package bisq.core.dao.governance.proposal.storage.appendonly;
-import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.persistence.PersistableNetworkPayloadStore;
import com.google.protobuf.Message;
@@ -34,7 +33,7 @@
* definition and provide a hashMap for the domain access.
*/
@Slf4j
-public class ProposalStore extends PersistableNetworkPayloadStore {
+public class ProposalStore extends PersistableNetworkPayloadStore {
ProposalStore() {
}
@@ -45,7 +44,7 @@ public class ProposalStore extends PersistableNetworkPayloadStore {
///////////////////////////////////////////////////////////////////////////////////////////
private ProposalStore(List list) {
- list.forEach(item -> map.put(new P2PDataStorage.ByteArray(item.getHash()), item));
+ super(list);
}
public Message toProtoMessage() {
@@ -67,8 +66,4 @@ public static ProposalStore fromProto(protobuf.ProposalStore proto) {
.map(ProposalPayload::fromProto).collect(Collectors.toList());
return new ProposalStore(list);
}
-
- public boolean containsKey(P2PDataStorage.ByteArray hash) {
- return map.containsKey(hash);
- }
}
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStorageService.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStorageService.java
index 5dd2fc8507d..d39b6f5470d 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStorageService.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStorageService.java
@@ -22,10 +22,10 @@
import bisq.network.p2p.storage.persistence.MapStoreService;
import bisq.common.config.Config;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
-import javax.inject.Named;
import javax.inject.Inject;
+import javax.inject.Named;
import java.io.File;
@@ -44,8 +44,8 @@ public class TempProposalStorageService extends MapStoreService persistableNetworkPayloadMapStorage) {
- super(storageDir, persistableNetworkPayloadMapStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -57,6 +57,11 @@ public String getFileName() {
return FILE_NAME;
}
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
+
@Override
public Map getMap() {
return store.getMap();
@@ -67,6 +72,12 @@ public boolean canHandle(ProtectedStorageEntry entry) {
return entry.getProtectedStoragePayload() instanceof TempProposalPayload;
}
+ @Override
+ protected void readFromResources(String postFix) {
+ // We do not have a resource file for that store, so we just call the readStore method instead.
+ readStore();
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////
// Protected
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
index 229f173368b..6ff483eae2e 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
@@ -21,7 +21,7 @@
import bisq.network.p2p.storage.payload.ProtectedStorageEntry;
import bisq.common.proto.network.NetworkProtoResolver;
-import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
+import bisq.common.proto.persistable.PersistableEnvelope;
import com.google.protobuf.Message;
@@ -42,9 +42,9 @@
* definition and provide a hashMap for the domain access.
*/
@Slf4j
-public class TempProposalStore implements ThreadedPersistableEnvelope {
+public class TempProposalStore implements PersistableEnvelope {
@Getter
- private Map map = new ConcurrentHashMap<>();
+ private final Map map = new ConcurrentHashMap<>();
@Inject
TempProposalStore() {
diff --git a/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java b/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
index c486ee4a047..604746bcbba 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
@@ -39,7 +39,7 @@
import bisq.common.UserThread;
import bisq.common.config.Config;
import bisq.common.crypto.Hash;
-import bisq.common.storage.FileManager;
+import bisq.common.file.FileUtil;
import bisq.common.util.Utilities;
import javax.inject.Inject;
@@ -419,7 +419,7 @@ private void removeFile(String storeName) {
File corrupted = new File(storageDir, storeName);
try {
if (corrupted.exists()) {
- FileManager.removeAndBackupFile(storageDir, corrupted, newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, corrupted, newFileName, backupDirName);
}
} catch (Throwable t) {
t.printStackTrace();
diff --git a/core/src/main/java/bisq/core/dao/node/explorer/ExportJsonFilesService.java b/core/src/main/java/bisq/core/dao/node/explorer/ExportJsonFilesService.java
index 8babe94535c..1c9c605f04d 100644
--- a/core/src/main/java/bisq/core/dao/node/explorer/ExportJsonFilesService.java
+++ b/core/src/main/java/bisq/core/dao/node/explorer/ExportJsonFilesService.java
@@ -27,8 +27,8 @@
import bisq.core.dao.state.model.blockchain.TxType;
import bisq.common.config.Config;
-import bisq.common.storage.FileUtil;
-import bisq.common.storage.JsonFileManager;
+import bisq.common.file.FileUtil;
+import bisq.common.file.JsonFileManager;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Utils;
diff --git a/core/src/main/java/bisq/core/dao/node/full/RpcService.java b/core/src/main/java/bisq/core/dao/node/full/RpcService.java
index 62c613bf79a..d694cee91c2 100644
--- a/core/src/main/java/bisq/core/dao/node/full/RpcService.java
+++ b/core/src/main/java/bisq/core/dao/node/full/RpcService.java
@@ -82,7 +82,7 @@ public class RpcService {
// We could use multiple threads but then we need to support ordering of results in a queue
// Keep that for optimization after measuring performance differences
- private final ListeningExecutorService executor = Utilities.getSingleThreadExecutor("RpcService");
+ private final ListeningExecutorService executor = Utilities.getSingleThreadListeningExecutor("RpcService");
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateService.java b/core/src/main/java/bisq/core/dao/state/DaoStateService.java
index 5ad729e25d5..620415a12ca 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateService.java
+++ b/core/src/main/java/bisq/core/dao/state/DaoStateService.java
@@ -149,10 +149,6 @@ public DaoState getClone() {
return DaoState.getClone(daoState);
}
- DaoState getClone(DaoState snapshotCandidate) {
- return DaoState.getClone(snapshotCandidate);
- }
-
public byte[] getSerializedStateForHashChain() {
return daoState.getSerializedStateForHashChain();
}
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java b/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
index df98840cd02..0c0e506016e 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
+++ b/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
@@ -22,6 +22,7 @@
import bisq.core.dao.monitoring.model.DaoStateHash;
import bisq.core.dao.state.model.DaoState;
import bisq.core.dao.state.model.blockchain.Block;
+import bisq.core.dao.state.storage.DaoStateStorageService;
import javax.inject.Inject;
@@ -92,13 +93,12 @@ public void maybeCreateSnapshot(Block block) {
// At trigger event we store the latest snapshotCandidate to disc
long ts = System.currentTimeMillis();
if (daoStateSnapshotCandidate != null) {
- // We clone because storage is in a threaded context and we set the snapshotCandidate to our current
- // state in the next step
- DaoState clonedDaoState = daoStateService.getClone(daoStateSnapshotCandidate);
- LinkedList clonedDaoStateHashChain = new LinkedList<>(daoStateHashChainSnapshotCandidate);
- daoStateStorageService.persist(clonedDaoState, clonedDaoStateHashChain);
-
- log.debug("Saved snapshotCandidate with height {} to Disc at height {} took {} ms",
+ // Serialisation happens on the userThread so we do not need to clone the data. Write to disk happens
+ // in a thread but does not interfere with our objects as they got already serialized when passed to the
+ // write thread. We use requestPersistence so we do not write immediately but at next scheduled interval.
+ // This avoids frequent write at dao sync and better performance.
+ daoStateStorageService.requestPersistence(daoStateSnapshotCandidate, daoStateHashChainSnapshotCandidate);
+ log.info("Serializing snapshotCandidate for writing to Disc with height {} at height {} took {} ms",
daoStateSnapshotCandidate.getChainHeight(), chainHeight, System.currentTimeMillis() - ts);
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java b/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
index d3b4a1f97eb..25eaa415e62 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
@@ -20,7 +20,7 @@
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.state.model.ImmutableDaoStateModel;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import java.util.ArrayList;
import java.util.List;
@@ -35,7 +35,7 @@
*/
@Immutable
@EqualsAndHashCode(callSuper = true)
-public class BallotList extends UserThreadMappedPersistableList implements ConsensusCritical, ImmutableDaoStateModel {
+public class BallotList extends PersistableList implements ConsensusCritical, ImmutableDaoStateModel {
public BallotList(List list) {
super(list);
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java
similarity index 67%
rename from core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java
rename to core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java
index 8571eb2b12e..ece0166da8e 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java
+++ b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java
@@ -15,7 +15,7 @@
* along with bisq. If not, see .
*/
-package bisq.core.dao.state;
+package bisq.core.dao.state.storage;
import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.core.dao.monitoring.model.DaoStateHash;
@@ -24,10 +24,9 @@
import bisq.network.p2p.storage.persistence.ResourceDataStoreService;
import bisq.network.p2p.storage.persistence.StoreService;
-import bisq.common.UserThread;
import bisq.common.config.Config;
-import bisq.common.storage.FileManager;
-import bisq.common.storage.Storage;
+import bisq.common.file.FileUtil;
+import bisq.common.persistence.PersistenceManager;
import javax.inject.Inject;
import javax.inject.Named;
@@ -36,7 +35,6 @@
import java.io.IOException;
import java.util.LinkedList;
-import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@@ -45,11 +43,6 @@
*/
@Slf4j
public class DaoStateStorageService extends StoreService {
- // We needed to rename the db file as we have a new file structure with the hashChain feature and need to enforce the
- // new file to be used.
- // We can rename to DaoStateStore before mainnet launch again.
- // Another update due to some data field changes which would cause diff. hashes, so to enforce users to get the new
- // data we rename it to DaoStateStore
private static final String FILE_NAME = "DaoStateStore";
private final DaoState daoState;
@@ -65,8 +58,8 @@ public DaoStateStorageService(ResourceDataStoreService resourceDataStoreService,
DaoState daoState,
DaoStateMonitoringService daoStateMonitoringService,
@Named(Config.STORAGE_DIR) File storageDir,
- Storage daoSnapshotStorage) {
- super(storageDir, daoSnapshotStorage);
+ PersistenceManager persistenceManager) {
+ super(storageDir, persistenceManager);
this.daoState = daoState;
this.daoStateMonitoringService = daoStateMonitoringService;
@@ -83,16 +76,10 @@ public String getFileName() {
return FILE_NAME;
}
- public void persist(DaoState daoState, LinkedList daoStateHashChain) {
- persist(daoState, daoStateHashChain, 200);
- }
-
- private void persist(DaoState daoState, LinkedList daoStateHashChain, long delayInMilli) {
- store.modifySynchronized(() -> {
- store.setDaoState(daoState);
- store.setDaoStateHashChain(daoStateHashChain);
- });
- storage.queueUpForSave(store, delayInMilli);
+ public void requestPersistence(DaoState daoState, LinkedList daoStateHashChain) {
+ store.setDaoState(daoState);
+ store.setDaoStateHashChain(daoStateHashChain);
+ persistenceManager.requestPersistence();
}
public DaoState getPersistedBsqState() {
@@ -104,8 +91,9 @@ public LinkedList getPersistedDaoStateHashChain() {
}
public void resyncDaoStateFromGenesis(Runnable resultHandler) {
- persist(new DaoState(), new LinkedList<>(), 1);
- UserThread.runAfter(resultHandler, 300, TimeUnit.MILLISECONDS);
+ store.setDaoState(new DaoState());
+ store.setDaoStateHashChain(new LinkedList<>());
+ persistenceManager.persistNow(resultHandler);
}
public void resyncDaoStateFromResources(File storageDir) throws IOException {
@@ -114,20 +102,20 @@ public void resyncDaoStateFromResources(File storageDir) throws IOException {
long currentTime = System.currentTimeMillis();
String backupDirName = "out_of_sync_dao_data";
String newFileName = "BlindVoteStore_" + currentTime;
- FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BlindVoteStore"), newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, new File(storageDir, "BlindVoteStore"), newFileName, backupDirName);
newFileName = "ProposalStore_" + currentTime;
- FileManager.removeAndBackupFile(storageDir, new File(storageDir, "ProposalStore"), newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, new File(storageDir, "ProposalStore"), newFileName, backupDirName);
// We also need to remove ballot list as it contains the proposals as well. It will be recreated at resync
newFileName = "BallotList_" + currentTime;
- FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BallotList"), newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, new File(storageDir, "BallotList"), newFileName, backupDirName);
newFileName = "UnconfirmedBsqChangeOutputList_" + currentTime;
- FileManager.removeAndBackupFile(storageDir, new File(storageDir, "UnconfirmedBsqChangeOutputList"), newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, new File(storageDir, "UnconfirmedBsqChangeOutputList"), newFileName, backupDirName);
newFileName = "DaoStateStore_" + currentTime;
- FileManager.removeAndBackupFile(storageDir, new File(storageDir, "DaoStateStore"), newFileName, backupDirName);
+ FileUtil.removeAndBackupFile(storageDir, new File(storageDir, "DaoStateStore"), newFileName, backupDirName);
}
@@ -139,4 +127,9 @@ public void resyncDaoStateFromResources(File storageDir) throws IOException {
protected DaoStateStore createStore() {
return new DaoStateStore(DaoState.getClone(daoState), new LinkedList<>(daoStateMonitoringService.getDaoStateHashChain()));
}
+
+ @Override
+ protected void initializePersistenceManager() {
+ persistenceManager.initialize(store, PersistenceManager.Source.NETWORK);
+ }
}
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateStore.java b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStore.java
similarity index 94%
rename from core/src/main/java/bisq/core/dao/state/DaoStateStore.java
rename to core/src/main/java/bisq/core/dao/state/storage/DaoStateStore.java
index 144479c2817..fe99e39724a 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateStore.java
+++ b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStore.java
@@ -15,12 +15,12 @@
* along with Bisq. If not, see .
*/
-package bisq.core.dao.state;
+package bisq.core.dao.state.storage;
import bisq.core.dao.monitoring.model.DaoStateHash;
import bisq.core.dao.state.model.DaoState;
-import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
+import bisq.common.proto.persistable.PersistableEnvelope;
import com.google.protobuf.Message;
@@ -35,7 +35,7 @@
@Slf4j
-public class DaoStateStore implements ThreadedPersistableEnvelope {
+public class DaoStateStore implements PersistableEnvelope {
// DaoState is always a clone and must not be used for read access beside initial read from disc when we apply
// the snapshot!
@Getter
diff --git a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
index 391afda22f7..2deae256979 100644
--- a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
+++ b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
@@ -17,7 +17,7 @@
package bisq.core.dao.state.unconfirmed;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import com.google.protobuf.Message;
@@ -28,7 +28,7 @@
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
-public class UnconfirmedBsqChangeOutputList extends UserThreadMappedPersistableList {
+public class UnconfirmedBsqChangeOutputList extends PersistableList {
UnconfirmedBsqChangeOutputList() {
super();
diff --git a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputListService.java b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputListService.java
index 432f3c86959..467800748ff 100644
--- a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputListService.java
+++ b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputListService.java
@@ -20,8 +20,8 @@
import bisq.core.dao.state.model.blockchain.TxType;
import bisq.common.app.DevEnv;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
@@ -40,11 +40,13 @@
@Slf4j
public class UnconfirmedBsqChangeOutputListService implements PersistedDataHost {
private final UnconfirmedBsqChangeOutputList unconfirmedBsqChangeOutputList = new UnconfirmedBsqChangeOutputList();
- private final Storage storage;
+ private final PersistenceManager persistenceManager;
@Inject
- public UnconfirmedBsqChangeOutputListService(Storage storage) {
- this.storage = storage;
+ public UnconfirmedBsqChangeOutputListService(PersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+
+ this.persistenceManager.initialize(unconfirmedBsqChangeOutputList, PersistenceManager.Source.PRIVATE);
}
@@ -55,10 +57,9 @@ public UnconfirmedBsqChangeOutputListService(Storage {
unconfirmedBsqChangeOutputList.remove(txOutput);
- persist();
+ requestPersistence();
});
}
private void reset() {
unconfirmedBsqChangeOutputList.clear();
- persist();
+ requestPersistence();
}
- private void persist() {
- storage.queueUpForSave();
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java b/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
index f6c4d97e9d1..ca4322f3e16 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
@@ -21,6 +21,7 @@
import bisq.core.notifications.MobileMessage;
import bisq.core.notifications.MobileMessageType;
import bisq.core.notifications.MobileNotificationService;
+import bisq.core.support.SupportType;
import bisq.core.support.dispute.Dispute;
import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.support.dispute.refund.RefundManager;
@@ -123,6 +124,11 @@ private void onChatMessage(ChatMessage chatMessage, Dispute dispute) {
// trader/mediator/arbitrator who has reopened the case
if (dispute.isClosed() && !chatMessages.isEmpty() && !chatMessages.get(chatMessages.size() - 1).isResultMessage(dispute)) {
dispute.setIsClosed(false);
+ if (dispute.getSupportType() == SupportType.MEDIATION) {
+ mediationManager.requestPersistence();
+ } else if (dispute.getSupportType() == SupportType.REFUND) {
+ refundManager.requestPersistence();
+ }
}
}
}
diff --git a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
index 007583885ce..7bfe9556930 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
@@ -53,13 +53,13 @@ public TradeEvents(TradeManager tradeManager, KeyRing keyRing, MobileNotificatio
}
public void onAllServicesInitialized() {
- tradeManager.getTradesAsObservableList().addListener((ListChangeListener) c -> {
+ tradeManager.getObservableList().addListener((ListChangeListener) c -> {
c.next();
if (c.wasAdded()) {
c.getAddedSubList().forEach(this::setTradePhaseListener);
}
});
- tradeManager.getTradesAsObservableList().forEach(this::setTradePhaseListener);
+ tradeManager.getObservableList().forEach(this::setTradePhaseListener);
}
private void setTradePhaseListener(Trade trade) {
diff --git a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
index ee2d092ac83..bd170c08792 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
@@ -194,7 +194,7 @@ else if (!isFiatCurrency && !isSellOffer)
// In case we have disabled alerts wasSent is false and we do not
// persist the offer
marketAlertFilter.addAlertId(alertId);
- user.persist();
+ user.requestPersistence();
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/core/src/main/java/bisq/core/offer/OfferBookService.java b/core/src/main/java/bisq/core/offer/OfferBookService.java
index 2085429d054..4176132baa9 100644
--- a/core/src/main/java/bisq/core/offer/OfferBookService.java
+++ b/core/src/main/java/bisq/core/offer/OfferBookService.java
@@ -28,9 +28,9 @@
import bisq.common.UserThread;
import bisq.common.config.Config;
+import bisq.common.file.JsonFileManager;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
-import bisq.common.storage.JsonFileManager;
import bisq.common.util.Utilities;
import javax.inject.Inject;
diff --git a/core/src/main/java/bisq/core/offer/OpenOffer.java b/core/src/main/java/bisq/core/offer/OpenOffer.java
index ced8cce9834..5d9cfb4794e 100644
--- a/core/src/main/java/bisq/core/offer/OpenOffer.java
+++ b/core/src/main/java/bisq/core/offer/OpenOffer.java
@@ -18,14 +18,12 @@
package bisq.core.offer;
import bisq.core.trade.Tradable;
-import bisq.core.trade.TradableList;
import bisq.network.p2p.NodeAddress;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.proto.ProtoUtil;
-import bisq.common.storage.Storage;
import java.util.Date;
import java.util.Optional;
@@ -71,11 +69,9 @@ public enum State {
@Nullable
private NodeAddress refundAgentNodeAddress;
- transient private Storage> storage;
- public OpenOffer(Offer offer, Storage> storage) {
+ public OpenOffer(Offer offer) {
this.offer = offer;
- this.storage = storage;
state = State.AVAILABLE;
}
@@ -139,21 +135,15 @@ public String getShortId() {
return offer.getShortId();
}
- public void setStorage(Storage> storage) {
- this.storage = storage;
- }
-
public void setState(State state) {
- boolean changed = this.state != state;
this.state = state;
- if (changed && storage != null)
- storage.queueUpForSave();
// We keep it reserved for a limited time, if trade preparation fails we revert to available state
- if (this.state == State.RESERVED)
+ if (this.state == State.RESERVED) {
startTimeout();
- else
+ } else {
stopTimeout();
+ }
}
public boolean isDeactivated() {
@@ -164,9 +154,11 @@ private void startTimeout() {
stopTimeout();
timeoutTimer = UserThread.runAfter(() -> {
- log.debug("Timeout for resettin State.RESERVED reached");
- if (state == State.RESERVED)
+ log.debug("Timeout for resetting State.RESERVED reached");
+ if (state == State.RESERVED) {
+ // we do not need to persist that as at startup any RESERVED state would be reset to AVAILABLE anyway
setState(State.AVAILABLE);
+ }
}, TIMEOUT);
}
diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java
index 5b74864790c..1e72532a612 100644
--- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java
+++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java
@@ -60,9 +60,9 @@
import bisq.common.crypto.PubKeyRing;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.network.NetworkEnvelope;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import org.bitcoinj.core.Coin;
@@ -113,11 +113,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
private final RefundAgentManager refundAgentManager;
private final DaoFacade daoFacade;
private final FilterManager filterManager;
- private final Storage> openOfferTradableListStorage;
+ private final PersistenceManager> persistenceManager;
private final Map offersToBeEdited = new HashMap<>();
+ private final TradableList openOffers = new TradableList<>();
private boolean stopped;
private Timer periodicRepublishOffersTimer, periodicRefreshOffersTimer, retryRepublishOffersTimer;
- private TradableList openOffers;
///////////////////////////////////////////////////////////////////////////////////////////
@@ -142,7 +142,7 @@ public OpenOfferManager(CreateOfferService createOfferService,
RefundAgentManager refundAgentManager,
DaoFacade daoFacade,
FilterManager filterManager,
- Storage> storage) {
+ PersistenceManager> persistenceManager) {
this.createOfferService = createOfferService;
this.keyRing = keyRing;
this.user = user;
@@ -160,17 +160,18 @@ public OpenOfferManager(CreateOfferService createOfferService,
this.refundAgentManager = refundAgentManager;
this.daoFacade = daoFacade;
this.filterManager = filterManager;
+ this.persistenceManager = persistenceManager;
- openOfferTradableListStorage = storage;
-
- // In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook
- Runtime.getRuntime().addShutdownHook(new Thread(() ->
- UserThread.execute(OpenOfferManager.this::shutDown), "OpenOfferManager.ShutDownHook"));
+ this.persistenceManager.initialize(openOffers, "OpenOffers", PersistenceManager.Source.PRIVATE);
}
@Override
public void readPersisted() {
- openOffers = new TradableList<>(openOfferTradableListStorage, "OpenOffers");
+ TradableList persisted = persistenceManager.getPersisted();
+ if (persisted != null) {
+ openOffers.setAll(persisted.getList());
+ }
+
openOffers.forEach(e -> {
Offer offer = e.getOffer();
offer.setPriceFeedService(priceFeedService);
@@ -221,7 +222,7 @@ public void shutDown(@Nullable Runnable completeHandler) {
// we remove own offers from offerbook when we go offline
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
- int size = openOffers != null ? openOffers.size() : 0;
+ int size = openOffers.size();
log.info("Remove open offers at shutDown. Number of open offers: {}", size);
if (offerBookService.isBootstrapped() && size > 0) {
UserThread.execute(() -> openOffers.forEach(
@@ -240,7 +241,7 @@ public void removeAllOpenOffers(@Nullable Runnable completeHandler) {
}
private void removeOpenOffers(List openOffers, @Nullable Runnable completeHandler) {
- final int size = openOffers.size();
+ int size = openOffers.size();
// Copy list as we remove in the loop
List openOffersList = new ArrayList<>(openOffers);
openOffersList.forEach(openOffer -> removeOpenOffer(openOffer, () -> {
@@ -370,9 +371,9 @@ public void placeOffer(Offer offer,
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(
model,
transaction -> {
- OpenOffer openOffer = new OpenOffer(offer, openOfferTradableListStorage);
+ OpenOffer openOffer = new OpenOffer(offer);
openOffers.add(openOffer);
- openOfferTradableListStorage.queueUpForSave();
+ requestPersistence();
resultHandler.handleResult(transaction);
if (!stopped) {
startPeriodicRepublishOffersTimer();
@@ -406,10 +407,10 @@ public void activateOpenOffer(OpenOffer openOffer,
ErrorMessageHandler errorMessageHandler) {
if (!offersToBeEdited.containsKey(openOffer.getId())) {
Offer offer = openOffer.getOffer();
- openOffer.setStorage(openOfferTradableListStorage);
offerBookService.activateOffer(offer,
() -> {
openOffer.setState(OpenOffer.State.AVAILABLE);
+ requestPersistence();
log.debug("activateOpenOffer, offerId={}", offer.getId());
resultHandler.handleResult();
},
@@ -423,10 +424,10 @@ public void deactivateOpenOffer(OpenOffer openOffer,
ResultHandler resultHandler,
ErrorMessageHandler errorMessageHandler) {
Offer offer = openOffer.getOffer();
- openOffer.setStorage(openOfferTradableListStorage);
offerBookService.deactivateOffer(offer.getOfferPayload(),
() -> {
openOffer.setState(OpenOffer.State.DEACTIVATED);
+ requestPersistence();
log.debug("deactivateOpenOffer, offerId={}", offer.getId());
resultHandler.handleResult();
},
@@ -439,7 +440,6 @@ public void removeOpenOffer(OpenOffer openOffer,
if (!offersToBeEdited.containsKey(openOffer.getId())) {
Offer offer = openOffer.getOffer();
if (openOffer.isDeactivated()) {
- openOffer.setStorage(openOfferTradableListStorage);
onRemoved(openOffer, resultHandler, offer);
} else {
offerBookService.removeOffer(offer.getOfferPayload(),
@@ -481,15 +481,13 @@ public void editOpenOfferPublish(Offer editedOffer,
Optional openOfferOptional = getOpenOfferById(editedOffer.getId());
if (openOfferOptional.isPresent()) {
- final OpenOffer openOffer = openOfferOptional.get();
-
- openOffer.setStorage(openOfferTradableListStorage);
+ OpenOffer openOffer = openOfferOptional.get();
openOffer.getOffer().setState(Offer.State.REMOVED);
openOffer.setState(OpenOffer.State.CANCELED);
openOffers.remove(openOffer);
- final OpenOffer editedOpenOffer = new OpenOffer(editedOffer, openOfferTradableListStorage);
+ OpenOffer editedOpenOffer = new OpenOffer(editedOffer);
editedOpenOffer.setState(originalState);
openOffers.add(editedOpenOffer);
@@ -498,7 +496,7 @@ public void editOpenOfferPublish(Offer editedOffer,
republishOffer(editedOpenOffer);
offersToBeEdited.remove(openOffer.getId());
-
+ requestPersistence();
resultHandler.handleResult();
} else {
errorMessageHandler.handleErrorMessage("There is no offer with this id existing to be published.");
@@ -528,6 +526,7 @@ private void onRemoved(@NotNull OpenOffer openOffer, ResultHandler resultHandler
closedTradableManager.add(openOffer);
log.info("onRemoved offerId={}", offer.getId());
btcWalletService.resetAddressEntriesForOpenOffer(offer.getId());
+ requestPersistence();
resultHandler.handleResult();
}
@@ -539,11 +538,13 @@ public void closeOpenOffer(Offer offer) {
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
() -> log.trace("Successful removed offer"),
log::error);
+ requestPersistence();
});
}
public void reserveOpenOffer(OpenOffer openOffer) {
openOffer.setState(OpenOffer.State.RESERVED);
+ requestPersistence();
}
@@ -556,7 +557,7 @@ public boolean isMyOffer(Offer offer) {
}
public ObservableList getObservableList() {
- return openOffers.getList();
+ return openOffers.getObservableList();
}
public Optional getOpenOfferById(String offerId) {
@@ -828,7 +829,6 @@ private void maybeUpdatePersistedOffers() {
// remove old offer
originalOffer.setState(Offer.State.REMOVED);
originalOpenOffer.setState(OpenOffer.State.CANCELED);
- originalOpenOffer.setStorage(openOfferTradableListStorage);
openOffers.remove(originalOpenOffer);
// Create new Offer
@@ -836,10 +836,10 @@ private void maybeUpdatePersistedOffers() {
updatedOffer.setPriceFeedService(priceFeedService);
updatedOffer.setState(originalOfferState);
- OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOfferTradableListStorage);
+ OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer);
updatedOpenOffer.setState(originalOpenOfferState);
- updatedOpenOffer.setStorage(openOfferTradableListStorage);
openOffers.add(updatedOpenOffer);
+ requestPersistence();
log.info("Updating offer completed. id={}", originalOffer.getId());
}
@@ -899,7 +899,6 @@ private void republishOffer(OpenOffer openOffer) {
log.debug("We have stopped already. We ignore that offerBookService.republishOffers.onFault call.");
}
});
- openOffer.setStorage(openOfferTradableListStorage);
}
private void startPeriodicRepublishOffersTimer() {
@@ -969,6 +968,10 @@ private void restart() {
startPeriodicRepublishOffersTimer();
}
+ private void requestPersistence() {
+ persistenceManager.requestPersistence();
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////
// Private
diff --git a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
index aad97d33f42..8d183d40857 100644
--- a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
+++ b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
@@ -101,10 +101,6 @@ public long getTakersTradePrice() {
return offer.getPrice() != null ? offer.getPrice().getValue() : 0;
}
- @Override
- public void persist() {
- }
-
@Override
public void onComplete() {
}
diff --git a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
index 6862661b391..f6c04fa1982 100644
--- a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
+++ b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
@@ -34,7 +34,8 @@
@Slf4j
public class ProcessOfferAvailabilityResponse extends Task {
- public ProcessOfferAvailabilityResponse(TaskRunner taskHandler, OfferAvailabilityModel model) {
+ public ProcessOfferAvailabilityResponse(TaskRunner taskHandler,
+ OfferAvailabilityModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java b/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java
index 73f1cb7c1f1..3ee88536c64 100644
--- a/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java
+++ b/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java
@@ -30,7 +30,7 @@
@Slf4j
public class SendOfferAvailabilityRequest extends Task {
- public SendOfferAvailabilityRequest(TaskRunner taskHandler, OfferAvailabilityModel model) {
+ public SendOfferAvailabilityRequest(TaskRunner taskHandler, OfferAvailabilityModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
index 8a139de6eea..0c54d733ed0 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
@@ -87,10 +87,6 @@ public PlaceOfferModel(Offer offer,
this.filterManager = filterManager;
}
- @Override
- public void persist() {
- }
-
@Override
public void onComplete() {
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java
index 49c3702ba78..16def612ba0 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java
@@ -22,15 +22,9 @@
import bisq.common.taskrunner.Task;
import bisq.common.taskrunner.TaskRunner;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public class AddToOfferBook extends Task {
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(AddToOfferBook.class);
- @SuppressWarnings({"WeakerAccess", "unused"})
- public AddToOfferBook(TaskRunner taskHandler, PlaceOfferModel model) {
+ public AddToOfferBook(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CheckNumberOfUnconfirmedTransactions.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CheckNumberOfUnconfirmedTransactions.java
index 0dbe944ea4f..31e8d300032 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CheckNumberOfUnconfirmedTransactions.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CheckNumberOfUnconfirmedTransactions.java
@@ -7,7 +7,7 @@
import bisq.common.taskrunner.TaskRunner;
public class CheckNumberOfUnconfirmedTransactions extends Task {
- public CheckNumberOfUnconfirmedTransactions(TaskRunner taskHandler, PlaceOfferModel model) {
+ public CheckNumberOfUnconfirmedTransactions(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
index 51cd12b6f4f..df697134319 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
@@ -46,7 +46,7 @@ public class CreateMakerFeeTx extends Task {
private static final Logger log = LoggerFactory.getLogger(CreateMakerFeeTx.class);
@SuppressWarnings({"unused"})
- public CreateMakerFeeTx(TaskRunner taskHandler, PlaceOfferModel model) {
+ public CreateMakerFeeTx(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
index 05c88acf468..35d619feb4d 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
@@ -26,18 +26,11 @@
import org.bitcoinj.core.Coin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
public class ValidateOffer extends Task {
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(ValidateOffer.class);
-
- @SuppressWarnings({"WeakerAccess", "unused"})
- public ValidateOffer(TaskRunner taskHandler, PlaceOfferModel model) {
+ public ValidateOffer(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountList.java b/core/src/main/java/bisq/core/payment/PaymentAccountList.java
index efe9cccc229..a35801705ce 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccountList.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccountList.java
@@ -19,7 +19,7 @@
import bisq.core.proto.CoreProtoResolver;
-import bisq.common.proto.persistable.UserThreadMappedPersistableList;
+import bisq.common.proto.persistable.PersistableList;
import com.google.protobuf.Message;
@@ -30,7 +30,7 @@
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
-public class PaymentAccountList extends UserThreadMappedPersistableList {
+public class PaymentAccountList extends PersistableList {
public PaymentAccountList(List list) {
super(list);
diff --git a/core/src/main/java/bisq/core/presentation/TradePresentation.java b/core/src/main/java/bisq/core/presentation/TradePresentation.java
index e7f43c7f538..678f827b590 100644
--- a/core/src/main/java/bisq/core/presentation/TradePresentation.java
+++ b/core/src/main/java/bisq/core/presentation/TradePresentation.java
@@ -36,9 +36,6 @@ public class TradePresentation {
@Inject
public TradePresentation(TradeManager tradeManager) {
- // TODO replace for tradeManager.getTradesAsObservableList() once tradableList is refactored to a final field
- // (part of the persistence refactor PR)
-
tradeManager.getNumPendingTrades().addListener((observable, oldValue, newValue) -> {
long numPendingTrades = (long) newValue;
if (numPendingTrades > 0)
diff --git a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
index b38a015fbb1..efefffe881a 100644
--- a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
+++ b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
@@ -29,8 +29,8 @@
import bisq.core.dao.governance.proposal.MyProposalList;
import bisq.core.dao.governance.proposal.storage.appendonly.ProposalStore;
import bisq.core.dao.governance.proposal.storage.temp.TempProposalStore;
-import bisq.core.dao.state.DaoStateStore;
import bisq.core.dao.state.model.governance.BallotList;
+import bisq.core.dao.state.storage.DaoStateStore;
import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputList;
import bisq.core.payment.PaymentAccountList;
import bisq.core.proto.CoreProtoResolver;
@@ -45,23 +45,17 @@
import bisq.network.p2p.peers.peerexchange.PeerList;
import bisq.network.p2p.storage.persistence.SequenceNumberMap;
-import bisq.common.config.Config;
import bisq.common.proto.ProtobufferRuntimeException;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.NavigationPath;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistenceProtoResolver;
-import bisq.common.storage.CorruptedDatabaseFilesHandler;
-import bisq.common.storage.Storage;
import com.google.inject.Provider;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
-import java.io.File;
-
import lombok.extern.slf4j.Slf4j;
// TODO Use ProtobufferException instead of ProtobufferRuntimeException
@@ -70,19 +64,12 @@
public class CorePersistenceProtoResolver extends CoreProtoResolver implements PersistenceProtoResolver {
private final Provider btcWalletService;
private final NetworkProtoResolver networkProtoResolver;
- private final File storageDir;
- private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
@Inject
public CorePersistenceProtoResolver(Provider btcWalletService,
- NetworkProtoResolver networkProtoResolver,
- @Named(Config.STORAGE_DIR) File storageDir,
- CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) {
+ NetworkProtoResolver networkProtoResolver) {
this.btcWalletService = btcWalletService;
this.networkProtoResolver = networkProtoResolver;
- this.storageDir = storageDir;
-
- this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler;
}
@Override
@@ -96,22 +83,13 @@ public PersistableEnvelope fromProto(protobuf.PersistableEnvelope proto) {
case ADDRESS_ENTRY_LIST:
return AddressEntryList.fromProto(proto.getAddressEntryList());
case TRADABLE_LIST:
- return TradableList.fromProto(proto.getTradableList(),
- this,
- new Storage<>(storageDir, this, corruptedDatabaseFilesHandler),
- btcWalletService.get());
+ return TradableList.fromProto(proto.getTradableList(), this, btcWalletService.get());
case ARBITRATION_DISPUTE_LIST:
- return ArbitrationDisputeList.fromProto(proto.getArbitrationDisputeList(),
- this,
- new Storage<>(storageDir, this, corruptedDatabaseFilesHandler));
+ return ArbitrationDisputeList.fromProto(proto.getArbitrationDisputeList(), this);
case MEDIATION_DISPUTE_LIST:
- return MediationDisputeList.fromProto(proto.getMediationDisputeList(),
- this,
- new Storage<>(storageDir, this, corruptedDatabaseFilesHandler));
+ return MediationDisputeList.fromProto(proto.getMediationDisputeList(), this);
case REFUND_DISPUTE_LIST:
- return RefundDisputeList.fromProto(proto.getRefundDisputeList(),
- this,
- new Storage<>(storageDir, this, corruptedDatabaseFilesHandler));
+ return RefundDisputeList.fromProto(proto.getRefundDisputeList(), this);
case PREFERENCES_PAYLOAD:
return PreferencesPayload.fromProto(proto.getPreferencesPayload(), this);
case USER_PAYLOAD:
diff --git a/core/src/main/java/bisq/core/support/SupportManager.java b/core/src/main/java/bisq/core/support/SupportManager.java
index 5d3f33200c5..4017686fa8a 100644
--- a/core/src/main/java/bisq/core/support/SupportManager.java
+++ b/core/src/main/java/bisq/core/support/SupportManager.java
@@ -94,7 +94,7 @@ public SupportManager(P2PService p2PService, WalletsSetup walletsSetup) {
public abstract void addAndPersistChatMessage(ChatMessage message);
- public abstract void persist();
+ public abstract void requestPersistence();
///////////////////////////////////////////////////////////////////////////////////////////
@@ -174,7 +174,7 @@ private void onAckMessage(AckMessage ackMessage,
else
msg.setAckError(ackMessage.getErrorMessage());
});
- persist();
+ requestPersistence();
if (decryptedMessageWithPubKey != null)
p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
@@ -204,7 +204,7 @@ public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
message.setArrived(true);
- persist();
+ requestPersistence();
}
@Override
@@ -212,7 +212,7 @@ public void onStoredInMailbox() {
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
message.setStoredInMailbox(true);
- persist();
+ requestPersistence();
}
@Override
@@ -220,7 +220,7 @@ public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
message.setSendMessageError(errorMessage);
- persist();
+ requestPersistence();
}
}
);
diff --git a/core/src/main/java/bisq/core/support/dispute/Dispute.java b/core/src/main/java/bisq/core/support/dispute/Dispute.java
index 2cfd0850d7f..a622d6bc738 100644
--- a/core/src/main/java/bisq/core/support/dispute/Dispute.java
+++ b/core/src/main/java/bisq/core/support/dispute/Dispute.java
@@ -25,7 +25,7 @@
import bisq.common.crypto.PubKeyRing;
import bisq.common.proto.ProtoUtil;
import bisq.common.proto.network.NetworkPayload;
-import bisq.common.storage.Storage;
+import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
@@ -57,7 +57,7 @@
@Slf4j
@EqualsAndHashCode
@Getter
-public final class Dispute implements NetworkPayload {
+public final class Dispute implements NetworkPayload, PersistablePayload {
private final String tradeId;
private final String id;
private final int traderId;
@@ -85,15 +85,14 @@ public final class Dispute implements NetworkPayload {
private final PubKeyRing agentPubKeyRing; // dispute agent
private final boolean isSupportTicket;
private final ObservableList chatMessages = FXCollections.observableArrayList();
- private BooleanProperty isClosedProperty = new SimpleBooleanProperty();
+ private final BooleanProperty isClosedProperty = new SimpleBooleanProperty();
// disputeResultProperty.get is Nullable!
- private ObjectProperty disputeResultProperty = new SimpleObjectProperty<>();
+ private final ObjectProperty disputeResultProperty = new SimpleObjectProperty<>();
+ private final long openingDate;
@Nullable
+ @Setter
private String disputePayoutTxId;
- private long openingDate;
-
- transient private Storage extends DisputeList> storage;
-
+ @Setter
// Added v1.2.0
private SupportType supportType;
// Only used at refundAgent so that he knows how the mediator resolved the case
@@ -118,7 +117,7 @@ public final class Dispute implements NetworkPayload {
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
- public Dispute(Storage extends DisputeList> storage,
+ public Dispute(long openingDate,
String tradeId,
int traderId,
boolean disputeOpenerIsBuyer,
@@ -137,51 +136,7 @@ public Dispute(Storage extends DisputeList> storage,
PubKeyRing agentPubKeyRing,
boolean isSupportTicket,
SupportType supportType) {
- this(tradeId,
- traderId,
- disputeOpenerIsBuyer,
- disputeOpenerIsMaker,
- traderPubKeyRing,
- tradeDate,
- contract,
- contractHash,
- depositTxSerialized,
- payoutTxSerialized,
- depositTxId,
- payoutTxId,
- contractAsJson,
- makerContractSignature,
- takerContractSignature,
- agentPubKeyRing,
- isSupportTicket,
- supportType);
- this.storage = storage;
- openingDate = new Date().getTime();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // PROTO BUFFER
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- public Dispute(String tradeId,
- int traderId,
- boolean disputeOpenerIsBuyer,
- boolean disputeOpenerIsMaker,
- PubKeyRing traderPubKeyRing,
- long tradeDate,
- Contract contract,
- @Nullable byte[] contractHash,
- @Nullable byte[] depositTxSerialized,
- @Nullable byte[] payoutTxSerialized,
- @Nullable String depositTxId,
- @Nullable String payoutTxId,
- String contractAsJson,
- @Nullable String makerContractSignature,
- @Nullable String takerContractSignature,
- PubKeyRing agentPubKeyRing,
- boolean isSupportTicket,
- SupportType supportType) {
+ this.openingDate = openingDate;
this.tradeId = tradeId;
this.traderId = traderId;
this.disputeOpenerIsBuyer = disputeOpenerIsBuyer;
@@ -205,6 +160,11 @@ public Dispute(String tradeId,
uid = UUID.randomUUID().toString();
}
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTO BUFFER
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
@Override
public protobuf.Dispute toProtoMessage() {
// Needed to avoid ConcurrentModificationException
@@ -244,7 +204,8 @@ public protobuf.Dispute toProtoMessage() {
}
public static Dispute fromProto(protobuf.Dispute proto, CoreProtoResolver coreProtoResolver) {
- Dispute dispute = new Dispute(proto.getTradeId(),
+ Dispute dispute = new Dispute(proto.getOpeningDate(),
+ proto.getTradeId(),
proto.getTraderId(),
proto.getDisputeOpenerIsBuyer(),
proto.getDisputeOpenerIsMaker(),
@@ -267,7 +228,6 @@ public static Dispute fromProto(protobuf.Dispute proto, CoreProtoResolver corePr
.map(ChatMessage::fromPayloadProto)
.collect(Collectors.toList()));
- dispute.openingDate = proto.getOpeningDate();
dispute.isClosedProperty.set(proto.getIsClosed());
if (proto.hasDisputeResult())
dispute.disputeResultProperty.set(DisputeResult.fromProto(proto.getDisputeResult()));
@@ -299,7 +259,6 @@ public static Dispute fromProto(protobuf.Dispute proto, CoreProtoResolver corePr
public void addAndPersistChatMessage(ChatMessage chatMessage) {
if (!chatMessages.contains(chatMessage)) {
chatMessages.add(chatMessage);
- storage.queueUpForSave();
} else {
log.error("disputeDirectMessage already exists");
}
@@ -310,35 +269,14 @@ public void addAndPersistChatMessage(ChatMessage chatMessage) {
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
- // In case we get the object via the network storage is not set as its transient, so we need to set it.
- public void setStorage(Storage extends DisputeList> storage) {
- this.storage = storage;
- }
-
public void setIsClosed(boolean isClosed) {
- boolean changed = this.isClosedProperty.get() != isClosed;
this.isClosedProperty.set(isClosed);
- if (changed)
- storage.queueUpForSave();
}
public void setDisputeResult(DisputeResult disputeResult) {
- boolean changed = disputeResultProperty.get() == null || !disputeResultProperty.get().equals(disputeResult);
disputeResultProperty.set(disputeResult);
- if (changed)
- storage.queueUpForSave();
}
- public void setDisputePayoutTxId(String disputePayoutTxId) {
- boolean changed = this.disputePayoutTxId == null || !this.disputePayoutTxId.equals(disputePayoutTxId);
- this.disputePayoutTxId = disputePayoutTxId;
- if (changed)
- storage.queueUpForSave();
- }
-
- public void setSupportType(SupportType supportType) {
- this.supportType = supportType;
- }
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@@ -396,7 +334,6 @@ public String toString() {
",\n disputeResultProperty=" + disputeResultProperty +
",\n disputePayoutTxId='" + disputePayoutTxId + '\'' +
",\n openingDate=" + openingDate +
- ",\n storage=" + storage +
",\n supportType=" + supportType +
",\n mediatorsDisputeResult='" + mediatorsDisputeResult + '\'' +
",\n delayedPayoutTxId='" + delayedPayoutTxId + '\'' +
diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeList.java b/core/src/main/java/bisq/core/support/dispute/DisputeList.java
index 468699c4abf..15069649567 100644
--- a/core/src/main/java/bisq/core/support/dispute/DisputeList.java
+++ b/core/src/main/java/bisq/core/support/dispute/DisputeList.java
@@ -17,18 +17,11 @@
package bisq.core.support.dispute;
-import bisq.common.proto.persistable.PersistableEnvelope;
-import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
-import bisq.common.storage.Storage;
+import bisq.common.proto.persistable.PersistableListAsObservable;
+import bisq.common.proto.persistable.PersistablePayload;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
+import java.util.Collection;
-import java.util.List;
-import java.util.stream.Stream;
-
-import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@@ -40,67 +33,12 @@
* Calls to the List are delegated because this class intercepts the add/remove calls so changes
* can be saved to disc.
*/
-public abstract class DisputeList implements UserThreadMappedPersistableEnvelope, PersistedDataHost {
- transient protected final Storage storage;
-
- @Getter
- protected final ObservableList list = FXCollections.observableArrayList();
-
- public DisputeList(Storage storage) {
- this.storage = storage;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // PROTO BUFFER
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- protected DisputeList(Storage storage, List list) {
- this.storage = storage;
- this.list.addAll(list);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // API
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- public boolean add(Dispute dispute) {
- if (!list.contains(dispute)) {
- list.add(dispute);
- persist();
- return true;
- } else {
- return false;
- }
- }
-
- public boolean remove(Object dispute) {
- //noinspection SuspiciousMethodCalls
- boolean changed = list.remove(dispute);
- if (changed)
- persist();
- return changed;
- }
-
- public void persist() {
- storage.queueUpForSave();
- }
-
- public int size() {
- return list.size();
- }
-
- public boolean isEmpty() {
- return list.isEmpty();
- }
+public abstract class DisputeList extends PersistableListAsObservable {
- @SuppressWarnings({"SuspiciousMethodCalls"})
- public boolean contains(Object o) {
- return list.contains(o);
+ public DisputeList() {
}
- public Stream stream() {
- return list.stream();
+ protected DisputeList(Collection collection) {
+ super(collection);
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeListService.java b/core/src/main/java/bisq/core/support/dispute/DisputeListService.java
index d3f57cb03a2..ffbec7dc985 100644
--- a/core/src/main/java/bisq/core/support/dispute/DisputeListService.java
+++ b/core/src/main/java/bisq/core/support/dispute/DisputeListService.java
@@ -22,8 +22,8 @@
import bisq.network.p2p.NodeAddress;
import bisq.common.UserThread;
+import bisq.common.persistence.PersistenceManager;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.storage.Storage;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
@@ -31,8 +31,6 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
-import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.HashMap;
@@ -47,12 +45,11 @@
import javax.annotation.Nullable;
@Slf4j
-public abstract class DisputeListService> implements PersistedDataHost {
+public abstract class DisputeListService> implements PersistedDataHost {
@Getter
- protected final Storage storage;
- @Nullable
+ protected final PersistenceManager persistenceManager;
@Getter
- private T disputeList;
+ private final T disputeList;
private final Map disputeIsClosedSubscriptionsMap = new HashMap<>();
@Getter
private final IntegerProperty numOpenDisputes = new SimpleIntegerProperty();
@@ -62,8 +59,11 @@ public abstract class DisputeListService storage) {
- this.storage = storage;
+ public DisputeListService(PersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+ disputeList = getConcreteDisputeList();
+
+ this.persistenceManager.initialize(disputeList, getFileName(), PersistenceManager.Source.PRIVATE);
}
@@ -80,9 +80,14 @@ public DisputeListService(Storage storage) {
@Override
public void readPersisted() {
- disputeList = getConcreteDisputeList();
- disputeList.readPersisted();
- disputeList.stream().forEach(dispute -> dispute.setStorage(storage));
+ T persisted = persistenceManager.getPersisted(getFileName());
+ if (persisted != null) {
+ disputeList.setAll(persisted.getList());
+ }
+ }
+
+ protected String getFileName() {
+ return disputeList.getDefaultStorageFileName();
}
@@ -91,19 +96,12 @@ public void readPersisted() {
///////////////////////////////////////////////////////////////////////////////////////////
public void cleanupDisputes(@Nullable Consumer closedDisputeHandler) {
- if (disputeList != null) {
- disputeList.stream().forEach(dispute -> {
- dispute.setStorage(storage);
- String tradeId = dispute.getTradeId();
- if (dispute.isClosed()) {
- if (closedDisputeHandler != null) {
- closedDisputeHandler.accept(tradeId);
- }
- }
- });
- } else {
- log.warn("disputes is null");
- }
+ disputeList.stream().forEach(dispute -> {
+ String tradeId = dispute.getTradeId();
+ if (dispute.isClosed() && closedDisputeHandler != null) {
+ closedDisputeHandler.accept(tradeId);
+ }
+ });
}
@@ -112,19 +110,15 @@ public void cleanupDisputes(@Nullable Consumer closedDisputeHandler) {
///////////////////////////////////////////////////////////////////////////////////////////
void onAllServicesInitialized() {
- if (disputeList != null) {
- disputeList.getList().addListener((ListChangeListener) change -> {
- change.next();
- onDisputesChangeListener(change.getAddedSubList(), change.getRemoved());
- });
- onDisputesChangeListener(disputeList.getList(), null);
- } else {
- log.warn("disputes is null");
- }
+ disputeList.addListener(change -> {
+ change.next();
+ onDisputesChangeListener(change.getAddedSubList(), change.getRemoved());
+ });
+ onDisputesChangeListener(disputeList.getList(), null);
}
String getNrOfDisputes(boolean isBuyer, Contract contract) {
- return String.valueOf(getDisputesAsObservableList().stream()
+ return String.valueOf(getObservableList().stream()
.filter(e -> {
Contract contract1 = e.getContract();
if (contract1 == null)
@@ -141,12 +135,8 @@ String getNrOfDisputes(boolean isBuyer, Contract contract) {
.collect(Collectors.toSet()).size());
}
- ObservableList getDisputesAsObservableList() {
- if (disputeList == null) {
- log.warn("disputes is null");
- return FXCollections.observableArrayList();
- }
- return disputeList.getList();
+ ObservableList getObservableList() {
+ return disputeList.getObservableList();
}
@@ -169,22 +159,18 @@ private void onDisputesChangeListener(List extends Dispute> addedList,
String id = dispute.getId();
Subscription disputeStateSubscription = EasyBind.subscribe(dispute.isClosedProperty(),
isClosed -> {
- if (disputeList != null) {
- // We get the event before the list gets updated, so we execute on next frame
- UserThread.execute(() -> {
- int openDisputes = (int) disputeList.getList().stream()
- .filter(e -> !e.isClosed()).count();
- numOpenDisputes.set(openDisputes);
- });
- }
+ // We get the event before the list gets updated, so we execute on next frame
+ UserThread.execute(() -> {
+ int openDisputes = (int) disputeList.getList().stream()
+ .filter(e -> !e.isClosed()).count();
+ numOpenDisputes.set(openDisputes);
+ });
});
disputeIsClosedSubscriptionsMap.put(id, disputeStateSubscription);
});
}
- public void persist() {
- if (disputeList != null) {
- disputeList.persist();
- }
+ public void requestPersistence() {
+ persistenceManager.requestPersistence();
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java
index 63ad2ef092b..45fc43f35e1 100644
--- a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java
+++ b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java
@@ -53,7 +53,6 @@
import bisq.common.crypto.PubKeyRing;
import bisq.common.handlers.FaultHandler;
import bisq.common.handlers.ResultHandler;
-import bisq.common.storage.Storage;
import bisq.common.util.MathUtils;
import bisq.common.util.Tuple2;
@@ -67,6 +66,7 @@
import java.security.KeyPair;
+import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -81,7 +81,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
-public abstract class DisputeManager> extends SupportManager {
+public abstract class DisputeManager> extends SupportManager {
protected final TradeWalletService tradeWalletService;
protected final BtcWalletService btcWalletService;
protected final TradeManager tradeManager;
@@ -137,8 +137,8 @@ public DisputeManager(P2PService p2PService,
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public void persist() {
- disputeListService.persist();
+ public void requestPersistence() {
+ disputeListService.requestPersistence();
}
@Override
@@ -181,6 +181,7 @@ public void addAndPersistChatMessage(ChatMessage message) {
findDispute(message).ifPresent(dispute -> {
if (dispute.getChatMessages().stream().noneMatch(m -> m.getUid().equals(message.getUid()))) {
dispute.addAndPersistChatMessage(message);
+ requestPersistence();
} else {
log.warn("We got a chatMessage that we have already stored. UId = {} TradeId = {}",
message.getUid(), message.getTradeId());
@@ -218,12 +219,8 @@ public IntegerProperty getNumOpenDisputes() {
return disputeListService.getNumOpenDisputes();
}
- public Storage extends DisputeList> getStorage() {
- return disputeListService.getStorage();
- }
-
public ObservableList getDisputesAsObservableList() {
- return disputeListService.getDisputesAsObservableList();
+ return disputeListService.getObservableList();
}
public String getNrOfDisputes(boolean isBuyer, Contract contract) {
@@ -263,7 +260,7 @@ public void onUpdatedDataReceived() {
tryApplyMessages();
cleanupDisputes();
- ObservableList disputes = getDisputeList().getList();
+ List disputes = getDisputeList().getList();
disputes.forEach(dispute -> {
try {
TradeDataValidation.validateDonationAddress(dispute, dispute.getDonationAddressOfDelayedPayoutTx(), daoFacade);
@@ -296,6 +293,7 @@ public Optional findOwnDispute(String tradeId) {
return disputeList.stream().filter(e -> e.getTradeId().equals(tradeId)).findAny();
}
+
///////////////////////////////////////////////////////////////////////////////////////////
// Message handler
///////////////////////////////////////////////////////////////////////////////////////////
@@ -310,7 +308,6 @@ protected void onOpenNewDisputeMessage(OpenNewDisputeMessage openNewDisputeMessa
String errorMessage = null;
Dispute dispute = openNewDisputeMessage.getDispute();
- dispute.setStorage(disputeListService.getStorage());
// Disputes from clients < 1.2.0 always have support type ARBITRATION in dispute as the field didn't exist before
dispute.setSupportType(openNewDisputeMessage.getSupportType());
@@ -359,6 +356,7 @@ protected void onOpenNewDisputeMessage(OpenNewDisputeMessage openNewDisputeMessa
log.error(e.toString());
validationExceptions.add(e);
}
+ requestPersistence();
}
// Not-dispute-requester receives that msg from dispute agent
@@ -395,7 +393,6 @@ protected void onPeerOpenedDisputeMessage(PeerOpenedDisputeMessage peerOpenedDis
if (!disputeList.contains(dispute)) {
Optional storedDisputeOptional = findDispute(dispute);
if (!storedDisputeOptional.isPresent()) {
- dispute.setStorage(disputeListService.getStorage());
disputeList.add(dispute);
trade.setDisputeState(getDisputeStateStartedByPeer());
errorMessage = null;
@@ -421,6 +418,7 @@ protected void onPeerOpenedDisputeMessage(PeerOpenedDisputeMessage peerOpenedDis
}
sendAckMessage(peerOpenedDisputeMessage, dispute.getAgentPubKeyRing(), errorMessage == null, errorMessage);
+ requestPersistence();
}
@@ -499,7 +497,7 @@ public void onArrived() {
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true);
- disputeList.persist();
+ requestPersistence();
resultHandler.handleResult();
}
@@ -514,7 +512,7 @@ public void onStoredInMailbox() {
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true);
- disputeList.persist();
+ requestPersistence();
resultHandler.handleResult();
}
@@ -529,7 +527,7 @@ public void onFault(String errorMessage) {
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage);
- disputeList.persist();
+ requestPersistence();
faultHandler.handleFault("Sending dispute message failed: " +
errorMessage, new DisputeMessageDeliveryFailedException());
}
@@ -541,6 +539,7 @@ public void onFault(String errorMessage) {
log.warn(msg);
faultHandler.handleFault(msg, new DisputeAlreadyOpenException());
}
+ requestPersistence();
}
// Dispute agent sends that to trading peer when he received openDispute request
@@ -566,7 +565,7 @@ private void doSendPeerOpenedDisputeMessage(Dispute disputeFromOpener,
return;
}
- Dispute dispute = new Dispute(disputeListService.getStorage(),
+ Dispute dispute = new Dispute(new Date().getTime(),
disputeFromOpener.getTradeId(),
pubKeyRing.hashCode(),
!disputeFromOpener.isDisputeOpenerIsBuyer(),
@@ -592,8 +591,7 @@ private void doSendPeerOpenedDisputeMessage(Dispute disputeFromOpener,
// Valid case if both have opened a dispute and agent was not online.
if (storedDisputeOptional.isPresent()) {
- log.info("We got a dispute already open for that trade and trading peer. TradeId = {}",
- dispute.getTradeId());
+ log.info("We got a dispute already open for that trade and trading peer. TradeId = {}", dispute.getTradeId());
return;
}
@@ -645,7 +643,7 @@ public void onArrived() {
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true);
- disputeList.persist();
+ requestPersistence();
}
@Override
@@ -659,7 +657,7 @@ public void onStoredInMailbox() {
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true);
- disputeList.persist();
+ requestPersistence();
}
@Override
@@ -673,10 +671,11 @@ public void onFault(String errorMessage) {
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage);
- disputeList.persist();
+ requestPersistence();
}
}
);
+ requestPersistence();
}
// dispute agent send result to trader
@@ -726,7 +725,7 @@ public void onArrived() {
// We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true);
- disputeList.persist();
+ requestPersistence();
}
@Override
@@ -740,7 +739,7 @@ public void onStoredInMailbox() {
// We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true);
- disputeList.persist();
+ requestPersistence();
}
@Override
@@ -754,10 +753,11 @@ public void onFault(String errorMessage) {
// We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage);
- disputeList.persist();
+ requestPersistence();
}
}
);
+ requestPersistence();
}
@@ -837,6 +837,7 @@ private void addMediationResultMessage(Dispute dispute) {
p2PService.getAddress());
mediatorsDisputeResultMessage.setSystemMessage(true);
dispute.addAndPersistChatMessage(mediatorsDisputeResultMessage);
+ requestPersistence();
}
}
@@ -909,6 +910,7 @@ protected void addPriceInfoMessage(Dispute dispute, int counter) {
p2PService.getAddress());
priceInfoMessage.setSystemMessage(true);
dispute.addAndPersistChatMessage(priceInfoMessage);
+ requestPersistence();
}
@Nullable
diff --git a/core/src/main/java/bisq/core/support/dispute/agent/MultipleHolderNameDetection.java b/core/src/main/java/bisq/core/support/dispute/agent/MultipleHolderNameDetection.java
index 80a64808c64..3bcbf50aa92 100644
--- a/core/src/main/java/bisq/core/support/dispute/agent/MultipleHolderNameDetection.java
+++ b/core/src/main/java/bisq/core/support/dispute/agent/MultipleHolderNameDetection.java
@@ -113,20 +113,20 @@ private static String getIsBuyerSubString(boolean isBuyer) {
// Class fields
///////////////////////////////////////////////////////////////////////////////////////////
- private final DisputeManager extends DisputeList extends DisputeList>> disputeManager;
+ private final DisputeManager extends DisputeList> disputeManager;
// Key is hex of hash of sig pubKey which we consider a trader identity. We could use onion address as well but
// once we support multiple onion addresses that would not work anymore.
@Getter
- private Map> suspiciousDisputesByTraderMap = new HashMap<>();
- private List listeners = new CopyOnWriteArrayList<>();
+ private final Map> suspiciousDisputesByTraderMap = new HashMap<>();
+ private final List listeners = new CopyOnWriteArrayList<>();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
- public MultipleHolderNameDetection(DisputeManager extends DisputeList extends DisputeList>> disputeManager) {
+ public MultipleHolderNameDetection(DisputeManager extends DisputeList> disputeManager) {
this.disputeManager = disputeManager;
disputeManager.getDisputesAsObservableList().addListener((ListChangeListener) c -> {
diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeList.java b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeList.java
index 9d625f4a01e..aa6bcc23721 100644
--- a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeList.java
+++ b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeList.java
@@ -23,11 +23,10 @@
import bisq.core.support.dispute.DisputeList;
import bisq.common.proto.ProtoUtil;
-import bisq.common.storage.Storage;
import com.google.protobuf.Message;
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -44,19 +43,10 @@
* Calls to the List are delegated because this class intercepts the add/remove calls so changes
* can be saved to disc.
*/
-public final class ArbitrationDisputeList extends DisputeList {
+public final class ArbitrationDisputeList extends DisputeList {
- ArbitrationDisputeList(Storage storage) {
- super(storage);
- }
-
- @Override
- public void readPersisted() {
- // We need to use DisputeList as file name to not lose existing disputes which are stored in the DisputeList file
- ArbitrationDisputeList persisted = storage.initAndGetPersisted(this, "DisputeList", 50);
- if (persisted != null) {
- list.addAll(persisted.getList());
- }
+ ArbitrationDisputeList() {
+ super();
}
@@ -64,30 +54,26 @@ public void readPersisted() {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- private ArbitrationDisputeList(Storage storage, List list) {
- super(storage, list);
+ protected ArbitrationDisputeList(Collection collection) {
+ super(collection);
}
@Override
public Message toProtoMessage() {
- list.forEach(dispute -> checkArgument(dispute.getSupportType().equals(SupportType.ARBITRATION), "Support type has to be ARBITRATION"));
+ forEach(dispute -> checkArgument(dispute.getSupportType().equals(SupportType.ARBITRATION), "Support type has to be ARBITRATION"));
return protobuf.PersistableEnvelope.newBuilder().setArbitrationDisputeList(protobuf.ArbitrationDisputeList.newBuilder()
- .addAllDispute(ProtoUtil.collectionToProto(new ArrayList<>(list), protobuf.Dispute.class))).build();
+ .addAllDispute(ProtoUtil.collectionToProto(getList(), protobuf.Dispute.class))).build();
}
public static ArbitrationDisputeList fromProto(protobuf.ArbitrationDisputeList proto,
- CoreProtoResolver coreProtoResolver,
- Storage storage) {
+ CoreProtoResolver coreProtoResolver) {
List list = proto.getDisputeList().stream()
.map(disputeProto -> Dispute.fromProto(disputeProto, coreProtoResolver))
+ .filter(e -> e.getSupportType().equals(SupportType.ARBITRATION))
.collect(Collectors.toList());
- list.forEach(e -> {
- checkArgument(e.getSupportType().equals(SupportType.ARBITRATION), "Support type has to be ARBITRATION");
- e.setStorage(storage);
- });
- return new ArbitrationDisputeList(storage, list);
+ return new ArbitrationDisputeList(list);
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeListService.java b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeListService.java
index 3d456f686ef..d9b57bb595f 100644
--- a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeListService.java
+++ b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationDisputeListService.java
@@ -19,7 +19,7 @@
import bisq.core.support.dispute.DisputeListService;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -32,8 +32,8 @@ public final class ArbitrationDisputeListService extends DisputeListService storage) {
- super(storage);
+ public ArbitrationDisputeListService(PersistenceManager persistenceManager) {
+ super(persistenceManager);
}
@@ -43,6 +43,11 @@ public ArbitrationDisputeListService(Storage storage) {
@Override
protected ArbitrationDisputeList getConcreteDisputeList() {
- return new ArbitrationDisputeList(storage);
+ return new ArbitrationDisputeList();
+ }
+
+ @Override
+ protected String getFileName() {
+ return "DisputeList";
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java
index dd21166f7d3..8552003199d 100644
--- a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java
+++ b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java
@@ -337,6 +337,8 @@ public void onFailure(TxBroadcastException exception) {
// If we would use the disputeResultMessage we could not lookup for the msg when we receive the AckMessage.
sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), success, errorMessage);
}
+
+ requestPersistence();
}
// Losing trader or in case of 50/50 the seller gets the tx sent from the winner or buyer
@@ -371,6 +373,7 @@ private void onDisputedPayoutTxMessage(PeerPublishedDisputePayoutTxMessage peerP
// We can only send the ack msg if we have the peersPubKeyRing which requires the dispute
sendAckMessage(peerPublishedDisputePayoutTxMessage, peersPubKeyRing, true, null);
+ requestPersistence();
}
diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeList.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeList.java
index 59208c23b7d..00b7b4df821 100644
--- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeList.java
+++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeList.java
@@ -18,15 +18,15 @@
package bisq.core.support.dispute.mediation;
import bisq.core.proto.CoreProtoResolver;
+import bisq.core.support.SupportType;
import bisq.core.support.dispute.Dispute;
import bisq.core.support.dispute.DisputeList;
import bisq.common.proto.ProtoUtil;
-import bisq.common.storage.Storage;
import com.google.protobuf.Message;
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -41,18 +41,10 @@
* Calls to the List are delegated because this class intercepts the add/remove calls so changes
* can be saved to disc.
*/
-public final class MediationDisputeList extends DisputeList {
+public final class MediationDisputeList extends DisputeList {
- MediationDisputeList(Storage storage) {
- super(storage);
- }
-
- @Override
- public void readPersisted() {
- MediationDisputeList persisted = storage.initAndGetPersisted(this, "MediationDisputeList", 0);
- if (persisted != null) {
- list.addAll(persisted.getList());
- }
+ MediationDisputeList() {
+ super();
}
@@ -60,23 +52,22 @@ public void readPersisted() {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- private MediationDisputeList(Storage storage, List list) {
- super(storage, list);
+ protected MediationDisputeList(Collection collection) {
+ super(collection);
}
@Override
public Message toProtoMessage() {
return protobuf.PersistableEnvelope.newBuilder().setMediationDisputeList(protobuf.MediationDisputeList.newBuilder()
- .addAllDispute(ProtoUtil.collectionToProto(new ArrayList<>(list), protobuf.Dispute.class))).build();
+ .addAllDispute(ProtoUtil.collectionToProto(getList(), protobuf.Dispute.class))).build();
}
public static MediationDisputeList fromProto(protobuf.MediationDisputeList proto,
- CoreProtoResolver coreProtoResolver,
- Storage storage) {
+ CoreProtoResolver coreProtoResolver) {
List list = proto.getDisputeList().stream()
.map(disputeProto -> Dispute.fromProto(disputeProto, coreProtoResolver))
+ .filter(e -> e.getSupportType().equals(SupportType.MEDIATION))
.collect(Collectors.toList());
- list.forEach(e -> e.setStorage(storage));
- return new MediationDisputeList(storage, list);
+ return new MediationDisputeList(list);
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeListService.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeListService.java
index cb4fbf40010..70cbd5bf786 100644
--- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeListService.java
+++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationDisputeListService.java
@@ -19,7 +19,7 @@
import bisq.core.support.dispute.DisputeListService;
-import bisq.common.storage.Storage;
+import bisq.common.persistence.PersistenceManager;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -32,8 +32,8 @@ public final class MediationDisputeListService extends DisputeListService storage) {
- super(storage);
+ public MediationDisputeListService(PersistenceManager persistenceManager) {
+ super(persistenceManager);
}
@@ -43,6 +43,6 @@ public MediationDisputeListService(Storage storage) {
@Override
protected MediationDisputeList getConcreteDisputeList() {
- return new MediationDisputeList(storage);
+ return new MediationDisputeList();
}
}
diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java
index 09b40f513b7..7e00146ee8d 100644
--- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java
+++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java
@@ -209,6 +209,8 @@ public void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
}
sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), true, null);
+
+ requestPersistence();
}
diff --git a/core/src/main/java/bisq/core/support/dispute/refund/RefundDisputeList.java b/core/src/main/java/bisq/core/support/dispute/refund/RefundDisputeList.java
index 6602008a2e6..1194ac9c0d0 100644
--- a/core/src/main/java/bisq/core/support/dispute/refund/RefundDisputeList.java
+++ b/core/src/main/java/bisq/core/support/dispute/refund/RefundDisputeList.java
@@ -23,11 +23,10 @@
import bisq.core.support.dispute.DisputeList;
import bisq.common.proto.ProtoUtil;
-import bisq.common.storage.Storage;
import com.google.protobuf.Message;
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -44,19 +43,10 @@
* Calls to the List are delegated because this class intercepts the add/remove calls so changes
* can be saved to disc.
*/
-public final class RefundDisputeList extends DisputeList {
+public final class RefundDisputeList extends DisputeList {
- RefundDisputeList(Storage storage) {
- super(storage);
- }
-
- @Override
- public void readPersisted() {
- // We need to use DisputeList as file name to not lose existing disputes which are stored in the DisputeList file
- RefundDisputeList persisted = storage.initAndGetPersisted(this, "RefundDisputeList", 50);
- if (persisted != null) {
- list.addAll(persisted.getList());
- }
+ RefundDisputeList() {
+ super();
}
@@ -64,30 +54,24 @@ public void readPersisted() {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- private RefundDisputeList(Storage storage, List list) {
- super(storage, list);
+ protected RefundDisputeList(Collection collection) {
+ super(collection);
}
@Override
public Message toProtoMessage() {
-
- list.forEach(dispute -> checkArgument(dispute.getSupportType().equals(SupportType.REFUND), "Support type has to be REFUND"));
+ forEach(dispute -> checkArgument(dispute.getSupportType().equals(SupportType.REFUND), "Support type has to be REFUND"));
return protobuf.PersistableEnvelope.newBuilder().setRefundDisputeList(protobuf.RefundDisputeList.newBuilder()
- .addAllDispute(ProtoUtil.collectionToProto(new ArrayList<>(list), protobuf.Dispute.class))).build();
+ .addAllDispute(ProtoUtil.collectionToProto(getList(), protobuf.Dispute.class))).build();
}
public static RefundDisputeList fromProto(protobuf.RefundDisputeList proto,
- CoreProtoResolver coreProtoResolver,
- Storage storage) {
+ CoreProtoResolver coreProtoResolver) {
List