public void CancelSchedule(Schedule schedule) { bool alreadyCommitted = false; alreadyCommitted = context.SchedulingPool.Any(h => h.ScheduleID == schedule.Id); if (alreadyCommitted) { IrqHandle irqhandle = new IrqHandle() { ScheduleID = schedule.Id, Level = IRQL.Passive, TimeStamp = DateTime.Now }; context.IrqQueue.Add(irqhandle); } }
// TODO: set dispatch status to callback & generate interrupt // Only start time & callback info are allowed for updates public static void SetCallback(Dispatch ThisDispatch) { Dispatch dispatch; DbEntityEntry entry; IrqHandle irq; DateTime currentdatetimeutc = DateTime.UtcNow; using (SchedulingContext se = new SchedulingContext()) { dispatch = se.Dispatches.Find(ThisDispatch.Id); entry = se.Entry <Dispatch>(dispatch); entry.CurrentValues.SetValues(ThisDispatch); if (entry.State == System.Data.EntityState.Modified) { entry.Property("CreatedDateTimeUtc").CurrentValue = entry.Property("CreatedDateTimeUtc").OriginalValue; dispatch.LastModifiedDateTimeUtc = currentdatetimeutc; irq = new IrqHandle() { ScheduleID = ThisDispatch.ScheduleID, DispatchID = ThisDispatch.Id, Level = IRQL.Dispatch, TimeStamp = currentdatetimeutc }; se.IrqQueue.Add(irq); // simple strategy to retry only once on concurrency update failure try { se.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { // Update original values from the database entry = ex.Entries.Single(); entry.OriginalValues.SetValues(entry.GetDatabaseValues()); se.SaveChanges(); } } } }
protected override void Execute(CodeActivityContext context) { IEnumerable <IrqHandle> interrupts; IrqHandle currentIRQ = new IrqHandle(); bool isdispatchirq = false; bool irqlocked = false; DateTime currentdatetimeutc = DateTime.UtcNow; using (DispatchEngineContainer dec = new DispatchEngineContainer()) { isdispatchirq = dec.IrqQueue.Any(i => i.Level == IRQL.Dispatch); if (isdispatchirq) { interrupts = dec.IrqQueue.Where(irq => irq.Level == IRQL.Dispatch).ToArray(); } else { interrupts = dec.IrqQueue.ToArray(); } foreach (var irqhandle in interrupts) { irqhandle.TimeStamp = currentdatetimeutc; try { dec.SaveChanges(); dec.Entry(irqhandle).Reload(); currentIRQ = irqhandle; irqlocked = true; } catch (DbUpdateConcurrencyException ex) { // TODO: log exception & increment counter } if (irqlocked) { break; } } } if (irqlocked) { if (isdispatchirq) { Dispatch dispatch; bool isdispatchcallback; bool isdispatchready; using (DispatchEngineContainer dec = new DispatchEngineContainer()) { dispatch = dec.Dispatches.Single(d => d.Id == currentIRQ.DispatchID); isdispatchcallback = DispatchStatus.Callback == dispatch.StatusID; // we should check status pending to prevent completed/failed from running again isdispatchready = currentdatetimeutc > dispatch.StartDateTimeUtc && DispatchStatus.Pending == dispatch.StatusID; } if (isdispatchcallback) { Dispatcher.RelocateCallbackDispatch(currentIRQ); } else if (isdispatchready) { Dispatcher.MarkDispatchReady(currentIRQ); } else { Dispatcher.SweepSchedulingPool(currentIRQ); } } else { Schedule schedule = null; bool isscheduleadded; using (DispatchEngineContainer dec = new DispatchEngineContainer()) { try { schedule = dec.Schedules.Single(s => s.Id == currentIRQ.ScheduleID); } catch { // TODO: log exception & increment counter } isscheduleadded = !dec.SchedulingPool.Any(s => s.ScheduleID == currentIRQ.ScheduleID); } if (schedule != null) { if (isscheduleadded) { Dispatcher.MarkNewSchedule(currentIRQ); } else { Dispatcher.SweepSchedulingPool(currentIRQ); } } else { // bug fix to handle interrupts for schedules that has been deleted using (DispatchEngineContainer dec = new DispatchEngineContainer()) { // remove current interrupt dec.IrqQueue.Attach(currentIRQ); dec.IrqQueue.Remove(currentIRQ); dec.SaveChanges(); } } } } }
protected override CallbackResult Execute(CodeActivityContext context) { Dispatch dispatch; IrqHandle handle; List <CallbackDevice> devices2remove = new List <CallbackDevice>(); ScheduleContextData data = context.GetValue(this.ContextData); CallbackResult result = new CallbackResult() { ScheduleID = data.ScheduleID, DispatchID = data.DispatchID, Success = false, }; using (DispatchEngineContainer dec = new DispatchEngineContainer()) { try { dispatch = dec.Dispatches.Where(d => d.Id == data.DispatchID).Single(); dispatch.CallbackInfo = data.CallbackInfo; // Remove any devices not needed for callback if (data.Devices != null) { var deviceids = (from d in data.Devices select d.Id).ToList(); devices2remove = (from cd in dec.CallbackDevices where cd.DispatchID == data.DispatchID && !(from id in deviceids select id).Contains(cd.DeviceID) select cd).ToList(); } else { devices2remove = (from cd in dec.CallbackDevices where cd.DispatchID == data.DispatchID select cd).ToList(); } foreach (var callbackdevice in devices2remove) { dec.CallbackDevices.Remove(callbackdevice); } // set dispatch to callback status dispatch.StatusID = DispatchStatus.Callback; // Interrupt engine at dispatch level handle = new IrqHandle() { ScheduleID = dispatch.ScheduleID, DispatchID = dispatch.Id, Level = IRQL.Dispatch, TimeStamp = DateTime.Now }; dec.IrqQueue.Add(handle); dec.SaveChanges(); result.Success = true; } catch (Exception ex) { result.Success = false; result.ErrorMsg = ex.Message; } } return(result); }