コード例 #1
0
        private void ReceiveReservationYes(Message m,
		                                      string src,
		                                      List<string> userlist,
		                                      int reservationSequenceNumber,
		                                      string messageSubType)
        {
            int s = Int32.Parse (m.PopString ());
            DebugLogic ("Received YES for slot {0}, reservation number {1}",s,reservationSequenceNumber);

            Slot slot = m_numberToSlotMap[s];
            Reservation res = m_activeReservationSessions[reservationSequenceNumber];

            int ackcount;
            if (res.m_acksForSlot.ContainsKey (s))
            {
                res.m_acksForSlot[s]++;
                ackcount = res.m_acksForSlot[s];
            }
            else
            {
                ackcount = 1;
                res.m_acksForSlot[s] = ackcount;
            }

            if (ackcount == res.m_userList.Count
                // the below two conditions are sanity checks.
                && res.m_reservationState != CalendarServiceClient.ReservationState.COMMITTED
                && m_numberToSlotMap[s].m_calendarState != CalendarServiceClient.CalendarState.ASSIGNED)
            {
                DebugLogic ("Woopee! I can haz slot! {0}", s);

                //send DoCommit
                Message docommitMsg = new Message ();
                docommitMsg.SetSourceUserName (m_client.UserName);
                docommitMsg.SetDestinationUsers (res.m_userList);
                docommitMsg.SetMessageType ("calendar");
                docommitMsg.PushString (s.ToString ());
                docommitMsg.PushString (reservationSequenceNumber.ToString ());
                docommitMsg.PushString ("docommit");
                SendMessage (docommitMsg);

                // If you have to send this, then you can commit.
                // TODO: Handle 2/1, 1/2 deadlock.
                slot.m_calendarState = CalendarServiceClient.CalendarState.ASSIGNED;
                res.m_reservationState = CalendarServiceClient.ReservationState.COMMITTED;
            }
        }
コード例 #2
0
 private void UnPackUserTable(Message ack)
 {
     int size = Int32.Parse (ack.PopString ());
     for (int i = 0; i < size; i++)
     {
         string[] tuple = ack.PopString ().Split (',');
         m_server.m_userTableService.UserConnect (tuple[0], tuple[1]);
     }
 }
