/// <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 ActiveOperations.Add(message.RequestID); AcksCounter = 0; // Create local callback AsyncCallback remoteCallback = new AsyncCallback(AddCallback); // Repeat request until all replicas have acknowledged receipt while (AcksCounter < Quorum()) { //Send multicast message to all members of the view this.Multicast(message, remoteCallback); } ActiveOperations.Remove(message.RequestID); Console.WriteLine("Add " + (++AddCounter) + ": OK"); }
/// <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 async void BeginOperation(string operationName) { if (CurrentDocument == null) { return; } _oldObjects.Clear(); _oldObjects.AddRange(CurrentDocument.ObjectsDictionary.Values); CurrentDocument.ObjectsDictionary.StartAccessList(); //call operation if (OperationsDictionary.ContainsKey(operationName)) { var operation = (UserOperation)Activator.CreateInstance(OperationsDictionary[operationName]); operation.OwnerDocument = CurrentDocument; ActiveOperations.Add(operation); OperationReturnValue result = OperationReturnValue.CancelOperation; Task <OperationReturnValue> task = new Task <OperationReturnValue>(operation.Execute); try { task.Start(); result = await task; } catch (Exception e) { Log.Error(e.Message); } if (result == OperationReturnValue.EndOperation) { ActiveOperations.Remove(operation); foreach (var o in new Dictionary <int, CADObject>(operation.TemporaryObjectsDictionary)) { CurrentDocument.PostCreateCADObject(o.Value); o.Value.LockOperation = null; } EndOperation(operation); } else { ActiveOperations.Remove(operation); operation.TemporaryObjectsDictionary.Clear(); } } }
/**************************************************************** * 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); }
/// <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++); ActiveOperations.Add(request.RequestID); request.MsgView = GetCurrentView(); AsyncCallback remoteCallback = new AsyncCallback(AcksCallback); // Clear acks count AcksCounter = 0; // Repeat until all replicas have acknowledged receipt while (AcksCounter < Quorum()) { // Send request to all replicas in the view this.Multicast(request, remoteCallback); } ActiveOperations.Remove(request.RequestID); Console.WriteLine("Add " + (++AddCounter) + ": OK"); }
/// <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 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++); ActiveOperations.Add(request.RequestID); // 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 < Quorum()) { // 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; } } ActiveOperations.Remove(request.RequestID); } Console.WriteLine("Read " + (++ReadCounter) + ": OK"); // Return after the first replica answers return(Tuple); }
/// <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++); ActiveOperations.Add(request.RequestID); request.MsgView = GetCurrentView(); //Clear acks from last request AcksCounter = 0; // Repeat untill all replicas have answered while (AcksCounter < Quorum()) { // 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; } } ActiveOperations.Remove(request.RequestID); } Console.WriteLine("Take " + (++TakeCounter) + ": OK"); 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) { if (message.RequestID != null && ActiveOperations.Contains(message.RequestID)) { ActiveOperations.Remove(message.RequestID); } message.RequestID = ClientID + "_" + (++SequenceNumber); ActiveOperations.Add(message.RequestID); AcksCounter = 0; // Waits until one replica returns a tuple or // all replicas answered that they dont have a match while (AcksCounter < Quorum()) { // 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; } } } ActiveOperations.Remove(message.RequestID); // Return first response. Console.WriteLine("Read " + (++ReadCounter) + ": OK"); return(Tuple); }
/// <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(); ActiveOperations.Add(message.RequestID); // 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 < Quorum()) { //Send multicast take request to all members of the view this.Multicast(message, remoteCallback); } ActiveOperations.Remove(message.RequestID); 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 ActiveOperations.Add(message.RequestID); AcksCounter = 0; // Create remote callback remoteCallback = new AsyncCallback(AddCallback); // Repeat until all replicas have acknowledged release while (AcksCounter < Quorum()) { //Send multicast take request to all members of the view this.Multicast(message, remoteCallback); } ActiveOperations.Remove(message.RequestID); Console.WriteLine("Take 1: intersection = {}"); return(null); } return(intersection[0]); }