Search in sources :

Example 1 with GetUpdatedDataRequest

use of io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest in project bitsquare by bitsquare.

the class RequestDataHandler method requestData.

///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void requestData(NodeAddress nodeAddress, boolean isPreliminaryDataRequest) {
    Log.traceCall("nodeAddress=" + nodeAddress);
    peersNodeAddress = nodeAddress;
    if (!stopped) {
        GetDataRequest getDataRequest;
        // We collect the keys of the PersistedStoragePayload items so we exclude them in our request.
        // PersistedStoragePayload items don't get removed, so we don't have an issue with the case that
        // an object gets removed in between PreliminaryGetDataRequest and the GetUpdatedDataRequest and we would 
        // miss that event if we do not load the full set or use some delta handling.
        Set<byte[]> excludedKeys = dataStorage.getMap().entrySet().stream().filter(e -> e.getValue().getStoragePayload() instanceof PersistedStoragePayload).map(e -> e.getKey().bytes).collect(Collectors.toSet());
        if (isPreliminaryDataRequest)
            getDataRequest = new PreliminaryGetDataRequest(nonce, excludedKeys);
        else
            getDataRequest = new GetUpdatedDataRequest(networkNode.getNodeAddress(), nonce, excludedKeys);
        if (timeoutTimer == null) {
            timeoutTimer = UserThread.runAfter(() -> {
                // setup before sending to avoid race conditions
                if (!stopped) {
                    String errorMessage = "A timeout occurred at sending getDataRequest:" + getDataRequest + " on nodeAddress:" + nodeAddress;
                    log.debug(errorMessage + " / RequestDataHandler=" + RequestDataHandler.this);
                    handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT);
                } else {
                    log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + "Might be caused by an previous networkNode.sendMessage.onFailure.");
                }
            }, TIME_OUT_SEC);
        }
        log.debug("We send a {} to peer {}. ", getDataRequest.getClass().getSimpleName(), nodeAddress);
        networkNode.addMessageListener(this);
        SettableFuture<Connection> future = networkNode.sendMessage(nodeAddress, getDataRequest);
        Futures.addCallback(future, new FutureCallback<Connection>() {

            @Override
            public void onSuccess(Connection connection) {
                if (!stopped) {
                    RequestDataHandler.this.connection = connection;
                    log.trace("Send " + getDataRequest + " to " + nodeAddress + " succeeded.");
                } else {
                    log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + "Might be caused by an previous timeout.");
                }
            }

            @Override
            public void onFailure(@NotNull Throwable throwable) {
                if (!stopped) {
                    String errorMessage = "Sending getDataRequest to " + nodeAddress + " failed. That is expected if the peer is offline.\n\t" + "getDataRequest=" + getDataRequest + "." + "\n\tException=" + throwable.getMessage();
                    log.debug(errorMessage);
                    handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE);
                } else {
                    log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + "Might be caused by an previous timeout.");
                }
            }
        });
    } else {
        log.warn("We have stopped already. We ignore that requestData call.");
    }
}
Also used : java.util(java.util) ProtectedStorageEntry(io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry) LoggerFactory(org.slf4j.LoggerFactory) Connection(io.bitsquare.p2p.network.Connection) Timer(io.bitsquare.common.Timer) SettableFuture(com.google.common.util.concurrent.SettableFuture) GetDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetDataRequest) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) PersistedStoragePayload(io.bitsquare.p2p.storage.payload.PersistedStoragePayload) PeerManager(io.bitsquare.p2p.peers.PeerManager) Log(io.bitsquare.app.Log) P2PDataStorage(io.bitsquare.p2p.storage.P2PDataStorage) GetUpdatedDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest) Logger(org.slf4j.Logger) GetDataResponse(io.bitsquare.p2p.peers.getdata.messages.GetDataResponse) UserThread(io.bitsquare.common.UserThread) Message(io.bitsquare.p2p.Message) NodeAddress(io.bitsquare.p2p.NodeAddress) StoragePayload(io.bitsquare.p2p.storage.payload.StoragePayload) Collectors(java.util.stream.Collectors) FutureCallback(com.google.common.util.concurrent.FutureCallback) TimeUnit(java.util.concurrent.TimeUnit) Nullable(org.jetbrains.annotations.Nullable) Futures(com.google.common.util.concurrent.Futures) LazyProcessedStoragePayload(io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload) MessageListener(io.bitsquare.p2p.network.MessageListener) CloseConnectionReason(io.bitsquare.p2p.network.CloseConnectionReason) NotNull(org.jetbrains.annotations.NotNull) NetworkNode(io.bitsquare.p2p.network.NetworkNode) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) PersistedStoragePayload(io.bitsquare.p2p.storage.payload.PersistedStoragePayload) Connection(io.bitsquare.p2p.network.Connection) GetDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetDataRequest) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) GetUpdatedDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest)

Example 2 with GetUpdatedDataRequest

use of io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest in project bitsquare by bitsquare.

the class GetDataRequestHandler method handle.

