Ticket #11108: mythtv-11108-2.patch

File mythtv-11108-2.patch, 16.3 KB (added by gigem, 11 years ago)

Cleanup revision

  • 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) 
    18061806    RecIter   startIter       = reclist.begin();
    18071807    QDateTime idleSince       = QDateTime();
    18081808    int       maxSleep        = 60000; // maximum sleep time in milliseconds
    1809     int       schedRunTime    = 30; // max scheduler run time in seconds
     1809    int       schedRunTime    = 0; // max scheduler run time in seconds
    18101810    bool      statuschanged   = false;
     1811    QDateTime nextStartTime   = MythDate::current().addDays(1);
     1812    QDateTime nextSleepTime   = MythDate::current().addMSecs(maxSleep);
    18111813
    18121814    while (doRun)
    18131815    {
    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());
    18151831
    18161832        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));
    18191838
    18201839        // If we're about to start a recording don't do any reschedules...
    18211840        // instead sleep for a bit
    1822         if (secs_to_next < (schedRunTime + 2))
     1841        if (secs_to_next < schedRunTime + 2)
    18231842        {
    1824             int msecs = CalcTimeToNextHandleRecordingEvent(
    1825                 curtime, startIter, reclist, prerollseconds, maxSleep);
    18261843            LOG(VB_SCHEDULE, LOG_INFO,
    18271844                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);
    18311848            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;
    18331860        }
    18341861        else
    18351862        {
    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);
    18491875
    18501876            QTime t; t.start();
    1851             if (HaveQueuedRequests() && HandleReschedule())
     1877
     1878            if (HandleReschedule())
    18521879            {
    18531880                statuschanged = true;
    18541881                startIter = reclist.begin();
    1855 
    1856                 // The master backend is a long lived program, so
    1857                 // 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);
    18681882            }
    18691883
    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);
    18771886
    18781887            if (firstRun)
    18791888            {
     1889                firstRun = false;
    18801890                blockShutdown &= HandleRunSchedulerStartup(
    18811891                    prerollseconds, idleWaitForRecordingTime);
    1882                 firstRun = false;
    18831892
    18841893                // HandleRunSchedulerStartup releases the schedLock so the
    18851894                // reclist may have changed. If it has go to top of loop
    void Scheduler::run(void) 
    19021911            }
    19031912        }
    19041913
     1914        nextStartTime = MythDate::current().addDays(1);
     1915        nextSleepTime = MythDate::current().addMSecs(maxSleep);
     1916
    19051917        // Skip past recordings that are already history
    19061918        // (i.e. AddHistory() has been called setting oldrecstatus)
    19071919        for ( ; startIter != reclist.end(); ++startIter)
    void Scheduler::run(void) 
    19201932        for (RecIter it = startIter; it != reclist.end() && !done; ++it)
    19211933        {
    19221934            done = HandleRecording(
    1923                 **it, statuschanged, prerollseconds, tuningTimeout);
     1935                **it, statuschanged, nextStartTime, nextSleepTime,
     1936                prerollseconds, tuningTimeout);
    19241937        }
    19251938
    19261939        // HandleRecording() and HandleTuning() temporarily unlocks
    void Scheduler::run(void) 
    19621975    RunEpilog();
    19631976}
    19641977
    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 have
    1977         // 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         else
    2024         {
    2025             msecs = min(msecs, (secs_to_next-1) * 1000);
    2026         }
    2027     }
    2028 
    2029     return min(msecs, max_sleep);
    2030 }
    2031 
    20321978void Scheduler::ResetDuplicates(uint recordid, uint findid,
    20331979                                const QString &title, const QString &subtitle,
    20341980                                const QString &descrip,
    bool Scheduler::HandleReschedule(void) 
    21322078        if (request.size() < 1 || tokens.size() < 1)
    21332079        {
    21342080            LOG(VB_GENERAL, LOG_ERR, "Empty Reschedule request received");
    2135             return false;
     2081            continue;
    21362082        }
    21372083
    21382084        LOG(VB_GENERAL, LOG_INFO, QString("Reschedule requested for %1")
    void Scheduler::HandleWakeSlave(RecordingInfo &ri, int prerollseconds) 
    24382384
    24392385bool Scheduler::HandleRecording(
    24402386    RecordingInfo &ri, bool &statuschanged,
     2387    QDateTime &nextStartTime, QDateTime &nextSleepTime,
    24412388    int prerollseconds, int tuningTimeout)
    24422389{
    24432390    if (ri.GetRecordingStatus() == rsTuning)
    24442391    {
    2445         HandleTuning(ri, statuschanged, tuningTimeout);
     2392        HandleTuning(ri, statuschanged, nextSleepTime, tuningTimeout);
    24462393        return reclist_changed;
    24472394    }
    24482395
    24492396    if (ri.GetRecordingStatus() != rsWillRecord)
    24502397    {
    2451         if (ri.GetRecordingStatus() != ri.oldrecstatus &&
    2452             ri.GetRecordingStartTime() <= MythDate::current())
     2398        if (ri.GetRecordingStatus() != ri.oldrecstatus)
    24532399        {
    2454             ri.AddHistory(false);
     2400            if (ri.GetRecordingStartTime() <= MythDate::current())
     2401                ri.AddHistory(false);
     2402            else
     2403                nextSleepTime = min(nextSleepTime, ri.GetRecordingStartTime());
    24552404        }
    24562405        return false;
    24572406    }
    bool Scheduler::HandleRecording( 
    24632412
    24642413    // This check needs to be shorter than the related one in
    24652414    // SchedLiveTV().
    2466     if (secsleft - prerollseconds < 60)
     2415    if (secsleft - prerollseconds > 60)
    24672416    {
    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");
    24762430    }
    24772431
    24782432    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    }
    24802439
    24812440    QMap<int, EncoderLink*>::iterator tvit = m_tvList->find(ri.GetCardID());
    24822441    if (tvit == m_tvList->end())
    bool Scheduler::HandleRecording( 
    25152474    // changes.
    25162475    RecordingInfo tempri(ri);
    25172476
    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)
    25252480    {
    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;
    25302486
    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    }
    25352492
    25362493    if (secsleft > 30)
     2494    {
     2495        nextStartTime = min(nextStartTime, ri.GetRecordingStartTime());
     2496        nextSleepTime = min(nextSleepTime, curtime.addSecs(secsleft - 30));
    25372497        return false;
     2498    }
    25382499
    25392500    if (nexttv->IsWaking())
    25402501    {
    bool Scheduler::HandleRecording( 
    25682529            EnqueuePlace("SlaveNotAwake");
    25692530        }
    25702531
     2532        nextStartTime = min(nextStartTime, ri.GetRecordingStartTime());
     2533        nextSleepTime = min(nextSleepTime, curtime.addSecs(1));
    25712534        return false;
    25722535    }
    25732536
    bool Scheduler::HandleRecording( 
    25982561    }
    25992562
    26002563    if (secsleft > 0)
     2564    {
     2565        nextStartTime = min(nextStartTime, ri.GetRecordingStartTime());
     2566        nextSleepTime = min(nextSleepTime, curtime.addSecs(secsleft));
    26012567        return false;
     2568    }
    26022569
    26032570    QDateTime recstartts = MythDate::current(true).addSecs(30);
    26042571    recstartts = QDateTime(
    bool Scheduler::HandleRecording( 
    26222589            recStatus = nexttv->StartRecording(&tempri);
    26232590            schedLock.lock();
    26242591
     2592            if (recStatus == rsTuning)
     2593                nextSleepTime = min(nextSleepTime, curtime.addSecs(1));
     2594
    26252595            // activate auto expirer
    26262596            if (m_expirer)
    26272597                m_expirer->Update(ri.GetCardID(), fsID, true);
    void Scheduler::HandleRecordingStatusChange( 
    26722642}
    26732643
    26742644void Scheduler::HandleTuning(
    2675     RecordingInfo &ri, bool &statuschanged, int tuningTimeout)
     2645    RecordingInfo &ri, bool &statuschanged, QDateTime &nextSleepTime,
     2646    int tuningTimeout)
    26762647{
    26772648    if (rsTuning != ri.GetRecordingStatus())
    26782649        return;
    void Scheduler::HandleTuning( 
    27092680                            "%1 seconds, has been exceeded.")
    27102681                    .arg(tuningTimeout));
    27112682            }
     2683            else
     2684            {
     2685                nextSleepTime = min(nextSleepTime, curtime.addSecs(1));
     2686            }
    27122687        }
    27132688    }
    27142689
  • 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 
    159159                         const RecList &reclist);
    160160    void FillDirectoryInfoCache(bool force = false);
    161161
    162     int CalcTimeToNextHandleRecordingEvent(
    163         const QDateTime &curtime,
    164         RecConstIter startIter, const RecList &reclist,
    165         int prerollseconds, int max_sleep /*ms*/);
    166162    void OldRecordedFixups(void);
    167163    void ResetDuplicates(uint recordid, uint findid, const QString &title,
    168164                         const QString &subtitle, const QString &descrip,
    class Scheduler : public MThread, public MythScheduler 
    171167    bool HandleRunSchedulerStartup(
    172168        int prerollseconds, int idleWaitForRecordingTime);
    173169    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);
    179175    void HandleRecordingStatusChange(
    180176        RecordingInfo &ri, RecStatusTypes recStatus, const QString &details);
    181177    void HandleIdleShutdown(