Bugfixes, refactorings,...

This commit is contained in:
Manfred Karrer 2016-01-30 23:43:58 +01:00
parent d933110a8d
commit 9dd9decb96
22 changed files with 124 additions and 82 deletions

View File

@ -121,7 +121,7 @@ public class AddressEntry implements Serializable {
// For display we usually only display the first 8 characters.
@Nullable
public String getShortOfferId() {
return offerId != null ? offerId.substring(0, 8) : null;
return offerId != null ? offerId.substring(0, Math.min(8, offerId.length())) : null;
}
public Context getContext() {

View File

@ -968,7 +968,7 @@ public class TradeWalletService {
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
checkNotNull(sigKey, "sigKey must not be null");
checkNotNull(sigKey, "signInput: sigKey must not be null. input.getOutpoint()=" + input.getOutpoint().toString());
Sha256Hash hash = transaction.hashForSignature(inputIndex, scriptPubKey, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = sigKey.sign(hash, aesKey);
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);

View File

@ -26,6 +26,7 @@ public class BlockChainAccountContractData extends PaymentAccountContractData im
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
private String address;
// used in crypto note coins. not supported now but hopefully in future, so leave it for now.
private String paymentId;
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) {

View File

@ -198,7 +198,7 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
}
public String getReferenceText() {
return id.substring(0, 8);
return id.substring(0, Math.min(8, id.length()));
}
@ -263,7 +263,7 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
}
public String getShortId() {
return id.substring(0, 8);
return id.substring(0, Math.min(8, id.length()));
}
public NodeAddress getOffererNodeAddress() {

View File

@ -66,7 +66,7 @@ public class ProcessPayDepositRequest extends TradeTask {
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}

View File

@ -54,7 +54,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}

View File

@ -27,13 +27,11 @@ import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.AnchorPane;
import java.util.function.Consumer;
public class TextFieldWithCopyIcon extends AnchorPane {
private final StringProperty text = new SimpleStringProperty();
private final TextField textField;
private Consumer<String> handler;
private boolean copyWithoutCurrencyPostFix;
///////////////////////////////////////////////////////////////////////////////////////////
@ -48,10 +46,19 @@ public class TextFieldWithCopyIcon extends AnchorPane {
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
AnchorPane.setRightAnchor(copyIcon, 0.0);
copyIcon.setOnMouseClicked(e -> {
if (getText() != null && getText().length() > 0) {
Utilities.copyToClipboard(getText());
if (handler != null)
handler.accept(getText());
String text = getText();
if (text != null && text.length() > 0) {
String copyText;
if (copyWithoutCurrencyPostFix) {
String[] strings = text.split(" ");
if (strings.length > 1)
copyText = strings[0]; // exclude the BTC postfix
else
copyText = text;
} else {
copyText = text;
}
Utilities.copyToClipboard(copyText);
}
});
textField = new TextField();
@ -85,7 +92,8 @@ public class TextFieldWithCopyIcon extends AnchorPane {
this.text.set(text);
}
public void setHandler(Consumer<String> handler) {
this.handler = handler;
public void setCopyWithoutCurrencyPostFix(boolean copyWithoutCurrencyPostFix) {
this.copyWithoutCurrencyPostFix = copyWithoutCurrencyPostFix;
}
}

View File

@ -54,20 +54,20 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
public static final String TITLE_KEY = "view.title";
public static BorderPane getBaseApplicationContainer() {
return baseApplicationContainer;
public static StackPane getRootContainer() {
return MainView.rootContainer;
}
public static void blur() {
transitions.blur(MainView.base);
transitions.blur(MainView.rootContainer);
}
public static void blurLight() {
transitions.blur(MainView.base, Transitions.DEFAULT_DURATION, true, false, 5);
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 5);
}
public static void removeBlur() {
transitions.removeBlur(baseApplicationContainer);
transitions.removeBlur(MainView.rootContainer);
}
private final ToggleGroup navButtons = new ToggleGroup();
@ -86,9 +86,9 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
private ProgressBar btcSyncIndicator;
private Label btcSplashInfo;
private List<String> persistedFilesCorrupted;
private static BorderPane baseApplicationContainer;
private static StackPane base;
private BorderPane baseApplicationContainer;
private Popup p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup;
private static StackPane rootContainer;
@Inject
public MainView(MainViewModel model, CachingViewLoader viewLoader, Navigation navigation, Transitions transitions,
@ -102,8 +102,8 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
@Override
protected void initialize() {
MainView.base = this.root;
MainView.rootContainer = this.root;
ToggleButton marketButton = new NavButton(MarketView.class, "Market");
ToggleButton buyButton = new NavButton(BuyOfferView.class, "Buy BTC");
ToggleButton sellButton = new NavButton(SellOfferView.class, "Sell BTC");

View File

@ -225,7 +225,8 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
private void onRequestUpload() {
if (tempAttachments.size() < 3) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open file to attach");
int maxSizeInKB = Connection.getMaxMsgSize() / 1024;
fileChooser.setTitle("Open file to attach (max. file size: " + maxSizeInKB + " kb)");
/* if (Utilities.isUnix())
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/
File result = fileChooser.showOpenDialog(stage);
@ -238,7 +239,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
tempAttachments.add(new DisputeDirectMessage.Attachment(result.getName(), filesAsBytes));
inputTextArea.setText(inputTextArea.getText() + "\n[Attachment " + result.getName() + "]");
} else {
new Popup().error("The max. allowed file size is 100 kB.").show();
new Popup().error("The max. allowed file size is " + maxSizeInKB + " kB.").show();
}
} catch (java.io.IOException e) {
e.printStackTrace();

View File

@ -19,6 +19,7 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
import io.bitsquare.gui.components.TitledGroupBg;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.components.paymentmethods.*;
@ -208,8 +209,9 @@ public class StartPaymentView extends TradeStepDetailsView {
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
TitledGroupBg accountTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Payments details", Layout.GROUP_DISTANCE);
addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:", model.getFiatAmount(),
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:", model.getFiatAmount(),
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
field.setCopyWithoutCurrencyPostFix(true);
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
String paymentMethodName = paymentAccountContractData.getPaymentMethodName();

View File

@ -103,6 +103,7 @@ public class ContractPopup extends Popup {
if (sellerPaymentAccountContractData instanceof BlockChainAccountContractData &&
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
rows++;
isPaymentIdAvailable = true;
}
addTitledGroupBg(gridPane, ++rowIndex, rows, "Contract");
addLabelTextFieldWithCopyIcon(gridPane, rowIndex, "Offer ID:", offer.getId(),
@ -123,7 +124,7 @@ public class ContractPopup extends Popup {
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", contract.arbitratorNodeAddress.getFullAddress());
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer payment details:",
BSResources.get(contract.getBuyerPaymentAccountContractData().getPaymentDetails())).second.setMouseTransparent(false);
addLabelTextField(gridPane, ++rowIndex, "Seller payment details:",
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Seller payment details:",
BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false);
if (isPaymentIdAvailable)
addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:",

View File

@ -208,7 +208,7 @@ public class Popup {
protected void createPopup() {
if (owner == null)
owner = MainView.getBaseApplicationContainer();
owner = MainView.getRootContainer();
stage = new Stage();
Scene scene = new Scene(gridPane);

View File

@ -28,7 +28,7 @@ public class NodeAddress implements Serializable {
// We use just a few chars form or address to blur the potential receiver for sent messages
public byte[] getAddressPrefixHash() {
if (addressPrefixHash == null)
addressPrefixHash = Hash.getHash(getFullAddress().substring(0, 2));
addressPrefixHash = Hash.getHash(getFullAddress().substring(0, Math.min(2, getFullAddress().length())));
return addressPrefixHash;
}

View File

@ -80,6 +80,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
private ChangeListener<NodeAddress> connectionNodeAddressListener;
private Subscription networkReadySubscription;
private boolean isBootstrapped;
private ChangeListener<Number> numOfBroadcastsChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
@ -537,18 +538,35 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
log.debug("remove result=" + result);
sendMailboxMessageListener.onFault("A timeout occurred when trying to broadcast mailbox data.");
}, 30);
broadcaster.addOneTimeListener(message -> {
Broadcaster.Listener listener = message -> {
if (message instanceof AddDataMessage &&
((AddDataMessage) message).data.equals(protectedMailboxData)) {
sendMailboxMessageListener.onStoredInMailbox();
sendMailboxMessageTimeoutTimer.cancel();
}
});
};
broadcaster.addListener(listener);
if (numOfBroadcastsChangeListener != null) {
log.warn("numOfBroadcastsChangeListener should be null");
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
}
numOfBroadcastsChangeListener = (observable, oldValue, newValue) -> {
// We want to get at least 1 successful broadcast
if ((int) newValue > 0)
broadcaster.removeListener(listener);
UserThread.execute(() -> {
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
numOfBroadcastsChangeListener = null;
});
};
broadcaster.getNumOfBroadcastsProperty().addListener(numOfBroadcastsChangeListener);
boolean result = p2PDataStorage.add(protectedMailboxData, networkNode.getNodeAddress());
if (!result) {
sendMailboxMessageTimeoutTimer.cancel();
broadcaster.removeListener(listener);
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
sendMailboxMessageListener.onFault("Data already exists in our local database");
boolean result2 = p2PDataStorage.remove(protectedMailboxData, networkNode.getNodeAddress());
log.debug("remove result=" + result2);

View File

@ -3,7 +3,8 @@ package io.bitsquare.p2p.network;
public enum IllegalRequest {
MaxSizeExceeded(1),
InvalidDataType(0),
WrongNetworkId(0);
WrongNetworkId(0),
TooManyMessages(1);
public final int maxTolerance;

View File

@ -107,7 +107,6 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
return outboundConnection;
} catch (Throwable throwable) {
if (!(throwable instanceof ConnectException || throwable instanceof IOException)) {
throwable.printStackTrace();
log.error("Executing task failed. " + throwable.getMessage());
}
throw throwable;

View File

@ -8,6 +8,8 @@ import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.network.Connection;
import io.bitsquare.p2p.network.NetworkNode;
import io.bitsquare.p2p.storage.messages.DataBroadcastMessage;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@ -27,12 +29,16 @@ public class Broadcaster {
private final NetworkNode networkNode;
private final Set<Listener> listeners = new CopyOnWriteArraySet<>();
private IntegerProperty numOfBroadcasts = new SimpleIntegerProperty(0);
public Broadcaster(NetworkNode networkNode) {
this.networkNode = networkNode;
}
public void broadcast(DataBroadcastMessage message, @Nullable NodeAddress sender) {
Log.traceCall("Sender " + sender + ". Message " + message.toString());
numOfBroadcasts.set(0);
Set<Connection> receivers = networkNode.getConfirmedConnections();
if (!receivers.isEmpty()) {
log.info("Broadcast message to {} peers. Message: {}", receivers.size(), message);
@ -46,9 +52,9 @@ public class Broadcaster {
@Override
public void onSuccess(Connection connection) {
log.trace("Broadcast to " + connection + " succeeded.");
numOfBroadcasts.set(numOfBroadcasts.get() + 1);
listeners.stream().forEach(listener -> {
listener.onBroadcasted(message);
listeners.remove(listener);
});
}
@ -64,9 +70,16 @@ public class Broadcaster {
}
}
public IntegerProperty getNumOfBroadcastsProperty() {
return numOfBroadcasts;
}
// That listener gets immediately removed after the handler is called
public void addOneTimeListener(Listener listener) {
public void addListener(Listener listener) {
listeners.add(listener);
}
public void removeListener(Listener listener) {
listeners.remove(listener);
}
}

View File

@ -253,6 +253,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
!peerManager.isConfirmed(e))
.collect(Collectors.toList())
.stream()
.filter(e -> e.lastActivityDate != null)
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
.map(e -> e.nodeAddress)
.collect(Collectors.toList());

View File

@ -8,7 +8,6 @@ import io.bitsquare.p2p.network.*;
import io.bitsquare.p2p.peers.messages.data.UpdateDataRequest;
import io.bitsquare.storage.Storage;
import javafx.beans.value.ChangeListener;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -44,13 +43,13 @@ public class PeerManager implements ConnectionListener, MessageListener {
private static final int MAX_REPORTED_PEERS = 1000;
private static final int MAX_PERSISTED_PEERS = 500;
private static final long MAX_AGE = 14 * 24 * 60 * 60 * 1000; // max age for reported peers is 14 days
private static final long DAY = 24 * 60 * 60 * 1000; // max age for reported peers is 14 days
private static final long MAX_AGE = 14 * DAY; // max age for reported peers is 14 days
private final NetworkNode networkNode;
private final Set<NodeAddress> seedNodeAddresses;
@Nullable
private Storage<HashSet<ReportedPeer>> dbStorage;
private final Storage<HashSet<ReportedPeer>> dbStorage;
private final HashSet<ReportedPeer> persistedPeers = new HashSet<>();
private final Set<ReportedPeer> reportedPeers = new HashSet<>();
@ -66,7 +65,12 @@ public class PeerManager implements ConnectionListener, MessageListener {
this.networkNode = networkNode;
this.seedNodeAddresses = new HashSet<>(seedNodeAddresses);
networkNode.addConnectionListener(this);
createDbStorage(storageDir);
dbStorage = new Storage<>(storageDir);
HashSet<ReportedPeer> persistedPeers = dbStorage.initAndGetPersisted("persistedPeers");
if (persistedPeers != null) {
log.info("We have persisted reported peers. persistedPeers.size()=" + persistedPeers.size());
this.persistedPeers.addAll(persistedPeers);
}
connectionNodeAddressListener = (observable, oldValue, newValue) -> {
// Every time we get a new peer connected with a known address we check if we need to remove peers
@ -79,21 +83,6 @@ public class PeerManager implements ConnectionListener, MessageListener {
};
}
private void createDbStorage(File storageDir) {
dbStorage = new Storage<>(storageDir);
initPersistedPeers();
}
private void initPersistedPeers() {
if (dbStorage != null) {
HashSet<ReportedPeer> persistedPeers = dbStorage.initAndGetPersisted("persistedPeers");
if (persistedPeers != null) {
log.info("We have persisted reported peers. persistedPeers.size()=" + persistedPeers.size());
this.persistedPeers.addAll(persistedPeers);
}
}
}
public void shutDown() {
Log.traceCall();
@ -124,10 +113,15 @@ public class PeerManager implements ConnectionListener, MessageListener {
public void onDisconnect(Reason reason, Connection connection) {
connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener);
connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> {
ReportedPeer reportedPeer = new ReportedPeer(nodeAddress);
reportedPeers.remove(reportedPeer);
persistedPeers.add(reportedPeer);
dbStorage.queueUpForSave(persistedPeers, 5000);
penalizeUnreachablePeer(nodeAddress);
Optional<ReportedPeer> reportedPeerOptional = reportedPeers.stream()
.filter(e -> e.nodeAddress.equals(nodeAddress)).findAny();
if (reportedPeerOptional.isPresent()) {
ReportedPeer reportedPeer = reportedPeerOptional.get();
reportedPeers.remove(reportedPeer);
persistedPeers.add(reportedPeer);
dbStorage.queueUpForSave(persistedPeers, 5000);
}
});
}
@ -215,12 +209,14 @@ public class PeerManager implements ConnectionListener, MessageListener {
private void removeTooOldReportedPeers() {
Set<ReportedPeer> reportedPeersToRemove = reportedPeers.stream()
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
.filter(reportedPeer -> reportedPeer.lastActivityDate != null &&
new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
.collect(Collectors.toSet());
reportedPeersToRemove.forEach(this::removeReportedPeer);
Set<ReportedPeer> persistedPeersToRemove = persistedPeers.stream()
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
.filter(reportedPeer -> reportedPeer.lastActivityDate != null &&
new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
.collect(Collectors.toSet());
persistedPeersToRemove.forEach(this::removeFromPersistedPeers);
}
@ -312,6 +308,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
if (toRemove2 > 0) {
// now we remove second half with a list sorted by oldest lastActivityDate
list = new ArrayList<>(persistedPeers);
list = list.stream().filter(e -> e.lastActivityDate != null).collect(Collectors.toList());
list.sort((o1, o2) -> o1.lastActivityDate.compareTo(o2.lastActivityDate));
for (int i = 0; i < toRemove2; i++) {
persistedPeers.remove(list.get(i));
@ -330,10 +327,11 @@ public class PeerManager implements ConnectionListener, MessageListener {
private void printReportedPeers() {
if (!reportedPeers.isEmpty()) {
StringBuilder result = new StringBuilder("\n\n------------------------------------------------------------\n" +
"Reported peers for node " + networkNode.getNodeAddress() + ":");
"Reported peers:");
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
result.append("\n------------------------------------------------------------\n");
log.info(result.toString());
log.debug(result.toString());
log.info("Number of reported peers: {}", reportedPeers.size());
}
}
@ -372,21 +370,16 @@ public class PeerManager implements ConnectionListener, MessageListener {
reportedPeers.stream()
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
.findAny()
.ifPresent(this::adjustLastActivityDate);
.ifPresent(ReportedPeer::penalizeLastActivityDate);
persistedPeers.stream()
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
.findAny()
.ifPresent(reportedPeer -> {
adjustLastActivityDate(reportedPeer);
reportedPeer.penalizeLastActivityDate();
dbStorage.queueUpForSave(persistedPeers, 5000);
});
}
private void adjustLastActivityDate(ReportedPeer reportedPeer) {
long now = new Date().getTime();
long diff = now - reportedPeer.lastActivityDate.getTime();
long reduced = now - diff * 2;
reportedPeer.setLastActivityDate(new Date(reduced));
removeTooOldReportedPeers();
}
public Set<ReportedPeer> getConnectedAndReportedPeers() {

View File

@ -18,12 +18,13 @@ public class ReportedPeer implements Serializable {
this.lastActivityDate = lastActivityDate;
}
public ReportedPeer(NodeAddress nodeAddress) {
this(nodeAddress, null);
}
public void setLastActivityDate(Date lastActivityDate) {
this.lastActivityDate = lastActivityDate;
public void penalizeLastActivityDate() {
if (lastActivityDate != null) {
long now = new Date().getTime();
long diff = Math.max(24 * 60 * 60 * 1000, now - lastActivityDate.getTime());
long reduced = now - diff * 2;
lastActivityDate = new Date(reduced);
}
}
// We don't use the lastActivityDate for identity

View File

@ -173,7 +173,7 @@ public class RequestDataManager implements MessageListener {
errorMessage, nodeAddress);
peerManager.penalizeUnreachablePeer(nodeAddress);
if (!remainingNodeAddresses.isEmpty()) {
log.info("There are remaining nodes available for requesting data. " +
"We will try requestDataFromPeers again.");
@ -233,6 +233,7 @@ public class RequestDataManager implements MessageListener {
!peerManager.isSelf(e))
.collect(Collectors.toList())
.stream()
.filter(e -> e.lastActivityDate != null)
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
.map(e -> e.nodeAddress)
.collect(Collectors.toList());

View File

@ -161,7 +161,8 @@ public class P2PDataStorage implements MessageListener {
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
sb.append("Data set after addProtectedExpirableData (truncated)");
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()
.substring(0, Math.min(50, e.toString().length()))).append("...\n"));
sb.append("\n------------------------------------------------------------\n");
log.trace(sb.toString());
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
@ -280,7 +281,8 @@ public class P2PDataStorage implements MessageListener {
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" +
"Data set after removeProtectedExpirableData: (truncated)");
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()
.substring(0, Math.min(50, e.toString().length()))).append("...\n"));
sb.append("\n------------------------------------------------------------\n");
log.trace(sb.toString());
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());