コード例 #3
0
        private void ReceiveReservationRequest(Message m,
		                                        string src,
		                                        List<string> userlist,
		                                        int reservationSequenceNumber,
		                                        string messageSubType)
        {
            /* If I get a reservation request for a slot
             * that is either FREE or ACKNOWLEDGED, then
             * respond with an ACK, else if it is either
             * BOOKED, or ASSIGNED, then respond with a NACK
             */
            int numSlots = Int32.Parse (m.PopString ()); // number of slots
            List<int> slotlist = new List<int> (); // unpack all the slots
            for (int i = 0; i < numSlots; i++)
            {
                slotlist.Add (Int32.Parse (m.PopString ()));
            }

            string description = m.PopString (); // description
            DebugLogic ("Received Message:" +
                               "[{0}, {1}, {2}, {3}, {4}, {5}, {6}]",
                               src, userlist.ToString (), messageSubType, reservationSequenceNumber, numSlots, slotlist.ToString (), description);

            /* Message unpacked, now create a reservation object
             */

            if (m_activeReservationSessions.ContainsKey (reservationSequenceNumber))
            {
                DebugFatal ("Duplicate reservation request received {0}", reservationSequenceNumber);
            }

            /* Create reservation object
             */
            Reservation reservation = new Reservation ();
            reservation.m_description = description;
            reservation.m_sequenceNumber = reservationSequenceNumber;
            reservation.m_userList = userlist;
            reservation.m_slotNumberList = slotlist;
            reservation.m_initiator = src;

            /*
             * check if slots are free
             * and proceed to respond with an ACK or NACK.
             */
            List<int> availableslots = new List<int> ();
            foreach (int i in slotlist)
            {
                // If slot is being encountered for the
                // first time...
                if (!m_numberToSlotMap.ContainsKey (i))
                {
                    DebugLogic ("Creating new slot instance for slot-number: {0}", i);
                    // Then create new slot.
                    // TODO: Probably need internal methods for this
                    Slot tempslot = new Slot ();
                    tempslot.m_calendarState = CalendarState.FREE;
                    tempslot.m_slotNumber = i;
                    tempslot.m_reservationsForThisSlot = new List<Reservation> ();
                    tempslot.m_preCommitList = new SortedList<int, Reservation> ();
                    tempslot.m_lockedReservation = -1;

                    // Add to int-to-slot-object map
                    m_numberToSlotMap.Add (i, tempslot);
                }

                // Get the concerned slot
                Slot slot = m_numberToSlotMap[i];

                if (slot.m_calendarState == CalendarServiceClient.CalendarState.FREE ||
                    slot.m_calendarState == CalendarServiceClient.CalendarState.ACKNOWLEDGED)
                {
                    // Update the slot's reservation list
                    slot.m_reservationsForThisSlot.Add (reservation);

                    // Append to list of slots.
                    availableslots.Add (i);

                    // Update slot state
                    slot.m_calendarState = CalendarServiceClient.CalendarState.ACKNOWLEDGED;
                    DebugLogic ("Slot {0} is now in ACKNOWLEDGED state", i);
                }
            }

            // Respond with ACK/NACK
            if (availableslots.Count > 0)
            {
                // We do have at least one free slot, so respond with an ACK
                Message ack = new Message ();

                ack.SetSourceUserName (m_client.UserName);
                ack.SetDestinationUsers (src);
                ack.SetMessageType ("calendar");

                /*
                 * ACK Message format, data part
                 *
                 * - Number of Slots
                 * - Slot 1
                 * - Slot 2
                 * ...
                 * - Slot N
                 */
                availableslots.Reverse ();

                foreach (int i in availableslots)
                {
                    ack.PushString (i.ToString ());
                    DebugInfo ("Slot {0} is available", i);
                }

                ack.PushString (availableslots.Count.ToString ());
                ack.PushString (reservationSequenceNumber.ToString ());
                ack.PushString ("reservationack");

                DebugLogic ("Sending an ack to: {0}", src);

                SendMessage (ack);
                m_activeReservationSessions.Add (reservationSequenceNumber, reservation);
            }
            else
            {
                Message nack = new Message ();
                // No free slots, so respond with a NACK
                nack.SetSourceUserName (m_client.UserName);
                nack.SetDestinationUsers (src);
                nack.SetMessageType ("calendar");

                nack.PushString ("reservationnack");

                DebugLogic ("Sending a nack to: {0}", src);

                SendMessage (nack);
            }
        }
コード例 #4
0
        private void ReceiveReservationPreCommit(Message m,
		                                          string src,
		                                          List<string> userlist,
		                                          int reservationSequenceNumber,
		                                          string messageSubType)
        {
            /* If I get a PRECOMMIT update for a slot,
             * and it is still in ACKNOWLEDGED state, then
             * respond with YES!. Else, respond with a NO!
             *
             * 		If I responded with a YES, then

             * 		move into PRECOMMIT state and begin
             * 		verification and commit timers.
             *
             * 			When verification timer fires, verify
             * 			your neighbours. TODO: Might need ping
             * 			utility
             *
             * 				If verification fails, ABORT, else do nothing.
             *
             * 			When commit timer fires, commit.
             *
             * 		If I responded with a NO, then move
             * 		into ABORT.
             *
             * 		If between any of the above, the coordinator
             * 		sends an ABORT message, then ABORT. DUH!
             */

            int s = Int32.Parse (m.PopString ());
            DebugLogic ("Received precommit for slot {0}, reservation number {1}",s,reservationSequenceNumber);

            Slot slot = m_numberToSlotMap[s];
            Reservation res = m_activeReservationSessions[reservationSequenceNumber];

            if (slot.m_calendarState == CalendarServiceClient.CalendarState.ACKNOWLEDGED
                || slot.m_calendarState == CalendarServiceClient.CalendarState.BOOKED)
            {

                if (slot.m_preCommitList.Count == 0 && slot.m_lockedReservation == -1)
                {
                    res.m_reservationState = CalendarServiceClient.ReservationState.TENTATIVELY_BOOKED;
                    slot.m_calendarState = CalendarServiceClient.CalendarState.BOOKED;
                    // No one has a lock, so this reservation gets it.
                    Message yes = new Message ();

                    yes.SetDestinationUsers (src);
                    yes.SetMessageType ("calendar");
                    yes.SetSourceUserName (m_client.UserName);
                    yes.PushString (s.ToString ());
                    yes.PushString (reservationSequenceNumber.ToString ());
                    yes.PushString ("yes");

                    slot.m_lockedReservation = reservationSequenceNumber;

                    SendMessage (yes);
                }
                else if (slot.m_lockedReservation != -1 && slot.m_lockedReservation < s)
                {
                    // Some reservation older is already locked, so wait.
                    slot.m_preCommitList.Add (reservationSequenceNumber, res);
                }
                else
                {
                    // Add older reservation to queue, we may upgrade or abort this
                    // depending on the result of the next step

                    slot.m_preCommitList.Add (reservationSequenceNumber, res);

                    // A newer reservation has been locked. For now,
                    // we try and ABORT the newer one in favour of the older one.
                    // But the optimisation here would be for coordinators to
                    // initiate an is-there-a-deadlock check, which the cohort
                    // would ask the coordinator to initiate.
                    Message abortmsg = new Message ();

                    abortmsg.SetDestinationUsers (m_activeReservationSessions[reservationSequenceNumber].m_initiator);
                    abortmsg.SetMessageType ("calendar");
                    abortmsg.SetSourceUserName (m_client.UserName);
                    abortmsg.PushString (s.ToString ()); // we need to mention the slot that is being aborted
                    abortmsg.PushString (slot.m_lockedReservation.ToString ());
                    abortmsg.PushString ("abort");

                    SendMessage (abortmsg);
                    ReservationAbortCohort (slot.m_lockedReservation, s);
                }
            }
        }
