Ticket #11108: mythtv-11108-1.patch
File mythtv-11108-1.patch, 14.9 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..30efca7 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 nextHardTime = MythDate::current().addDays(1); 1812 nextSoftTime = MythDate::current().addMSecs(maxSleep); 1811 1813 1812 1814 while (doRun) 1813 1815 { 1816 if (!doRun) 1817 break; 1818 1814 1819 reclist_changed = false; 1815 1820 1821 nextSoftTime = min(nextSoftTime, nextHardTime); 1822 nextSoftTime.addMSecs(-nextSoftTime.time().msec()); 1823 1816 1824 QDateTime curtime = MythDate::current(); 1817 int secs_to_next = (startIter != reclist.end()) ? 1818 curtime.secsTo((*startIter)->GetRecordingStartTime()) : 60*60; 1825 int secs_to_next = max(curtime.secsTo(nextHardTime), 0); 1826 int sched_sleep = max(curtime.msecsTo(nextSoftTime), (qint64)0); 1827 LOG(VB_GENERAL, LOG_INFO, 1828 QString("### s2n: %1 ss: %2)") 1829 .arg(secs_to_next).arg(sched_sleep)); 1819 1830 1820 1831 // If we're about to start a recording don't do any reschedules... 1821 1832 // instead sleep for a bit 1822 if (secs_to_next < (schedRunTime + 2))1833 if (secs_to_next < schedRunTime + 2) 1823 1834 { 1824 int msecs = CalcTimeToNextHandleRecordingEvent(1825 curtime, startIter, reclist, prerollseconds, maxSleep);1826 1835 LOG(VB_SCHEDULE, LOG_INFO, 1827 1836 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);1837 .arg(sched_sleep).arg(secs_to_next).arg(schedRunTime)); 1838 if (sched_sleep < 100) 1839 (void) ::usleep(sched_sleep); 1831 1840 else 1832 reschedWait.wait(&schedLock, msecs); 1841 { 1842 if (reschedWait.wait(&schedLock, sched_sleep)) 1843 continue; 1844 } 1845 } 1846 else if (!HaveQueuedRequests()) 1847 { 1848 LOG(VB_SCHEDULE, LOG_INFO, 1849 QString("sleeping for %1 ms (interuptable)").arg(sched_sleep)); 1850 if (reschedWait.wait(&schedLock, sched_sleep)) 1851 continue; 1833 1852 } 1834 1853 else 1835 1854 { 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 } 1855 // The master backend is a long lived program, so 1856 // we reload some key settings on each reschedule. 1857 prerollseconds = 1858 gCoreContext->GetNumSetting("RecordPreRoll", 0); 1859 wakeThreshold = 1860 gCoreContext->GetNumSetting("WakeUpThreshold", 300); 1861 idleTimeoutSecs = 1862 gCoreContext->GetNumSetting("idleTimeoutSecs", 0); 1863 idleWaitForRecordingTime = 1864 gCoreContext->GetNumSetting("idleWaitForRecordingTime", 15); 1865 tuningTimeout = 1866 gCoreContext->GetNumSetting("tuningTimeout", 180); 1849 1867 1850 1868 QTime t; t.start(); 1851 if (HaveQueuedRequests() && HandleReschedule()) 1869 1870 if (HandleReschedule()) 1852 1871 { 1853 1872 statuschanged = true; 1854 1873 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 1874 } 1869 1875 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 } 1876 schedRunTime = max((int)(((t.elapsed() + 999) / 1000) * 1.5f), 1877 schedRunTime); 1877 1878 1878 1879 if (firstRun) 1879 1880 { 1881 firstRun = false; 1880 1882 blockShutdown &= HandleRunSchedulerStartup( 1881 1883 prerollseconds, idleWaitForRecordingTime); 1882 firstRun = false;1883 1884 1884 1885 // HandleRunSchedulerStartup releases the schedLock so the 1885 1886 // reclist may have changed. If it has go to top of loop 1886 1887 // and update secs_to_next... 1887 1888 if (reclist_changed) 1889 { 1890 nextHardTime = MythDate::current(); 1888 1891 continue; 1892 } 1889 1893 } 1890 1894 1891 1895 // Unless a recording is about to start, check for slaves … … void Scheduler::run(void) 1902 1906 } 1903 1907 } 1904 1908 1909 nextHardTime = MythDate::current().addDays(1); 1910 nextSoftTime = MythDate::current().addMSecs(maxSleep); 1911 1905 1912 // Skip past recordings that are already history 1906 1913 // (i.e. AddHistory() has been called setting oldrecstatus) 1907 1914 for ( ; startIter != reclist.end(); ++startIter) … … void Scheduler::run(void) 1927 1934 // schedLock. If anything changed, reclist iterators could be 1928 1935 // invalidated so start over. 1929 1936 if (reclist_changed) 1937 { 1938 // Re-run immediately as there might be other recordings 1939 // that need to start now. 1940 nextHardTime = MythDate::current(); 1930 1941 continue; 1942 } 1931 1943 1932 1944 /// Wake any slave backends that need waking 1933 1945 curtime = MythDate::current(); … … void Scheduler::run(void) 1962 1974 RunEpilog(); 1963 1975 } 1964 1976 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 1977 void Scheduler::ResetDuplicates(uint recordid, uint findid, 2033 1978 const QString &title, const QString &subtitle, 2034 1979 const QString &descrip, … … bool Scheduler::HandleReschedule(void) 2132 2077 if (request.size() < 1 || tokens.size() < 1) 2133 2078 { 2134 2079 LOG(VB_GENERAL, LOG_ERR, "Empty Reschedule request received"); 2135 return false;2080 continue; 2136 2081 } 2137 2082 2138 2083 LOG(VB_GENERAL, LOG_INFO, QString("Reschedule requested for %1") … … bool Scheduler::HandleRecording( 2448 2393 2449 2394 if (ri.GetRecordingStatus() != rsWillRecord) 2450 2395 { 2451 if (ri.GetRecordingStatus() != ri.oldrecstatus && 2452 ri.GetRecordingStartTime() <= MythDate::current()) 2396 if (ri.GetRecordingStatus() != ri.oldrecstatus) 2453 2397 { 2454 ri.AddHistory(false); 2398 if (ri.GetRecordingStartTime() <= MythDate::current()) 2399 ri.AddHistory(false); 2400 else 2401 nextSoftTime = min(nextSoftTime, ri.GetRecordingStartTime()); 2455 2402 } 2456 2403 return false; 2457 2404 } … … bool Scheduler::HandleRecording( 2463 2410 2464 2411 // This check needs to be shorter than the related one in 2465 2412 // SchedLiveTV(). 2466 if (secsleft - prerollseconds <60)2413 if (secsleft - prerollseconds > 60) 2467 2414 { 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 } 2415 nextHardTime = min(nextHardTime, ri.GetRecordingStartTime()); 2416 nextSoftTime = min(nextSoftTime, curtime 2417 .addSecs(secsleft - prerollseconds - 60)); 2418 return true; 2419 } 2420 2421 if (!recPendingList.contains(schedid)) 2422 { 2423 recPendingList[schedid] = false; 2424 // If we haven't rescheduled in a while, do so now to 2425 // accomodate LiveTV. 2426 if (schedTime.secsTo(curtime) > 30) 2427 EnqueuePlace("PrepareToRecord"); 2476 2428 } 2477 2429 2478 2430 if (secsleft - prerollseconds > 35) 2479 return true; 2431 { 2432 nextHardTime = min(nextHardTime, ri.GetRecordingStartTime()); 2433 nextSoftTime = min(nextSoftTime, curtime 2434 .addSecs(secsleft - prerollseconds - 35)); 2435 return false; 2436 } 2480 2437 2481 2438 QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID()); 2482 2439 if (tvit == m_tvList->end()) … … bool Scheduler::HandleRecording( 2515 2472 // changes. 2516 2473 RecordingInfo tempri(ri); 2517 2474 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) 2475 if (prerollseconds > 0) 2525 2476 { 2526 // Will use pre-roll settings only if no other 2527 // program is currently being recorded 2528 secsleft -= prerollseconds; 2477 schedLock.unlock(); 2478 bool isBusyRecording = IsBusyRecording(&tempri); 2479 schedLock.lock(); 2480 if (reclist_changed) 2481 return reclist_changed; 2482 2483 if (isBusyRecording) 2484 { 2485 // Don't wait any longer than 5 seconds before checking 2486 // again. The recorder might free up and let us still use 2487 // some of the preroll. 2488 nextSoftTime = min(nextSoftTime, curtime.addSecs(5)); 2489 } 2490 else 2491 { 2492 // Will use pre-roll settings only if no other 2493 // program is currently being recorded 2494 secsleft -= prerollseconds; 2495 } 2529 2496 } 2530 2497 2531 2498 #if 0 … … bool Scheduler::HandleRecording( 2534 2501 #endif 2535 2502 2536 2503 if (secsleft > 30) 2504 { 2505 nextHardTime = min(nextHardTime, ri.GetRecordingStartTime()); 2506 nextSoftTime = min(nextSoftTime, curtime.addSecs(secsleft - 30)); 2537 2507 return false; 2508 } 2538 2509 2539 2510 if (nexttv->IsWaking()) 2540 2511 { … … bool Scheduler::HandleRecording( 2568 2539 EnqueuePlace("SlaveNotAwake"); 2569 2540 } 2570 2541 2542 nextHardTime = min(nextHardTime, ri.GetRecordingStartTime()); 2543 nextSoftTime = min(nextSoftTime, curtime.addSecs(1)); 2571 2544 return false; 2572 2545 } 2573 2546 … … bool Scheduler::HandleRecording( 2598 2571 } 2599 2572 2600 2573 if (secsleft > 0) 2574 { 2575 nextHardTime = min(nextHardTime, ri.GetRecordingStartTime()); 2576 nextSoftTime = min(nextSoftTime, curtime.addSecs(secsleft)); 2601 2577 return false; 2578 } 2602 2579 2603 2580 QDateTime recstartts = MythDate::current(true).addSecs(30); 2604 2581 recstartts = QDateTime( … … bool Scheduler::HandleRecording( 2622 2599 recStatus = nexttv->StartRecording(&tempri); 2623 2600 schedLock.lock(); 2624 2601 2602 if (recStatus == rsTuning) 2603 nextSoftTime = min(nextSoftTime, curtime.addSecs(1)); 2604 2625 2605 // activate auto expirer 2626 2606 if (m_expirer) 2627 2607 m_expirer->Update(ri.GetCardID(), fsID, true); … … void Scheduler::HandleTuning( 2709 2689 "%1 seconds, has been exceeded.") 2710 2690 .arg(tuningTimeout)); 2711 2691 } 2692 else 2693 { 2694 nextSoftTime = min(nextSoftTime, curtime.addSecs(1)); 2695 } 2712 2696 } 2713 2697 } 2714 2698 -
mythtv/programs/mythbackend/scheduler.h
diff --git a/mythtv/programs/mythbackend/scheduler.h b/mythtv/programs/mythbackend/scheduler.h index fedab8f..fd38a1f 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 217 213 InputGroupMap igrp; 218 214 219 215 QDateTime schedTime; 216 QDateTime nextHardTime; 217 QDateTime nextSoftTime; 220 218 bool reclist_changed; 221 219 222 220 bool specsched;