///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void handle(GetDataRequest getDataRequest, final Connection connection) {
    Log.traceCall(getDataRequest + "\n\tconnection=" + connection);
    final HashSet<ProtectedStorageEntry> filteredDataSet = new HashSet<>();
    final Set<Integer> lookupSet = new HashSet<>();
    Set<P2PDataStorage.ByteArray> excludedItems = getDataRequest.getExcludedKeys() != null ? getDataRequest.getExcludedKeys().stream().map(P2PDataStorage.ByteArray::new).collect(Collectors.toSet()) : new HashSet<>();
    for (ProtectedStorageEntry protectedStorageEntry : dataStorage.getFilteredValues(excludedItems)) {
        final StoragePayload storagePayload = protectedStorageEntry.getStoragePayload();
        boolean doAdd = false;
        if (storagePayload instanceof CapabilityRequiringPayload) {
            final List<Integer> requiredCapabilities = ((CapabilityRequiringPayload) storagePayload).getRequiredCapabilities();
            final List<Integer> supportedCapabilities = connection.getSupportedCapabilities();
            if (supportedCapabilities != null) {
                for (int messageCapability : requiredCapabilities) {
                    for (int connectionCapability : supportedCapabilities) {
                        if (messageCapability == connectionCapability) {
                            doAdd = true;
                            break;
                        }
                    }
                }
                if (!doAdd)
                    log.debug("We do not send the message to the peer because he does not support the required capability for that message type.\n" + "Required capabilities is: " + requiredCapabilities.toString() + "\n" + "Supported capabilities is: " + supportedCapabilities.toString() + "\n" + "storagePayload is: " + Utilities.toTruncatedString(storagePayload));
            } else {
                log.debug("We do not send the message to the peer because he uses an old version which does not support capabilities.\n" + "Required capabilities is: " + requiredCapabilities.toString() + "\n" + "storagePayload is: " + Utilities.toTruncatedString(storagePayload));
            }
        } else {
            doAdd = true;
        }
        if (doAdd) {
            // We have TradeStatistic data of both traders but we only send 1 item, 
            // so we use lookupSet as for a fast lookup. Using filteredDataSet would require a loop as it stores 
            // protectedStorageEntry not storagePayload. protectedStorageEntry is different for both traders but storagePayload not, 
            // as we ignore the pubKey and data there in the hashCode method.
            boolean notContained = lookupSet.add(storagePayload.hashCode());
            if (notContained)
                filteredDataSet.add(protectedStorageEntry);
        }
    }
    GetDataResponse getDataResponse = new GetDataResponse(filteredDataSet, getDataRequest.getNonce(), getDataRequest instanceof GetUpdatedDataRequest);
    if (timeoutTimer == null) {
        timeoutTimer = UserThread.runAfter(() -> {
            // setup before sending to avoid race conditions
            String errorMessage = "A timeout occurred for getDataResponse:" + getDataResponse + " on connection:" + connection;
            handleFault(errorMessage, CloseConnectionReason.SEND_MSG_TIMEOUT, connection);
        }, TIME_OUT_SEC, TimeUnit.SECONDS);
    }
    SettableFuture<Connection> future = networkNode.sendMessage(connection, getDataResponse);
    Futures.addCallback(future, new FutureCallback<Connection>() {

        @Override
        public void onSuccess(Connection connection) {
            if (!stopped) {
                log.trace("Send DataResponse to {} succeeded. getDataResponse={}", connection.getPeersNodeAddressOptional(), getDataResponse);
                cleanup();
                listener.onComplete();
            } else {
                log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call.");
            }
        }

        @Override
        public void onFailure(@NotNull Throwable throwable) {
            if (!stopped) {
                String errorMessage = "Sending getDataRequest to " + connection + " failed. That is expected if the peer is offline. getDataResponse=" + getDataResponse + "." + "Exception: " + throwable.getMessage();
                handleFault(errorMessage, CloseConnectionReason.SEND_MSG_FAILURE, connection);
            } else {
                log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call.");
            }
        }
    });
}
Also used : Connection(io.bitsquare.p2p.network.Connection) CapabilityRequiringPayload(io.bitsquare.p2p.storage.payload.CapabilityRequiringPayload) GetDataResponse(io.bitsquare.p2p.peers.getdata.messages.GetDataResponse) GetUpdatedDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest) StoragePayload(io.bitsquare.p2p.storage.payload.StoragePayload) HashSet(java.util.HashSet) ProtectedStorageEntry(io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry)

Aggregations

Connection (io.bitsquare.p2p.network.Connection)2 GetDataResponse (io.bitsquare.p2p.peers.getdata.messages.GetDataResponse)2 GetUpdatedDataRequest (io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest)2 StoragePayload (io.bitsquare.p2p.storage.payload.StoragePayload)2 ProtectedStorageEntry (io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 FutureCallback (com.google.common.util.concurrent.FutureCallback)1 Futures (com.google.common.util.concurrent.Futures)1 SettableFuture (com.google.common.util.concurrent.SettableFuture)1 Log (io.bitsquare.app.Log)1 Timer (io.bitsquare.common.Timer)1 UserThread (io.bitsquare.common.UserThread)1 Message (io.bitsquare.p2p.Message)1 NodeAddress (io.bitsquare.p2p.NodeAddress)1 CloseConnectionReason (io.bitsquare.p2p.network.CloseConnectionReason)1 MessageListener (io.bitsquare.p2p.network.MessageListener)1 NetworkNode (io.bitsquare.p2p.network.NetworkNode)1 PeerManager (io.bitsquare.p2p.peers.PeerManager)1 GetDataRequest (io.bitsquare.p2p.peers.getdata.messages.GetDataRequest)1 PreliminaryGetDataRequest (io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest)1