From b6aab142b697825e34b085a5a7fb5be1301c7ec1 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Thu, 8 Nov 2018 15:14:01 -0600 Subject: [PATCH] - Added a method to remove nodes from LatencyNodeProvider and implemented a HashSet to keep track of such removed nodes. The reason is that calls to this class are asynchronous and only removing a node from the mFullNodeHeap was not enough to guarantee that it was not going to be added again. - Added a isRemoved variable to FullNode class, so that the object can carry itself the removal status information and be able to use the same publish subject to broadcast the status of the FullNode. - Added a method to remove nodes from NodeLatencyVerifier, removed such nodes from pending node latency measurements map 'nodeURLMap' and publish/broadcast the FullNode information with isRemoved=true so that components listening can act accordingly. - Make proper changes to sample app's RemoteNodeActivity so that it removes 'removed' nodes from the list. --- .../graphenej/api/android/NetworkService.java | 8 ++++--- .../agorise/graphenej/network/FullNode.java | 9 ++++++++ .../network/LatencyNodeProvider.java | 21 ++++++++++++++++--- .../network/NodeLatencyVerifier.java | 20 ++++++++++++++++++ .../graphenej/network/NodeProvider.java | 10 +++++++-- .../labs/sample/RemoveNodeActivity.java | 16 ++++++++++++-- 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java b/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java index 3553143..1b8a44b 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java @@ -703,9 +703,11 @@ public class NetworkService extends Service { mApiIds.clear(); if (removeSelectedNode) { - // TODO change method to actually remove the node from the list - mSelectedNode.addLatencyValue(Long.MAX_VALUE); - nodeProvider.updateNode(mSelectedNode); + // Remove node from node provider so that it is not returned for following connections + nodeProvider.removeNode(mSelectedNode); + + // Remove node from nodeLatencyVerifier, so that it publishes its removal + nodeLatencyVerifier.removeNode(mSelectedNode); } else { // Adding a very high latency value to this node in order to prevent // us from getting it again diff --git a/graphenej/src/main/java/cy/agorise/graphenej/network/FullNode.java b/graphenej/src/main/java/cy/agorise/graphenej/network/FullNode.java index be91d4a..4226b23 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/network/FullNode.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/network/FullNode.java @@ -10,6 +10,7 @@ public class FullNode implements Comparable { private String mUrl; private ExponentialMovingAverage mLatency; private boolean isConnected; + private boolean isRemoved; private FullNode(){} @@ -77,6 +78,14 @@ public class FullNode implements Comparable { isConnected = connected; } + public boolean isRemoved() { + return isRemoved; + } + + public void setRemoved(boolean removed) { + isRemoved = removed; + } + /** * Method that updates the mLatency average with a new value. * @param latency Most recent mLatency sample to be added to the exponential average diff --git a/graphenej/src/main/java/cy/agorise/graphenej/network/LatencyNodeProvider.java b/graphenej/src/main/java/cy/agorise/graphenej/network/LatencyNodeProvider.java index 1e12939..8531936 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/network/LatencyNodeProvider.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/network/LatencyNodeProvider.java @@ -2,14 +2,18 @@ package cy.agorise.graphenej.network; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.PriorityQueue; public class LatencyNodeProvider implements NodeProvider { + private HashSet mRemovedNodeURLs; + private PriorityQueue mFullNodeHeap; public LatencyNodeProvider(){ mFullNodeHeap = new PriorityQueue<>(); + mRemovedNodeURLs = new HashSet<>(); } @Override @@ -20,12 +24,16 @@ public class LatencyNodeProvider implements NodeProvider { @Override public void addNode(FullNode fullNode) { mFullNodeHeap.add(fullNode); + mRemovedNodeURLs.remove(fullNode.getUrl()); } @Override public boolean updateNode(FullNode fullNode) { - mFullNodeHeap.remove(fullNode); - return mFullNodeHeap.offer(fullNode); + if (!mRemovedNodeURLs.contains(fullNode.getUrl())) { + mFullNodeHeap.remove(fullNode); + return mFullNodeHeap.offer(fullNode); + } + return false; } /** @@ -36,7 +44,7 @@ public class LatencyNodeProvider implements NodeProvider { * @return True if the node priority was updated successfully */ public boolean updateNode(FullNode fullNode, int latency){ - if(mFullNodeHeap.remove(fullNode)){ + if(!mRemovedNodeURLs.contains(fullNode.getUrl()) && mFullNodeHeap.remove(fullNode)){ fullNode.addLatencyValue(latency); return mFullNodeHeap.add(fullNode); }else{ @@ -44,6 +52,13 @@ public class LatencyNodeProvider implements NodeProvider { } } + @Override + public void removeNode(FullNode fullNode) { + if (mFullNodeHeap.remove(fullNode)) { + mRemovedNodeURLs.add(fullNode.getUrl()); + } + } + @Override public List getSortedNodes() { FullNode[] nodeArray = mFullNodeHeap.toArray(new FullNode[mFullNodeHeap.size()]); diff --git a/graphenej/src/main/java/cy/agorise/graphenej/network/NodeLatencyVerifier.java b/graphenej/src/main/java/cy/agorise/graphenej/network/NodeLatencyVerifier.java index 0b97301..076ddfd 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/network/NodeLatencyVerifier.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/network/NodeLatencyVerifier.java @@ -183,4 +183,24 @@ public class NodeLatencyVerifier { } } } + + /** + * Removes the given node from the nodes list + * @param fullNode The node to remove + */ + public void removeNode(FullNode fullNode){ + for(FullNode node : mNodeList){ + if(node.equals(fullNode)){ + mNodeList.remove(node); + + String normalURL = node.getUrl().replace("wss://", "https://"); + HttpUrl key = HttpUrl.parse(normalURL); + nodeURLMap.remove(key); + + node.setRemoved(true); + subject.onNext(node); + break; + } + } + } } diff --git a/graphenej/src/main/java/cy/agorise/graphenej/network/NodeProvider.java b/graphenej/src/main/java/cy/agorise/graphenej/network/NodeProvider.java index 6f3821e..400158e 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/network/NodeProvider.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/network/NodeProvider.java @@ -26,13 +26,19 @@ public interface NodeProvider { /** * Updates the rating of a specific node that is already in the NodeProvider - * @param fullNode + * @param fullNode The node tu update */ boolean updateNode(FullNode fullNode); + /** + * Removes the given node from the nodes list + * @param fullNode The node to remove + */ + void removeNode(FullNode fullNode); + /** * Returns an ordered list of {@link FullNode} instances. - * @return + * @return The sorted list of nodes. */ List getSortedNodes(); } diff --git a/sample/src/main/java/cy/agorise/labs/sample/RemoveNodeActivity.java b/sample/src/main/java/cy/agorise/labs/sample/RemoveNodeActivity.java index 81f7a6b..2ab9954 100644 --- a/sample/src/main/java/cy/agorise/labs/sample/RemoveNodeActivity.java +++ b/sample/src/main/java/cy/agorise/labs/sample/RemoveNodeActivity.java @@ -32,6 +32,7 @@ import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnClick; import cy.agorise.graphenej.api.android.NetworkService; import cy.agorise.graphenej.network.FullNode; import io.reactivex.Observer; @@ -67,6 +68,11 @@ public class RemoveNodeActivity extends AppCompatActivity implements ServiceConn rvNodes.setAdapter(nodesAdapter); } + @OnClick(R.id.btnRemoveCurrentNode) + public void removeCurrentNode() { + mNetworkService.removeCurrentNodeAndReconnect(); + } + @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { // We've bound to LocalService, cast the IBinder and get LocalService instance @@ -86,7 +92,7 @@ public class RemoveNodeActivity extends AppCompatActivity implements ServiceConn @Override public void onServiceDisconnected(ComponentName componentName) { - + mNetworkService = null; } /** @@ -98,7 +104,10 @@ public class RemoveNodeActivity extends AppCompatActivity implements ServiceConn @Override public void onNext(FullNode fullNode) { - nodesAdapter.add(fullNode); + if (!fullNode.isRemoved()) + nodesAdapter.add(fullNode); + else + nodesAdapter.remove(fullNode); } @Override @@ -265,6 +274,9 @@ public class RemoveNodeActivity extends AppCompatActivity implements ServiceConn mSortedList.addAll(fullNodes); } + public void remove(FullNode fullNode) { + mSortedList.remove(fullNode); + } @Override public int getItemCount() {