\section{Introduction}
We have to make sure, that either all operational participants commit the
transaction or none of them. Each participant has one of two votes for the
possible transaction: YES or NO. For the transaction to happen all participants
have to vote YES, so a decision cannot be reversed.
The init participant acts as the coordinator and sends a 'vote request' to all
other participants. After a participant receives this request, it responds with
either YES or NO. In case of NO the decision is already 'Abort'. If all
participants vote YES, the coordinator decides 'Commit' and sends a commit
message to all participants. Otherwise it sends an abort message to all
participants that voted YES.

\includegraphics[width=1.0\textwidth]{pictures/TimelineCorrectTransfer.png}

\section{ActionInvokeSentMoney}
This action is invoked by the graphical user interface of the wallets.
The target is to transfer an amount of money to a given Walletname.
If the targetname has a allready a mapping to an ActorRef, 
an ActionInvokeDistributedCommitedTransfer will be sent to the Supervisor.
Otherwise an Gossip is invoked using the ActionSearchWalletReference,
and the same ActionInvokeSentMoney is invoked after 200ms.
\begin{lstlisting}
protected void onAction(ActorRef sender, 
						ActorRef self,
						UntypedActorContext context, 
						Wallet wallet) {
	log(wallet.getKnownNeighbors()+"");
	if(wallet.getKnownNeighbors().containsKey(name)){
		wallet.getRemoteSuperVisorActor().tell(
			new ActionInvokeDistributedCommitedTransfer(
				self,
				wallet.getKnownNeighbors().get(name),
				amount), 
			sender);
		}else{
			ActionSearchWalletReference aswr = new ActionSearchWalletReference(name);
			for(ActorRef neighbor : wallet.getKnownNeighbors().values()){
				neighbor.tell(aswr, self);
			}
			sleep(self, context, 200);
			self.tell(this, self);
		}
}

\end{lstlisting}
\section{ActionInvokeDistributedCommitedTransfer}
The ActionInvokeDistributedCommitedTransfer creates an DistributedCommitedTransferRequest,
which contains a random generated id, on the Server,
with a timout of 500ms, and store this to a map Long --> Request accoring to the id.
The Timeout is handled by the ActionUpdateQueue explained later.
The request will spread out to all clients. The clients can answer with an acknowledgement or an abort afterwards(see below).

\begin{lstlisting}
protected void onAction(ActorRef sender, 
						ActorRef self,
						UntypedActorContext context, 
						SuperVisor superVisor) {
	log("invoke transaction "+source.path().name()+
		" sends "+amount+" to "+target.path().name());
	long timeout = System.currentTimeMillis()+500;
	DistributedCommitedTransferRequest ds = 
	new DistributedCommitedTransferRequest(source,target,timeout);
	superVisor.addDistributedCommitedTransferRequest(ds);
	ActionPrepareDistributedCommitedTransfer apdct = 
	new ActionPrepareDistributedCommitedTransfer(
		source,
		target,
		amount,
		timeout,
		ds.getId());
	for(ActorRef neighbor : superVisor.getKnownNeighbors().values()){
		neighbor.tell(apdct, self);
	}
}
\end{lstlisting}
\section{ActionPrepareDistributedCommitedTransfer}
The clients will reply an request with an acknowlegment if one of two cases occurs.
The first case will appear if the Supervisor(Bank) will send a user some money.
Otherwise it would be neccessary that the sender is known by this client and have enough money.
\begin{lstlisting}
protected void onAction(ActorRef sender, 
						ActorRef self,
						UntypedActorContext context, 
						Wallet wallet) {
						//sender is supervisor(bank) has allways money
	boolean granted = sender.compareTo(source)==0	
					  //sender is unknown, might be valid
					  ||(wallet.amounts.containsKey(source) 	
					  //sender have enough money
					  &&wallet.amounts.getOrDefault(source,0)>=amount); 
	sender.tell(
		new ActionPrepareDistributedCommitedTransferAnswer(source, 
															target, 
															amount,
															timestamp,
															granted,
															id),
		self);
}
\end{lstlisting}
\section{ActionPrepareDistributedCommitedTransferAnswer}
After an answer of a client reaches the server, the server tries to find the correspong request.
If the answer was a acknowlegement, the request will get another positive answers.
When the same amount of positive answers equals the count of knownneighbors received on the server, 
all client will be informed to commit the change, and the request will be deleted.
If the answer was a Abort all client will be invoked to abort the transaction.
\begin{lstlisting}
protected void onAction(ActorRef sender, ActorRef self,
			UntypedActorContext context, SuperVisor superVisor) {
		log(""+superVisor.getKnownNeighbors());
		log("granted?"+granted);
		DistributedCommitedTransferRequest request = superVisor.getRequest(id);
		if(granted){
			if(request==null)//unknown DistributedCommitedTransferRequest ignore
				return;
			int newCount = request.addPositiveAnswer(sender);
			if(newCount == superVisor.getKnownNeighbors().size()){
				ActionCommitDistributedCommitedTransfer acdct = new ActionCommitDistributedCommitedTransfer(source,target,amount,true,timestamp,id);
				for(ActorRef neighbor : request.getAnswers()){
					neighbor.tell(acdct, self);
				}
				superVisor.deleteRequest(request);
			}
		}else{
			//A client wants to rollback
			if(request!=null){
				ActionCommitDistributedCommitedTransfer acdct = new ActionCommitDistributedCommitedTransfer(source,target,amount,false,timestamp,id); 
				for(ActorRef neighbor : request.getAnswers()){
					neighbor.tell(acdct, self);
				}
			}
		}
	}
\end{lstlisting}
\section{ActionCommitDistributedCommitedTransfer}
If a client shall commit the given changes, it will perforrm the 
changes on the amounts map. Othwise it will just print a abort
transaction message.
\begin{lstlisting}
protected void onAction(ActorRef sender, ActorRef self,
			UntypedActorContext context, Wallet wallet) {
		log("ActionCommitDistributedCommitedTransfer is granted?"+granted);
		if(granted){
			Integer sourceAmount = wallet.amounts.getOrDefault(source,0);
			Integer targetAmount = wallet.amounts.getOrDefault(target,0);
			wallet.amounts.put(source,sourceAmount-amount);
			wallet.amounts.put(target,targetAmount+amount);
			if(source.compareTo(self)==0)wallet.amount-=amount;
			else if(target.compareTo(self)==0)wallet.amount+=amount;
			wallet.log("have now "+wallet.amounts.get(self)+" Fucoins");
		}else{
			log("abort transaction with id"+id);
		}
		log("wallet.amounts:"+wallet.amounts);	
}
\end{lstlisting}
\section{ActionUpdateQueue}
the ActionUpdateQueue Event will be invoked each second on the server,
and removes all outdated request. If a request is deleted all clients,
will be informed to abort this transaction.
\begin{lstlisting}
protected void onAction(ActorRef sender, ActorRef self,
			UntypedActorContext context, SuperVisor superVisor) {
		
		List<DistributedCommitedTransferRequest> deletes = superVisor.updateList();
		
		for(DistributedCommitedTransferRequest outdatedRequest : deletes){
			ActionCommitDistributedCommitedTransfer acdct = new ActionCommitDistributedCommitedTransfer(outdatedRequest);
			for(ActorRef neighbor : superVisor.getKnownNeighbors().values()){
				neighbor.tell(acdct, self);
			}
		}
		sleep(self,context,1000);
		self.tell(this, self);
	}
\end{lstlisting}
