private List <ScheduleEntry> GetScheduleEntriesForService(ScheduleEntries entriesInStore, Service service) { List <ScheduleEntry> entries = new List <ScheduleEntry>(); ServiceStartTimeKey start_key = new ServiceStartTimeKey(service, new DateTime(0)); long id = service.Id; using (StoredObjectsEnumerator <ScheduleEntry> enumerator = entriesInStore.GetStoredObjectsEnumerator()) { if (enumerator.Seek(start_key, SeekType.AfterEQ)) { do { ScheduleEntry entry = enumerator.Current; if (entry.Service == null) { Util.Trace(TraceLevel.Error, "Schedule entry with no service assignment: {0}", entry); continue; } if (entry.Service.Id != id) { break; } entries.Add(entry); } while (enumerator.MoveNext()); } } return(entries); }
public void CreateScheduleEntries() { // lopp through all data lines looking for header lines which determine a new Schedule Entry for (int index = 0; index < _dataLines.Count; index++) { if (ScheduleEntryLine.IsHeader(_dataLines[index])) { int entryStartLineIndex = index; // get the lines of text that constitute a schedule entry and intialise to a new ScheduleEntry ScheduleEntryInitialiser scheduleEntryInitialiser = new ScheduleEntryInitialiser(); ScheduleEntry scheduleEntry = scheduleEntryInitialiser.Initialise(entryStartLineIndex, _dataLines); // getting EntryText into a fixed column data structure EntryTextColumnBuilder builder = new EntryTextColumnBuilder(_ruleEngine, _whiteSpaceCalculator, _noteExtractor); string[] scheduleEntryColumns = builder.Build(scheduleEntry.EntryText); // setting relevant properties on Schedule Entry by using colum data ScheduleEntrySetter method = new ScheduleEntrySetter(scheduleEntry); method.Process(_noteExtractor, scheduleEntryColumns); // fast forward the loop to the already known next HEADER line index = scheduleEntryInitialiser.EntryEndLineIndex - 1; // add initialised entry to collection ScheduleEntries.Add(scheduleEntry); } } }
private void ReplacementConstructor(ObjectStore objStore) { OriginalConstructor(objStore); ScheduleEntries scheduleEntries = ThisAsScheduleEntries(); scheduleEntries.ProgramMerger.AlwaysReplace = true; scheduleEntries.ProgramMerger.NeverReplace = false; scheduleEntries.ProgramMatcher.MatchTitleEpisode = false; }
public MxfService getService(string stationId) { if (!_services.TryGetValue(stationId, out MxfService service)) { Services.Add(service = new MxfService() { index = Services.Count + 1, StationID = stationId }); ScheduleEntries.Add(service.mxfScheduleEntries); _services.Add(stationId, service); } return(service); }
public MxfService GetService(string stationId) { if (_services.TryGetValue(stationId, out var service)) { return(service); } Services.Add(service = new MxfService() { Index = Services.Count + 1, StationId = stationId }); ScheduleEntries.Add(service.MxfScheduleEntries); _services.Add(stationId, service); return(service); }
private void ReplacementMergeScheduleEntriesInner(ScheduleEntry[] scheduleEntriesToMerge) { if (scheduleEntriesToMerge.Count() == 0) { return; // nothing to do. } Util.WaitForBackgroundThreads(); Service targetService = scheduleEntriesToMerge[0].Service; Util.Trace(TraceLevel.Info, "Processing schedule entries for {0}", targetService); long id = targetService.Id; FixServiceAssignmentsForServiceChannels(targetService); Util.WaitForBackgroundThreads(); OriginalMergeScheduleEntries(scheduleEntriesToMerge); Util.WaitForBackgroundThreads(); ScheduleEntries self = ThisAsScheduleEntries(); Mutex mutex = null; try { mutex = targetService.AcquireUpdateLock(); List <ScheduleEntry> storeEntries = GetScheduleEntriesForService(new ScheduleEntries(self.ObjectStore), targetService); storeEntries.Sort(CompareScheduleEntryStartTimes); Util.Trace(TraceLevel.Verbose, "store: {0} mxf: {1}", ListScheduleEntrys(storeEntries), ListScheduleEntrys(scheduleEntriesToMerge)); #region pad store entry list with bogus begin/end time entries // Create bogus store entries at the beginning and end of time to make the loop below simpler. ScheduleEntry endOfTimeEntry = new ScheduleEntry(); endOfTimeEntry.StartTime = DateTime.MaxValue; endOfTimeEntry.EndTime = DateTime.MaxValue; storeEntries.Add(endOfTimeEntry); ScheduleEntry beginningOfTimeEntry = new ScheduleEntry(); beginningOfTimeEntry.StartTime = DateTime.MinValue; beginningOfTimeEntry.StartTime = DateTime.MinValue; storeEntries.Insert(0, beginningOfTimeEntry); #endregion List <ScheduleEntry> adds = new List <ScheduleEntry>(); List <ScheduleEntry> updates = new List <ScheduleEntry>(); List <ScheduleEntry> deletes = new List <ScheduleEntry>(); int mxfIndex = 0; int storeIndex = 1; DateTime lastMXFEndTime = new DateTime(0); while (mxfIndex < scheduleEntriesToMerge.Count()) { ScheduleEntry mxfEntry = scheduleEntriesToMerge[mxfIndex]; ScheduleEntry storeEntry = storeEntries[storeIndex]; if (lastMXFEndTime > storeEntry.StartTime) { ScheduleEntry lastMxfEntry = scheduleEntriesToMerge[mxfIndex - 1]; if (lastMXFEndTime > storeEntry.EndTime) { Util.Trace(TraceLevel.Verbose, "Store entry is contained within timeslot of previous MXF entry, removing it. store: {0} mxf: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { deletes.Add(storeEntry); } ++storeIndex; continue; } Util.Trace(TraceLevel.Verbose, "Store entry overlaps with previous MXF entry. Truncating start. store: {0} mxf: {1}", storeEntry, lastMxfEntry); if (!Program.options.safeMode) { storeEntry.StartTime = lastMxfEntry.EndTime; updates.Add(storeEntry); ++storeIndex; continue; } } if (TimeIsAboutAtOrBefore(storeEntry.EndTime, mxfEntry.StartTime)) { Util.Trace(TraceLevel.Verbose, "Ignoring store ScheduleEntry {0} as it does not overlap the current MXF entry : {1}", storeEntry, mxfEntry); ++storeIndex; continue; } if (TimeslotsMatch(mxfEntry, storeEntry)) { lastMXFEndTime = storeEntry.EndTime; if (mxfEntry.Program.Id != storeEntry.Program.Id) { SeriesInfo mxfSeries = mxfEntry.Program.Series; SeriesInfo storeSeries = storeEntry.Program.Series; if (mxfSeries != null && storeSeries != null && mxfSeries.Id == storeSeries.Id && mxfEntry.Program.IsGeneric && !storeEntry.Program.IsGeneric) { Util.Trace(TraceLevel.Info, "Skipping update because the MXF has a generic entry while DB already has a specific episode: store: {0} mxf: {1}", storeEntry, mxfEntry); } else { Util.Trace(TraceLevel.Warning, "Programs do not match after normal ScheduleEntriesToMerge, queueing update. Store: {0} MXF: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { storeEntry.Program = mxfEntry.Program; MergeProgramsInjector.UpdateScheduleEntryFlags(mxfEntry, storeEntry); updates.Add(storeEntry); } } } else if (!MergeProgramsInjector.ScheduleEntryFlagsMatch(storeEntry, mxfEntry)) { Util.Trace(TraceLevel.Warning, "Mismatched scheduleEntry flags found, queueing update. store: {0} MXF: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { MergeProgramsInjector.UpdateScheduleEntryFlags(mxfEntry, storeEntry); // MS MergeScheduleEntries treats this as an add/remove rather than an update. I don't like this, hopefully // this way can work. updates.Add(storeEntry); } } else { Util.Trace(TraceLevel.Verbose, "Entry for store and MXF already match: {0}", storeEntry); } ++mxfIndex; ++storeIndex; continue; } ScheduleEntry lastStoreEntry = storeEntries[storeIndex - 1]; // If we get here, store entry ends after mxf entry starts. Find out if the program ID matches; it may be only a timeslot change. if (storeEntry.Program.Id == mxfEntry.Program.Id) { Util.Trace(TraceLevel.Warning, "DB entry overlapping the MXF ScheduleEntry has the same program. Updating the timeslot and possibly flags. store: {0} MXF: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { if (TimeApproxEquals(mxfEntry.StartTime, lastStoreEntry.EndTime)) { storeEntry.StartTime = lastStoreEntry.EndTime; } else { storeEntry.StartTime = mxfEntry.StartTime; } ScheduleEntry nextStoreEntry = storeEntries[storeIndex + 1]; if (TimeApproxEquals(mxfEntry.EndTime, nextStoreEntry.StartTime)) { storeEntry.EndTime = nextStoreEntry.StartTime; } else { storeEntry.EndTime = mxfEntry.EndTime; } MergeProgramsInjector.UpdateScheduleEntryFlags(mxfEntry, storeEntry); updates.Add(storeEntry); } lastMXFEndTime = storeEntry.EndTime; ++mxfIndex; ++storeIndex; continue; } if (storeEntry.StartTime < mxfEntry.StartTime && TimeIsAboutAtOrBefore(storeEntry.EndTime, mxfEntry.EndTime)) { Util.Trace(TraceLevel.Warning, "DB entry overlapping MXF ScheduleEntry is earlier. Truncating the end of it. store: {0} mxf: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { storeEntry.EndTime = mxfEntry.StartTime; updates.Add(storeEntry); } ++storeIndex; continue; } if (TimeIsAboutAtOrBefore(mxfEntry.StartTime, storeEntry.StartTime) && TimeIsAboutAtOrBefore(storeEntry.EndTime, mxfEntry.EndTime)) { Util.Trace(TraceLevel.Warning, "DB entry timeslot is within MXF ScheduleEntry timeslot. Deleting it. store: {0} mxf: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { deletes.Add(storeEntry); } ++storeIndex; continue; } if (TimeIsAboutAtOrBefore(mxfEntry.EndTime, storeEntry.StartTime)) { Util.Trace(TraceLevel.Warning, "Next db entry is entirely after the MXF entry. Adding the MXF entry. store: {0} mxf: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { // check for rounding error. if (mxfEntry.EndTime > storeEntry.StartTime) { mxfEntry.EndTime = storeEntry.StartTime; } adds.Add(mxfEntry); } lastMXFEndTime = mxfEntry.EndTime; ++mxfIndex; continue; } // If we ge there, store entry starts within MXF entry and ends later. Util.Trace(TraceLevel.Warning, "Overlapping store entry is at end of MXF ScheduleEntry. Truncating the start. store: {0} mxf: {1}", storeEntry, mxfEntry); if (!Program.options.safeMode) { storeEntry.StartTime = mxfEntry.EndTime; updates.Add(storeEntry); } ++storeIndex; } if (!Program.options.safeMode && updates.Count + adds.Count + deletes.Count > 0) { List <ScheduleEntry> emptyList = new List <ScheduleEntry>(); ApplyMergedScheduleEntriesToStore(targetService, emptyList, emptyList, deletes); ApplyMergedScheduleEntriesToStore(targetService, updates, emptyList, emptyList); ApplyMergedScheduleEntriesToStore(targetService, emptyList, adds, emptyList); } } finally { targetService.ReleaseUpdateLock(mutex); } }
private List<ScheduleEntry> GetScheduleEntriesForService(ScheduleEntries entriesInStore, Service service) { List<ScheduleEntry> entries = new List<ScheduleEntry>(); ServiceStartTimeKey start_key = new ServiceStartTimeKey(service, new DateTime(0)); long id = service.Id; using (StoredObjectsEnumerator<ScheduleEntry> enumerator = entriesInStore.GetStoredObjectsEnumerator()) { if (enumerator.Seek(start_key, SeekType.AfterEQ)) { do { ScheduleEntry entry = enumerator.Current; if (entry.Service == null) { Util.Trace(TraceLevel.Error, "Schedule entry with no service assignment: {0}", entry); continue; } if (entry.Service.Id != id) break; entries.Add(entry); } while (enumerator.MoveNext()); } } return entries; }