Merge pull request #4025 from stejbac/make-persistence-thread-safe

Make serialisation in FileManager::saveToFile thread-safe
This commit is contained in:
Christoph Atteneder 2020-03-23 13:49:27 +01:00 committed by GitHub
commit 557ec7f449
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 214 additions and 90 deletions

View file

@ -21,7 +21,6 @@ import bisq.common.util.CollectionUtils;
import com.google.protobuf.Message;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
@ -36,7 +35,7 @@ import lombok.Setter;
@Getter
@Setter
public class NavigationPath implements PersistableEnvelope {
private List<String> path = new ArrayList<>();
private List<String> path = List.of();
@Override
public Message toProtoMessage() {
@ -45,7 +44,7 @@ public class NavigationPath implements PersistableEnvelope {
return protobuf.PersistableEnvelope.newBuilder().setNavigationPath(builder).build();
}
public static PersistableEnvelope fromProto(protobuf.NavigationPath proto) {
return new NavigationPath(new ArrayList<>(proto.getPathList()));
public static NavigationPath fromProto(protobuf.NavigationPath proto) {
return new NavigationPath(List.copyOf(proto.getPathList()));
}
}

View file

@ -19,8 +19,14 @@ package bisq.common.proto.persistable;
import bisq.common.Envelope;
import com.google.protobuf.Message;
/**
* Interface for the outside envelope object persisted to disk.
*/
public interface PersistableEnvelope extends Envelope {
default Message toPersistableMessage() {
return toProtoMessage();
}
}

View file

@ -0,0 +1,44 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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).
* <p>
* 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();
}
}
}

View file

@ -0,0 +1,45 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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.
* <p>
* 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<Message> toProtoOnUserThread = new FutureTask<>(this::toProtoMessage);
UserThread.execute(toProtoOnUserThread);
//noinspection UnstableApiUsage
return Futures.getUnchecked(toProtoOnUserThread);
}
}

View file

@ -0,0 +1,31 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.common.proto.persistable;
import java.util.List;
public class UserThreadMappedPersistableList<T extends PersistablePayload> extends PersistableList<T>
implements UserThreadMappedPersistableEnvelope {
public UserThreadMappedPersistableList(List<T> list) {
super(list);
}
public UserThreadMappedPersistableList() {
}
}

View file

