use of io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry in project bitsquare by bitsquare.
the class RequestDataHandler method onMessage.
///////////////////////////////////////////////////////////////////////////////////////////
// MessageListener implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onMessage(Message message, Connection connection) {
if (connection.getPeersNodeAddressOptional().isPresent() && connection.getPeersNodeAddressOptional().get().equals(peersNodeAddress)) {
if (message instanceof GetDataResponse) {
Log.traceCall(message.toString() + "\n\tconnection=" + connection);
if (!stopped) {
GetDataResponse getDataResponse = (GetDataResponse) message;
Map<String, Set<StoragePayload>> payloadByClassName = new HashMap<>();
final HashSet<ProtectedStorageEntry> dataSet = getDataResponse.dataSet;
dataSet.stream().forEach(e -> {
final StoragePayload storagePayload = e.getStoragePayload();
String className = storagePayload.getClass().getSimpleName();
if (!payloadByClassName.containsKey(className))
payloadByClassName.put(className, new HashSet<>());
payloadByClassName.get(className).add(storagePayload);
});
StringBuilder sb = new StringBuilder("Received data size: ").append(dataSet.size()).append(", data items: ");
payloadByClassName.entrySet().stream().forEach(e -> sb.append(e.getValue().size()).append(" items of ").append(e.getKey()).append("; "));
log.info(sb.toString());
if (getDataResponse.requestNonce == nonce) {
stopTimeoutTimer();
checkArgument(connection.getPeersNodeAddressOptional().isPresent(), "RequestDataHandler.onMessage: connection.getPeersNodeAddressOptional() must be present " + "at that moment");
final NodeAddress sender = connection.getPeersNodeAddressOptional().get();
List<ProtectedStorageEntry> processDelayedItems = new ArrayList<>();
dataSet.stream().forEach(e -> {
if (e.getStoragePayload() instanceof LazyProcessedStoragePayload)
processDelayedItems.add(e);
else {
dataStorage.add(e, sender, null, false, false);
}
});
// We process the LazyProcessedStoragePayload items (TradeStatistics) in batches with a delay in between.
// We want avoid that the UI get stuck when processing many entries.
// The dataStorage.add call is a bit expensive as sig checks is done there.
// Using a background thread might be an alternative but it would require much more effort and
// it would also decrease user experience if the app gets under heavy load (like at startup with wallet sync).
// Beside that we mitigated the problem already as we will not get the whole TradeStatistics as we
// pass the excludeKeys and we pack the latest data dump
// into the resources, so a new user do not need to request all data.
// In future we will probably limit by date or load on demand from user intent to not get too much data.
// We split the list into sub lists with max 50 items and delay each batch with 200 ms.
int size = processDelayedItems.size();
int chunkSize = 50;
int chunks = 1 + size / chunkSize;
int startIndex = 0;
for (int i = 0; i < chunks && startIndex < size; i++, startIndex += chunkSize) {
long delay = (i + 1) * 200;
int endIndex = Math.min(size, startIndex + chunkSize);
List<ProtectedStorageEntry> subList = processDelayedItems.subList(startIndex, endIndex);
UserThread.runAfter(() -> {
subList.stream().forEach(protectedStorageEntry -> dataStorage.add(protectedStorageEntry, sender, null, false, false));
}, delay, TimeUnit.MILLISECONDS);
}
cleanup();
listener.onComplete();
} else {
log.debug("Nonce not matching. That can happen rarely if we get a response after a canceled " + "handshake (timeout causes connection close but peer might have sent a msg before " + "connection was closed).\n\t" + "We drop that message. nonce={} / requestNonce={}", nonce, getDataResponse.requestNonce);
}
} else {
log.warn("We have stopped already. We ignore that onDataRequest call.");
}
}
} else {
log.trace("We got a message from another connection and ignore it.");
}
}
use of io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry in project bitsquare by bitsquare.
the class P2PService method addData.
///////////////////////////////////////////////////////////////////////////////////////////
// Data storage
///////////////////////////////////////////////////////////////////////////////////////////
public boolean addData(StoragePayload storagePayload, boolean isDataOwner) {
Log.traceCall();
checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen.");
if (isBootstrapped()) {
try {
ProtectedStorageEntry protectedStorageEntry = p2PDataStorage.getProtectedData(storagePayload, optionalKeyRing.get().getSignatureKeyPair());
return p2PDataStorage.add(protectedStorageEntry, networkNode.getNodeAddress(), null, isDataOwner);
} catch (CryptoException e) {
log.error("Signing at getDataWithSignedSeqNr failed. That should never happen.");
return false;
}
} else {
throw new NetworkNotReadyException();
}
}
use of io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry in project bitsquare by bitsquare.
the class TradeStatisticsManager method init.
private void init(P2PService p2PService) {
if (dumpStatistics) {
this.statisticsJsonStorage.initWithFileName("trade_statistics.json");
this.fiatCurrencyListJsonStorage.initWithFileName("fiat_currency_list.json");
ArrayList<CurrencyTuple> fiatCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedFiatCurrencies().stream().map(e -> new CurrencyTuple(e.getCode(), e.getName(), 8)).collect(Collectors.toList()));
fiatCurrencyListJsonStorage.queueUpForSave(new PlainTextWrapper(Utilities.objectToJson(fiatCurrencyList)), 2000);
this.cryptoCurrencyListJsonStorage.initWithFileName("crypto_currency_list.json");
ArrayList<CurrencyTuple> cryptoCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedCryptoCurrencies().stream().map(e -> new CurrencyTuple(e.getCode(), e.getName(), 8)).collect(Collectors.toList()));
cryptoCurrencyList.add(0, new CurrencyTuple("BTC", "Bitcoin", 8));
cryptoCurrencyListJsonStorage.queueUpForSave(new PlainTextWrapper(Utilities.objectToJson(cryptoCurrencyList)), 2000);
}
HashSet<TradeStatistics> persisted = statisticsStorage.initAndGetPersistedWithFileName("TradeStatistics");
if (persisted != null)
persisted.stream().forEach(e -> add(e, false));
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
@Override
public void onAdded(ProtectedStorageEntry data) {
final StoragePayload storagePayload = data.getStoragePayload();
if (storagePayload instanceof TradeStatistics)
add((TradeStatistics) storagePayload, true);
}
@Override
public void onRemoved(ProtectedStorageEntry data) {
// We don't remove items
}
});
// At startup the P2PDataStorage inits earlier, otherwise we ge the listener called.
p2PService.getP2PDataStorage().getMap().values().forEach(e -> {
final StoragePayload storagePayload = e.getStoragePayload();
if (storagePayload instanceof TradeStatistics)
add((TradeStatistics) storagePayload, false);
});
}
use of io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry in project bitsquare by bitsquare.
the class P2PService method removeData.
public boolean removeData(StoragePayload storagePayload, boolean isDataOwner) {
Log.traceCall();
checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen.");
if (isBootstrapped()) {
try {
ProtectedStorageEntry protectedStorageEntry = p2PDataStorage.getProtectedData(storagePayload, optionalKeyRing.get().getSignatureKeyPair());
return p2PDataStorage.remove(protectedStorageEntry, networkNode.getNodeAddress(), isDataOwner);
} catch (CryptoException e) {
log.error("Signing at getDataWithSignedSeqNr failed. That should never happen.");
return false;
}
} else {
throw new NetworkNotReadyException();
}
}
use of io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry in project bitsquare by bitsquare.
the class P2PDataStorage method printData.
private void printData(String info) {
if (LoggerFactory.getLogger(Log.class).isInfoEnabled() || LoggerFactory.getLogger(Log.class).isDebugEnabled()) {
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
sb.append("Data set ").append(info).append(" operation");
// We print the items sorted by hash with the payload class name and id
List<Tuple2<String, ProtectedStorageEntry>> tempList = map.values().stream().map(e -> new Tuple2<>(org.bitcoinj.core.Utils.HEX.encode(getHashAsByteArray(e.getStoragePayload()).bytes), e)).collect(Collectors.toList());
tempList.sort((o1, o2) -> o1.first.compareTo(o2.first));
tempList.stream().forEach(e -> {
final ProtectedStorageEntry storageEntry = e.second;
final StoragePayload storagePayload = storageEntry.getStoragePayload();
final MapValue mapValue = sequenceNumberMap.get(getHashAsByteArray(storagePayload));
sb.append("\n").append("Hash=").append(e.first).append("; Class=").append(storagePayload.getClass().getSimpleName()).append("; SequenceNumbers (Object/Stored)=").append(storageEntry.sequenceNumber).append(" / ").append(mapValue != null ? mapValue.sequenceNr : "null").append("; TimeStamp (Object/Stored)=").append(storageEntry.creationTimeStamp).append(" / ").append(mapValue != null ? mapValue.timeStamp : "null").append("; Payload=").append(Utilities.toTruncatedString(storagePayload));
});
sb.append("\n------------------------------------------------------------\n");
log.debug(sb.toString());
log.debug("Data set " + info + " operation: size=" + map.values().size());
}
}
Aggregations