/// <summary> /// Callback function for the phase 1 of the take operation. /// </summary> /// <param name="result">Async calback result.</param> public void Take1Callback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); //Console.WriteLine("take1" + response); if (!ValidView(response)) { return; } // Stores the list of matching tuples // and the RequestID of the server that answered if (response.Code.Equals("OK")) { // Tuples have to be added before the acks are incremented lock (MatchingTuples) { MatchingTuples.Add(new List <ITuple>(response.Tuples)); Interlocked.Increment(ref AcksCounter); } if (verbose) { Console.WriteLine("Response:"); Console.WriteLine(response); } } }
/// <summary> /// Adds a tuple to the distributed tuple space. /// </summary> /// <param name="tuple">Tuple to be added.</param> public void Add(ITuple tuple) { if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return; } // Create request message TSpaceMsg message = new TSpaceMsg(); message.Code = "add"; message.Tuple = tuple; message.RequestID = ClientID + "_" + (++SequenceNumber); message.MsgView = GetCurrentView(); //Clear acks AcksCounter = 0; // Create local callback AsyncCallback remoteCallback = new AsyncCallback(AddCallback); // Repeat request until all replicas have acknowledged receipt while (AcksCounter < View.Count) { //Send multicast message to all members of the view this.Multicast(message, remoteCallback); } Console.WriteLine("Add " + (++AddCounter) + ": OK"); }
private void ReadCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (!ValidView(response)) { return; } // Stores the tuple returned // and the OperationID of the server that answered if (response.Code.Equals("OK")) { if (response.Tuple != null) { lock (LockRef) { Tuple = response.Tuple; } if (verbose) { Console.WriteLine("Response:"); Console.WriteLine(response); } } Interlocked.Increment(ref AcksCounter); } }
/**************************************************************** * CALLBACK FUNCTIONS ****************************************************************/ private void PropesedSeqCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (!ValidView(response)) { return; } if (response.Code.Equals("proposedSeq")) { //Console.WriteLine("Proposed Seq"); lock (ProposedSeq) { // Store porposed sequence number ProposedSeq.Add(response.SequenceNumber); Interlocked.Increment(ref AcksCounter); } } }
/// <summary> /// Makes an async remote invocation of TSpaceServer.ProcessRequest /// </summary> /// <param name="message">Argument of the ProcessRequest method.</param> /// <param name="asyncCallback">Callback function of the remote call.</param> private void Multicast(TSpaceMsg message, AsyncCallback asyncCallback) { if (CheckNeedUpdateView()) { Console.WriteLine("Update to " + GetCurrentView()); message.MsgView = GetCurrentView(); } //Console.WriteLine("Sending " + message.Code + " in view " + message.MsgView); RemoteAsyncDelegate remoteDel; foreach (ITSpaceServer server in View) { // Create delegate for remote method remoteDel = new RemoteAsyncDelegate(server.ProcessRequest); try { // Call remote method remoteDel.BeginInvoke(message, asyncCallback, null); }catch (Exception e) { Console.WriteLine("Failed to send"); } } }
/// <summary> /// Adds a tuple to the distributed tuple space. /// </summary> /// <param name="tuple">Tuple to be added.</param> public void Add(ITuple tuple) { if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return; } // Create message TSpaceMsg request = new TSpaceMsg(); request.Code = "add"; request.Tuple = tuple; // Create unique message identifier request.OperationID = ClientID + "_" + (OperationCounter++); // Get the sequence number of the request in the view request.SequenceNumber = GetSequenceNumber(request.OperationID); request.RequestID = ClientID + "_" + (RequestCounter++); request.MsgView = GetCurrentView(); AsyncCallback remoteCallback = new AsyncCallback(AcksCallback); // Clear acks count AcksCounter = 0; // Repeat until all replicas have acknowledged receipt while (AcksCounter < View.Count) { // Send request to all replicas in the view this.Multicast(request, remoteCallback); } Console.WriteLine("Add " + (++AddCounter) + ": OK"); }
/// <summary> /// Callback function for the read operation. /// </summary> /// <param name="result">Async callback result.</param> public void ReadCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (!ValidView(response)) { return; } // Stores the tuple returned // and the RequestID of the server that answered if (response.Code.Equals("OK")) { lock (LockRef) { if (response.Tuple != null) { Tuple = response.Tuple; } } IncrementAcksCounter(response.RequestID); } }
public TSpaceMsg ProcessRequest(TSpaceMsg msg) { TSpaceMsg response; //Console.WriteLine("started processing"); //Console.WriteLine(msg); TSMan.Processing(); response = SMRProcessRequest(msg); lock (TSpaceManager.ProcessedRequests) { if (response.Code != "Repeated" && response.Code != "badView" && TSpaceManager.ProcessedRequests.Contains(msg.RequestID)) { TSpaceManager.ProcessedRequests.UpdateResponse(msg.RequestID, response); //Console.WriteLine("SAVED THIS TRASH: " + response.ToString()); } } TSMan.FinishedProcessing(); //Console.WriteLine("finished processing"); //Console.WriteLine("RESPONSE:" + response); return(response); }
/// <summary> /// Makes an async remote invocation of TSpaceServer.ProcessRequest /// </summary> /// <param name="message">Argument of the ProcessRequest method.</param> /// <param name="asyncCallback">Callback function of the remote call.</param> private void Multicast(TSpaceMsg message, AsyncCallback asyncCallback) { //Never happens in this implementation if (message.Code.Equals("badView") && message.MsgView.ID > TSMan.ServerView.ID) { AcksCounter = 0; } List <ITSpaceServer> servers = TSMan.ServerView.GetProxys(TSMan.URL); RemoteAsyncDelegate remoteDel; foreach (ITSpaceServer server in servers) { // Create delegate for remote method remoteDel = new RemoteAsyncDelegate(server.ProcessRequest); try { // Call remote method remoteDel.BeginInvoke(message, asyncCallback, null); } catch (Exception) { Console.WriteLine("Failed to send"); } } }
/// <summary> /// Returns a tuple from the distributed tuple space, deleting it. /// </summary> /// <param name="template">Template of the requested tuple.</param> /// <returns></returns> public ITuple Take(ITuple template) { if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return(null); } /*------------------------------------------------ * Phase 1: Selecting the tuple to be removed * ------------------------------------------------*/ ITuple selectedTuple = null; // Repeat phase 1 until all replicas return at least // one common matching tuple while (selectedTuple == null) { Console.WriteLine("Take 1: " + SequenceNumber); selectedTuple = this.Take1(template); } Console.WriteLine("Take: Phase 1 completed"); /*------------------------------------------------ * Phase 2: Removing the selected tuple * ------------------------------------------------*/ TSpaceMsg message = new TSpaceMsg(); message.Code = "take2"; message.Tuple = selectedTuple; message.ProcessID = ClientID.ToString(); message.RequestID = ClientID + "_" + (++SequenceNumber); message.MsgView = GetCurrentView(); // Create local callback. AsyncCallback remoteCallback = new AsyncCallback(AddCallback); //Clear acks ActiveOperations.Add(message.RequestID); AcksCounter = 0; //Repeat until all replicas have acknowledged deletion while (AcksCounter < Quorum()) { // Send multicast request to remove tuples to all members of the view this.Multicast(message, remoteCallback); } ActiveOperations.Remove(message.RequestID); Console.WriteLine("Take: Phase 2 completed"); Console.WriteLine("Take " + (++TakeCounter) + ": OK"); return(message.Tuple); }
public void UpdateResponse(String id, TSpaceMsg response) { foreach (LogEntry entry in Log) { if (entry.Request.RequestID == id) { entry.Response = response; } } }
public bool ValidView(TSpaceMsg msg) { lock (ServerView) { if (msg.MsgView == null) { Console.WriteLine("NO VIEW SENT WITH MSG"); } return(msg.MsgView.ID == ServerView.ID); } }
public TSpaceMsg CreateBadViewReply(TSpaceMsg msg) { TSpaceMsg response = new TSpaceMsg { Code = "badView", ProcessID = URL, OperationID = msg.OperationID, RequestID = msg.RequestID, MsgView = GetTotalView() }; return(response); }
private static void AddMessageToQueue(TSpaceMsg msg) { lock (MessageQueue) { Message newMessage = new Message(); newMessage.ProcessID = msg.ProcessID; newMessage.SequenceNumber = SequenceNumber; newMessage.Deliverable = false; newMessage.MessageID = msg.OperationID; // Add message to queue MessageQueue.Add(newMessage); MessageQueue.Sort(); } }
/*********************************************************** * CALLBACK FUNCTIONS ***********************************************************/ /// <summary> /// Callback function for the acknowledgements. /// </summary> /// <param name="result">Async callback result.</param> public void AddCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (!ValidView(response)) { return; } if (response.Code.Equals("ACK")) { IncrementAcksCounter(response.RequestID); } }
/// <summary> /// Callback function for the acknowledgements. /// </summary> /// <param name="result">Async call result.</param> private void AcksCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (!ValidView(response)) { return; } if (response.Code.Equals("ACK")) { Interlocked.Increment(ref AcksCounter); } }
/**************************************************************** * AUX FUNCTIONS / CLASSES ****************************************************************/ /// <summary> /// Determines the agreed sequence number of a message /// </summary> /// <param name="id">Message OperationID</param> /// <returns>Agreed sequence number</returns> private int GetSequenceNumber(string id) { //Console.WriteLine("Message " + id + " : request proposed sequence number"); // Create request message TSpaceMsg message = new TSpaceMsg(); message.Code = "proposeSeq"; message.OperationID = id; message.ProcessID = ClientID.ToString(); message.RequestID = ClientID + "_" + (RequestCounter++); ActiveOperations.Add(message.RequestID); message.SequenceNumber = -1; message.MsgView = GetCurrentView(); // Create local callback AsyncCallback asyncCallback = new AsyncCallback(PropesedSeqCallback); // Clear proposed sequence number for previous messages lock (ProposedSeq) { AcksCounter = 0; ProposedSeq.Clear(); } // Send message to all replicas until all have proposed a sequence number while (AcksCounter < Quorum()) { this.Multicast(message, asyncCallback); } int agreedSeq; lock (ProposedSeq) { // Agreed sequence number = highest proposed sequence number agreedSeq = ProposedSeq.Max(); } Console.WriteLine("Message " + message.OperationID + " (agreedSeq = " + agreedSeq + ")"); // Remove operation from active operations ActiveOperations.Remove(message.RequestID); return(agreedSeq); }
public void Add(TSpaceMsg request) { LogEntry entry = new LogEntry { Request = request }; if (!request.Code.Equals("proposeSeq")) { entry.Agreed = true; } else { entry.Agreed = false; } Log.Add(entry); }
public TSpaceMsg ProcessRequest(TSpaceMsg msg) { TSpaceMsg response; TSMan.Processing(); response = XLProcessRequest(msg); lock (TSpaceManager.ProcessedRequests) { if (response.Code != "Repeated" && response.Code != "badView" && TSpaceManager.ProcessedRequests.Contains(msg.RequestID)) { TSpaceManager.ProcessedRequests.UpdateResponse(msg.RequestID, response); } } TSMan.FinishedProcessing(); return response; }
/// <summary> /// Process a request /// </summary> /// <param name="msg"></param> /// <returns></returns> public TSpaceMsg ProcessRequest(TSpaceMsg msg) { TSpaceMsg response; //Acquires writers/readers lock TSMan.Processing(); response = SMRProcessRequest(msg); lock (TSpaceAdvManager.ProcessedRequests) { if (response.Code != "Repeated" && response.Code != "badView" && TSpaceAdvManager.ProcessedRequests.Contains(msg.RequestID)) { TSpaceAdvManager.ProcessedRequests.UpdateResponse(msg.RequestID, response); } } //Releases writers/readers lock TSMan.FinishedProcessing(); return(response); }
public bool ValidView(TSpaceMsg msg) { lock (ServerView){ if (msg.MsgView == null) { return(false); } if (msg.Code.Equals("badView") && msg.MsgView.ID > ServerView.ID) { InvalidView = true; SuggestView(msg.MsgView); return(false); } if (msg.MsgView.ID < ServerView.ID) { return(false); } } return(true); }
private void PropesedSeqCallback(IAsyncResult result) { RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)result).AsyncDelegate; // Retrieve results. TSpaceMsg response = del.EndInvoke(result); if (response == null || (response.Code.Equals("badView") && response.MsgView.ID > TSMan.ServerView.ID)) { return; } if (response.Code.Equals("proposedSeq")) { lock (ProposedSeq) { // Store porposed sequence number ProposedSeq.Add(response.SequenceNumber); Interlocked.Increment(ref AcksCounter); } } }
/// <summary> /// Returns a tuple from the distributed tuple space, deleting it. /// </summary> /// <param name="template">Template of the tuple requested</param> /// <returns>Tuple matching the template</returns> public ITuple Take(ITuple template) { if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return(null); } // Create message TSpaceMsg request = new TSpaceMsg(); request.Code = "take1"; request.Tuple = template; // Create remote callback AsyncCallback remoteCallback = new AsyncCallback(ReadCallback); // Clear response from last request lock (LockRef) { Tuple = null; } // Repeat until one matching tuple is found while (true) { // Create unique message identifier request.OperationID = ClientID + "_" + (OperationCounter++); // Get the sequence number of the request in the view request.SequenceNumber = this.GetSequenceNumber(request.OperationID); // Create unique identifier for the round request.RequestID = ClientID + "_" + (RequestCounter++); request.MsgView = GetCurrentView(); //Clear acks from last request AcksCounter = 0; // Repeat untill all replicas have answered while (AcksCounter < View.Count) { // Send take request to all members of the view this.Multicast(request, remoteCallback); } // Return if there is a match // Repeat otherwise lock (LockRef) { if (Tuple != null) { break; } } } Console.WriteLine("Take " + (++TakeCounter) + ": OK"); return(Tuple); }
/// <summary> /// Determines the agreed sequence number of a message /// </summary> /// <param name="id">Message OperationID</param> /// <returns>Agreed sequence number</returns> private int GetSequenceNumber(string id, string suspectDead) { Monitor.Enter(SequenceNumberLock); //Console.WriteLine("Message " + id + " : request proposed sequence number"); // Create request message TSpaceMsg message = new TSpaceMsg(); message.Code = "proposeSeq"; message.OperationID = id; // Replace ID with server url message.ProcessID = TSMan.URL; message.RequestID = message.ProcessID + "_" + (RequestCounter++); message.SequenceNumber = -1; message.SuspectedDead = suspectDead; // Create local callback AsyncCallback asyncCallback = new AsyncCallback(PropesedSeqCallback); // Clear proposed sequence number for previous messages lock (ProposedSeq) { AcksCounter = 1; ProposedSeq.Clear(); // Add my proposal lock (MessageQueue) { Interlocked.Increment(ref SequenceNumber); } ProposedSeq.Add(SequenceNumber); AddMessageToQueue(message); } // Send message to all replicas until all have proposed a sequence number while (AcksCounter < TSMan.Quorum(TSMan.ServerView.Count)) { if (message.MsgView != TSMan.ServerView) { AcksCounter = 1; ProposedSeq.Clear(); ProposedSeq.Add(SequenceNumber); message.MsgView = TSMan.ServerView; } this.Multicast(message, asyncCallback); } int agreedSeq; lock (ProposedSeq) { // Agreed sequence number = highest proposed sequence number agreedSeq = ProposedSeq.Max(); } Console.WriteLine("Message " + message.OperationID + " (agreedSeq = " + agreedSeq + ")"); Monitor.Exit(SequenceNumberLock); //UpdateMessage(id, agreedSeq); return(agreedSeq); }
public TSpaceMsg SMRProcessRequest(TSpaceMsg msg) { TSMan.CheckFreeze(); TSMan.CheckDelay(); lock (AggredOperations) { if (msg.Code != "proposeSeq") { AggredOperations[msg.OperationID] = msg.SequenceNumber; } else { //Console.WriteLine("Not Agreed: " + msg.OperationID); } } TSpaceMsg response = new TSpaceMsg { ProcessID = TSMan.URL, OperationID = msg.OperationID, RequestID = msg.RequestID, MsgView = TSMan.GetTotalView() }; // Verifying View! Wrong view sends updated view if (!TSMan.ValidView(msg)) { Console.WriteLine("Wrong View ( s = " + TSMan.ServerView.ID + "; c = " + msg.MsgView.ID + " )"); return(TSMan.CreateBadViewReply(msg)); } lock (TSpaceAdvManager.ProcessedRequests) { // Check if request as already been processed if (TSpaceAdvManager.ProcessedRequests.Contains(msg.RequestID)) { // Check if it was processed in a previous viwew if (TSpaceAdvManager.ProcessedRequests.GetByKey(msg.RequestID).Request.MsgView.ID < TSMan.ServerView.ID) { //Console.WriteLine(TSMan.ServerView.ID); TSpaceAdvManager.ProcessedRequests.UpdateView(msg.RequestID, TSMan.ServerView); TSpaceMsg resp = TSpaceAdvManager.ProcessedRequests.GetByKey(msg.RequestID).Response; if (resp == null) { Console.WriteLine("NULL RESPONSE SAVED"); return(null); } return(resp); } else { response.Code = "Repeated"; return(response); } } Console.WriteLine("Starting processing of request " + msg.RequestID); // Add sequence number of request to processed requests TSpaceAdvManager.ProcessedRequests.Add(msg); } string command = msg.Code; Message update = null; // Sequence number proposal request if (command.Equals("proposeSeq")) { lock (AggredOperations) { //Already was executed corresponsing operation if (AggredOperations.ContainsKey(msg.OperationID)) { response.Code = "proposedSeq"; response.SequenceNumber = AggredOperations[msg.OperationID]; return(response); } lock (MessageQueue) { // Increment sequence number Interlocked.Increment(ref SequenceNumber); } response.SequenceNumber = SequenceNumber; response.Code = "proposedSeq"; AddMessageToQueue(msg); } Console.WriteLine("Proposing (id = " + msg.OperationID + "; seq = " + response.SequenceNumber + ")"); return(response); } // Message with agreed sequence number else { //Update message queue with agreed seq number update = UpdateMessage(msg.OperationID, msg.SequenceNumber); if (update == null) { Console.WriteLine("Err: operation message not in queue"); //response.Code = "Err"; } } //Wait for the message head of queue Monitor.Enter(MessageQueue); while (MessageQueue.Count == 0 || !MessageQueue[0].MessageID.Equals(msg.OperationID)) { TSMan.FinishedProcessing(); Monitor.Wait(MessageQueue, 500); TSMan.Processing(); } Monitor.Exit(MessageQueue); Console.WriteLine("Execute operation " + msg.OperationID + ": code = " + command); // Execute the operation if (TSMan.Verbose) { Console.WriteLine(msg); } switch (command) { case "add": lock (TakeLock) { if (msg.Tuple == null) { response.Code = "ERR"; break; } TSMan.TSpace.Add(msg.Tuple); response.Code = "ACK"; break; } case "read": if (msg.Tuple == null) { response.Code = "ERR"; break; } response.Tuple = TSMan.TSpace.Read(msg.Tuple); response.Code = "OK"; if (response.Tuple == null) { Console.WriteLine("Match not Found"); } break; case "take1": lock (TakeLock) { if (msg.Tuple == null) { response.Code = "ERR"; break; } // Get matching tuple response.Tuple = TSMan.TSpace.Read(msg.Tuple); response.Code = "OK"; if (response.Tuple != null) { // Delete it TSMan.TSpace.Take2(response.Tuple); } } response.Code = "OK"; break; case "take2": Console.WriteLine("Current Tuple Space not in XL mode"); response.Code = "ERR"; break; // Operation exclusive of the XL Tuple Space case "releaseLocks": lock (TakeLock) response.Code = "ERR"; Console.WriteLine("Current Tuple Space not in XL mode"); break; default: Console.WriteLine("Invalid command."); break; } RemoveFromQueue(msg.OperationID); return(response); }
public TSpaceMsg XLProcessRequest(TSpaceMsg msg) { TSMan.CheckFreeze(); TSMan.CheckDelay(); TSpaceMsg response = new TSpaceMsg { ProcessID = TSMan.URL, RequestID = msg.RequestID, MsgView = TSMan.GetTotalView() }; // Verifying View! Wrong view sends updated view if (!TSMan.ValidView(msg)) { //Console.WriteLine("client:" + msg.MsgView.ToString() + "server:" +TSMan.GetTotalView().ToString()); Console.WriteLine("Wrong View ( s = " + TSMan.ServerView + "; c = " + msg.MsgView + " )"); return TSMan.CreateBadViewReply(msg); } if (TSMan.Verbose) Console.WriteLine(msg); lock (TSpaceManager.ProcessedRequests) { // Check if request as already been processed if (TSpaceManager.ProcessedRequests.Contains(msg.RequestID)) { LogEntry Temp = TSpaceManager.ProcessedRequests.GetByKey(msg.RequestID); // Check if it was processed in a previous viwew if (Temp.Request.MsgView.ID < TSMan.ServerView.ID || (Temp.Response != null && Temp.Response.ProcessID != TSMan.URL)) { //Console.WriteLine("Processed in previous view"); TSpaceMsg resp = TSpaceManager.ProcessedRequests.GetByKey(msg.RequestID).Response; if (resp == null) { Console.WriteLine("NULL RESPONSE SAVED"); return null; } resp.MsgView = TSMan.ServerView; TSpaceManager.ProcessedRequests.UpdateView(msg.RequestID, TSMan.ServerView); TSpaceManager.ProcessedRequests.UpdateResponse(msg.RequestID, resp); //Console.WriteLine(resp); return resp; } else { //Console.WriteLine("repeated"); response.Code = "Repeated"; return response; } } //Console.WriteLine("Starting processing of request " + msg.RequestID); // Add sequence number of request to processed requests TSpaceManager.ProcessedRequests.Add(msg); } string command = msg.Code; switch (command) { case "add": TSMan.TSpace.Add(msg.Tuple); response.Code = "ACK"; break; case "read": response.Tuple = TSMan.TSpace.Read(msg.Tuple); response.Code = "OK"; break; case "take1": lock (TSLockHandler.Lock) { // find suitable matches for tuple List<ITuple> matches = TSMan.TSpace.Take1(msg.Tuple); // Locks all unlocked and matchable tuples for UserID response.Tuples = TSLockHandler.LockTuples(msg.ProcessID, matches); } response.Code = "OK"; break; case "take2": lock (TSLockHandler.Lock) { // Deletes tuple TSMan.TSpace.Take2(msg.Tuple); // Unlocks all tuples previously locked under UserID TSLockHandler.UnlockTuples(msg.ProcessID); } response.Code = "ACK"; break; // Operation exclusive of the XL Tuple Space case "releaseLocks": try { TSLockHandler.UnlockTuples(msg.ProcessID); response.Code = "ACK"; } catch (InvalidCastException) { Console.WriteLine("Current Tuple Space not in XL mode"); response.Code = "ERR"; } break; default: Console.WriteLine("Invalid command."); break; } return response; }
/// <summary> /// Returns a tuple from the distributed tuple space, whithout deleting it. /// </summary> /// <param name="template">Template of the requested tuple.</param> /// <returns></returns> public ITuple Read(ITuple template) { Console.WriteLine("Read started"); if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return(null); } // Create message TSpaceMsg request = new TSpaceMsg(); request.Code = "read"; request.Tuple = template; AsyncCallback remoteCallback = new AsyncCallback(ReadCallback); // Clear responses to previous request // Clear previous answers lock (LockRef) { Tuple = null; } bool matchFound = false; while (!matchFound) { // Create unique id of the request request.RequestID = ClientID + "_" + (RequestCounter++); // Create unique message identifier request.OperationID = ClientID + "_" + (OperationCounter++); // Get the sequence number of the request in the view request.SequenceNumber = this.GetSequenceNumber(request.OperationID); request.MsgView = GetCurrentView(); AcksCounter = 0; // Waits until one replica returns a tuple or // all replicas answered that they dont have a match while (AcksCounter < View.Count) { // Send multicast request to all members of the view this.Multicast(request, remoteCallback); lock (LockRef) { if (Tuple != null) { matchFound = true; break; } } } lock (LockRef) { if (Tuple != null) { matchFound = true; } } } Console.WriteLine("Read " + (++ReadCounter) + ": OK"); // Return after the first replica answers return(Tuple); }
/// <summary> /// Returns a tuple from the distributed tuple space, whithout deleting it. /// </summary> /// <param name="template">Template of the requested tuple.</param> /// <returns></returns> public ITuple Read(ITuple template) { if (View.Count == 0) { Console.WriteLine("No tuple space servers available."); return(null); } // Create request message. TSpaceMsg message = new TSpaceMsg(); message.Code = "read"; message.Tuple = template; message.MsgView = GetCurrentView(); // Create local callback. AsyncCallback remoteCallback = new AsyncCallback(ReadCallback); // Clear previous answers lock (LockRef) { Tuple = null; } bool matchFound = false; while (!matchFound) { message.RequestID = ClientID + "_" + (++SequenceNumber); AcksCounter = 0; // Waits until one replica returns a tuple or // all replicas answered that they dont have a match while (AcksCounter < View.Count) { // Send multicast message to all members of the view. this.Multicast(message, remoteCallback); // Return after first response lock (LockRef) { if (Tuple != null) { matchFound = true; break; } } } lock (LockRef) { if (Tuple != null) { matchFound = true; } } } // Return first response. Console.WriteLine("Read " + (++ReadCounter) + ": OK"); return(Tuple); }
public TSpaceMsg SMRProcessRequest(TSpaceMsg msg) { TSMan.CheckFreeze(); TSMan.CheckDelay(); TSpaceMsg response = new TSpaceMsg { ProcessID = TSMan.URL, OperationID = msg.OperationID, RequestID = msg.RequestID, MsgView = TSMan.GetTotalView() }; //Console.WriteLine("client:" + msg.MsgView.ToString() + "server:" +TSMan.GetTotalView().ToString()); // Verifying View! Wrong view sends updated view if (!TSMan.ValidView(msg)) { //Console.WriteLine("client:" + msg.MsgView.ToString() + "server:" +TSMan.GetTotalView().ToString()); Console.WriteLine("Wrong View ( s = " + TSMan.ServerView + "; c = " + msg.MsgView + " )"); return(TSMan.CreateBadViewReply(msg)); } lock (TSpaceManager.ProcessedRequests) { // Check if request as already been processed if (TSpaceManager.ProcessedRequests.Contains(msg.RequestID)) { // Check if it was processed in a previous viwew if (TSpaceManager.ProcessedRequests.GetByKey(msg.RequestID).Request.MsgView.ID < TSMan.ServerView.ID) { //Console.WriteLine(TSMan.ServerView.ID); TSpaceManager.ProcessedRequests.UpdateView(msg.RequestID, TSMan.ServerView); TSpaceMsg resp = TSpaceManager.ProcessedRequests.GetByKey(msg.RequestID).Response; if (resp == null) { Console.WriteLine("NULL RESPONSE SAVED"); return(null); } return(resp); } else { //Console.WriteLine("repeated"); response.Code = "Repeated"; //Console.WriteLine("Repeated message response was:" + TSpaceManager.ProcessedRequests.GetByKey(msg.RequestID).Response); return(response); } } Console.WriteLine("Starting processing of request " + msg.RequestID); // Add sequence number of request to processed requests TSpaceManager.ProcessedRequests.Add(msg); } string command = msg.Code; //Console.WriteLine("Processing Request " + command + " (seq = " + msg.RequestID + ")"); Message update = null; // Sequence number proposal request if (command.Equals("proposeSeq")) { Console.WriteLine("Propose request received " + msg.OperationID); // Increment sequence number Interlocked.Increment(ref SequenceNumber); response.SequenceNumber = SequenceNumber; response.Code = "proposedSeq"; lock (MessageQueue) { Message newMessage = new Message(); newMessage.ProcessID = msg.ProcessID; newMessage.SequenceNumber = SequenceNumber; newMessage.Deliverable = false; newMessage.MessageID = msg.OperationID; // Add message to queue MessageQueue.Add(newMessage); MessageQueue.Sort(); } Console.WriteLine("Return propose answer" + msg.OperationID); return(response); } // Message with agreed sequence number else { update = UpdateMessage(msg.OperationID, msg.SequenceNumber); if (update == null) { Console.WriteLine("Err: operation message not in queue"); response.Code = "Err"; return(response); } } // Wait for message to be in the head of the queue Monitor.Enter(MessageQueue); while (MessageQueue.Count == 0 || !MessageQueue[0].MessageID.Equals(msg.OperationID)) { //Console.WriteLine("stuck at while"); Monitor.Wait(MessageQueue); } Monitor.Exit(MessageQueue); Console.WriteLine("Execute operation " + msg.OperationID + ": code = " + command); // Execute the operation if (TSMan.Verbose) { Console.WriteLine(msg); } switch (command) { case "add": lock (TakeLock) { if (msg.Tuple == null) { response.Code = "ERR"; break; } TSMan.TSpace.Add(msg.Tuple); response.Code = "ACK"; break; } case "read": if (msg.Tuple == null) { response.Code = "ERR"; break; } response.Tuple = TSMan.TSpace.Read(msg.Tuple); response.Code = "OK"; if (response.Tuple == null) { Console.WriteLine("Match not Found"); } //else //Console.WriteLine("Match found"); break; case "take1": lock (TakeLock) { if (msg.Tuple == null) { response.Code = "ERR"; break; } // Get matching tuple response.Tuple = TSMan.TSpace.Read(msg.Tuple); response.Code = "OK"; if (response.Tuple != null) { // Delete it TSMan.TSpace.Take2(response.Tuple); } } response.Code = "OK"; break; case "take2": Console.WriteLine("Current Tuple Space not in XL mode"); response.Code = "ERR"; break; // Operation exclusive of the XL Tuple Space case "releaseLocks": lock (TakeLock) response.Code = "ERR"; Console.WriteLine("Current Tuple Space not in XL mode"); break; default: Console.WriteLine("Invalid command."); break; } // Delete processed message from queue if (update != null) { lock (MessageQueue) { MessageQueue.Remove(update); Monitor.PulseAll(MessageQueue); } } Console.WriteLine("Return response " + msg.OperationID); return(response); }
/// <summary> /// Executes the phase 1 of the take operation. /// </summary> /// <param name="template">Template of the requested tuple.</param> /// <returns></returns> private ITuple Take1(ITuple template) { // Create request message. TSpaceMsg message = new TSpaceMsg(); message.Code = "take1"; message.Tuple = template; message.ProcessID = ClientID.ToString(); message.RequestID = ClientID + "_" + (++SequenceNumber); message.MsgView = GetCurrentView(); // Clear responses from previour requests lock (MatchingTuples) { AcksCounter = 0; MatchingTuples.Clear(); } // Create local callback. AsyncCallback remoteCallback = new AsyncCallback(Take1Callback); // Repeat until all replicas have responded while (AcksCounter < View.Count) { //Send multicast take request to all members of the view this.Multicast(message, remoteCallback); } if (AcksCounter > View.Count) { throw new Exception(); } List <ITuple> intersection; lock (MatchingTuples) { // Select one tuple from the intersection of all matching tuples lists intersection = MatchingTuples[0]; foreach (List <ITuple> tupleList in MatchingTuples) { intersection.Intersect(tupleList, new TupleComparator()); } } // If intersection = {} // Send release locks to all replicas if (intersection.Count == 0) { //Create message message.Code = "releaseLocks"; message.RequestID = ClientID + "_" + (++SequenceNumber); // Clear acks AcksCounter = 0; // Create remote callback remoteCallback = new AsyncCallback(AddCallback); // Repeat until all replicas have acknowledged release while (AcksCounter < View.Count) { //Send multicast take request to all members of the view this.Multicast(message, remoteCallback); } Console.WriteLine("Take 1: intersection = {}"); return(null); } return(intersection[0]); }