コード例 #5
0
        private void ReceiveReservationDoCommit(Message m,
		                                          string src,
		                                          List<string> userlist,
		                                          int reservationSequenceNumber,
		                                          string messageSubType)
        {
            int s = Int32.Parse (m.PopString ());
            DebugLogic ("Received docommit for slot {0}, reservation number {1}",s,reservationSequenceNumber);

            Slot slot = m_numberToSlotMap[s];
            Reservation res = m_activeReservationSessions[reservationSequenceNumber];

            slot.m_calendarState = CalendarServiceClient.CalendarState.ASSIGNED;
            res.m_reservationState = CalendarServiceClient.ReservationState.COMMITTED;

            DebugLogic ("Reservation ID: {0}, Slot: {1} has COMMITTED", reservationSequenceNumber, s);

            if (m_client.m_isPuppetControlled)
            {
                m_client.m_puppetService.SendInfoMsgToPuppetMaster ("Reservation ID: {0}, Slot: {1} has COMMITTED",
                                                                    reservationSequenceNumber, s);
            }

            // Perform cleanup of all reservation objects
            foreach (int i in res.m_slotNumberList)
            {
                if (i != s)
                {
                    m_numberToSlotMap[i].m_reservationsForThisSlot.Remove (res);
                }
            }

            foreach (int i in slot.m_preCommitList.Keys)
            {

                Message abortmsg = new Message ();

                abortmsg.SetDestinationUsers (m_activeReservationSessions[reservationSequenceNumber].m_initiator);
                abortmsg.SetMessageType ("calendar");
                abortmsg.SetSourceUserName (m_client.UserName);
                abortmsg.PushString (s.ToString ()); // we need to mention the slot that is being aborted
                abortmsg.PushString (reservationSequenceNumber.ToString ());
                abortmsg.PushString ("abort");

                SendMessage (abortmsg);
                ReservationAbortCohort (i, s);
            }
        }
