From 3e73718ff9a086d70f145d47964fa1160e121645 Mon Sep 17 00:00:00 2001 From: Bart de Jonge Date: Thu, 1 Feb 2018 23:14:24 +0100 Subject: [PATCH 1/3] transaction registration in batches, to keep the demo short --- .../CommunicationHelper.java | 7 +- .../SimulationMain.java | 2 + .../TrackerHelper.java | 65 ++++++++++++++----- .../model/TransactionRegistration.java | 31 +++++++++ tracker-server/routes/index.js | 13 ++++ tracker-server/views/demo.ejs | 2 +- 6 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/TransactionRegistration.java diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelper.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelper.java index de9be8c..620dccc 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelper.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/CommunicationHelper.java @@ -4,7 +4,6 @@ import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Log; import nl.tudelft.blockchain.scaleoutdistributedledger.validation.ValidationException; -import java.io.IOException; import java.util.logging.Level; /** @@ -38,11 +37,7 @@ public static boolean receiveTransaction(Proof proof, LocalStore localStore) { Log.log(Level.INFO, "Received and validated transaction: " + proof.getTransaction()); Log.log(Level.FINE, "Transaction " + proof.getTransaction() + " is valid, applying updates..."); proof.applyUpdates(localStore); - try { - TrackerHelper.registerTransaction(proof); - } catch (IOException e) { - Log.log(Level.WARNING, "Transaction registration failed", e); - } + TrackerHelper.registerTransaction(proof); if (proof.getTransaction().getAmount() > 0) { localStore.addUnspentTransaction(proof.getTransaction()); diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/SimulationMain.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/SimulationMain.java index 4c2e63e..546b800 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/SimulationMain.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/SimulationMain.java @@ -44,6 +44,8 @@ public final class SimulationMain { public static final long SENDING_WAIT_TIME = 5000; // The number of blocks (with the same or higher block number) that need to be committed before we send a certain block. public static final int REQUIRED_COMMITS = 2; + // The number of transactions that are registered in one batch. + public static final int REGISTER_TRANSACTIONS_EVERY = 10; private SimulationMain() {} diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java index 0ea3c1d..fa107bd 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java @@ -5,6 +5,7 @@ import nl.tudelft.blockchain.scaleoutdistributedledger.model.Node; import nl.tudelft.blockchain.scaleoutdistributedledger.model.OwnNode; import nl.tudelft.blockchain.scaleoutdistributedledger.model.Proof; +import nl.tudelft.blockchain.scaleoutdistributedledger.model.TransactionRegistration; import nl.tudelft.blockchain.scaleoutdistributedledger.utils.Log; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.HttpGet; @@ -22,13 +23,19 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.util.Enumeration; +import java.util.LinkedList; import java.util.Map; +import java.util.Queue; import java.util.logging.Level; /** * Helper class for interacting with the tracker. */ public final class TrackerHelper { + + private volatile static Queue transactionsToBeRegistered = new LinkedList<>(); + private volatile static Queue transactionsToBeSend; + private TrackerHelper() { throw new UnsupportedOperationException(); } @@ -213,32 +220,56 @@ private static byte[] jsonArrayToByteArray(JSONArray json) { } /** - * Registers a transaction to the tracker server. - * @param proof - the proof used to send the transaction - * @return - whether the registration was successful - * @throws IOException - exception while registering + * Registers a transaction to a queue, ready to be send to the server. + * @param proof - the proof used to send the transaction. */ - public static boolean registerTransaction(Proof proof) throws IOException { - JSONObject json = new JSONObject(); - json.put("from", proof.getTransaction().getSender().getId()); - json.put("to", proof.getTransaction().getReceiver().getId()); - json.put("amount", proof.getTransaction().getAmount()); - json.put("remainder", proof.getTransaction().getRemainder()); - json.put("numberOfChains", proof.getChainUpdates().size()); - json.put("numberOfBlocks", proof.getNumberOfBlocks()); + public synchronized static void registerTransaction(Proof proof) { +// System.out.println(proof.getTransaction()); + transactionsToBeRegistered.add(new TransactionRegistration( + proof.getTransaction(), proof.getChainUpdates().size(), proof.getNumberOfBlocks())); + + if (transactionsToBeRegistered.size() >= SimulationMain.REGISTER_TRANSACTIONS_EVERY) { + try { + transactionsToBeSend = transactionsToBeRegistered; + transactionsToBeRegistered = new LinkedList<>(); + sendTransactions(); + } catch (IOException e) { + Log.log(Level.WARNING, "Transaction registration failed", e); + } + } + } + + /** + * Actually send the transactions to the server. + * @throws IOException - exception while sending. + */ + private synchronized static void sendTransactions() throws IOException { + JSONArray transactionArray = new JSONArray(); + + while (!transactionsToBeSend.isEmpty()) { + TransactionRegistration next = transactionsToBeSend.poll(); + JSONObject json = new JSONObject(); + json.put("from", next.getTransaction().getSender().getId()); + json.put("to", next.getTransaction().getReceiver().getId()); + json.put("amount", next.getTransaction().getAmount()); + json.put("remainder", next.getTransaction().getRemainder()); + json.put("numberOfChains", next.getNumberOfChains()); + json.put("numberOfBlocks", next.getNumberOfBlocks()); + transactionArray.put(json); + } + JSONObject json = new JSONObject(); + json.put("transactions", transactionArray); try (CloseableHttpClient client = HttpClientBuilder.create().build()) { StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); - HttpPost request = new HttpPost(String.format("http://%s:%d/register-transaction", + HttpPost request = new HttpPost(String.format("http://%s:%d/register-transactions", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); request.setEntity(requestEntity); JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); if (response.getBoolean("success")) { - Log.log(Level.FINE, "Successfully registered transaction to tracker server"); - return true; + Log.log(Level.INFO, "Successfully registered " + transactionArray.length() + " transactions to tracker server"); } else { - Log.log(Level.WARNING, "Error while registering transaction " + proof.getTransaction()); - return false; + Log.log(Level.WARNING, "Error while registering transactions"); } } } diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/TransactionRegistration.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/TransactionRegistration.java new file mode 100644 index 0000000..17b4361 --- /dev/null +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/model/TransactionRegistration.java @@ -0,0 +1,31 @@ +package nl.tudelft.blockchain.scaleoutdistributedledger.model; + +import lombok.Getter; +import lombok.Setter; + +/** + * Class to store all information needed to register a transaction. + */ +public class TransactionRegistration { + + @Getter @Setter + private Transaction transaction; + + @Getter @Setter + private int numberOfChains; + + @Getter @Setter + private int numberOfBlocks; + + /** + * Constructor. + * @param transaction - the traansactions of this registration. + * @param numberOfChains - the number of chains used in the proof. + * @param numberOfBlocks - the number of blocks used in the proof. + */ + public TransactionRegistration(Transaction transaction, int numberOfChains, int numberOfBlocks) { + this.transaction = transaction; + this.numberOfChains = numberOfChains; + this.numberOfBlocks = numberOfBlocks; + } +} diff --git a/tracker-server/routes/index.js b/tracker-server/routes/index.js index 600bcbc..f4d649f 100644 --- a/tracker-server/routes/index.js +++ b/tracker-server/routes/index.js @@ -58,6 +58,19 @@ router.post('/register-transaction', (req, res) => { } }); +router.post('/register-transactions', (req, res) => { + if(!isPresent(req.body.transactions)) { + res.status(403); + res.json({success: false, err: 'Specify array of transactions'}); + } else { + req.body.transactions.forEach(tx => { + app.transactionList.addTransaction(new Transaction(tx.from, tx.to, tx.amount, tx.remainder, tx.numberOfChains, tx.numberOfBlocks)); + }); + updateSseClients(); + res.json({success: true}); + } +}); + /** * Update the running status of a node. */ diff --git a/tracker-server/views/demo.ejs b/tracker-server/views/demo.ejs index 83cbe99..9d0ca59 100644 --- a/tracker-server/views/demo.ejs +++ b/tracker-server/views/demo.ejs @@ -25,7 +25,7 @@ Total #transactions Average #chains per proof - Total #blocks per proof + Average #blocks per proof
From 00fa2c3bceebc8a1e52ed49a6e6e60f7a93b229c Mon Sep 17 00:00:00 2001 From: Bart de Jonge Date: Thu, 1 Feb 2018 23:16:11 +0100 Subject: [PATCH 2/3] Update TrackerHelper.java --- .../blockchain/scaleoutdistributedledger/TrackerHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java index fa107bd..b9c6644 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java @@ -224,7 +224,6 @@ private static byte[] jsonArrayToByteArray(JSONArray json) { * @param proof - the proof used to send the transaction. */ public synchronized static void registerTransaction(Proof proof) { -// System.out.println(proof.getTransaction()); transactionsToBeRegistered.add(new TransactionRegistration( proof.getTransaction(), proof.getChainUpdates().size(), proof.getNumberOfBlocks())); From 10b79da5ca25d603461ab4b77b4aaf5d492e84e7 Mon Sep 17 00:00:00 2001 From: Bart de Jonge Date: Thu, 1 Feb 2018 23:44:32 +0100 Subject: [PATCH 3/3] fixes --- .../TrackerHelper.java | 417 +++++++++--------- 1 file changed, 208 insertions(+), 209 deletions(-) diff --git a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java index fa107bd..64d1479 100644 --- a/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java +++ b/src/main/java/nl/tudelft/blockchain/scaleoutdistributedledger/TrackerHelper.java @@ -33,218 +33,219 @@ */ public final class TrackerHelper { - private volatile static Queue transactionsToBeRegistered = new LinkedList<>(); - private volatile static Queue transactionsToBeSend; + private volatile static Queue transactionsToBeRegistered = new LinkedList<>(); + private static final CloseableHttpClient client = HttpClientBuilder.create().build(); - private TrackerHelper() { - throw new UnsupportedOperationException(); - } + private TrackerHelper() { + throw new UnsupportedOperationException(); + } - /** - * Reset the tracker server with a new empty nodelist. - * @return - boolean identifying if the reset was successful - * @throws IOException - exception while resetting tracker server - */ - public static boolean resetTrackerServer() throws IOException { - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - HttpPost request = new HttpPost(String.format("http://%s:%d/reset", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); - if (response.getBoolean("success")) { - Log.log(Level.INFO, "Successfully resetted the tracker server"); - return true; - } - Log.log(Level.SEVERE, "Error while resetting the tracker server"); - return false; - } - } + /** + * Reset the tracker server with a new empty nodelist. + * @return - boolean identifying if the reset was successful + * @throws IOException - exception while resetting tracker server + */ + public static boolean resetTrackerServer() throws IOException { + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + HttpPost request = new HttpPost(String.format("http://%s:%d/reset", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); + if (response.getBoolean("success")) { + Log.log(Level.INFO, "Successfully resetted the tracker server"); + return true; + } + Log.log(Level.SEVERE, "Error while resetting the tracker server"); + return false; + } + } - /** - * Registers this node with the given public key. - * @param nodePort - the port of the node - * @param publicKey - the publicKey of the new node - * @param id - the id of the node - * @return - the registered node - * @throws IOException - IOException while registering node - * @throws NodeRegisterFailedException - Server side exception while registering node - */ - public static OwnNode registerNode(int nodePort, byte[] publicKey, int id) throws IOException, NodeRegisterFailedException { - String address = getIP(); - JSONObject json = new JSONObject(); - json.put("address", address); - json.put("port", nodePort); - json.put("publicKey", publicKey); - json.put("id", id); + /** + * Registers this node with the given public key. + * @param nodePort - the port of the node + * @param publicKey - the publicKey of the new node + * @param id - the id of the node + * @return - the registered node + * @throws IOException - IOException while registering node + * @throws NodeRegisterFailedException - Server side exception while registering node + */ + public static OwnNode registerNode(int nodePort, byte[] publicKey, int id) throws IOException, NodeRegisterFailedException { + String address = getIP(); + JSONObject json = new JSONObject(); + json.put("address", address); + json.put("port", nodePort); + json.put("publicKey", publicKey); + json.put("id", id); - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); - HttpPost request = new HttpPost(String.format("http://%s:%d/register-node", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - request.setEntity(requestEntity); - JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); - if (response.getBoolean("success")) { - Log.log(Level.INFO, "Successfully registered node to tracker server"); - return new OwnNode(id, publicKey, address, nodePort); - } - Log.log(Level.SEVERE, "Error while registering node"); - throw new NodeRegisterFailedException(); - } - } + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); + HttpPost request = new HttpPost(String.format("http://%s:%d/register-node", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + request.setEntity(requestEntity); + JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); + if (response.getBoolean("success")) { + Log.log(Level.INFO, "Successfully registered node to tracker server"); + return new OwnNode(id, publicKey, address, nodePort); + } + Log.log(Level.SEVERE, "Error while registering node"); + throw new NodeRegisterFailedException(); + } + } - /** - * Mark a node with the given id as initialized on the tracker. - * @param id - the id of the node to mark - * @param running - if the node is running or not - * @throws IOException - IOException while registering node - * @throws TrackerException - Server side exception while updating running status - */ - public static void setRunning(int id, boolean running) throws IOException, TrackerException { - JSONObject json = new JSONObject(); - json.put("id", id); - json.put("running", running); + /** + * Mark a node with the given id as initialized on the tracker. + * @param id - the id of the node to mark + * @param running - if the node is running or not + * @throws IOException - IOException while registering node + * @throws TrackerException - Server side exception while updating running status + */ + public static void setRunning(int id, boolean running) throws IOException, TrackerException { + JSONObject json = new JSONObject(); + json.put("id", id); + json.put("running", running); - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); - HttpPost request = new HttpPost(String.format("http://%s:%d/set-node-status", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - request.setEntity(requestEntity); - JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); - if (response.getBoolean("success")) { - Log.log(Level.INFO, "Successfully updated node " + id + " to running=" + running); - return; - } - Log.log(Level.SEVERE, "Error while updating the running status of the node"); - throw new TrackerException("Unable to update to running."); - } - } + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); + HttpPost request = new HttpPost(String.format("http://%s:%d/set-node-status", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + request.setEntity(requestEntity); + JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); + if (response.getBoolean("success")) { + Log.log(Level.INFO, "Successfully updated node " + id + " to running=" + running); + return; + } + Log.log(Level.SEVERE, "Error while updating the running status of the node"); + throw new TrackerException("Unable to update to running."); + } + } - /** - * Tries to resolve the IP(v4) address of this machine. - * When it fails to do so it uses the local IP. - * - * @return the IP of this machine - */ - public static String getIP() { - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface ni = interfaces.nextElement(); - Enumeration addrss = ni.getInetAddresses(); - while (addrss.hasMoreElements()) { - String addr = addrss.nextElement().getHostAddress(); - if (addr.contains(":") || addr.startsWith("127.")) continue; // IPv6 or Local - return addr; - } - } - } catch (SocketException e) { } // Intentionally empty catch block - try { - Log.log(Level.WARNING, "Could not resolve address, using localhost instead"); - return InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException e) { - Log.log(Level.SEVERE, "Could not resolve localhost address, please check your network configuration"); - return "0.0.0.0"; - } - } + /** + * Tries to resolve the IP(v4) address of this machine. + * When it fails to do so it uses the local IP. + * + * @return the IP of this machine + */ + public static String getIP() { + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface ni = interfaces.nextElement(); + Enumeration addrss = ni.getInetAddresses(); + while (addrss.hasMoreElements()) { + String addr = addrss.nextElement().getHostAddress(); + if (addr.contains(":") || addr.startsWith("127.")) continue; // IPv6 or Local + return addr; + } + } + } catch (SocketException e) { } // Intentionally empty catch block + try { + Log.log(Level.WARNING, "Could not resolve address, using localhost instead"); + return InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + Log.log(Level.SEVERE, "Could not resolve localhost address, please check your network configuration"); + return "0.0.0.0"; + } + } - /** - * Updates the given map of nodes with new information from the tracker. - * @param nodes - the map of nodes - * @throws IOException - exception while updating nodes - */ - public static void updateNodes(Map nodes, OwnNode ownNode) throws IOException { - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - HttpGet request = new HttpGet(String.format("http://%s:%d", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - JSONArray nodesArray = (JSONArray) new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())).get("nodes"); + /** + * Updates the given map of nodes with new information from the tracker. + * @param nodes - the map of nodes + * @throws IOException - exception while updating nodes + */ + public static void updateNodes(Map nodes, OwnNode ownNode) throws IOException { + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + HttpGet request = new HttpGet(String.format("http://%s:%d", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + JSONArray nodesArray = (JSONArray) new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())).get("nodes"); - for (int i = 0; i < nodesArray.length(); i++) { - JSONObject object = (JSONObject) nodesArray.get(i); - byte[] publicKey = jsonArrayToByteArray((JSONArray) object.get("publicKey")); - String address = object.getString("address"); - int port = object.getInt("port"); - if (nodes.containsKey(i)) { - Node node = nodes.get(i); - node.setAddress(address); - node.setPort(port); - } else { - Node node = new Node(i, publicKey, address, port); - - //TODO Check if we need this. - if (ownNode != null) { - node.getChain().setGenesisBlock(ownNode.getChain().getGenesisBlock()); - } - - nodes.put(i, node); - } - } - } - } + for (int i = 0; i < nodesArray.length(); i++) { + JSONObject object = (JSONObject) nodesArray.get(i); + byte[] publicKey = jsonArrayToByteArray((JSONArray) object.get("publicKey")); + String address = object.getString("address"); + int port = object.getInt("port"); + if (nodes.containsKey(i)) { + Node node = nodes.get(i); + node.setAddress(address); + node.setPort(port); + } else { + Node node = new Node(i, publicKey, address, port); - /** - * Get the status of the tracker. - * @return a JSON object describing the status of the tracker - * @throws IOException when problems with creating/closing http client - */ - public static JSONObject getStatus() throws IOException { - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - HttpGet request = new HttpGet(String.format("http://%s:%d/status", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - return new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); - } - } + //TODO Check if we need this. + if (ownNode != null) { + node.getChain().setGenesisBlock(ownNode.getChain().getGenesisBlock()); + } - /** - * Get the number of running nodes from the tracker. - * @return the number of nodes already registered in tracker - * @throws IOException when problems with creating/closing http client - */ - public static int getRunning() throws IOException { - return getStatus().getInt("running"); - } + nodes.put(i, node); + } + } + } + } - /** - * Get the number of registered nodes from the tracker. - * @return the number of nodes already registered in tracker - * @throws IOException when problems with creating/closing http client - */ - public static int getRegistered() throws IOException { - return getStatus().getInt("registered"); - } + /** + * Get the status of the tracker. + * @return a JSON object describing the status of the tracker + * @throws IOException when problems with creating/closing http client + */ + public static JSONObject getStatus() throws IOException { + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + HttpGet request = new HttpGet(String.format("http://%s:%d/status", Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + return new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); + } + } + + /** + * Get the number of running nodes from the tracker. + * @return the number of nodes already registered in tracker + * @throws IOException when problems with creating/closing http client + */ + public static int getRunning() throws IOException { + return getStatus().getInt("running"); + } + + /** + * Get the number of registered nodes from the tracker. + * @return the number of nodes already registered in tracker + * @throws IOException when problems with creating/closing http client + */ + public static int getRegistered() throws IOException { + return getStatus().getInt("registered"); + } - /** - * Converts JSONArray containing ints to byte array. - * @param json - the jsonarray to convert. - * @return - the generated byte array - */ - private static byte[] jsonArrayToByteArray(JSONArray json) { - byte[] res = new byte[json.length()]; - for (int i = 0; i < json.length(); i++) { - res[i] = (byte) json.getInt(i); - } - return res; - } + /** + * Converts JSONArray containing ints to byte array. + * @param json - the jsonarray to convert. + * @return - the generated byte array + */ + private static byte[] jsonArrayToByteArray(JSONArray json) { + byte[] res = new byte[json.length()]; + for (int i = 0; i < json.length(); i++) { + res[i] = (byte) json.getInt(i); + } + return res; + } - /** - * Registers a transaction to a queue, ready to be send to the server. - * @param proof - the proof used to send the transaction. - */ - public synchronized static void registerTransaction(Proof proof) { -// System.out.println(proof.getTransaction()); - transactionsToBeRegistered.add(new TransactionRegistration( - proof.getTransaction(), proof.getChainUpdates().size(), proof.getNumberOfBlocks())); + /** + * Registers a transaction to a queue, ready to be send to the server. + * @param proof - the proof used to send the transaction. + */ + public static synchronized void registerTransaction(Proof proof) { + transactionsToBeRegistered.add(new TransactionRegistration( + proof.getTransaction(), proof.getChainUpdates().size(), proof.getNumberOfBlocks())); - if (transactionsToBeRegistered.size() >= SimulationMain.REGISTER_TRANSACTIONS_EVERY) { - try { - transactionsToBeSend = transactionsToBeRegistered; - transactionsToBeRegistered = new LinkedList<>(); - sendTransactions(); - } catch (IOException e) { - Log.log(Level.WARNING, "Transaction registration failed", e); - } - } - } + try { + Queue transactionsToBeSend; + synchronized (TrackerHelper.class) { + if (transactionsToBeRegistered.size() < SimulationMain.REGISTER_TRANSACTIONS_EVERY) return; + transactionsToBeSend = transactionsToBeRegistered; + transactionsToBeRegistered = new LinkedList<>(); + } + sendTransactions(transactionsToBeSend); + } catch (IOException e) { + Log.log(Level.WARNING, "Transaction registration failed", e); + } + } - /** - * Actually send the transactions to the server. - * @throws IOException - exception while sending. - */ - private synchronized static void sendTransactions() throws IOException { - JSONArray transactionArray = new JSONArray(); + /** + * Actually send the transactions to the server. + * @throws IOException - exception while sending. + */ + private static synchronized void sendTransactions(Queue transactionsToBeSend) throws IOException { + JSONArray transactionArray = new JSONArray(); while (!transactionsToBeSend.isEmpty()) { TransactionRegistration next = transactionsToBeSend.poll(); @@ -260,17 +261,15 @@ private synchronized static void sendTransactions() throws IOException { JSONObject json = new JSONObject(); json.put("transactions", transactionArray); - try (CloseableHttpClient client = HttpClientBuilder.create().build()) { - StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); - HttpPost request = new HttpPost(String.format("http://%s:%d/register-transactions", - Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); - request.setEntity(requestEntity); - JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); - if (response.getBoolean("success")) { - Log.log(Level.INFO, "Successfully registered " + transactionArray.length() + " transactions to tracker server"); - } else { - Log.log(Level.WARNING, "Error while registering transactions"); - } - } - } + StringEntity requestEntity = new StringEntity(json.toString(), ContentType.APPLICATION_JSON); + HttpPost request = new HttpPost(String.format("http://%s:%d/register-transactions", + Application.TRACKER_SERVER_ADDRESS, Application.TRACKER_SERVER_PORT)); + request.setEntity(requestEntity); + JSONObject response = new JSONObject(IOUtils.toString(client.execute(request).getEntity().getContent())); + if (response.getBoolean("success")) { + Log.log(Level.INFO, "Successfully registered " + transactionArray.length() + " transactions to tracker server"); + } else { + Log.log(Level.WARNING, "Error while registering transactions"); + } + } }