@ -189,7 +189,7 @@ public class FileManager<T extends PersistableEnvelope> {
log.debug("Write to disc: {}", storageFile.getName());
protobuf.PersistableEnvelope protoPersistable;
try {
protoPersistable = (protobuf.PersistableEnvelope) persistable.toProtoMessage();
protoPersistable = (protobuf.PersistableEnvelope) persistable.toPersistableMessage();
if (protoPersistable.toByteArray().length == 0)
log.error("protoPersistable is empty. persistable=" + persistable.getClass().getSimpleName());
} catch (Throwable e) {

View file

@ -21,7 +21,7 @@ package bisq.core.account.sign;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -40,7 +40,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class SignedWitnessStore implements PersistableEnvelope {
public class SignedWitnessStore implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
@ -70,7 +70,7 @@ public class SignedWitnessStore implements PersistableEnvelope {
return protobuf.SignedWitnessStore.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.SignedWitnessStore proto) {
public static SignedWitnessStore fromProto(protobuf.SignedWitnessStore proto) {
List<SignedWitness> list = proto.getItemsList().stream()
.map(SignedWitness::fromProto).collect(Collectors.toList());
return new SignedWitnessStore(list);

View file

@ -20,7 +20,7 @@ package bisq.core.account.witness;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class AccountAgeWitnessStore implements PersistableEnvelope {
public class AccountAgeWitnessStore implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
@ -69,7 +69,7 @@ public class AccountAgeWitnessStore implements PersistableEnvelope {
return protobuf.AccountAgeWitnessStore.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.AccountAgeWitnessStore proto) {
public static AccountAgeWitnessStore fromProto(protobuf.AccountAgeWitnessStore proto) {
List<AccountAgeWitness> list = proto.getItemsList().stream()
.map(AccountAgeWitness::fromProto).collect(Collectors.toList());
return new AccountAgeWitnessStore(list);

View file

@ -17,8 +17,8 @@
package bisq.core.btc.model;
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;
@ -44,7 +44,7 @@ import lombok.extern.slf4j.Slf4j;
*/
@ToString
@Slf4j
public final class AddressEntryList implements PersistableEnvelope, PersistedDataHost {
public final class AddressEntryList implements UserThreadMappedPersistableEnvelope, PersistedDataHost {
transient private Storage<AddressEntryList> storage;
transient private Wallet wallet;
@Getter

View file

@ -19,8 +19,7 @@ package bisq.core.dao.governance.blindvote;
import bisq.core.dao.governance.ConsensusCritical;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import com.google.protobuf.Message;
@ -34,7 +33,7 @@ import lombok.EqualsAndHashCode;
* List of my own blind votes. Blind votes received from other voters are stored in the BlindVoteStore.
*/
@EqualsAndHashCode(callSuper = true)
public class MyBlindVoteList extends PersistableList<BlindVote> implements ConsensusCritical {
public class MyBlindVoteList extends UserThreadMappedPersistableList<BlindVote> implements ConsensusCritical {
MyBlindVoteList() {
super();
@ -59,7 +58,7 @@ public class MyBlindVoteList extends PersistableList<BlindVote> implements Conse
.build();
}
public static PersistableEnvelope fromProto(protobuf.MyBlindVoteList proto) {
public static MyBlindVoteList fromProto(protobuf.MyBlindVoteList proto) {
return new MyBlindVoteList(new ArrayList<>(proto.getBlindVoteList().stream()
.map(BlindVote::fromProto)
.collect(Collectors.toList())));

View file

@ -20,7 +20,7 @@ package bisq.core.dao.governance.blindvote.storage;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class BlindVoteStore implements PersistableEnvelope {
public class BlindVoteStore implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
@ -69,7 +69,7 @@ public class BlindVoteStore implements PersistableEnvelope {
return protobuf.BlindVoteStore.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.BlindVoteStore proto) {
public static BlindVoteStore fromProto(protobuf.BlindVoteStore proto) {
List<BlindVotePayload> list = proto.getItemsList().stream()
.map(BlindVotePayload::fromProto).collect(Collectors.toList());
return new BlindVoteStore(list);

View file

@ -17,7 +17,7 @@
package bisq.core.dao.governance.bond.reputation;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import java.util.ArrayList;
import java.util.List;
@ -29,7 +29,7 @@ import lombok.EqualsAndHashCode;
* PersistableEnvelope wrapper for list of MyReputations.
*/
@EqualsAndHashCode(callSuper = true)
public class MyReputationList extends PersistableList<MyReputation> {
public class MyReputationList extends UserThreadMappedPersistableList<MyReputation> {
private MyReputationList(List<MyReputation> list) {
super(list);
@ -69,4 +69,3 @@ public class MyReputationList extends PersistableList<MyReputation> {
.collect(Collectors.toList());
}
}

View file

@ -17,8 +17,7 @@
package bisq.core.dao.governance.myvote;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import com.google.protobuf.Message;
@ -29,9 +28,9 @@ import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class MyVoteList extends PersistableList<MyVote> {
public class MyVoteList extends UserThreadMappedPersistableList<MyVote> {
public MyVoteList() {
MyVoteList() {
super();
}
@ -53,7 +52,7 @@ public class MyVoteList extends PersistableList<MyVote> {
.build();
}
public static PersistableEnvelope fromProto(protobuf.MyVoteList proto) {
public static MyVoteList fromProto(protobuf.MyVoteList proto) {
return new MyVoteList(new ArrayList<>(proto.getMyVoteList().stream()
.map(MyVote::fromProto)
.collect(Collectors.toList())));
@ -66,4 +65,3 @@ public class MyVoteList extends PersistableList<MyVote> {
.collect(Collectors.toList());
}
}

View file

@ -17,7 +17,7 @@
package bisq.core.dao.governance.proofofburn;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import java.util.ArrayList;
import java.util.List;
@ -29,7 +29,7 @@ import lombok.EqualsAndHashCode;
* PersistableEnvelope wrapper for list of MyProofOfBurn objects.
*/
@EqualsAndHashCode(callSuper = true)
public class MyProofOfBurnList extends PersistableList<MyProofOfBurn> {
public class MyProofOfBurnList extends UserThreadMappedPersistableList<MyProofOfBurn> {
private MyProofOfBurnList(List<MyProofOfBurn> list) {
super(list);
@ -69,4 +69,3 @@ public class MyProofOfBurnList extends PersistableList<MyProofOfBurn> {
.collect(Collectors.toList());
}
}

View file

@ -20,7 +20,7 @@ package bisq.core.dao.governance.proposal;
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.state.model.governance.Proposal;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import java.util.ArrayList;
import java.util.List;
@ -32,7 +32,7 @@ import lombok.EqualsAndHashCode;
* PersistableEnvelope wrapper for list of proposals. Used in vote consensus, so changes can break consensus!
*/
@EqualsAndHashCode(callSuper = true)
public class MyProposalList extends PersistableList<Proposal> implements ConsensusCritical {
public class MyProposalList extends UserThreadMappedPersistableList<Proposal> implements ConsensusCritical {
public MyProposalList(List<Proposal> list) {
super(list);
@ -72,4 +72,3 @@ public class MyProposalList extends PersistableList<Proposal> implements Consens
.collect(Collectors.toList());
}
}

View file

@ -20,7 +20,7 @@ package bisq.core.dao.governance.proposal.storage.appendonly;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class ProposalStore implements PersistableEnvelope {
public class ProposalStore implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
@ -69,7 +69,7 @@ public class ProposalStore implements PersistableEnvelope {
return protobuf.ProposalStore.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.ProposalStore proto) {
public static ProposalStore fromProto(protobuf.ProposalStore proto) {
List<ProposalPayload> list = proto.getItemsList().stream()
.map(ProposalPayload::fromProto).collect(Collectors.toList());
return new ProposalStore(list);

View file

@ -21,7 +21,7 @@ import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.ProtectedStorageEntry;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -42,7 +42,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class TempProposalStore implements PersistableEnvelope {
public class TempProposalStore implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, ProtectedStorageEntry> map = new ConcurrentHashMap<>();
@ -72,7 +72,7 @@ public class TempProposalStore implements PersistableEnvelope {
return protobuf.TempProposalStore.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.TempProposalStore proto, NetworkProtoResolver networkProtoResolver) {
public static TempProposalStore fromProto(protobuf.TempProposalStore proto, NetworkProtoResolver networkProtoResolver) {
List<ProtectedStorageEntry> list = proto.getItemsList().stream()
.map(entry -> ProtectedStorageEntry.fromProto(entry, networkProtoResolver))
.collect(Collectors.toList());

View file

@ -86,8 +86,10 @@ public class DaoStateStorageService extends StoreService<DaoStateStore> {
}
private void persist(DaoState daoState, LinkedList<DaoStateHash> daoStateHashChain, long delayInMilli) {
store.setDaoState(daoState);
store.setDaoStateHashChain(daoStateHashChain);
store.modifySynchronized(() -> {
store.setDaoState(daoState);
store.setDaoStateHashChain(daoStateHashChain);
});
storage.queueUpForSave(store, delayInMilli);
}

View file

@ -20,7 +20,7 @@ package bisq.core.dao.state;
import bisq.core.dao.monitoring.model.DaoStateHash;
import bisq.core.dao.state.model.DaoState;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -35,7 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class DaoStateStore implements PersistableEnvelope {
public class DaoStateStore implements ThreadedPersistableEnvelope {
// DaoState is always a clone and must not be used for read access beside initial read from disc when we apply
// the snapshot!
@Getter
@ -67,7 +67,7 @@ public class DaoStateStore implements PersistableEnvelope {
.build();
}
public static PersistableEnvelope fromProto(protobuf.DaoStateStore proto) {
public static DaoStateStore fromProto(protobuf.DaoStateStore proto) {
LinkedList<DaoStateHash> daoStateHashList = proto.getDaoStateHashList().isEmpty() ?
new LinkedList<>() :
new LinkedList<>(proto.getDaoStateHashList().stream()

View file

@ -20,7 +20,7 @@ package bisq.core.dao.state.model.governance;
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.state.model.ImmutableDaoStateModel;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import java.util.ArrayList;
import java.util.List;
@ -35,7 +35,7 @@ import javax.annotation.concurrent.Immutable;
*/
@Immutable
@EqualsAndHashCode(callSuper = true)
public class BallotList extends PersistableList<Ballot> implements ConsensusCritical, ImmutableDaoStateModel {
public class BallotList extends UserThreadMappedPersistableList<Ballot> implements ConsensusCritical, ImmutableDaoStateModel {
public BallotList(List<Ballot> list) {
super(list);
@ -75,4 +75,3 @@ public class BallotList extends PersistableList<Ballot> implements ConsensusCrit
.collect(Collectors.toList());
}
}

View file

@ -17,8 +17,7 @@
package bisq.core.dao.state.unconfirmed;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import com.google.protobuf.Message;
@ -29,7 +28,7 @@ import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class UnconfirmedBsqChangeOutputList extends PersistableList<UnconfirmedTxOutput> {
public class UnconfirmedBsqChangeOutputList extends UserThreadMappedPersistableList<UnconfirmedTxOutput> {
UnconfirmedBsqChangeOutputList() {
super();
@ -52,7 +51,7 @@ public class UnconfirmedBsqChangeOutputList extends PersistableList<UnconfirmedT
.build();
}
public static PersistableEnvelope fromProto(protobuf.UnconfirmedBsqChangeOutputList proto) {
public static UnconfirmedBsqChangeOutputList fromProto(protobuf.UnconfirmedBsqChangeOutputList proto) {
return new UnconfirmedBsqChangeOutputList(new ArrayList<>(proto.getUnconfirmedTxOutputList().stream()
.map(UnconfirmedTxOutput::fromProto)
.collect(Collectors.toList())));

View file

@ -19,8 +19,7 @@ package bisq.core.payment;
import bisq.core.proto.CoreProtoResolver;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.UserThreadMappedPersistableList;
import com.google.protobuf.Message;
@ -31,7 +30,7 @@ import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class PaymentAccountList extends PersistableList<PaymentAccount> {
public class PaymentAccountList extends UserThreadMappedPersistableList<PaymentAccount> {
public PaymentAccountList(List<PaymentAccount> list) {
super(list);
@ -45,7 +44,7 @@ public class PaymentAccountList extends PersistableList<PaymentAccount> {
.build();
}
public static PersistableEnvelope fromProto(protobuf.PaymentAccountList proto, CoreProtoResolver coreProtoResolver) {
public static PaymentAccountList fromProto(protobuf.PaymentAccountList proto, CoreProtoResolver coreProtoResolver) {
return new PaymentAccountList(new ArrayList<>(proto.getPaymentAccountList().stream()
.map(e -> PaymentAccount.fromProto(e, coreProtoResolver))
.collect(Collectors.toList())));

View file

@ -19,6 +19,7 @@ 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 javafx.collections.FXCollections;
@ -39,7 +40,7 @@ import lombok.extern.slf4j.Slf4j;
* 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<T extends PersistableEnvelope> implements PersistableEnvelope, PersistedDataHost {
public abstract class DisputeList<T extends PersistableEnvelope> implements UserThreadMappedPersistableEnvelope, PersistedDataHost {
transient protected final Storage<T> storage;
@Getter

View file

@ -23,7 +23,7 @@ import bisq.core.proto.CoreProtoResolver;
import bisq.common.proto.ProtoUtil;
import bisq.common.proto.ProtobufferRuntimeException;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
import bisq.common.storage.Storage;
import com.google.protobuf.Message;
@ -41,7 +41,7 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public final class TradableList<T extends Tradable> implements PersistableEnvelope {
public final class TradableList<T extends Tradable> implements UserThreadMappedPersistableEnvelope {
transient final private Storage<TradableList<T>> storage;
@Getter
private final ObservableList<T> list = FXCollections.observableArrayList();
@ -78,10 +78,10 @@ public final class TradableList<T extends Tradable> implements PersistableEnvelo
.build();
}
public static TradableList fromProto(protobuf.TradableList proto,
CoreProtoResolver coreProtoResolver,
Storage<TradableList<Tradable>> storage,
BtcWalletService btcWalletService) {
public static TradableList<Tradable> fromProto(protobuf.TradableList proto,
CoreProtoResolver coreProtoResolver,
Storage<TradableList<Tradable>> storage,
BtcWalletService btcWalletService) {
List<Tradable> list = proto.getTradableList().stream()
.map(tradable -> {
switch (tradable.getMessageCase()) {

View file

@ -20,7 +20,7 @@ package bisq.core.trade.statistics;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -38,7 +38,7 @@ import lombok.extern.slf4j.Slf4j;
* definition and provide a hashMap for the domain access.
*/
@Slf4j
public class TradeStatistics2Store implements PersistableEnvelope {
public class TradeStatistics2Store implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
@ -68,7 +68,7 @@ public class TradeStatistics2Store implements PersistableEnvelope {
return protobuf.TradeStatistics2Store.newBuilder().addAllItems(protoList);
}
public static PersistableEnvelope fromProto(protobuf.TradeStatistics2Store proto) {
public static TradeStatistics2Store fromProto(protobuf.TradeStatistics2Store proto) {
List<TradeStatistics2> list = proto.getItemsList().stream()
.map(TradeStatistics2::fromProto).collect(Collectors.toList());
return new TradeStatistics2Store(list);

View file

@ -25,7 +25,7 @@ import bisq.core.payment.PaymentAccount;
import bisq.core.proto.CoreProtoResolver;
import bisq.common.proto.ProtoUtil;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
import com.google.protobuf.Message;
@ -49,7 +49,7 @@ import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAs
@Slf4j
@Data
@AllArgsConstructor
public final class PreferencesPayload implements PersistableEnvelope {
public final class PreferencesPayload implements UserThreadMappedPersistableEnvelope {
private String userLanguage;
private Country userCountry;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@ -132,7 +132,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
public PreferencesPayload() {
PreferencesPayload() {
}
@ -207,7 +207,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
return protobuf.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build();
}
public static PersistableEnvelope fromProto(protobuf.PreferencesPayload proto, CoreProtoResolver coreProtoResolver) {
public static PreferencesPayload fromProto(protobuf.PreferencesPayload proto, CoreProtoResolver coreProtoResolver) {
final protobuf.Country userCountry = proto.getUserCountry();
PaymentAccount paymentAccount = null;
if (proto.hasSelectedPaymentAccountForCreateOffer() && proto.getSelectedPaymentAccountForCreateOffer().hasPaymentMethod())
@ -275,6 +275,5 @@ public final class PreferencesPayload implements PersistableEnvelope {
proto.getBuyerSecurityDepositAsPercentForCrypto(),
proto.getBlockNotifyPort(),
proto.getTacAcceptedV120());
}
}

View file

@ -28,7 +28,7 @@ import bisq.core.support.dispute.mediation.mediator.Mediator;
import bisq.core.support.dispute.refund.refundagent.RefundAgent;
import bisq.common.proto.ProtoUtil;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
import java.util.ArrayList;
import java.util.HashSet;
@ -46,7 +46,7 @@ import javax.annotation.Nullable;
@Slf4j
@Data
@AllArgsConstructor
public class UserPayload implements PersistableEnvelope {
public class UserPayload implements UserThreadMappedPersistableEnvelope {
@Nullable
private String accountId;
@Nullable

View file

@ -141,7 +141,7 @@ public final class Navigation implements PersistedDataHost {
private void queueUpForSave() {
if (currentPath.tip() != null) {
navigationPath.setPath(currentPath.stream().map(Class::getName).collect(Collectors.toList()));
navigationPath.setPath(currentPath.stream().map(Class::getName).collect(Collectors.toUnmodifiableList()));
}
storage.queueUpForSave(navigationPath, 1000);
}

View file

@ -18,7 +18,6 @@
package bisq.network.p2p.peers.peerexchange;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
import com.google.protobuf.Message;
@ -27,23 +26,30 @@ import java.util.List;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@EqualsAndHashCode(callSuper = true)
public class PeerList extends PersistableList<Peer> {
@EqualsAndHashCode
public class PeerList implements PersistableEnvelope {
@Getter
private final List<Peer> list;
public PeerList(List<Peer> list) {
super(list);
this.list = list;
}
public int size() {
return list.size();
}
@Override
public Message toProtoMessage() {
return protobuf.PersistableEnvelope.newBuilder()
.setPeerList(protobuf.PeerList.newBuilder()
.addAllPeer(getList().stream().map(Peer::toProtoMessage).collect(Collectors.toList())))
.addAllPeer(list.stream().map(Peer::toProtoMessage).collect(Collectors.toList())))
.build();
}
public static PersistableEnvelope fromProto(protobuf.PeerList proto) {
public static PeerList fromProto(protobuf.PeerList proto) {
return new PeerList(new ArrayList<>(proto.getPeerList().stream()
.map(Peer::fromProto)
.collect(Collectors.toList())));

View file

@ -20,8 +20,8 @@ package bisq.network.p2p.storage.persistence;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import com.google.protobuf.Message;
@ -42,11 +42,11 @@ import lombok.extern.slf4j.Slf4j;
// TODO at next hard fork we can rename the PB definition and class name.
@Deprecated
@Slf4j
public class PersistableNetworkPayloadList implements PersistableEnvelope {
public class PersistableNetworkPayloadList implements ThreadedPersistableEnvelope {
@Getter
private Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new ConcurrentHashMap<>();
public PersistableNetworkPayloadList() {
PersistableNetworkPayloadList() {
}
@ -54,7 +54,7 @@ public class PersistableNetworkPayloadList implements PersistableEnvelope {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
public PersistableNetworkPayloadList(Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map) {
private PersistableNetworkPayloadList(Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map) {
this.map.putAll(map);
}
@ -69,8 +69,8 @@ public class PersistableNetworkPayloadList implements PersistableEnvelope {
.build();
}
public static PersistableEnvelope fromProto(protobuf.PersistableNetworkPayloadList proto,
PersistenceProtoResolver resolver) {
public static PersistableNetworkPayloadList fromProto(protobuf.PersistableNetworkPayloadList proto,
PersistenceProtoResolver resolver) {
Map<P2PDataStorage.ByteArray, PersistableNetworkPayload> map = new HashMap<>();
proto.getItemsList()
.forEach(e -> {

View file

@ -19,7 +19,7 @@ package bisq.network.p2p.storage.persistence;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.ThreadedPersistableEnvelope;
import java.util.HashMap;
import java.util.Map;
@ -34,7 +34,7 @@ import lombok.Setter;
* in protobuffer the map construct can't be anything, so the straightforward mapping was not possible.
* Hence this Persistable class.
*/
public class SequenceNumberMap implements PersistableEnvelope {
public class SequenceNumberMap implements ThreadedPersistableEnvelope {
@Getter
@Setter
private Map<P2PDataStorage.ByteArray, P2PDataStorage.MapValue> map = new ConcurrentHashMap<>();
@ -70,7 +70,7 @@ public class SequenceNumberMap implements PersistableEnvelope {
public static SequenceNumberMap fromProto(protobuf.SequenceNumberMap proto) {
HashMap<P2PDataStorage.ByteArray, P2PDataStorage.MapValue> map = new HashMap<>();
proto.getSequenceNumberEntriesList().stream()
proto.getSequenceNumberEntriesList()
.forEach(e -> map.put(P2PDataStorage.ByteArray.fromProto(e.getBytes()), P2PDataStorage.MapValue.fromProto(e.getMapValue())));
return new SequenceNumberMap(map);
}