diff --git a/src/main/java/fucoin/AbstractNode.java b/src/main/java/fucoin/AbstractNode.java index fb3d50ee5f91b7ebeeeb4d0482d68b61293a4635..c374656de5d1a211c7ba096664ace6b6c9ee4ba1 100644 --- a/src/main/java/fucoin/AbstractNode.java +++ b/src/main/java/fucoin/AbstractNode.java @@ -3,10 +3,6 @@ package fucoin; import akka.actor.ActorRef; import akka.actor.Address; import akka.actor.UntypedActor; -import com.google.gson.ExclusionStrategy; -import com.google.gson.FieldAttributes; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import fucoin.actions.transaction.ActionGetAmount; import fucoin.wallet.AbstractWallet; @@ -14,7 +10,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.Serializable; -import java.time.LocalTime; +import java.time.LocalDateTime; import java.util.HashMap; public abstract class AbstractNode extends UntypedActor implements Serializable { @@ -77,16 +73,21 @@ public abstract class AbstractNode extends UntypedActor implements Serializable return knownNeighbors; } - public void createDump(String name, String content, LocalTime time) { - String filename = "snapshots/Dump_" + time.getNano() + "_" + name + ".json"; + public void createDump(String name, String content, LocalDateTime time) { + String folder = time.getYear() + "-" + time.getMonthValue() + "-" + time.getDayOfMonth() + " " + + time.getHour() + "." + time.getMinute() + "." + time.getSecond(); + String filename = "snapshots/" + folder + "/" + name + ".json"; try { File theDir = new File("snapshots"); - // if the directory does not exist, create it if (!theDir.exists()) { theDir.mkdir(); } + theDir = new File("snapshots/" + folder); + if (!theDir.exists()) { + theDir.mkdir(); + } File myFile = new File(filename); myFile.createNewFile(); diff --git a/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java b/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java index 7bfa9d159ab8a987152961ad9701ea59b9f88adb..a08d0dbf6832f32b488892d97a855e19cfdab3e5 100644 --- a/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java +++ b/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java @@ -5,16 +5,21 @@ import akka.actor.UntypedActorContext; import fucoin.actions.SuperVisorAction; import fucoin.supervisor.SuperVisorImpl; +import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.Map; +/** + * SuperVisor create a snapshot by sending all Wallets a Snapshot Msg. + */ public class ActionCreateSuperVisorSnapshot extends SuperVisorAction { /** * Timestamp for the file name */ - private final LocalTime time; + private final LocalDateTime time; - public ActionCreateSuperVisorSnapshot(LocalTime time) { + public ActionCreateSuperVisorSnapshot(LocalDateTime time) { this.time = time; } @@ -22,5 +27,9 @@ public class ActionCreateSuperVisorSnapshot extends SuperVisorAction { @Override protected void onAction(ActorRef sender, ActorRef self, UntypedActorContext context, SuperVisorImpl abstractNode) { abstractNode.createDump(time); + System.out.println("Create Dumps"); + for (Map.Entry<String, ActorRef> wallet: abstractNode.getKnownNeighbors().entrySet()) { + wallet.getValue().tell(new ActionCreateWalletSnapshot(time), self); + } } } diff --git a/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java b/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java index f730419483b8709a32e036160f6e97fd5807b07d..6d51193292ddfe3e204ece422cbad1792c76def7 100644 --- a/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java +++ b/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java @@ -2,23 +2,19 @@ package fucoin.actions.control; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; -import com.google.gson.Gson; import fucoin.actions.ClientAction; import fucoin.wallet.AbstractWallet; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.time.LocalTime; +import java.time.LocalDateTime; public class ActionCreateWalletSnapshot extends ClientAction { /** * Timestamp for the file name */ - private final LocalTime time; + private final LocalDateTime time; - public ActionCreateWalletSnapshot(LocalTime time) { + public ActionCreateWalletSnapshot(LocalDateTime time) { this.time = time; } diff --git a/src/main/java/fucoin/actions/persist/ActionInvokeLeave.java b/src/main/java/fucoin/actions/persist/ActionInvokeLeave.java index 201c090bad9b3c9f8e5b9ec68610e67cabeb9379..5d3d587b298a93fa2e771c126711596e8cdba8ad 100644 --- a/src/main/java/fucoin/actions/persist/ActionInvokeLeave.java +++ b/src/main/java/fucoin/actions/persist/ActionInvokeLeave.java @@ -1,6 +1,7 @@ package fucoin.actions.persist; import akka.actor.ActorRef; +import akka.actor.PoisonPill; import akka.actor.UntypedActorContext; import fucoin.wallet.AbstractWallet; diff --git a/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java b/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java index 5a5fc7cbe15c199502176c254a473a27ed9f4928..14daba8b02777c9a90943c92e65f585158a738c1 100644 --- a/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java +++ b/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java @@ -3,7 +3,6 @@ package fucoin.configurations; import akka.actor.ActorRef; import akka.pattern.Patterns; import fucoin.actions.control.ActionCreateSuperVisorSnapshot; -import fucoin.actions.control.ActionCreateWalletSnapshot; import fucoin.actions.statistics.ActionInterchangeState; import fucoin.actions.transaction.ActionGetAmount; import fucoin.actions.transaction.ActionGetAmountAnswer; @@ -11,9 +10,10 @@ import fucoin.configurations.internal.ConfigurationName; import scala.concurrent.Await; import scala.concurrent.Future; -import java.time.LocalTime; +import java.time.LocalDateTime; import java.util.Collections; import java.util.List; +import java.util.concurrent.ThreadLocalRandom; /** * This configuration spawns 200 wallets to demonstrate the spawning of many headless wallets @@ -25,7 +25,7 @@ public class StatisticsWalletConfiguration extends AbstractConfiguration { */ private final static int sNumberOfWallets = 10; - private int numberOfInterchangeStatistic = 20; + //private int numberOfInterchangeStatistic = 20; @Override public void run() { @@ -37,26 +37,37 @@ public class StatisticsWalletConfiguration extends AbstractConfiguration { System.out.println("Wallet spawning timed out!"); } - randomTransactions(10, 10); - + //Wait until init money was send to wallets try { - //Busy wait - while (activeActors.size() < sNumberOfWallets) { - - } - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("=========== Stats runs"); - interchangeStatistic(); - } catch (Exception e) { + Thread.sleep(1000); + } catch (InterruptedException e) { e.printStackTrace(); } + + //Send InterchangeState messages between wallets + new Thread(() -> { + System.out.println("Randomly interchange message process started."); + boolean toggle = true; + while (true) { + try { + if (toggle) { + randomTransactions(wallets().size() / 4, 10); + } else { + interchangeStatistic(wallets().size() * 4); + } + toggle = !toggle; + Thread.sleep(ThreadLocalRandom.current().nextInt(10) * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }).run(); + + //Transfer random many between wallets + } - private void interchangeStatistic() throws Exception { + private void interchangeStatistic(int numberOfInterchangeStatistic) { if (!(numberOfInterchangeStatistic > 0)) { //stop interchange statistics return; @@ -67,17 +78,20 @@ public class StatisticsWalletConfiguration extends AbstractConfiguration { ActorRef sender = wallets.get(0); ActorRef recipient = wallets.get(1); + try { + Future<Object> future = Patterns.ask(sender, new ActionGetAmount(), timeout); + ActionGetAmountAnswer answer = (ActionGetAmountAnswer) Await.result(future, timeout.duration()); + recipient.tell(new ActionInterchangeState(answer.amount), sender); + } catch (Exception e) { + e.printStackTrace(); + } - Future<Object> future = Patterns.ask(sender, new ActionGetAmount(), timeout); - ActionGetAmountAnswer answer = (ActionGetAmountAnswer) Await.result(future, timeout.duration()); - - recipient.tell(new ActionInterchangeState(answer.amount), sender); numberOfInterchangeStatistic--; if (numberOfInterchangeStatistic == 0) { createDump(); } else { - interchangeStatistic(); + interchangeStatistic(numberOfInterchangeStatistic); } } @@ -85,12 +99,7 @@ public class StatisticsWalletConfiguration extends AbstractConfiguration { * Create a Dump of the SuperVisor and all active Wallets. */ private void createDump() { - System.out.println("Create Dumps"); - LocalTime time = LocalTime.now(); - superVisor.tell(new ActionCreateSuperVisorSnapshot(time), superVisor); - for (ActorRef wallet: activeActors) { - wallet.tell(new ActionCreateWalletSnapshot(time), wallet); - } + superVisor.tell(new ActionCreateSuperVisorSnapshot(LocalDateTime.now()), self()); } @Override diff --git a/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java b/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java index f5d75e4911692e610dbe688e5cbf4d46fcf287b8..219b684fac0c60b2275b8eee1fb6478dff4b4b84 100644 --- a/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java +++ b/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java @@ -1,5 +1,6 @@ package fucoin.gui; +import akka.actor.ActorRef; import fucoin.supervisor.AmountTableModel; import fucoin.supervisor.SuperVisorImpl; @@ -10,6 +11,7 @@ import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.Map; public class SuperVisorGuiControlImpl implements SuperVisorGuiControl { private SuperVisorImpl superVisor; @@ -93,4 +95,8 @@ public class SuperVisorGuiControlImpl implements SuperVisorGuiControl { public boolean isLogActive() { return logActive; } + + public void createSnapshot() { + + } } diff --git a/src/main/java/fucoin/supervisor/SuperVisorImpl.java b/src/main/java/fucoin/supervisor/SuperVisorImpl.java index df903535e6c8ce9f45a1a948586101762984f4ae..9fb69e349a3e69a26de51fcda4aa1984f634bcba 100644 --- a/src/main/java/fucoin/supervisor/SuperVisorImpl.java +++ b/src/main/java/fucoin/supervisor/SuperVisorImpl.java @@ -1,10 +1,12 @@ package fucoin.supervisor; import akka.actor.ActorRef; +import akka.actor.PoisonPill; import akka.actor.Props; import com.google.gson.Gson; import fucoin.actions.Action; import fucoin.actions.control.ActionWalletCreationDone; +import fucoin.actions.persist.ActionInvokeLeave; import fucoin.actions.persist.ActionInvokeUpdate; import fucoin.actions.transaction.ActionGetAmountAnswer; import fucoin.actions.transaction.ActionNotifyObserver; @@ -15,6 +17,7 @@ import fucoin.gui.TransactionLogger; import fucoin.wallet.WalletStatistics; import javax.swing.*; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; import java.util.Map.Entry; @@ -73,10 +76,19 @@ public class SuperVisorImpl extends AbstractNode implements TransactionLogger { } public void exit() { + //Kill all Wallets + for(Map.Entry<String, ActorRef> wallet: getKnownNeighbors().entrySet()) { + wallet.getValue().tell(PoisonPill.getInstance(), self()); + } + //Stop supervisor getContext().stop(getSelf()); + if (gui != null) { gui.onLeave(); } + + System.exit(0); + } @Override @@ -168,30 +180,41 @@ public class SuperVisorImpl extends AbstractNode implements TransactionLogger { this.bankCommitObserver = bankCommitObserver; } - public void createDump(LocalTime time) { - Snapshot snapshot = new Snapshot(); - snapshot.amountTableModel = this.gui.getTable(); - snapshot.statistics = new WalletStatistics(); + public WalletStatistics getStatistics() { + WalletStatistics statistics = new WalletStatistics(); int sum = 0; - Vector rows = snapshot.amountTableModel.getDataVector(); + Vector rows = gui.getTable().getDataVector(); for (int i = 0; i < rows.size(); i++) { if (rows.get(i) instanceof Vector) { Vector<Object> row = (Vector<Object>) rows.get(i); int amount = (Integer) row.get(2); - snapshot.statistics.setMin(amount); - snapshot.statistics.setMax(amount); + statistics.setMin(amount); + statistics.setMax(amount); sum += amount; } } - snapshot.statistics.setSum(sum); - snapshot.statistics.setCount(rows.size()); - snapshot.statistics.setAvg(sum / rows.size()); + statistics.setSum(sum); + statistics.setCount(rows.size()); + statistics.setAvg(sum / rows.size()); + + return statistics; + } + + public void createDump(LocalDateTime time) { + Snapshot snapshot = new Snapshot(); + snapshot.amountTableModel = this.gui.getTable(); + snapshot.statistics = getStatistics(); String str = new Gson().toJson(snapshot); super.createDump("SuperVisor", str, time); } class Snapshot { + public Snapshot() { + time = LocalDateTime.now(); + } + WalletStatistics statistics; AmountTableModel amountTableModel; + LocalDateTime time; } } diff --git a/src/main/java/fucoin/wallet/AbstractWallet.java b/src/main/java/fucoin/wallet/AbstractWallet.java index ec1e0aee186574cef980f97a4850dbe6b474d949..780aa43826af1fd49d2de04108bb7b220b05740e 100644 --- a/src/main/java/fucoin/wallet/AbstractWallet.java +++ b/src/main/java/fucoin/wallet/AbstractWallet.java @@ -6,6 +6,7 @@ import fucoin.gui.TransactionLogger; import scala.concurrent.Future; import java.io.Serializable; +import java.time.LocalDateTime; import java.time.LocalTime; /** @@ -128,5 +129,5 @@ public abstract class AbstractWallet extends AbstractNode implements Serializabl */ public abstract void send(String address, int amount, ActorRef observer); - public abstract void createDump(LocalTime time); + public abstract void createDump(LocalDateTime time); } diff --git a/src/main/java/fucoin/wallet/WalletImpl.java b/src/main/java/fucoin/wallet/WalletImpl.java index 41b0a4b09b791437cfd72c98569522d19edb7f34..413cc2a1c4125562abf2e96e07c5ff9cdd61e4e3 100644 --- a/src/main/java/fucoin/wallet/WalletImpl.java +++ b/src/main/java/fucoin/wallet/WalletImpl.java @@ -18,11 +18,11 @@ import fucoin.actions.transaction.ActionInvokeSentMoney; import fucoin.gui.WalletGuiControl; import scala.concurrent.Future; -import static akka.dispatch.Futures.future; - -import java.time.LocalTime; +import java.time.LocalDateTime; import java.util.concurrent.ConcurrentLinkedQueue; +import static akka.dispatch.Futures.future; + public class WalletImpl extends AbstractWallet { private transient ActorRef preKnownNeighbour; @@ -251,7 +251,7 @@ public class WalletImpl extends AbstractWallet { } } - public void createDump(LocalTime time){ + public void createDump(LocalDateTime time) { Gson gson = new GsonBuilder() .setExclusionStrategies(new ExcludeAttributes()) //.serializeNulls() <-- uncomment to serialize NULL fields as well @@ -269,13 +269,13 @@ public class WalletImpl extends AbstractWallet { public boolean shouldSkipField(FieldAttributes f) { return !(f.getName().equals("statistics") || - f.getName().equals("min") || - f.getName().equals("max") || - f.getName().equals("sum") || - f.getName().equals("avg") || - f.getName().equals("count") || - f.getName().equals("amount") || - f.getName().equals("name")); + f.getName().equals("min") || + f.getName().equals("max") || + f.getName().equals("sum") || + f.getName().equals("avg") || + f.getName().equals("count") || + f.getName().equals("amount") || + f.getName().equals("name")); } }