Ticket #11108: mythtv-11108-2.patch
File mythtv-11108-2.patch, 16.3 KB (added by , 11 years ago) |
---|
-
mythtv/programs/mythbackend/scheduler.cpp
diff --git a/mythtv/programs/mythbackend/scheduler.cpp b/mythtv/programs/mythbackend/scheduler.cpp index eed332a..4b75569 100644
a b void Scheduler::run(void) 1806 1806 RecIter startIter = reclist.begin(); 1807 1807 QDateTime idleSince = QDateTime(); 1808 1808 int maxSleep = 60000; // maximum sleep time in milliseconds 1809 int schedRunTime = 30; // max scheduler run time in seconds1809 int schedRunTime = 0; // max scheduler run time in seconds 1810 1810 bool statuschanged = false; 1811 QDateTime nextStartTime = MythDate::current().addDays(1); 1812 QDateTime nextSleepTime = MythDate::current().addMSecs(maxSleep); 1811 1813 1812 1814 while (doRun) 1813 1815 { 1814 reclist_changed = false; 1816 if (!doRun) 1817 break; 1818 1819 // If something changed, it might have short circuited a pass 1820 // through the list or changed the next run times. Start a 1821 // new pass immediately to take care of anything that still 1822 // needs attention right now and reset the run times. 1823 if (reclist_changed) 1824 { 1825 nextStartTime = MythDate::current(); 1826 reclist_changed = false; 1827 } 1828 1829 nextSleepTime = min(nextSleepTime, nextStartTime); 1830 nextSleepTime.addMSecs(-nextSleepTime.time().msec()); 1815 1831 1816 1832 QDateTime curtime = MythDate::current(); 1817 int secs_to_next = (startIter != reclist.end()) ? 1818 curtime.secsTo((*startIter)->GetRecordingStartTime()) : 60*60; 1833 int secs_to_next = max(curtime.secsTo(nextStartTime), 0); 1834 int sched_sleep = max(curtime.msecsTo(nextSleepTime), (qint64)0); 1835 LOG(VB_GENERAL, LOG_INFO, 1836 QString("### s2n: %1 ss: %2)") 1837 .arg(secs_to_next).arg(sched_sleep)); 1819 1838 1820 1839 // If we're about to start a recording don't do any reschedules... 1821 1840 // instead sleep for a bit 1822 if (secs_to_next < (schedRunTime + 2))1841 if (secs_to_next < schedRunTime + 2) 1823 1842 { 1824 int msecs = CalcTimeToNextHandleRecordingEvent(1825 curtime, startIter, reclist, prerollseconds, maxSleep);1826 1843 LOG(VB_SCHEDULE, LOG_INFO, 1827 1844 QString("sleeping for %1 ms (s2n: %2 sr: %3)") 1828 .arg(msecs).arg(secs_to_next).arg(schedRunTime));1829 if ( msecs< 100)1830 (void) ::usleep( msecs * 1000);1845 .arg(sched_sleep).arg(secs_to_next).arg(schedRunTime)); 1846 if (sched_sleep < 100) 1847 (void) ::usleep(sched_sleep); 1831 1848 else 1832 reschedWait.wait(&schedLock, msecs); 1849 { 1850 if (reschedWait.wait(&schedLock, sched_sleep)) 1851 continue; 1852 } 1853 } 1854 else if (!HaveQueuedRequests()) 1855 { 1856 LOG(VB_SCHEDULE, LOG_INFO, 1857 QString("sleeping for %1 ms (interuptable)").arg(sched_sleep)); 1858 if (reschedWait.wait(&schedLock, sched_sleep)) 1859 continue; 1833 1860 } 1834 1861 else 1835 1862 { 1836 if (!HaveQueuedRequests()) 1837 { 1838 int sched_sleep = (secs_to_next - schedRunTime - 1) * 1000; 1839 sched_sleep = min(sched_sleep, maxSleep); 1840 if (secs_to_next < prerollseconds + (maxSleep/1000)) 1841 sched_sleep = min(sched_sleep, 5000); 1842 LOG(VB_SCHEDULE, LOG_INFO, 1843 QString("sleeping for %1 ms (interuptable)") 1844 .arg(sched_sleep)); 1845 reschedWait.wait(&schedLock, sched_sleep); 1846 if (!doRun) 1847 break; 1848 } 1863 // The master backend is a long lived program, so 1864 // we reload some key settings on each reschedule. 1865 prerollseconds = 1866 gCoreContext->GetNumSetting("RecordPreRoll", 0); 1867 wakeThreshold = 1868 gCoreContext->GetNumSetting("WakeUpThreshold", 300); 1869 idleTimeoutSecs = 1870 gCoreContext->GetNumSetting("idleTimeoutSecs", 0); 1871 idleWaitForRecordingTime = 1872 gCoreContext->GetNumSetting("idleWaitForRecordingTime", 15); 1873 tuningTimeout = 1874 gCoreContext->GetNumSetting("tuningTimeout", 180); 1849 1875 1850 1876 QTime t; t.start(); 1851 if (HaveQueuedRequests() && HandleReschedule()) 1877 1878 if (HandleReschedule()) 1852 1879 { 1853 1880 statuschanged = true; 1854 1881 startIter = reclist.begin(); 1855 1856 // The master backend is a long lived program, so1857 // we reload some key settings on each reschedule.1858 prerollseconds =1859 gCoreContext->GetNumSetting("RecordPreRoll", 0);1860 wakeThreshold =1861 gCoreContext->GetNumSetting("WakeUpThreshold", 300);1862 idleTimeoutSecs =1863 gCoreContext->GetNumSetting("idleTimeoutSecs", 0);1864 idleWaitForRecordingTime =1865 gCoreContext->GetNumSetting("idleWaitForRecordingTime", 15);1866 tuningTimeout =1867 gCoreContext->GetNumSetting("tuningTimeout", 180);1868 1882 } 1869 1883 1870 int e = t.elapsed(); 1871 if (e > 0) 1872 { 1873 schedRunTime = (firstRun) ? 0 : schedRunTime; 1874 schedRunTime = 1875 max((int)(((e + 999) / 1000) * 1.5f), schedRunTime); 1876 } 1884 schedRunTime = max((int)(((t.elapsed() + 999) / 1000) * 1.5f), 1885 schedRunTime); 1877 1886 1878 1887 if (firstRun) 1879 1888 { 1889 firstRun = false; 1880 1890 blockShutdown &= HandleRunSchedulerStartup( 1881 1891 prerollseconds, idleWaitForRecordingTime); 1882 firstRun = false;1883 1892 1884 1893 // HandleRunSchedulerStartup releases the schedLock so the 1885 1894 // reclist may have changed. If it has go to top of loop … … void Scheduler::run(void) 1902 1911 } 1903 1912 } 1904 1913 1914 nextStartTime = MythDate::current().addDays(1); 1915 nextSleepTime = MythDate::current().addMSecs(maxSleep); 1916 1905 1917 // Skip past recordings that are already history 1906 1918 // (i.e. AddHistory() has been called setting oldrecstatus) 1907 1919 for ( ; startIter != reclist.end(); ++startIter) … … void Scheduler::run(void) 1920 1932 for (RecIter it = startIter; it != reclist.end() && !done; ++it) 1921 1933 { 1922 1934 done = HandleRecording( 1923 **it, statuschanged, prerollseconds, tuningTimeout); 1935 **it, statuschanged, nextStartTime, nextSleepTime, 1936 prerollseconds, tuningTimeout); 1924 1937 } 1925 1938 1926 1939 // HandleRecording() and HandleTuning() temporarily unlocks … … void Scheduler::run(void) 1962 1975 RunEpilog(); 1963 1976 } 1964 1977 1965 int Scheduler::CalcTimeToNextHandleRecordingEvent(1966 const QDateTime &curtime,1967 RecConstIter startIter, const RecList &reclist,1968 int prerollseconds, int max_sleep /*ms*/)1969 {1970 if (startIter == reclist.end())1971 return max_sleep;1972 1973 int msecs = max_sleep;1974 for (RecConstIter i = startIter; i != reclist.end() && (msecs > 0); ++i)1975 {1976 // Check on recordings that we've told to start, but have1977 // not yet started every second or so.1978 if ((*i)->GetRecordingStatus() == rsTuning)1979 {1980 msecs = min(msecs, 1000);1981 continue;1982 }1983 1984 // These recordings have already been handled..1985 if ((*i)->GetRecordingStatus() == (*i)->oldrecstatus)1986 continue;1987 1988 int secs_to_next = curtime.secsTo((*i)->GetRecordingStartTime());1989 1990 if ((*i)->GetRecordingStatus() == rsWillRecord &&1991 !recPendingList.contains((*i)->MakeUniqueSchedulerKey()))1992 secs_to_next -= 30;1993 1994 if (secs_to_next < 0)1995 {1996 msecs = 0;1997 break;1998 }1999 2000 // This is what normally breaks us out of the loop...2001 if (secs_to_next > max_sleep)2002 {2003 msecs = min(msecs, max_sleep);2004 break;2005 }2006 2007 if (secs_to_next > 31)2008 {2009 msecs = min(msecs, 30 * 1000);2010 continue;2011 }2012 2013 if ((secs_to_next-1) * 1000 > msecs)2014 continue;2015 2016 if (secs_to_next < 15)2017 {2018 QTime st = (*i)->GetRecordingStartTime().time();2019 int tmp = curtime.time().msecsTo(st);2020 tmp = (tmp < 0) ? tmp + 86400000 : tmp;2021 msecs = (tmp > 15*1000) ? 0 : min(msecs, tmp);2022 }2023 else2024 {2025 msecs = min(msecs, (secs_to_next-1) * 1000);2026 }2027 }2028 2029 return min(msecs, max_sleep);2030 }2031 2032 1978 void Scheduler::ResetDuplicates(uint recordid, uint findid, 2033 1979 const QString &title, const QString &subtitle, 2034 1980 const QString &descrip, … … bool Scheduler::HandleReschedule(void) 2132 2078 if (request.size() < 1 || tokens.size() < 1) 2133 2079 { 2134 2080 LOG(VB_GENERAL, LOG_ERR, "Empty Reschedule request received"); 2135 return false;2081 continue; 2136 2082 } 2137 2083 2138 2084 LOG(VB_GENERAL, LOG_INFO, QString("Reschedule requested for %1") … … void Scheduler::HandleWakeSlave(RecordingInfo &ri, int prerollseconds) 2438 2384 2439 2385 bool Scheduler::HandleRecording( 2440 2386 RecordingInfo &ri, bool &statuschanged, 2387 QDateTime &nextStartTime, QDateTime &nextSleepTime, 2441 2388 int prerollseconds, int tuningTimeout) 2442 2389 { 2443 2390 if (ri.GetRecordingStatus() == rsTuning) 2444 2391 { 2445 HandleTuning(ri, statuschanged, tuningTimeout);2392 HandleTuning(ri, statuschanged, nextSleepTime, tuningTimeout); 2446 2393 return reclist_changed; 2447 2394 } 2448 2395 2449 2396 if (ri.GetRecordingStatus() != rsWillRecord) 2450 2397 { 2451 if (ri.GetRecordingStatus() != ri.oldrecstatus && 2452 ri.GetRecordingStartTime() <= MythDate::current()) 2398 if (ri.GetRecordingStatus() != ri.oldrecstatus) 2453 2399 { 2454 ri.AddHistory(false); 2400 if (ri.GetRecordingStartTime() <= MythDate::current()) 2401 ri.AddHistory(false); 2402 else 2403 nextSleepTime = min(nextSleepTime, ri.GetRecordingStartTime()); 2455 2404 } 2456 2405 return false; 2457 2406 } … … bool Scheduler::HandleRecording( 2463 2412 2464 2413 // This check needs to be shorter than the related one in 2465 2414 // SchedLiveTV(). 2466 if (secsleft - prerollseconds <60)2415 if (secsleft - prerollseconds > 60) 2467 2416 { 2468 if (!recPendingList.contains(schedid)) 2469 { 2470 recPendingList[schedid] = false; 2471 // If we haven't rescheduled in a while, do so now to 2472 // accomodate LiveTV. 2473 if (schedTime.secsTo(curtime) > 30) 2474 EnqueuePlace("PrepareToRecord"); 2475 } 2417 nextStartTime = min(nextStartTime, ri.GetRecordingStartTime()); 2418 nextSleepTime = min(nextSleepTime, curtime 2419 .addSecs(secsleft - prerollseconds - 60)); 2420 return true; 2421 } 2422 2423 if (!recPendingList.contains(schedid)) 2424 { 2425 recPendingList[schedid] = false; 2426 // If we haven't rescheduled in a while, do so now to 2427 // accomodate LiveTV. 2428 if (schedTime.secsTo(curtime) > 30) 2429 EnqueuePlace("PrepareToRecord"); 2476 2430 } 2477 2431 2478 2432 if (secsleft - prerollseconds > 35) 2479 return true; 2433 { 2434 nextStartTime = min(nextStartTime, ri.GetRecordingStartTime()); 2435 nextSleepTime = min(nextSleepTime, curtime 2436 .addSecs(secsleft - prerollseconds - 35)); 2437 return false; 2438 } 2480 2439 2481 2440 QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID()); 2482 2441 if (tvit == m_tvList->end()) … … bool Scheduler::HandleRecording( 2515 2474 // changes. 2516 2475 RecordingInfo tempri(ri); 2517 2476 2518 schedLock.unlock(); 2519 bool isBusyRecording = IsBusyRecording(&tempri); 2520 schedLock.lock(); 2521 if (reclist_changed) 2522 return reclist_changed; 2523 2524 if (prerollseconds > 0 && !isBusyRecording) 2477 // Try to use preroll. If we can't right now, try again in a 2478 // little while in case the recorder frees up. 2479 if (prerollseconds > 0) 2525 2480 { 2526 // Will use pre-roll settings only if no other 2527 // program is currently being recorded 2528 secsleft -= prerollseconds; 2529 } 2481 schedLock.unlock(); 2482 bool isBusyRecording = IsBusyRecording(&tempri); 2483 schedLock.lock(); 2484 if (reclist_changed) 2485 return reclist_changed; 2530 2486 2531 #if 0 2532 LOG(VB_GENERAL, LOG_DEBUG, QString("%1 seconds until %2"). 2533 .arg(secsleft) .arg(ri.GetTitle())); 2534 #endif 2487 if (isBusyRecording) 2488 nextSleepTime = min(nextSleepTime, curtime.addSecs(5)); 2489 else 2490 secsleft -= prerollseconds; 2491 } 2535 2492 2536 2493 if (secsleft > 30) 2494 { 2495 nextStartTime = min(nextStartTime, ri.GetRecordingStartTime()); 2496 nextSleepTime = min(nextSleepTime, curtime.addSecs(secsleft - 30)); 2537 2497 return false; 2498 } 2538 2499 2539 2500 if (nexttv->IsWaking()) 2540 2501 { … … bool Scheduler::HandleRecording( 2568 2529 EnqueuePlace("SlaveNotAwake"); 2569 2530 } 2570 2531 2532 nextStartTime = min(nextStartTime, ri.GetRecordingStartTime()); 2533 nextSleepTime = min(nextSleepTime, curtime.addSecs(1)); 2571 2534 return false; 2572 2535 } 2573 2536 … … bool Scheduler::HandleRecording( 2598 2561 } 2599 2562 2600 2563 if (secsleft > 0) 2564 { 2565 nextStartTime = min(nextStartTime, ri.GetRecordingStartTime()); 2566 nextSleepTime = min(nextSleepTime, curtime.addSecs(secsleft)); 2601 2567 return false; 2568 } 2602 2569 2603 2570 QDateTime recstartts = MythDate::current(true).addSecs(30); 2604 2571 recstartts = QDateTime( … … bool Scheduler::HandleRecording( 2622 2589 recStatus = nexttv->StartRecording(&tempri); 2623 2590 schedLock.lock(); 2624 2591 2592 if (recStatus == rsTuning) 2593 nextSleepTime = min(nextSleepTime, curtime.addSecs(1)); 2594 2625 2595 // activate auto expirer 2626 2596 if (m_expirer) 2627 2597 m_expirer->Update(ri.GetCardID(), fsID, true); … … void Scheduler::HandleRecordingStatusChange( 2672 2642 } 2673 2643 2674 2644 void Scheduler::HandleTuning( 2675 RecordingInfo &ri, bool &statuschanged, int tuningTimeout) 2645 RecordingInfo &ri, bool &statuschanged, QDateTime &nextSleepTime, 2646 int tuningTimeout) 2676 2647 { 2677 2648 if (rsTuning != ri.GetRecordingStatus()) 2678 2649 return; … … void Scheduler::HandleTuning( 2709 2680 "%1 seconds, has been exceeded.") 2710 2681 .arg(tuningTimeout)); 2711 2682 } 2683 else 2684 { 2685 nextSleepTime = min(nextSleepTime, curtime.addSecs(1)); 2686 } 2712 2687 } 2713 2688 } 2714 2689 -
mythtv/programs/mythbackend/scheduler.h
diff --git a/mythtv/programs/mythbackend/scheduler.h b/mythtv/programs/mythbackend/scheduler.h index fedab8f..be4e9a4 100644
a b class Scheduler : public MThread, public MythScheduler 159 159 const RecList &reclist); 160 160 void FillDirectoryInfoCache(bool force = false); 161 161 162 int CalcTimeToNextHandleRecordingEvent(163 const QDateTime &curtime,164 RecConstIter startIter, const RecList &reclist,165 int prerollseconds, int max_sleep /*ms*/);166 162 void OldRecordedFixups(void); 167 163 void ResetDuplicates(uint recordid, uint findid, const QString &title, 168 164 const QString &subtitle, const QString &descrip, … … class Scheduler : public MThread, public MythScheduler 171 167 bool HandleRunSchedulerStartup( 172 168 int prerollseconds, int idleWaitForRecordingTime); 173 169 void HandleWakeSlave(RecordingInfo &ri, int prerollseconds); 174 bool HandleRecording( 175 RecordingInfo &ri, bool &statuschanged,176 int prerollseconds, int tuningTimeout);177 void HandleTuning( 178 RecordingInfo &ri, bool &statuschanged, int tuningTimeout);170 bool HandleRecording(RecordingInfo &ri, bool &statuschanged, 171 QDateTime &nextStartTime, QDateTime &nextSleepTime, 172 int prerollseconds, int tuningTimeout); 173 void HandleTuning(RecordingInfo &ri, bool &statuschanged, 174 QDateTime &nextSleepTime, int tuningTimeout); 179 175 void HandleRecordingStatusChange( 180 176 RecordingInfo &ri, RecStatusTypes recStatus, const QString &details); 181 177 void HandleIdleShutdown(