/// <summary> /// set event new schedule created /// </summary> /// <param name="e"></param> private void OnNewScheduleCreated(SchedulingInformationEventArgs e) { if (NewScheduleCreatedEvent != null) { NewScheduleCreatedEvent(this, e); } }
//================================== #endregion #region Scheduling algorithms //================================== /// <summary> /// The main method of creating scheduler /// </summary> private void Schedule(bool reschedule = false) { lock (_unscheduledRequests) { lock (_scheduledRequests) { // Set need reschedule to false in order to avoid more schedule from other threads _needReschedule = false; #region Manage history and find services to schedule // ------------------------------------ // Move pending uninitialized services to the unscheduled list so they can be rescheduled foreach (SchedulingRequest request in _scheduledRequests.RemoveNotActivated()) { if (request.RequestedTime + request.Rule.MaxDeviationAfter > DateTime.Now) { _unscheduledRequests.Add(request); } else { request.SchedulingStatus = SchedulingStatus.Expired; } } // Get Services for next time line foreach (SchedulingRequest request in GetServicesForTimeLine(reschedule)) { _unscheduledRequests.Add(request); } // Copy unscheduled requests to an ordered list var servicesForNextTimeLine = new List <SchedulingRequest>(_unscheduledRequests .OrderBy(schedulingdata => schedulingdata.RequestedTime) .ThenByDescending(schedulingdata => schedulingdata.Configuration.Priority) ); // ------------------------------------ #endregion #region Find Match services // ------------------------------------ //Same services or same services with same profile foreach (SchedulingRequest schedulingRequest in servicesForNextTimeLine) { //Get all services with same configurationID var requestsWithSameConfiguration = _scheduledRequests.GetWithSameConfiguration(schedulingRequest); //Get all services with same profileID var requestsWithSameProfile = _scheduledRequests.GetWithSameProfile(schedulingRequest); //Find the first available time this service with specific service and profile TimeSpan avgExecutionTime = GetAverageExecutionTime(schedulingRequest.Configuration.Name, schedulingRequest.Configuration.Profile.ID, _percentile); DateTime baseStartTime = (schedulingRequest.RequestedTime < DateTime.Now) ? DateTime.Now : schedulingRequest.RequestedTime; DateTime baseEndTime = baseStartTime.Add(avgExecutionTime); DateTime calculatedStartTime = baseStartTime; DateTime calculatedEndTime = baseEndTime; bool found = false; while (!found) { IOrderedEnumerable <SchedulingRequest> whereToLookNext = null; int countedPerConfiguration = requestsWithSameConfiguration.Count(s => (calculatedStartTime >= s.ScheduledStartTime && calculatedStartTime <= s.ScheduledEndTime) || (calculatedEndTime >= s.ScheduledStartTime && calculatedEndTime <= s.ScheduledEndTime)); if (countedPerConfiguration < schedulingRequest.Configuration.MaxConcurrent) { int countedPerProfile = requestsWithSameProfile.Count(s => (calculatedStartTime >= s.ScheduledStartTime && calculatedStartTime <= s.ScheduledEndTime) || (calculatedEndTime >= s.ScheduledStartTime && calculatedEndTime <= s.ScheduledEndTime)); if (countedPerProfile < schedulingRequest.Configuration.MaxConcurrentPerProfile) { if (!(schedulingRequest.Configuration is ServiceInstanceConfiguration)) { // Not a child instance, so we need to create a new instance ServiceInstance serviceInstance = ServiceInstance.FromLegacyInstance( Legacy.Service.CreateInstance(schedulingRequest.Configuration.LegacyConfiguration, int.Parse(schedulingRequest.Configuration.Profile.Settings["AccountID"].ToString())), schedulingRequest.Configuration ); // Make the request point to the instance configuration now that we have it schedulingRequest.Configuration = serviceInstance.Configuration; } schedulingRequest.ScheduledStartTime = calculatedStartTime; schedulingRequest.ScheduledEndTime = calculatedEndTime; schedulingRequest.Instance.SchedulingRequest = schedulingRequest; schedulingRequest.Instance.StateChanged += new EventHandler(Instance_StateChanged); schedulingRequest.Instance.OutcomeReported += new EventHandler(Instance_OutcomeReported); // Legacy stuff TimeSpan maxExecutionTime = TimeSpan.FromMilliseconds(avgExecutionTime.TotalMilliseconds * double.Parse(AppSettings.Get(this, "MaxExecutionTimeProduct"))); schedulingRequest.Configuration.MaxExecutionTime = maxExecutionTime; found = true; } else { whereToLookNext = requestsWithSameProfile; } } else { whereToLookNext = requestsWithSameConfiguration; } if (!found) { if (whereToLookNext == null) { throw new Exception("This should not have happened."); } calculatedStartTime = whereToLookNext.Where(s => s.ScheduledEndTime >= calculatedStartTime).Min(s => s.ScheduledEndTime); if (calculatedStartTime < DateTime.Now) { calculatedStartTime = DateTime.Now; } //Get end time calculatedEndTime = calculatedStartTime.Add(avgExecutionTime); ////remove unfree time from servicePerConfiguration and servicePerProfile if (calculatedStartTime <= _timeLineTo) { requestsWithSameConfiguration = from s in requestsWithSameConfiguration where s.ScheduledEndTime > calculatedStartTime orderby s.ScheduledStartTime select s; requestsWithSameProfile = from s in requestsWithSameProfile where s.ScheduledEndTime > calculatedStartTime orderby s.ScheduledStartTime select s; } } } if (schedulingRequest.ActualDeviation <= schedulingRequest.Rule.MaxDeviationAfter || schedulingRequest.Rule.MaxDeviationAfter == TimeSpan.Zero) { _scheduledRequests.Add(schedulingRequest); _unscheduledRequests.Remove(schedulingRequest); schedulingRequest.SchedulingStatus = SchedulingStatus.Scheduled; } } #endregion } SchedulingInformationEventArgs args = new SchedulingInformationEventArgs(); args.ScheduleInformation = new List <SchedulingRequest>(); foreach (var scheduleService in _scheduledRequests) { args.ScheduleInformation.Add(scheduleService); } OnNewScheduleCreated(args); NotifyServicesToRun(); } }