コード例 #6
0
        private void ReceiveReservationAckNack(Message m,
		                                        string src,
		                                        List<string> userlist,
		                                        int reservationSequenceNumber,
		                                        string messageSubType)
        {
            /* If I am the initiator of the reservation,
             * then keep collecting ACKS/NACKS from all participants
             *
             *      If ACK rcvd, then update received ACK counter.
             *
             * 			If all ACKS rcvd, move reservation state to
             *	    	TENTATIVELY_BOOKED for those slots.
             * 			Then inform all nodes about decision with a
             * 			PRECOMMIT message and move to PRECOMMIT state.
             *
             * 		If at least one NACK, move reservation state
             * 		to ABORTED. TODO: Should we notify others?
             */

            DebugLogic ("Received {0} from {1} for reservation ID: {2}",
                            messageSubType, src, reservationSequenceNumber);

            // obtain reservation objects
            Reservation res = m_activeReservationSessions[reservationSequenceNumber];
            int slotCount = Int32.Parse (m.PopString ());

            if (messageSubType.Equals ("reservationack")
                && res.m_reservationState != CalendarServiceClient.ReservationState.ABORTED)
            {

                List<int> validSlots = new List<int> ();
                int ackcount = 0;

                while (slotCount > 0)
                {
                    int s = Int32.Parse (m.PopString ());

                    if (m_numberToSlotMap[s].m_calendarState != CalendarServiceClient.CalendarState.BOOKED
                        && m_numberToSlotMap[s].m_lockedReservation == -1)
                    {
                        validSlots.Add (s);

                        DebugInfo ("Adding {0} to validslot list", s);
                        if (res.m_acksForSlot.ContainsKey (s))
                        {
                            res.m_acksForSlot[s]++;
                            ackcount = res.m_acksForSlot[s];
                        }
                        else
                        {
                            ackcount = 1;
                            res.m_acksForSlot[s] = ackcount;
                        }
                    }

                    slotCount--;
                }

                // If there are slots which were not part of
                // the ack, then we do some cleanup.
                if (validSlots.Count != res.m_slotNumberList.Count)
                {
                    foreach (int i in res.m_slotNumberList)
                    {
                        bool isPresent = false;
                        foreach (int j in validSlots)
                        {
                            if (i == j)
                            {
                                isPresent = true;
                            }
                        }

                        if (!isPresent)
                        {
                            m_numberToSlotMap[i].m_reservationsForThisSlot.Remove (res);
                        }
                    }

                }

                res.m_slotNumberList = validSlots;

                // If enough ACKS, then proceed with precommit for
                // each valid slot, one by one.

                if (res.m_userList.Count == ackcount)
                {
                    res.m_reservationState = CalendarServiceClient.ReservationState.TENTATIVELY_BOOKED;
                    m_numberToSlotMap[res.m_slotNumberList[0]].m_calendarState = CalendarServiceClient.CalendarState.BOOKED;
                    m_numberToSlotMap[res.m_slotNumberList[0]].m_lockedReservation = reservationSequenceNumber;
                    SendPreCommitMessage (res, res.m_slotNumberList[0]);

                    res.m_acksForSlot.Clear ();
                }
            }
            else if (messageSubType.Equals ("reservationnack"))
            {
                res.m_reservationState = CalendarServiceClient.ReservationState.ABORTED;

                DebugLogic ("Send NACK to {0}", src);
                foreach (int i in res.m_slotNumberList)
                {
                    m_numberToSlotMap[i].m_reservationsForThisSlot.Remove (res);
                }
            }
        }
コード例 #7
0
        private void ReceiveReservationAbort(Message m,
		                                      string src,
		                                      List<string> userlist,
		                                      int reservationSequenceNumber,
		                                      string messageSubType)
        {
            int s = Int32.Parse (m.PopString ());
            DebugLogic ("Received ABORT for slot {0}, reservation number {1}",s,reservationSequenceNumber);

            Slot slot = m_numberToSlotMap[s];
            Reservation res = m_activeReservationSessions[reservationSequenceNumber];

            // if i am the initiator, and the reservation has not already committed,
            // or has not already been aborted by someone else,
            // then send every1 aborts.
            if (res.m_initiator.Equals (m_client.UserName)
                && res.m_reservationState != CalendarServiceClient.ReservationState.COMMITTED
                && res.m_reservationState != CalendarServiceClient.ReservationState.ABORTED)
            {
                //Perform my own cleanup,
                res.m_slotNumberList.Remove (s);

                // The earlier reservation is now removed from this slot
                slot.m_reservationsForThisSlot.Remove (res);

                // If this was the last slot in contention for
                // the reservation...
                if (res.m_slotNumberList.Count == 0)
                {
                    // ... then the reservation should be in ABORTED state. Sigh.
                    res.m_reservationState = CalendarServiceClient.ReservationState.ABORTED;
                }
                else
                {
                    // Pick next tentatively booked slot and send out precommit messages
                    SendPreCommitMessage (res, res.m_slotNumberList[0]);
                }

                // TODO:send everyone abort messages.
            }
            else
            {
                // Abort the reservation entry for this particular slot.
                ReservationAbortCohort (reservationSequenceNumber, s);
            }
        }