Skip to content
Snippets Groups Projects
Wallet.java 8.67 KiB
Newer Older
Michael Kmoch's avatar
Michael Kmoch committed
package fucoin;

Michael Kmoch's avatar
Michael Kmoch committed
import java.util.Map.Entry;
import java.util.concurrent.Semaphore;
Michael Kmoch's avatar
Michael Kmoch committed

import akka.actor.ActorRef;
import akka.actor.Props;
Michael Kmoch's avatar
Michael Kmoch committed
import fucoin.actions.ActionGetAmount;
import fucoin.actions.ActionGetAmountAnswer;
import fucoin.actions.ActionInvokeLeave;
import fucoin.actions.ActionInvokeRevive;
import fucoin.actions.ActionInvokeSentMoney;
import fucoin.actions.ActionInvokeSentMoney2;
import fucoin.gui.IWalletControle;
import fucoin.gui.IWalletGuiControle;
Michael Kmoch's avatar
Michael Kmoch committed
public class Wallet extends AbstractWallet implements IWalletControle{
Michael Kmoch's avatar
Michael Kmoch committed
	private ActorRef preknownNeighbour;
	private ActorRef remoteSuperVisorActor;
	private IWalletGuiControle gui;
	private String preknownNeighbourName;
	private boolean isActive;
Michael Kmoch's avatar
Michael Kmoch committed
	public Wallet(ActorRef preknownNeighbour, String preknownNeighbourName, String walletName, ActorRef remoteSuperVisorActor) {
		super(walletName);
		this.preknownNeighbourName=preknownNeighbourName;
		this.preknownNeighbour=preknownNeighbour;
		this.remoteSuperVisorActor=remoteSuperVisorActor;
Michael Kmoch's avatar
Michael Kmoch committed
	}
Michael Kmoch's avatar
Michael Kmoch committed
	@Override
Michael Kmoch's avatar
Michael Kmoch committed
	public String getAddress() {
		return getAddress(getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
	private String getAddress(ActorRef self) {
		return self.path().toSerializationFormatWithAddress(self.path().address());
Michael Kmoch's avatar
Michael Kmoch committed
	public void send(String name, int amount){
		//System.out.println("search wallet"+name+" in "+knownNeighbors.keySet());
		if(knownNeighbors.containsKey(name)){
			addAmount(-amount);
			knownNeighbors.get(name).tell(new ActionReceiveTransaction(amount), getSelf());
		}else{
			for(ActorRef neighbor : knownNeighbors.values()){
				neighbor.tell(new ActionSearchWalletReference(name,System.currentTimeMillis()+10), getSelf());
			}
			
			try {
				getContext().unwatch(getSelf());
				Thread.sleep(200);
				getContext().watch(getSelf());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//getContext().unwatch(getSelf());
			getSelf().tell(new ActionInvokeSentMoney(name, amount), getSelf());
			
		}
	
Michael Kmoch's avatar
Michael Kmoch committed
	}
Michael Kmoch's avatar
Michael Kmoch committed
	private void addAmount(int amount) {
		setAmount(this.amount+amount);
		log(" My amount is now "+this.amount);
		if(gui!=null){
			gui.setAmount(this.amount);
		}
Michael Kmoch's avatar
Michael Kmoch committed
	}
Michael Kmoch's avatar
Michael Kmoch committed
	@Override
Michael Kmoch's avatar
Michael Kmoch committed
	public void leave() {
		for(ActorRef neighbor : knownNeighbors.values()){
			if(getSelf().compareTo(neighbor)!=0){
				neighbor.tell(new ActionStoreOrUpdate(this), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
		remoteSuperVisorActor.tell(new ActionStoreOrUpdate(this), getSelf());
		isActive=false;
		backedUpNeighbors.clear();
		knownNeighbors.clear();
		knownNeighbors.put(preknownNeighbourName,preknownNeighbour);
Michael Kmoch's avatar
Michael Kmoch committed
	}
Michael Kmoch's avatar
Michael Kmoch committed
	@Override
Michael Kmoch's avatar
Michael Kmoch committed
	public void onReceive(Object message) {
		log(getSender().path().name()+" invokes "+getSelf().path().name()+" to do "+message.getClass().getSimpleName());
		if(message instanceof ActionInvokeRevive){
			isActive=true;
Michael Kmoch's avatar
Michael Kmoch committed
			preknownNeighbour.tell(new ActionJoin(), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
		}
		if(!isActive)return;
		//System.out.println(message);
		if(message instanceof ActionJoin){
			ActionJoinAnswer aja = new ActionJoinAnswer();
			aja.someNeighbors.putAll(knownNeighbors);
			getSender().tell(aja, getSelf());
		}else if(message instanceof ActionJoinAnswer){
			ActionJoinAnswer aja = (ActionJoinAnswer) message;
			for(Entry<String, ActorRef> neighbor : knownNeighbors.entrySet()){
				addKnownNeighbor(neighbor.getKey(),neighbor.getValue());
				neighbor.getValue().tell(new ActionSearchMyWallet(name), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(message instanceof ActionSearchMyWallet){
			ActionSearchMyWallet asmw = (ActionSearchMyWallet) message;
			//If I know that somebody is searching himself, 
			//I can store him under the searched wallet name
			addKnownNeighbor(asmw.name, getSender());
Michael Kmoch's avatar
Michael Kmoch committed
			AbstractWallet storedWallet = backedUpNeighbors.get(asmw.name);
			log(" "+knownNeighbors);
			if(storedWallet!=null){
				getSender().tell(new ActionSearchMyWalletAnswer(storedWallet), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
			}
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(message instanceof ActionSearchMyWalletAnswer){
			ActionSearchMyWalletAnswer asmwa = (ActionSearchMyWalletAnswer) message;
			setAmount(asmwa.w.amount);
			getSender().tell(new ActionInvalidate(name), getSelf());
		}else if(message instanceof ActionInvalidate){
			ActionInvalidate ai = (ActionInvalidate) message;
			backedUpNeighbors.remove(ai.name);
		}else if(message instanceof ActionSearchWalletReference){
			ActionSearchWalletReference aswr = (ActionSearchWalletReference) message;
			System.out.println("I search for you"+aswr.name);
			if(this.name.equals(aswr.name)){
				getSender().tell(new ActionSearchWalletReferenceAnswer(aswr.name,getAddress()),getSelf());
			}else if(backedUpNeighbors.containsKey(aswr.name)){
				getSender().tell(new ActionSearchWalletReferenceAnswer(aswr.name,backedUpNeighbors.get(aswr.name).getAddress()),getSelf());
			} else if(knownNeighbors.containsKey(aswr.name)){
				getSender().tell(new ActionSearchWalletReferenceAnswer(aswr.name,getAddress(knownNeighbors.get(aswr.name))),getSelf());
			} else if (System.currentTimeMillis()<aswr.ttl){
				//for(ActorRef actor : knownNeighbors.values()){
				//	actor.tell(aswr,getSelf());
				//}
				//Because Sender is maybe unknown
				//getSender().tell(aswr, getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
			}
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(message instanceof ActionSearchWalletReferenceAnswer){
			ActionSearchWalletReferenceAnswer aswra = (ActionSearchWalletReferenceAnswer) message;
			ActorRef target = getContext().actorSelection(aswra.address).anchor();
			addKnownNeighbor(aswra.name,target);
		}else if(message instanceof ActionInvokeSentMoney){
			ActionInvokeSentMoney aism = (ActionInvokeSentMoney) message;
			
			send(aism.name, aism.amount);
		}else if(message instanceof ActionInvokeSentMoney2){
			if(knownNeighbors.containsKey(name)){
				addAmount(-amount);
				knownNeighbors.get(name).tell(new ActionReceiveTransaction(amount), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
			}
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(message instanceof ActionReceiveTransaction){
			ActionReceiveTransaction art = (ActionReceiveTransaction) message;
			System.out.println(message.getClass().getSimpleName()+" "+art.amount);
			addAmount(art.amount);
		}else if(message instanceof ActionStoreOrUpdate){
			ActionStoreOrUpdate asou = (ActionStoreOrUpdate) message;
			backedUpNeighbors.put(asou.w.name, asou.w);
		}else if(message instanceof ActionGetAmount){
			ActionGetAmountAnswer agaa = new ActionGetAmountAnswer(getAddress(),getName(),amount);
			getSender().tell(agaa, getSelf());
		}else if(message instanceof ActionInvokeLeave){
			leave();
		}else if(message instanceof ActionInvokeRevive){
			
		}else{
			unhandled(message);
			System.err.println("Unexpected Error: "+message+" not handeld");
		}
	}
	
	private void addKnownNeighbor(String key, ActorRef value) {
		if(!knownNeighbors.containsKey(key)){
			System.out.println(knownNeighbors.keySet()+" does not contain "+key);
			knownNeighbors.put(key,value);
			if(gui!=null){
				gui.addKnownAddress(key);
Michael Kmoch's avatar
Michael Kmoch committed
			}
Michael Kmoch's avatar
Michael Kmoch committed
			System.out.println(key+"-->"+value);
Michael Kmoch's avatar
Michael Kmoch committed
	private void log(String string) {
		System.out.println(getSelf()+": "+string);
Michael Kmoch's avatar
Michael Kmoch committed
	@Override
	public void preStart() throws Exception {
Michael Kmoch's avatar
Michael Kmoch committed
		isActive=true;
		if(gui!=null){
			gui.setAddress(getAddress());
		}
		String path = "akka.tcp://Core@127.0.0.1:1234/user/Main";
		System.out.println(getContext().provider().getExternalAddressFor(getSelf().path().address()));
		//log("my address should be "+getAddress());
		//log(""+preknownNeighbour);
		//knownNeighbors.put(getName(),getSelf());
		
		System.out.println(knownNeighbors);
Michael Kmoch's avatar
Michael Kmoch committed
		if(preknownNeighbour!=null){
Michael Kmoch's avatar
Michael Kmoch committed
			knownNeighbors.put(preknownNeighbourName,preknownNeighbour);
			preknownNeighbour.tell(new ActionJoin(), getSelf());
			ActionJoinAnswer aja = new ActionJoinAnswer();
			aja.someNeighbors.putAll(knownNeighbors);
			preknownNeighbour.tell(aja, getSelf());
			
Michael Kmoch's avatar
Michael Kmoch committed
		}
Michael Kmoch's avatar
Michael Kmoch committed
		setAmount(100);
		remoteSuperVisorActor.tell(new ActionJoin(), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
	@Override
	public void postStop() throws Exception {
		leave();
		super.postStop();
Michael Kmoch's avatar
Michael Kmoch committed
	public static Props props(ActorRef preknownNeighbour, String preknownNeighbourName, String walletName, ActorRef remoteSuperVisorActor) {
		return Props.create(Wallet.class,new WalletCreator(preknownNeighbour,preknownNeighbourName,walletName,remoteSuperVisorActor));
Michael Kmoch's avatar
Michael Kmoch committed
	}
	
	@Override
Michael Kmoch's avatar
Michael Kmoch committed
	public boolean equals(Object obj) {
		if(obj instanceof Wallet){
			Wallet wobj = (Wallet) obj;
			return amount==wobj.amount&&name.equals(wobj.name);
		}
		return false;
Michael Kmoch's avatar
Michael Kmoch committed
	}

	public void setGui(IWalletGuiControle gui) {
		this.gui=gui;
	}
Michael Kmoch's avatar
Michael Kmoch committed
	
	Semaphore mutex = new Semaphore(1);
	public void setAmount(int amount){
		try {
			mutex.acquire();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.amount = amount;
		if(remoteSuperVisorActor != null){
			remoteSuperVisorActor.tell(new ActionGetAmountAnswer(getAddress(), getName(), amount), getSelf());
		}
		if(gui!=null){
			gui.setAmount(this.amount);
		}
		mutex.release();
	}