/// <summary>Ctor. </summary> /// <param name="maxAgeSec">is the maximum age in seconds</param> /// <param name="purgeIntervalSec">is the purge interval in seconds</param> /// <param name="cacheReferenceType">indicates whether hard, soft or weak references are used in the cache</param> /// <param name="schedulingService">is a service for call backs at a scheduled time, for purging</param> /// <param name="scheduleSlot">slot for scheduling callbacks for this cache</param> /// <param name="epStatementAgentInstanceHandle">is the statements-own handle for use in registering callbacks with services</param> public DataCacheExpiringImpl(double maxAgeSec, double purgeIntervalSec, ConfigurationCacheReferenceType cacheReferenceType, SchedulingService schedulingService, ScheduleSlot scheduleSlot, EPStatementAgentInstanceHandle epStatementAgentInstanceHandle) { MaxAgeMSec = (long)maxAgeSec * 1000; PurgeIntervalMSec = (long)purgeIntervalSec * 1000; _schedulingService = schedulingService; _scheduleSlot = scheduleSlot; if (cacheReferenceType == ConfigurationCacheReferenceType.HARD) { _cache = new Dictionary <Object, Item>(); } else if (cacheReferenceType == ConfigurationCacheReferenceType.SOFT) { _cache = new ReferenceMap <Object, Item>(ReferenceType.SOFT, ReferenceType.SOFT); } else { _cache = new WeakDictionary <Object, Item>(); } _epStatementAgentInstanceHandle = epStatementAgentInstanceHandle; }
public Result AddReservationsToScheduleSlot(int scheduleSlotId, ICollection <Reservation> reservations) { try { ScheduleSlot scheduleSlot = GetScheduleSlotById(scheduleSlotId); if (scheduleSlot == null) { return(new Result(false)); } string reservationsRaw = scheduleSlot.Reservations != null ? scheduleSlot.Reservations : ""; foreach (Reservation reservation in reservations) { reservationsRaw += reservationsRaw != "" ? string.Format(";{0}", reservation.Id) : reservation.Id.ToString(); } scheduleSlot.Reservations = reservationsRaw; databaseContext.ScheduleSlots.Update(scheduleSlot); return(new Result()); } catch (Exception ex) { return(new Result(ex)); } }
/// <summary> /// Constructor. /// </summary> /// <param name="timeBatchViewFactory">for copying this view in a group-by</param> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeDeltaComputation">computes the number of milliseconds to batch events for</param> /// <param name="referencePoint">is the reference point onto which to base intervals, or null ifthere is no such reference point supplied</param> /// <param name="forceOutput">is true if the batch should produce empty output if there is no value to output following time intervals</param> /// <param name="isStartEager">is true for start-eager</param> /// <param name="viewUpdatedCollection">is a collection that the view must Update when receiving events</param> public TimeBatchView(TimeBatchViewFactory timeBatchViewFactory, AgentInstanceViewFactoryChainContext agentInstanceContext, ExprTimePeriodEvalDeltaConst timeDeltaComputation, long?referencePoint, bool forceOutput, bool isStartEager, ViewUpdatedCollection viewUpdatedCollection) { _agentInstanceContext = agentInstanceContext; _timeBatchViewFactory = timeBatchViewFactory; _timeDeltaComputation = timeDeltaComputation; _initialReferencePoint = referencePoint; _isStartEager = isStartEager; _viewUpdatedCollection = viewUpdatedCollection; _isForceOutput = forceOutput; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); // schedule the first callback if (isStartEager) { if (_currentReferencePoint == null) { _currentReferencePoint = agentInstanceContext.StatementContext.SchedulingService.Time; } ScheduleCallback(); _isCallbackScheduled = true; } agentInstanceContext.AddTerminationCallback(Stop); }
public Result RemoveSchedule(int scheduleId) { try { Schedule schedule = databaseContext.Schedules.FirstOrDefault(x => x.Id == scheduleId); if (schedule == null) { return(new Result(false)); } string[] scheduleSlotIds = schedule.MovieSchedule.Split(';', StringSplitOptions.RemoveEmptyEntries); List <ScheduleSlot> removedScheduleSlots = new List <ScheduleSlot>(); foreach (string id in scheduleSlotIds) { ScheduleSlot scheduleSlot = GetScheduleSlotById(int.Parse(id)); if (scheduleSlot != null) { removedScheduleSlots.Add(scheduleSlot); } } databaseContext.ScheduleSlots.RemoveRange(removedScheduleSlots); databaseContext.Schedules.Remove(schedule); databaseContext.SaveChanges(); return(new Result()); } catch (Exception ex) { return(new Result(ex)); } }
/// <summary> /// Constructor. /// </summary> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeWindowViewFactory">for copying the view in a group-by</param> /// <param name="timeDeltaComputation">is the computation of number of milliseconds before events gets pushedout of the timeWindow as oldData in the Update method.</param> /// <param name="viewUpdatedCollection">is a collection the view must Update when receiving events</param> public TimeWindowView( AgentInstanceViewFactoryChainContext agentInstanceContext, TimeWindowViewFactory timeWindowViewFactory, ExprTimePeriodEvalDeltaConst timeDeltaComputation, ViewUpdatedCollection viewUpdatedCollection) { _agentInstanceContext = agentInstanceContext; _timeWindowViewFactory = timeWindowViewFactory; _timeDeltaComputation = timeDeltaComputation; _viewUpdatedCollection = viewUpdatedCollection; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); _timeWindow = new TimeWindow(agentInstanceContext.IsRemoveStream); ScheduleHandleCallback callback = new ProxyScheduleHandleCallback { ProcScheduledTrigger = extensionServicesContext => Instrument.With( i => i.QViewScheduledEval(this, timeWindowViewFactory.ViewName), i => i.AViewScheduledEval(), Expire) }; _handle = new EPStatementHandleCallback(agentInstanceContext.EpStatementAgentInstanceHandle, callback); if (agentInstanceContext.StatementContext.ScheduleAdjustmentService != null) { agentInstanceContext.StatementContext.ScheduleAdjustmentService.AddCallback(this); } agentInstanceContext.AddTerminationCallback(Stop); }
private void ScheduleNextCallback() { var nextScheduleCallback = new ProxyScheduleHandleCallback(delegate { ContinueSendingEvents(); }); var spi = (EPServiceProviderSPI)_epService; var metricsHandle = spi.MetricReportingService.GetStatementHandle(-1, "AbstractCoordinatedAdapter"); var lockImpl = ReaderWriterLockManager.CreateLock("CSV"); var stmtHandle = new EPStatementHandle(-1, "AbstractCoordinatedAdapter", null, StatementType.ESPERIO, "AbstractCoordinatedAdapter", false, metricsHandle, 0, false, false, spi.ServicesContext.MultiMatchHandlerFactory.GetDefaultHandler()); var agentInstanceHandle = new EPStatementAgentInstanceHandle(stmtHandle, lockImpl, -1, new StatementAgentInstanceFilterVersion(), null); var scheduleCSVHandle = new EPStatementHandleCallback(agentInstanceHandle, nextScheduleCallback); ScheduleSlot nextScheduleSlot; if (EventsToSend.IsEmpty()) { if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".scheduleNextCallback no events to send, scheduling callback in 100 ms"); } nextScheduleSlot = new ScheduleSlot(0, 0); _schedulingService.Add(100, scheduleCSVHandle, nextScheduleSlot); } else { // Offset is not a function of the currentTime alone. var first = EventsToSend.First(); long baseMsec = _currentTime - _startTime; long afterMsec = first.SendTime - baseMsec; nextScheduleSlot = first.ScheduleSlot; if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".scheduleNextCallback schedulingCallback in " + afterMsec + " milliseconds"); } _schedulingService.Add(afterMsec, scheduleCSVHandle, nextScheduleSlot); } }
/// <summary> /// Constructor. /// </summary> /// <param name="timeBatchViewFactory">for copying this view in a group-by</param> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeDeltaComputation">is the number of milliseconds to batch events for</param> /// <param name="numberOfEvents">is the event count before the batch fires off</param> /// <param name="forceOutput">is true if the batch should produce empty output if there is no value to output following time intervals</param> /// <param name="isStartEager">is true for start-eager</param> /// <param name="viewUpdatedCollection">is a collection that the view must Update when receiving events</param> public TimeLengthBatchView( TimeLengthBatchViewFactory timeBatchViewFactory, AgentInstanceViewFactoryChainContext agentInstanceContext, ExprTimePeriodEvalDeltaConst timeDeltaComputation, long numberOfEvents, bool forceOutput, bool isStartEager, ViewUpdatedCollection viewUpdatedCollection) { _agentInstanceContext = agentInstanceContext; _timeLengthBatchViewFactory = timeBatchViewFactory; _timeDeltaComputation = timeDeltaComputation; _numberOfEvents = numberOfEvents; _isStartEager = isStartEager; _viewUpdatedCollection = viewUpdatedCollection; _isForceOutput = forceOutput; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); // schedule the first callback if (isStartEager) { ScheduleCallback(0); } agentInstanceContext.AddTerminationCallback(Stop); }
/// <summary> /// Ctor. /// </summary> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeOrderViewFactory">for copying this view in a group-by</param> /// <param name="timestampExpr">the property name of the event supplying timestamp values</param> /// <param name="timestampEvaluator">The timestamp evaluator.</param> /// <param name="timeDeltaComputation">The time delta computation.</param> /// <param name="optionalSortedRandomAccess">is the friend class handling the random access, if required byexpressions</param> public TimeOrderView( AgentInstanceViewFactoryChainContext agentInstanceContext, TimeOrderViewFactory timeOrderViewFactory, ExprNode timestampExpr, ExprEvaluator timestampEvaluator, ExprTimePeriodEvalDeltaConst timeDeltaComputation, IStreamSortRankRandomAccess optionalSortedRandomAccess) { _agentInstanceContext = agentInstanceContext; _timeOrderViewFactory = timeOrderViewFactory; _timestampExpression = timestampExpr; _timestampEvaluator = timestampEvaluator; _timeDeltaComputation = timeDeltaComputation; _optionalSortedRandomAccess = optionalSortedRandomAccess; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); _sortedEvents = new OrderedDictionary <Object, Object>(); ScheduleHandleCallback callback = new ProxyScheduleHandleCallback { ProcScheduledTrigger = extensionServicesContext => Instrument.With( i => i.QViewScheduledEval(this, _timeOrderViewFactory.ViewName), i => i.AViewScheduledEval(), Expire) }; _handle = new EPStatementHandleCallback(agentInstanceContext.EpStatementAgentInstanceHandle, callback); agentInstanceContext.AddTerminationCallback(Stop); }
/// <inheritdoc /> public DateTime?CalculateNextRun(ScheduleSlot slot, DateTime afterDateTime) { if (slot == null) { throw new ArgumentNullException(nameof(slot)); } if (afterDateTime == null) { throw new ArgumentNullException(nameof(afterDateTime)); } if (slot.DayOfWeek.Equals(DaysOfWeek.None)) { return(null); } if (slot.DayOfWeek.HasFlag(afterDateTime.DayOfWeek.AsDaysOfWeek()) && slot.TimeOfDay >= afterDateTime.TimeOfDay) { return(afterDateTime.Date.Add(slot.TimeOfDay)); } var next = slot.DayOfWeek.Next(afterDateTime.DayOfWeek); int daysUntil = ((int)next - (int)afterDateTime.DayOfWeek + 7) % 7; // If the next day is the current weekday, we add a week. Because we already now it is not today if (daysUntil == 0) { daysUntil = 7; } return(afterDateTime.Date.AddDays(daysUntil).Add(slot.TimeOfDay)); }
/// <summary>Ctor. </summary> /// <param name="scheduleSpec">specification containing the crontab schedule</param> /// <param name="beginState">start state</param> /// <param name="observerEventEvaluator">receiver for events</param> public TimerAtObserver(ScheduleSpec scheduleSpec, MatchedEventMap beginState, ObserverEventEvaluator observerEventEvaluator) { _scheduleSpec = scheduleSpec; _beginState = beginState; _observerEventEvaluator = observerEventEvaluator; _scheduleSlot = observerEventEvaluator.Context.PatternContext.ScheduleBucket.AllocateSlot(); }
public bool CanCancelReservation(int reservationId) { Reservation reservation = reservationRepository.GetById(reservationId); if (reservation.ReservationStatus == ReservationStatus.Sold) // Check reservation date if older than 30 min or the scheduled movie starts in less than 15 minues { ScheduleSlot scheduleSlot = scheduleRepository.GetScheduleSlotById(reservation.ScheduleSlotId); if (scheduleSlot == null) { return(false); } ReservationDto reservationDto = parser.ToReservationDto(reservation); //Check if reservation is older than 30 minutes or if movie start is less than 15 minutes away. If so deny the cancellation if (DateTime.Now.Subtract(reservation.BookingDate).TotalMinutes > 30 || scheduleSlot.Start.Subtract(DateTime.Now).TotalMinutes < 15) { return(false); } } else { return(false); } return(true); }
/// <summary>Ctor. </summary> /// <param name="msec">number of millisecond to guard expiration</param> /// <param name="numCountTo">max number of counts</param> /// <param name="quitable">to use to indicate that the gaurd quitted</param> public TimerWithinOrMaxCountGuard(long msec, int numCountTo, Quitable quitable) { this._msec = msec; this._numCountTo = numCountTo; this._quitable = quitable; this._scheduleSlot = quitable.Context.PatternContext.ScheduleBucket.AllocateSlot(); }
/// <summary> /// Constructor. /// </summary> /// <param name="timeBatchViewFactory">for copying this view in a group-by</param> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeDeltaComputation">The time delta computation.</param> public TimeAccumViewRStream( TimeAccumViewFactory timeBatchViewFactory, AgentInstanceViewFactoryChainContext agentInstanceContext, ExprTimePeriodEvalDeltaConst timeDeltaComputation) { _agentInstanceContext = agentInstanceContext; _factory = timeBatchViewFactory; _timeDeltaComputation = timeDeltaComputation; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); ScheduleHandleCallback callback = new ProxyScheduleHandleCallback { ProcScheduledTrigger = extensionServicesContext => { using (Instrument.With( i => i.QViewScheduledEval(this, _factory.ViewName), i => i.AViewScheduledEval())) { SendRemoveStream(); } } }; _handle = new EPStatementHandleCallback(agentInstanceContext.EpStatementAgentInstanceHandle, callback); agentInstanceContext.AddTerminationCallback(Stop); }
/// <summary> /// Ctor. /// </summary> /// <param name="spec">The spec.</param> /// <param name="beginState">start state</param> /// <param name="observerEventEvaluator">receiver for events</param> /// <param name="isFilterChildNonQuitting">if set to <c>true</c> [is filter child non quitting].</param> public TimerScheduleObserver(TimerScheduleSpec spec, MatchedEventMap beginState, ObserverEventEvaluator observerEventEvaluator, bool isFilterChildNonQuitting) { _beginState = beginState; _observerEventEvaluator = observerEventEvaluator; _scheduleSlot = observerEventEvaluator.Context.PatternContext.ScheduleBucket.AllocateSlot(); _spec = spec; _isFilterChildNonQuitting = isFilterChildNonQuitting; }
/// <summary>Ctor. </summary> /// <param name="time">of schedule</param> /// <param name="slot">slot</param> /// <param name="handle">handle to use</param> public ScheduleSetEntry(long time, ScheduleSlot slot, ScheduleHandle handle) { Time = time; Slot = slot; Handle = handle; }
public ContextControllerConditionCrontab(StatementContext statementContext, ScheduleSlot scheduleSlot, ContextDetailConditionCrontab spec, ContextControllerConditionCallback callback, ContextInternalFilterAddendum filterAddendum) { _statementContext = statementContext; _scheduleSlot = scheduleSlot; _spec = spec; _callback = callback; _filterAddendum = filterAddendum; }
protected ExpressionViewBase( ViewUpdatedCollection viewUpdatedCollection, ExprEvaluator expiryExpression, AggregationServiceFactoryDesc aggregationServiceFactoryDesc, ObjectArrayEventBean builtinEventProps, ISet <String> variableNames, AgentInstanceViewFactoryChainContext agentInstanceContext) { ViewUpdatedCollection = viewUpdatedCollection; ExpiryExpression = expiryExpression; BuiltinEventProps = builtinEventProps; EventsPerStream = new EventBean[] { null, builtinEventProps }; VariableNames = variableNames; AgentInstanceContext = agentInstanceContext; if (variableNames != null && !variableNames.IsEmpty()) { foreach (String variable in variableNames) { var variableName = variable; var agentInstanceId = agentInstanceContext.AgentInstanceId; var variableService = agentInstanceContext.StatementContext.VariableService; agentInstanceContext.StatementContext.VariableService.RegisterCallback(variable, agentInstanceId, Update); agentInstanceContext.AddTerminationCallback(() => variableService.UnregisterCallback(variableName, agentInstanceId, Update)); } ScheduleHandleCallback callback = new ProxyScheduleHandleCallback { ProcScheduledTrigger = extensionServicesContext => Instrument.With( i => i.QViewScheduledEval(this, ViewName), i => i.AViewScheduledEval(), ScheduleCallback) }; ScheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); ScheduleHandle = new EPStatementHandleCallback(agentInstanceContext.EpStatementAgentInstanceHandle, callback); agentInstanceContext.AddTerminationCallback(Stop); } else { ScheduleSlot = null; ScheduleHandle = null; } if (aggregationServiceFactoryDesc != null) { AggregationService = aggregationServiceFactoryDesc.AggregationServiceFactory.MakeService(agentInstanceContext.AgentInstanceContext, agentInstanceContext.AgentInstanceContext.StatementContext.MethodResolutionService); AggregateNodes = aggregationServiceFactoryDesc.Expressions; } else { AggregationService = null; AggregateNodes = Collections.GetEmptyList <AggregationServiceAggExpressionDesc>(); } }
/// <summary>Ctor. </summary> /// <param name="timestamp">to send</param> /// <param name="scheduleSlot">the schedule slot assigned by scheduling service</param> protected AbstractSendableEvent(long timestamp, ScheduleSlot scheduleSlot) { if (scheduleSlot == null) { throw new ArgumentNullException("scheduleSlot"); } this.timestamp = timestamp; this.scheduleSlot = scheduleSlot; }
public OutputConditionCrontab(OutputCallback outputCallback, AgentInstanceContext context, OutputConditionCrontabFactory factory, bool isStartConditionOnCreation) : base(outputCallback) { _context = context; _factory = factory; _scheduleSlot = context.StatementContext.ScheduleBucket.AllocateSlot(); if (isStartConditionOnCreation) { UpdateOutputCondition(0, 0); } }
public void CalculatesRunForSunday() { var from = new DateTime(2020, 1, 1, 10, 00, 00, DateTimeKind.Utc); var slot = new ScheduleSlot { DayOfWeek = DaysOfWeek.Sunday, TimeOfDay = new TimeSpan(9, 00, 00) }; var engine = _mocker.CreateInstance <SchedulingEngine>(); var result = engine.CalculateNextRun(slot, from); Assert.Equal(new DateTime(2020, 1, 5, 9, 00, 00, DateTimeKind.Utc), result); }
public void CalculatesNoRun() { var from = new DateTime(2020, 1, 1, 10, 00, 00, DateTimeKind.Utc); var slot = new ScheduleSlot { DayOfWeek = DaysOfWeek.None, TimeOfDay = new TimeSpan(9, 00, 00) }; var engine = _mocker.CreateInstance <SchedulingEngine>(); var result = engine.CalculateNextRun(slot, from); Assert.Null(result); }
public Result ScheduleMovie(int roomId, ScheduleSlot scheduleSlot, bool saveChanges = true) { try { Room room = roomRepository.GetRoomById(roomId); if (room == null) { return(new Result(false)); } var test = databaseContext.ScheduleSlots.FirstOrDefault(x => x.ScheduleId == room.ScheduleId && x.Start < scheduleSlot.End && scheduleSlot.Start < x.End); // If scheduled slot overlaps with already scheduled movies return false if (databaseContext.ScheduleSlots.Any(x => x.ScheduleId == room.ScheduleId && x.Start < scheduleSlot.End && scheduleSlot.Start < x.End)) { return(new Result(false)); } Schedule schedule = GetScheduleById(room.ScheduleId); if (schedule == null) { return(new Result(false)); } ICollection <ScheduleSlot> dbScheduleSlots = databaseContext.ScheduleSlots.ToList(); int id = dbScheduleSlots.Count + 1; bool duplicateId = false; do { duplicateId = dbScheduleSlots.Any(x => x.Id == id); if (duplicateId) { id++; } } while (duplicateId); scheduleSlot.Id = id; schedule.MovieSchedule += string.IsNullOrWhiteSpace(schedule.MovieSchedule) ? id.ToString() : ";" + id; databaseContext.Schedules.Update(schedule); databaseContext.ScheduleSlots.Add(scheduleSlot); if (saveChanges) { databaseContext.SaveChanges(); } return(new Result()); } catch (Exception ex) { return(new Result(ex)); } }
public void Remove(ScheduleHandle handle, ScheduleSlot slot) { if (AuditPath.IsInfoEnabled) { StringWriter message = new StringWriter(); message.Write("remove handle "); PrintHandle(message, handle); AuditPath.AuditLog(_engineUri, _statementName, AuditEnum.SCHEDULE, message.ToString()); } _spi.Remove(handle, slot); }
/// <summary> /// Unassigns all employees from a targeted schedule slot. /// </summary> /// <param name="target">The schedule slot to clear out</param> public void UnassignAll(ScheduleSlot target) { // get a list of all the usernames of employees assigned to this shift List <string> targets = new List <string>(target.Assigned); // for each one foreach (string employee in targets) { // get the employee and unassign them this.UnassignEmployee(target, this._employees.ReturnEmployee(employee)); } }
public ScheduleSlotDto ToScheduleSlotDto(ScheduleSlot scheduleSlot) { return(new ScheduleSlotDto() { Id = scheduleSlot.Id, Start = scheduleSlot.Start, End = scheduleSlot.End, Movie = ToMovieDto(movieRepository.GetById(scheduleSlot.MovieId)), MovieId = scheduleSlot.MovieId, Reservations = ReservationsStringToList(scheduleSlot.Reservations), ScheduleId = scheduleSlot.ScheduleId }); }
// Queries public IEnumerable <ScheduleSlot> GetBookingSchedule(Guid trailerId, DateTime startDate, DateTime endDate) { var slotsPerDay = 3; var slotLength = 4; var startHrs = 8; //var slotsPerDay = 5; //var slotLength = 3; //var startHrs = 6; // generate schedule var scheduleSlots = new List <ScheduleSlot>(); for (var day = startDate; day < endDate; day = day.AddDays(1)) { for (int slot = 0; slot < slotsPerDay; slot++) { var hrs = startHrs + slot * slotLength; var startTime = day.AddHours(hrs); var endTime = startTime.AddHours(slotLength); if (slot == slotsPerDay - 1) { endTime = day.AddDays(1).AddHours(startHrs); } var scheduleSlot = new ScheduleSlot() { TrailerId = trailerId, StartTime = startTime.Ticks, StartUtc = startTime.ToString("s"), EndTime = endTime.Ticks, EndUtc = endTime.ToString("s"), IsAvailable = endTime >= DateTime.Now, Date = day.ToString("yyyy-MM-dd") }; scheduleSlots.Add(scheduleSlot); } } // set already booked items to not available scheduleSlots.ForEach(s => { if (_bookings.Any(booking => (booking.Start >= s.StartTime && booking.Start < s.EndTime) || (booking.End > s.StartTime && booking.End <= s.EndTime) )) { s.IsAvailable = false; } }); return(scheduleSlots); }
public ContextControllerConditionTimePeriod( String contextName, AgentInstanceContext agentInstanceContext, ScheduleSlot scheduleSlot, ContextDetailConditionTimePeriod spec, ContextControllerConditionCallback callback, ContextInternalFilterAddendum filterAddendum) { _contextName = contextName; _agentInstanceContext = agentInstanceContext; _scheduleSlot = scheduleSlot; _spec = spec; _callback = callback; _filterAddendum = filterAddendum; }
/// <summary> /// Attempts to unassigns employee to this shift. /// Only allows assignment if employee is allowed to work said shift. /// </summary> /// <param name="shift">ScheduleSlot object of shift in question.</param> /// <param name="Employee">Employee object of employee.</param> public void UnassignEmployee(ScheduleSlot shift, Employee employee) { // tries to unassign shift if (employee.UnassignShift(shift._shiftInfo)) { // unassigning shift was successful on employee end, update schedule slot shift.UnassignToThisShift(employee.Username); // decrement filled count this._totalShiftsFilled--; // update conflict list ConflictChecker(shift._shiftInfo, employee, false); } }
public ICollection <Reservation> GetReservationsForUserId(int userId, bool getReservationHistory) { List <Reservation> reservationHistory = new List <Reservation>(); DateTime now = DateTime.Now; foreach (Reservation reservation in databaseContext.Reservations.Where(x => x.UserId == userId).ToList()) { ScheduleSlot slot = scheduleRepository.GetScheduleSlotById(reservation.ScheduleSlotId); if (slot.Start < now && getReservationHistory || slot.Start >= now && !getReservationHistory) { reservationHistory.Add(reservation); } } return(reservationHistory); }
/// <summary> /// Constructor. /// </summary> /// <param name="timeFirstViewFactory">For copying this view in a group-by</param> /// <param name="agentInstanceContext">The agent instance context.</param> /// <param name="timeDeltaComputation">The time delta computation.</param> public FirstTimeView( FirstTimeViewFactory timeFirstViewFactory, AgentInstanceViewFactoryChainContext agentInstanceContext, ExprTimePeriodEvalDeltaConst timeDeltaComputation) { AgentInstanceContext = agentInstanceContext; _timeFirstViewFactory = timeFirstViewFactory; _timeDeltaComputation = timeDeltaComputation; _scheduleSlot = agentInstanceContext.StatementContext.ScheduleBucket.AllocateSlot(); ScheduleCallback(); agentInstanceContext.AddTerminationCallback(Stop); }
SchedulerResult AllocateRegisters(ProgramInfo prog_info, int min_ii) { // despite my grand schemes, I doing the simplest thing possible for now and going sequential const int first_reg = 16; const int last_reg = 128; const int num_regs = last_reg - first_reg; // there is a bit of redundency here. allowed_reg_list starts with the allowed range of registers // and then removes the ones that can't be touched. do_not_touch_list starts empty and adds the // list of registers we can't touch. List<int> allowed_reg_list = Enumerable.Range(first_reg, num_regs).ToList(); List<int> do_not_touch_list = new List<int>(); // for tracking unused slots List<int>[] unused_slots = new List<int>[2]; unused_slots[0] = new List<int>(); unused_slots[1] = new List<int>(); int reg_cycle = 0; // each line in the schedule for (int slot = 0; slot < m_schedule.GetLength(0); ++slot) { // odd and even pipeline for (int pipe = 0; pipe < 2; ++pipe) { // its a nop or lnop if (m_schedule[slot, pipe] == null) { unused_slots[pipe].Add(slot); continue; } if (m_schedule[slot, pipe].m_inst.m_reg_info[0].m_dependents.Count == 0 && m_schedule[slot, pipe].m_inst.m_reg_info[0].IsOutputOperand() == true) { if (do_not_touch_list.Contains(m_schedule[slot, pipe].m_inst.m_reg_info[0].m_allocated_reg) == false) { do_not_touch_list.Add(m_schedule[slot, pipe].m_inst.m_reg_info[0].m_allocated_reg); } } for (int reg = 1; reg < m_schedule[slot, pipe].m_inst.m_reg_info.Count; ++reg) { if (m_schedule[slot, pipe].m_inst.m_reg_info[reg].m_allocated_reg != -1 && m_schedule[slot, pipe].m_inst.m_reg_info[reg].m_dependency == null && m_schedule[slot, pipe].m_inst.m_reg_info[reg].IsOutputOperand() == false) { if (do_not_touch_list.Contains(m_schedule[slot, pipe].m_inst.m_reg_info[reg].m_allocated_reg) == false) { do_not_touch_list.Add(m_schedule[slot, pipe].m_inst.m_reg_info[reg].m_allocated_reg); } } } } } allowed_reg_list.RemoveAll(u => do_not_touch_list.Contains(u)); // do each iteration at a time for (int iter = 0; iter < m_total_iterations; ++iter) { // each line in the schedule for (int slot = 0; slot < m_schedule.GetLength(0); ++slot) { // odd and even pipeline for (int pipe = 0; pipe < 2; ++pipe) { // wrong iteration, or its a nop if (m_schedule[slot,pipe] == null || m_schedule[slot,pipe].m_iter != iter) { continue; } // new register choosing logic! This is gonna suck. Here goes // The registers that are problems are the ones that have dependents in later iterations and then only // if the schedule slot of the dependent instruction is > that of the instruction being scheduled. This // is most esaily explained with an example // a) add r32, r31, r31 // b) add r33, r32, 4 // c) add r34, r32, 4 // which then gets scheduled as: // 0) add r33, r32, 4 (instruction b, iteration n + 1) ; uses r32 from previous iteration // 1) add r32, r31, r31 (instruction a, iteration n) ; writes a new value in r32 // 2) add r34, r32, 4 (instruction c, iteration n + 1) ; error: _should_ use r32 from previous iteration // So lets get started. Look at each instruction's output operand, and consider each dependent. If every // dependent is in the same iteration, or in the next iteration and scheduled before the current instruction, // then we don't need any register copying and we can just use regular register assignment logic. Otherwise, // things start to suck. We have to first decide where to put the register copy, and that includes deciding // whether to use odd or even pipeline, and then fix up the instruction dependents and dependencies to include // the new copy instruction. ProgramInfo.InstructionNode current_inst = m_schedule[slot, pipe].m_inst; if (current_inst.m_reg_info.Count > 0 && current_inst.m_reg_info[0].IsOutputOperand()) { // starting out optimistic... bool register_needs_copying = false; foreach (ProgramInfo.DepPair dependent in current_inst.m_reg_info[0].m_dependents) { InstructionToScheduleMapNode schedule_slot_info = m_instruction_to_schedule_map[dependent.m_inst_num]; if (schedule_slot_info.m_iteration > iter && schedule_slot_info.m_schedule_slot > slot) { register_needs_copying = true; break; } } // common case... I hope if (!register_needs_copying) { if (!m_schedule[slot, pipe].m_inst.m_reg_info[0].m_is_locked) { int next_reg = allowed_reg_list[reg_cycle]; m_schedule[slot, pipe].m_inst.m_reg_info[0].m_allocated_reg = next_reg; for (int r = 0; r < m_schedule[slot, pipe].m_inst.m_reg_info[0].m_dependents.Count; ++r) { int dependent_inst = m_schedule[slot, pipe].m_inst.m_reg_info[0].m_dependents[r].m_inst_num; int dependent_inst_reg = m_schedule[slot, pipe].m_inst.m_reg_info[0].m_dependents[r].m_oper_num; prog_info.m_original_program[dependent_inst].m_reg_info[dependent_inst_reg].m_allocated_reg = next_reg; } reg_cycle = (reg_cycle + 1) % num_regs; } } // welcome to antidependency hell, bitches! else { // the register move has to be inserted somewhere between here and the the end of the schedule, // either in the odd pipeline or the even pipeline. So how to decide? I guess first we check // how many nop/lnops are in the schedule AFTER the current instruction (plus latency). if (slot + current_inst.m_latency >= min_ii) { return SchedulerResult.SCHEDULE_FAILED_REG_ALLOC_LIVE_TOO_LONG; } // now look for nops and lnops after this instruction. Maybe we can use // an odd copy if we don't need the results for more than 4 cycles, and // an even copy otherwise! int odd_copy_slot = -1; int even_copy_slot = -1; foreach (int s in unused_slots[1]) { // earliest spot is current instruction + latency // must be this iteration, no wrapping around // result of the copy must be done before the value is needed // note: we are only copying regs if the dependent is > current slot, and this final check reflects this. // if that logic changes, this has to change as well if (s >= slot + current_inst.m_latency && (s + 4 <= min_ii || (s + 4) % min_ii <= slot)) { odd_copy_slot = s; break; } } foreach (int s in unused_slots[0]) { if (s >= slot + current_inst.m_latency && (s + 2 <= min_ii || (s + 2) % min_ii <= slot)) { even_copy_slot = s; break; } } // nowhere valid to schedule this copy if (even_copy_slot == -1 && odd_copy_slot == -1) { return SchedulerResult.SCHEDULE_FAILED_REG_ALLOC_LIVE_TOO_LONG; } int copy_slot = odd_copy_slot != -1? odd_copy_slot : even_copy_slot; Program.Pipe copy_pipe = odd_copy_slot != -1? Program.Pipe.ODD : Program.Pipe.EVEN; // if we get in here, obviously this is not a locked register int next_reg = allowed_reg_list[reg_cycle]; reg_cycle = (reg_cycle + 1) % num_regs; m_schedule[slot, pipe].m_inst.m_reg_info[0].m_allocated_reg = next_reg; // prefer odd when possible, and eventually replace with a better metric ProgramInfo.InstructionNode regcopy = CreateRegcopyInst(copy_pipe); regcopy.m_reg_info[1].m_allocated_reg = next_reg; next_reg = allowed_reg_list[reg_cycle]; reg_cycle = (reg_cycle + 1) % num_regs; regcopy.m_reg_info[0].m_allocated_reg = next_reg; // we also have to store it in the original program at the end, just because thats where indices index into // note, these copies have to be removed (and the original program restored) on scheduling failure and retry prog_info.m_original_program.Add(regcopy); int new_copy_inst_index = prog_info.m_original_program.Count - 1; // adjust dependents and dependencies. Also needs to be restored on rescheduling for (int d = 0; d < current_inst.m_reg_info[0].m_dependents.Count; ++d) { ProgramInfo.DepPair dependent = current_inst.m_reg_info[0].m_dependents[d]; regcopy.m_reg_info[0].m_dependents.Add(new ProgramInfo.DepPair(dependent.m_inst_num, dependent.m_oper_num)); prog_info.m_original_program[dependent.m_inst_num].m_reg_info[dependent.m_oper_num].m_dependency = new ProgramInfo.DepPair(new_copy_inst_index, 0); prog_info.m_original_program[dependent.m_inst_num].m_reg_info[dependent.m_oper_num].m_allocated_reg = next_reg; } current_inst.m_reg_info[0].m_dependents.Clear(); current_inst.m_reg_info[0].m_dependents.Add(new ProgramInfo.DepPair(new_copy_inst_index, 1)); regcopy.m_reg_info[1].m_dependency = new ProgramInfo.DepPair(current_inst.m_original_inst_num, 0); m_instruction_to_schedule_map.Add(new InstructionToScheduleMapNode(copy_slot, iter)); // add it to the schedule m_schedule[copy_slot, (int)copy_pipe] = new ScheduleSlot(regcopy, iter); // now schedule the copy, fixing up all dependencies and dependents and other things m_log += string.Format("\nregister move required, inserting slot {0} pipe {1}", copy_slot, copy_pipe); } } } } } return SchedulerResult.SCHEDULE_SUCCEEDED; }
public void SimpleSchedule(ProgramInfo prog_info, CheatSheet cheat_sheet) { if (prog_info.m_original_program.Count == 0) { m_log = "\n\nno instructions found to schedule. Try writing some code"; m_as_string = ""; return; } m_log = "\n\nscheduling logic:"; int mii = prog_info.MinII; m_schedule = new ScheduleSlot[mii, 2]; m_instruction_to_schedule_map = Enumerable.Repeat<InstructionToScheduleMapNode>(null, prog_info.m_original_program.Count).ToList(); // schedule the final jump int final_slot = prog_info.m_original_program.Count - 1; ProgramInfo.InstructionNode final_jump_inst = prog_info.m_original_program[final_slot]; if (!final_jump_inst.IsBranch(cheat_sheet)) { Debug.Fail("last instruction must be a jump to the start of the loop"); m_log += "\nlast instruction must be a jump to the start of the loop"; return; } m_instruction_to_schedule_map[final_slot] = new InstructionToScheduleMapNode(mii - 1, 0); m_schedule[mii - 1, 1] = new ScheduleSlot(final_jump_inst, 0); // schedule other instruction for (int i = 0; i < prog_info.m_original_program.Count - 1; ++i) { // step 1: find all dependencies and figure out when the last one finishes // each operand can have at most one dependency ProgramInfo.InstructionNode inst = prog_info.m_original_program[i]; // don't schedule instructions that are unused or don't need to be included if (inst.m_include_in_schedule == false) { continue; } int num_regs = inst.m_reg_info.Count; if (inst.IsBranch(cheat_sheet)) { Debug.Fail("no jump instructions allowed in the middle of a loop"); return; } // absolute cycle time, not which slot in the schedule. iteration num * mii + schedule slot num int cycle_to_schedule = 0; for (int d = 0; d < num_regs; ++d) { ProgramInfo.DepPair dep_pair = inst.m_reg_info[d].m_dependency; if (dep_pair != null) { int dependency_index = dep_pair.m_inst_num; InstructionToScheduleMapNode dependency_location = m_instruction_to_schedule_map[dependency_index]; if (dependency_location.m_schedule_slot >= 0) { ProgramInfo.InstructionNode dependency = prog_info.m_original_program[dependency_index]; cycle_to_schedule = Math.Max ( cycle_to_schedule, dependency_location.m_iteration * mii + dependency_location.m_schedule_slot + dependency.m_latency ); } } } // step 2: see if that slot is free. If not, keep going until free slot found // todo: what happens if we can't find a valid schedule? We need to back up and reschedule int schedule_slot = cycle_to_schedule % mii; int schedule_iter = cycle_to_schedule / mii; int pipeline_index = inst.m_pipeline == Program.Pipe.EVEN ? 0 : 1; while (m_schedule[schedule_slot, pipeline_index] != null) { ++cycle_to_schedule; schedule_slot = cycle_to_schedule % mii; schedule_iter = cycle_to_schedule / mii; } // step 3: schedule the instruction m_instruction_to_schedule_map[i] = new InstructionToScheduleMapNode(schedule_slot, schedule_iter); m_schedule[schedule_slot, pipeline_index] = new ScheduleSlot(inst, schedule_iter); m_total_iterations = Math.Max(m_total_iterations, schedule_iter + 1); m_log += string.Format("\nscheduling {0} in slot {1} iteration {2}", inst.m_opcode, schedule_slot, schedule_iter); } // so now that we have our schedule and know what belongs to what iteration, do register allocation. // this is necessary mainly to avoid anti-dependencies from rearranging instructions. // TODO: because we are now inserting copies to deal with antidependencies, register allocation can // fail if there is no valid place to put the copy. We need to be in a loop and try to schedule again // if something fails AllocateRegisters(prog_info, mii); GeneratePrologue(cheat_sheet); m_as_string = BuildScheduleString(cheat_sheet); }