00001 #ifndef SCHEDULER_H_
00002 #define SCHEDULER_H_
00003
00004
00005 #include <deque>
00006 #include <vector>
00007 using namespace std;
00008
00009
00010 #include <QWaitCondition>
00011 #include <QObject>
00012 #include <QString>
00013 #include <QMutex>
00014 #include <QMap>
00015 #include <QSet>
00016
00017
00018 #include "filesysteminfo.h"
00019 #include "recordinginfo.h"
00020 #include "remoteutil.h"
00021 #include "inputgroupmap.h"
00022 #include "mythdeque.h"
00023 #include "mythscheduler.h"
00024 #include "mthread.h"
00025 #include "scheduledrecording.h"
00026
00027 class EncoderLink;
00028 class MainServer;
00029 class AutoExpire;
00030
00031 class Scheduler;
00032
00033 class Scheduler : public MThread, public MythScheduler
00034 {
00035 public:
00036 Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
00037 QString recordTbl = "record", Scheduler *master_sched = NULL);
00038 ~Scheduler();
00039
00040 void Stop(void);
00041 void Wait(void) { MThread::wait(); }
00042
00043 void SetExpirer(AutoExpire *autoExpirer) { m_expirer = autoExpirer; }
00044
00045 void Reschedule(const QStringList &request);
00046 void RescheduleMatch(uint recordid, uint sourceid, uint mplexid,
00047 const QDateTime &maxstarttime, const QString &why)
00048 { Reschedule(ScheduledRecording::BuildMatchRequest(recordid, sourceid,
00049 mplexid, maxstarttime, why)); };
00050 void RescheduleCheck(const RecordingInfo &recinfo, const QString &why)
00051 { Reschedule(ScheduledRecording::BuildCheckRequest(recinfo, why)); };
00052 void ReschedulePlace(const QString &why)
00053 { Reschedule(ScheduledRecording::BuildPlaceRequest(why)); };
00054
00055 void AddRecording(const RecordingInfo&);
00056 void FillRecordListFromDB(uint recordid = 0);
00057 void FillRecordListFromMaster(void);
00058
00059 void UpdateRecStatus(RecordingInfo *pginfo);
00060 void UpdateRecStatus(uint cardid, uint chanid,
00061 const QDateTime &startts, RecStatusType recstatus,
00062 const QDateTime &recendts);
00063
00064
00065 bool GetAllPending(RecList &retList) const;
00066 virtual void GetAllPending(QStringList &strList) const;
00067 virtual QMap<QString,ProgramInfo*> GetRecording(void) const;
00068
00069 static void GetAllScheduled(QStringList &strList);
00070 static void GetAllScheduled(RecList &proglist);
00071
00072 void getConflicting(RecordingInfo *pginfo, QStringList &strlist);
00073 void getConflicting(RecordingInfo *pginfo, RecList *retlist);
00074
00075 void PrintList(bool onlyFutureRecordings = false)
00076 { PrintList(reclist, onlyFutureRecordings); };
00077 void PrintList(RecList &list, bool onlyFutureRecordings = false);
00078 void PrintRec(const RecordingInfo *p, const char *prefix = NULL);
00079
00080 void SetMainServer(MainServer *ms);
00081
00082 void SlaveConnected(RecordingList &slavelist);
00083 void SlaveDisconnected(uint cardid);
00084
00085 void DisableScheduling(void) { schedulingEnabled = false; }
00086 void EnableScheduling(void) { schedulingEnabled = true; }
00087 void GetNextLiveTVDir(uint cardid);
00088 void ResetIdleTime(void);
00089
00090 bool WasStartedAutomatically();
00091
00092 RecStatusType GetRecStatus(const ProgramInfo &pginfo);
00093
00094 int GetError(void) const { return error; }
00095
00096 protected:
00097 virtual void run(void);
00098
00099 private:
00100 QString recordTable;
00101 QString priorityTable;
00102
00103 bool VerifyCards(void);
00104
00105 void CreateTempTables(void);
00106 void DeleteTempTables(void);
00107 void UpdateDuplicates(void);
00108 bool FillRecordList(void);
00109 void UpdateMatches(uint recordid, uint sourceid, uint mplexid,
00110 const QDateTime maxstarttime);
00111 void UpdateManuals(uint recordid);
00112 void BuildWorkList(void);
00113 bool ClearWorkList(void);
00114 void AddNewRecords(void);
00115 void AddNotListed(void);
00116 void BuildNewRecordsQueries(uint recordid, QStringList &from,
00117 QStringList &where, MSqlBindings &bindings);
00118 void PruneOverlaps(void);
00119 void BuildListMaps(void);
00120 void ClearListMaps(void);
00121
00122 bool IsBusyRecording(const RecordingInfo *rcinfo);
00123
00124 bool IsSameProgram(const RecordingInfo *a, const RecordingInfo *b) const;
00125
00126 bool FindNextConflict(const RecList &cardlist,
00127 const RecordingInfo *p, RecConstIter &iter,
00128 int openEnd = 0) const;
00129 const RecordingInfo *FindConflict(const RecordingInfo *p, int openEnd = 0)
00130 const;
00131 void MarkOtherShowings(RecordingInfo *p);
00132 void MarkShowingsList(RecList &showinglist, RecordingInfo *p);
00133 void BackupRecStatus(void);
00134 void RestoreRecStatus(void);
00135 bool TryAnotherShowing(RecordingInfo *p, bool samePriority,
00136 bool preserveLive = false);
00137 void SchedNewRecords(void);
00138 void MoveHigherRecords(bool move_this = true);
00139 void SchedPreserveLiveTV(void);
00140 void PruneRedundants(void);
00141 void UpdateNextRecord(void);
00142
00143 bool ChangeRecordingEnd(RecordingInfo *oldp, RecordingInfo *newp);
00144
00145 bool CheckShutdownServer(int prerollseconds, QDateTime &idleSince,
00146 bool &blockShutdown);
00147 void ShutdownServer(int prerollseconds, QDateTime &idleSince);
00148 void PutInactiveSlavesToSleep(void);
00149 bool WakeUpSlave(QString slaveHostname, bool setWakingStatus = true);
00150 void WakeUpSlaves(void);
00151
00152 int FillRecordingDir(const QString &title,
00153 const QString &hostname,
00154 const QString &storagegroup,
00155 const QDateTime &recstartts,
00156 const QDateTime &recendts,
00157 uint cardid,
00158 QString &recording_dir,
00159 const RecList &reclist);
00160 void FillDirectoryInfoCache(bool force = false);
00161
00162 int CalcTimeToNextHandleRecordingEvent(
00163 const QDateTime &curtime,
00164 RecConstIter startIter, const RecList &reclist,
00165 int prerollseconds, int max_sleep );
00166 void OldRecordedFixups(void);
00167 void ResetDuplicates(uint recordid, uint findid, const QString &title,
00168 const QString &subtitle, const QString &descrip,
00169 const QString &programid);
00170 bool HandleReschedule(void);
00171 bool HandleRunSchedulerStartup(
00172 int prerollseconds, int idleWaitForRecordingTime);
00173 void HandleWakeSlave(RecordingInfo &ri, int prerollseconds);
00174 bool HandleRecording(
00175 RecordingInfo &ri, bool &statuschanged,
00176 int prerollseconds, int tuningTimeout);
00177 void HandleTuning(
00178 RecordingInfo &ri, bool &statuschanged, int tuningTimeout);
00179 void HandleRecordingStatusChange(
00180 RecordingInfo &ri, RecStatusTypes recStatus, const QString &details);
00181 void HandleIdleShutdown(
00182 bool &blockShutdown, QDateTime &idleSince, int prerollseconds,
00183 int idleTimeoutSecs, int idleWaitForRecordingTime,
00184 bool &statuschanged);
00185
00186 void EnqueueMatch(uint recordid, uint sourceid, uint mplexid,
00187 const QDateTime maxstarttime, const QString &why)
00188 { reschedQueue.enqueue(ScheduledRecording::BuildMatchRequest(recordid,
00189 sourceid, mplexid, maxstarttime, why)); };
00190 void EnqueueCheck(const RecordingInfo &recinfo, const QString &why)
00191 { reschedQueue.enqueue(ScheduledRecording::BuildCheckRequest(recinfo,
00192 why)); };
00193 void EnqueuePlace(const QString &why)
00194 { reschedQueue.enqueue(ScheduledRecording::BuildPlaceRequest(why)); };
00195
00196 MythDeque<QStringList> reschedQueue;
00197 mutable QMutex schedLock;
00198 QMutex recordmatchLock;
00199 QWaitCondition reschedWait;
00200 RecList reclist;
00201 RecList worklist;
00202 RecList retrylist;
00203 RecList conflictlist;
00204 QMap<uint, RecList> recordidlistmap;
00205 QMap<QString, RecList> titlelistmap;
00206 InputGroupMap igrp;
00207
00208 QDateTime schedTime;
00209 bool reclist_changed;
00210
00211 bool specsched;
00212 bool schedMoveHigher;
00213 bool schedulingEnabled;
00214 QMap<int, bool> schedAfterStartMap;
00215
00216 QMap<int, EncoderLink *> *m_tvList;
00217 AutoExpire *m_expirer;
00218
00219 QMap<QString, bool> recPendingList;
00220
00221 bool doRun;
00222
00223 MainServer *m_mainServer;
00224
00225 QMutex resetIdleTime_lock;
00226 bool resetIdleTime;
00227
00228 bool m_isShuttingDown;
00229 MSqlQueryInfo dbConn;
00230
00231 QDateTime fsInfoCacheFillTime;
00232 QMap<QString, FileSystemInfo> fsInfoCache;
00233
00234 int error;
00235
00236 QSet<QString> sysEvents[4];
00237
00238
00239 QDateTime livetvTime;
00240 int livetvpriority;
00241 int prefinputpri;
00242 QMap<QString, bool> hasLaterList;
00243
00244
00245 typedef pair<const RecordingInfo*,const RecordingInfo*> IsSameKey;
00246 typedef QMap<IsSameKey,bool> IsSameCacheType;
00247 mutable IsSameCacheType cache_is_same_program;
00248 };
00249
00250 #endif