Example #1
0
        static int Main(string[] args)
        {
            AppDomain currentDomain = AppDomain.CurrentDomain;

            currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(UnhandledThreadExceptionHandler);
            //ObjectStore.WaitForThenBlockBackgroundThreads(10000);
            try
            {
                if (!CommandLine.Parser.Default.ParseArguments(args, options))
                {
                    Console.WriteLine("Invalid command line options: {0}", options.GetUsage());
                    return(-1);
                }
                ScheduleEntriesInjector.InjectReplacementScheduleEntriesMethods();
                //MergeProgramsInjector.ReplaceMergePrograms();
                MergeProgramsInjector.ReplaceCheckIfProgramsMatch();
//                new SchedulerWorkerInjector().ReplaceThreadSetup();
                StoredObjectsEnumeratorInjector.ReplaceUpdate();
                ObjectStore objStore = Util.object_store;
                MxfImporter.Import(new StreamReader(options.inputMxfPath).BaseStream, Util.object_store, MxfImportProgressCallback);
                Console.WriteLine("Waiting for any background threads to complete.");
                Util.WaitForBackgroundThreads();
            }
            catch (Exception e) {
                Console.WriteLine("Exception occurred: {0} {1}", e, e.StackTrace);
                return(-1);
            }
            if (options.reindexWhenDone)
            {
                reindexDatabase();
            }
            return(0);
        }
        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);
            }
        }