private void PrepareCommitOrBookNextSlot(Reservation res, int slotID) { Monitor.Enter(_calendar[slotID]); CalendarSlot calendarSlot = _calendar[slotID]; ReservationSlot slot = GetSlot(res, slotID); if (calendarSlot.Locked || calendarSlot.State == CalendarSlotState.ASSIGNED || (calendarSlot.State == CalendarSlotState.BOOKED && res.ReservationID > calendarSlot.ReservationID)) { Log.Show(_userName, "Booking of slot " + slotID + " of reservation " + res.ReservationID + " failed. Trying to book next slot."); AbortReservationSlot(slot, true); Monitor.Exit(_calendar[slotID]); BookNextSlot(res); } else { Log.Show(_userName, "Slot " + slotID + " of reservation " + res.ReservationID + " was booked successfully. Starting commit process."); LockCalendarSlot(res, slot); Monitor.Exit(_calendar[slotID]); foreach (string participantID in res.Participants) { if (!participantID.Equals(_userName)) { _msgDispatcher.SendMessage(MessageType.PRE_COMMIT, res.ReservationID, participantID, slot.SlotID); } } } }
protected void rptSlots_ItemDataBound(object sender, RepeaterItemEventArgs e) { Panel pnlExisting = (Panel)e.Item.FindControl("pnlExisting"); Panel pnlAdd = (Panel)e.Item.FindControl("pnlAdd"); CalendarSlot slot = (CalendarSlot)e.Item.DataItem; pnlExisting.Visible = slot.CalendarItem != null; if (CRM_Venue != null && slot.CalendarItem != null && !slot.CalendarItem.CRM_CalendarVenues.Any(v => v.CRM_VenueID == CRM_Venue.ID)) { pnlExisting.Visible = false; } Repeater rptVenues = (Repeater)e.Item.FindControl("rptVenues"); if (slot.CalendarItem != null) { if (CRM_Venue != null) { rptVenues.DataSource = slot.CalendarItem.CRM_CalendarVenues.Where(v => v.CRM_VenueID == CRM_Venue.ID).OrderBy(v => v.DateTimeFrom); rptVenues.DataBind(); } else { rptVenues.DataSource = slot.CalendarItem.CRM_CalendarVenues.OrderBy(v => v.DateTimeFrom); rptVenues.DataBind(); } } pnlAdd.Visible = slot.Visible; }
/* * CALENDAR SHOULD BE LOCKED BEFORE CALLING THIS METHOD */ private void LockCalendarSlot(Reservation res, ReservationSlot resSlot) { //Change calendar and reservation slot states CalendarSlot calendarSlot = _calendar[resSlot.SlotID]; calendarSlot.Locked = true; resSlot.State = ReservationSlotState.COMMITTED; }
/* * AUX METHODS */ private void BookNextSlot(Reservation res) { bool booked = false; //LOCK HERE foreach (ReservationSlot slot in res.Slots) { Monitor.Enter(_calendar[slot.SlotID]); CalendarSlot cSlot = _calendar[slot.SlotID]; if (slot.State != ReservationSlotState.ABORTED && !cSlot.Locked && (cSlot.State == CalendarSlotState.ACKNOWLEDGED || (cSlot.State == CalendarSlotState.BOOKED && res.ReservationID < cSlot.ReservationID))) { booked = true; BookCalendarSlot(res, slot); Monitor.Exit(_calendar[slot.SlotID]); Log.Show(_userName, "Starting book process of slot " + slot.SlotID + " from reservation " + res.ReservationID); foreach (string participantID in res.Participants) { if (!participantID.Equals(_userName)) { _msgDispatcher.SendMessage(MessageType.BOOK_SLOT, res.ReservationID, participantID, slot.SlotID); } } break; } else { Monitor.Exit(_calendar[slot.SlotID]); } } if (!booked) { Log.Show(_userName, "No available slots. Aborting reservation " + res.ReservationID); foreach (IBookingService client in res.ClientStubs.Values) { try { Log.Show(_userName, "Sending abort to client..."); AbortDelegate bookSlot = new AbortDelegate(client.AbortReservation); IAsyncResult RemAr = bookSlot.BeginInvoke(res.ReservationID, null, null); } catch (SocketException e) { Log.Show(_userName, "ERROR: Could not connect to client. Exception: " + e); } } AbortReservation(res.ReservationID); } }
/* * CALENDAR SHOULD BE LOCKED BEFORE CALLING THIS METHOD */ private void BookCalendarSlot(Reservation res, ReservationSlot resSlot) { CalendarSlot calendarSlot = _calendar[resSlot.SlotID]; calendarSlot.WaitingBook.Remove(resSlot.ReservationID); res.CurrentSlot = resSlot.SlotID; calendarSlot.State = CalendarSlotState.BOOKED; calendarSlot.ReservationID = resSlot.ReservationID; resSlot.State = ReservationSlotState.TENTATIVELY_BOOKED; }
public IEnumerable <CalendarSlot> FetchSlotsForTime(DateTime StartDateTime, bool HideExternal, bool HideInternal, bool HideNonTagged, int type, int?adminCalendar) { var baseSet = (from c in db.CRM_Calendars where c.StartDateTime >= StartDateTime && c.StartDateTime < StartDateTime.AddHours(1) orderby c.ID select c).ToArray(); var unparsed = baseSet; baseSet = QueryBasetSet(baseSet, HideExternal, HideInternal, HideNonTagged, type, adminCalendar, out unparsed); var slotsAtThisStart = (from c in baseSet select new CalendarSlot(c.StartDateTime.ToString("dd/MM/yyyy HH:mm")) { CalendarItem = c, InsideFilter = baseSet.Contains(c) }).ToList(); int otherItemsInThisSlot = ItemsDuringThisTime(StartDateTime).Count(); List <CalendarSlot> additionalSlots = new List <CalendarSlot>(); int populatedSlots = slotsAtThisStart.Count(); CalendarSlot lastslot = new CalendarSlot(StartDateTime.ToString("dd/MM/yyyy HH:mm"), true) { CalendarItem = null }; additionalSlots.Add(lastslot); while (populatedSlots <= otherItemsInThisSlot) { CalendarSlot slot = new CalendarSlot(StartDateTime.ToString("dd/MM/yyyy HH:mm")) { CalendarItem = null, Visible = false }; additionalSlots.Add(slot); populatedSlots++; } additionalSlots.AddRange(slotsAtThisStart); return(additionalSlots.AsEnumerable()); }
void IBookingService.BookSlot(int resID, int slotID) { Log.Show(_userName, "Received book request from initiator for slot " + slotID + " of reservation " + resID); Reservation res; if (!_activeReservations.TryGetValue(resID, out res)) { Log.Show(_userName, "WARN: Received book request from unknown reservation " + resID); return; } ReservationSlot resSlot = GetSlotAndAbortPredecessors(res, slotID); if (resSlot == null) { Log.Show(_userName, "WARN: Received book request from unknown reservation " + resID); return; } bool ack; Monitor.Enter(_calendar[slotID]); try { CalendarSlot calendarSlot = _calendar[slotID]; calendarSlot.WaitingBook.Remove(resID); ack = !calendarSlot.Locked && (calendarSlot.State == CalendarSlotState.ACKNOWLEDGED || (calendarSlot.State == CalendarSlotState.BOOKED && resID < calendarSlot.ReservationID)); if (ack) { BookCalendarSlot(res, resSlot); } else { AbortReservationSlot(resSlot, true); } } finally { Monitor.Exit(_calendar[slotID]); } res.InitiatorStub.BookReply(resSlot.ReservationID, resSlot.SlotID, _userName, ack); }
void IBookingService.PrepareCommit(int resID, int slotID) { Log.Show(_userName, "Received prepare commit request from initiator for slot " + slotID + " of reservation " + resID); //Fetch reservation and slot objects Reservation res; if (!_activeReservations.TryGetValue(resID, out res)) { Log.Show(_userName, "WARN: Received pre-commit request from unknown reservation " + resID); return; } ReservationSlot resSlot = GetSlot(res, slotID); if (resSlot == null) { Log.Show(_userName, "WARN: Received prepare commit request from unknown reservation " + resID); return; } //GET LOCK HERE Monitor.Enter(_calendar[slotID]); CalendarSlot calendarSlot = _calendar[slotID]; bool ack = !calendarSlot.Locked && calendarSlot.State == CalendarSlotState.BOOKED && calendarSlot.ReservationID == resID; if (ack) { LockCalendarSlot(res, resSlot); } else { AbortReservationSlot(resSlot, true); } Monitor.Exit(_calendar[slotID]); //RELEASE LOCK HERE res.InitiatorStub.PrepareCommitReply(resSlot.ReservationID, resSlot.SlotID, _userName, ack); }
//Verify calendar slots and create reservation states private List <ReservationSlot> CreateReservationSlots(ReservationRequest req, int resID) { List <ReservationSlot> reservationSlots = new List <ReservationSlot>(); foreach (int slot in req.Slots) { ReservationSlotState state = ReservationSlotState.INITIATED; CalendarSlot calendarSlot; if (_calendar.TryGetValue(slot, out calendarSlot)) { if (calendarSlot.State == CalendarSlotState.ASSIGNED) { state = ReservationSlotState.ABORTED; } } else { calendarSlot = new CalendarSlot(); calendarSlot.SlotNum = slot; calendarSlot.State = CalendarSlotState.FREE; _calendar[slot] = calendarSlot; Log.Debug(_userName, "Creating new calendar entry. Slot: " + calendarSlot.SlotNum + ". State: " + calendarSlot.State); } Monitor.Enter(calendarSlot); if (calendarSlot.State == CalendarSlotState.FREE) { calendarSlot.State = CalendarSlotState.ACKNOWLEDGED; } Monitor.Exit(calendarSlot); calendarSlot.WaitingBook.Add(resID); ReservationSlot rs = new ReservationSlot(resID, slot, state); reservationSlots.Add(rs); } return(reservationSlots); }
/* * CALENDAR SHOULD BE LOCKED BEFORE CALLING THIS METHOD */ private void AssignCalendarSlot(Reservation res, ReservationSlot resSlot, bool clean) { //Change calendar and reservation slot states CalendarSlot calendarSlot = _calendar[resSlot.SlotID]; calendarSlot.State = CalendarSlotState.ASSIGNED; calendarSlot.ReservationID = res.ReservationID; calendarSlot.Participants = res.Participants; calendarSlot.Description = res.Description; foreach (ReservationSlot slot in res.Slots) { if (slot != resSlot && slot.State != ReservationSlotState.ABORTED) { AbortReservationSlot(slot, true); } } if (clean) { CleanReservation(res); } }
private void FreeCalendarSlot(ReservationSlot slot) { CalendarSlot cSlot = _calendar[slot.SlotID]; cSlot.WaitingBook.Remove(slot.ReservationID); if (cSlot.State == CalendarSlotState.ACKNOWLEDGED && cSlot.WaitingBook.Count == 0) { cSlot.State = CalendarSlotState.FREE; } else if (cSlot.State == CalendarSlotState.BOOKED && cSlot.ReservationID == slot.ReservationID) { if (cSlot.WaitingBook.Count > 0) { cSlot.State = CalendarSlotState.ACKNOWLEDGED; } else { cSlot.State = CalendarSlotState.FREE; } cSlot.Locked = false; } }
/* * SLOT MANAGER METHODS */ public bool StartReservation(ReservationRequest req) { //Updates request with sequence number int resID = RetrieveSequenceNumber(); //Create and populate local reservation Reservation res = CreateReservation(req, resID, _userName, Helper.GetIPAddress(), _port); //Mark slots initial states List <ReservationSlot> reservationSlots = CreateReservationSlots(req, resID); //Update reservation request, removing aborted slots foreach (ReservationSlot slot in new List <ReservationSlot>(reservationSlots)) { if (slot.State == ReservationSlotState.ABORTED) { Log.Show(_userName, "Slot " + slot + " not available on initiator. Removing from reservation."); //removing slot of original request, since it will be passed to participants reservationSlots.Remove(slot); req.Slots.Remove(slot.SlotID); } } res.Slots = reservationSlots; Log.Show(_userName, "Starting reservation " + res.ReservationID + ". With participants " + string.Join(",", res.Participants) + ". Slots: " + string.Join(",", res.Slots)); //If no slots are available, cancel reservation if (res.Slots.Count == 0) { Log.Show(_userName, "No available slots on initiator, aborting reservation."); return(false); } //just the initiator is on the reservation if (req.Users.Count == 1) { foreach (ReservationSlot slot in res.Slots) { Monitor.Enter(_calendar[slot.SlotID]); try { CalendarSlot cSlot = _calendar[slot.SlotID]; if (slot.State != ReservationSlotState.ABORTED && !cSlot.Locked && cSlot.State != CalendarSlotState.ASSIGNED) { AssignCalendarSlot(res, slot, true); return(true); } else if (slot.State != ReservationSlotState.ABORTED) { AbortReservationSlot(slot, true); } } finally { Monitor.Exit(_calendar[slot.SlotID]); } } return(false); } _clientMonitor.MonitorReservation(res); //Add reservation to map of active reservations _activeReservations[res.ReservationID] = res; foreach (string participantID in res.Participants) { if (!participantID.Equals(_userName)) { _msgDispatcher.SendMessage(MessageType.INIT_RESERVATION, resID, participantID, req, _userName, Helper.GetIPAddress(), _port); } } return(true); }