|
MythTV
0.26-pre
|
00001 // POSIX headers 00002 #include <unistd.h> 00003 #include <sys/types.h> 00004 #include <unistd.h> 00005 00006 // ANSI C headers 00007 #include <cstdlib> 00008 00009 // C++ headers 00010 #include <iostream> 00011 using namespace std; 00012 00013 // Qt headers 00014 #include <QStringList> 00015 #include <QDateTime> 00016 #include <QDir> 00017 #include <QFileInfo> 00018 00019 // MythTV headers 00020 #include "housekeeper.h" 00021 #include "jobqueue.h" 00022 #include "mythcorecontext.h" 00023 #include "mythdb.h" 00024 #include "mythmiscutil.h" 00025 #include "compat.h" 00026 #include "mythdirs.h" 00027 #include "programinfo.h" 00028 #include "eitcache.h" 00029 #include "scheduler.h" 00030 #include "mythcoreutil.h" 00031 #include "mythdownloadmanager.h" 00032 #include "exitcodes.h" 00033 #include "mythversion.h" 00034 #include "mythlogging.h" 00035 00036 void HouseKeepingThread::run(void) 00037 { 00038 RunProlog(); 00039 m_parent->RunHouseKeeping(); 00040 RunEpilog(); 00041 } 00042 00043 void MythFillDatabaseThread::run(void) 00044 { 00045 RunProlog(); 00046 m_parent->RunMFD(); 00047 RunEpilog(); 00048 } 00049 00050 HouseKeeper::HouseKeeper(bool runthread, bool master, Scheduler *lsched) : 00051 isMaster(master), sched(lsched), 00052 houseKeepingRun(runthread), houseKeepingThread(NULL), 00053 fillDBThread(NULL), fillDBStarted(false), 00054 fillDBMythSystem(NULL) 00055 { 00056 CleanupMyOldRecordings(); 00057 00058 if (runthread) 00059 { 00060 houseKeepingThread = new HouseKeepingThread(this); 00061 houseKeepingThread->start(); 00062 00063 QMutexLocker locker(&houseKeepingLock); 00064 while (houseKeepingRun && !houseKeepingThread->isRunning()) 00065 houseKeepingWait.wait(locker.mutex()); 00066 } 00067 } 00068 00069 HouseKeeper::~HouseKeeper() 00070 { 00071 if (houseKeepingThread) 00072 { 00073 { 00074 QMutexLocker locker(&houseKeepingLock); 00075 houseKeepingRun = false; 00076 houseKeepingWait.wakeAll(); 00077 } 00078 houseKeepingThread->wait(); 00079 delete houseKeepingThread; 00080 houseKeepingThread = NULL; 00081 } 00082 00083 if (fillDBThread) 00084 { 00085 KillMFD(); 00086 delete fillDBThread; 00087 fillDBThread = NULL; 00088 } 00089 } 00090 00091 bool HouseKeeper::wantToRun(const QString &dbTag, int period, int minhour, 00092 int maxhour, bool nowIfPossible) 00093 { 00094 bool runOK = false; 00095 unsigned int oneday = 60 * 60 * 24; 00096 int longEnough = 0; 00097 00098 if (period) 00099 longEnough = ((period * oneday) - oneday/2); 00100 else 00101 longEnough = oneday / 8; 00102 00103 QDateTime now = QDateTime::currentDateTime(); 00104 QDateTime lastrun; 00105 lastrun.setTime_t(0); 00106 00107 if (minhour < 0) 00108 minhour = 0; 00109 if (maxhour > 23) 00110 maxhour = 23; 00111 00112 MSqlQuery result(MSqlQuery::InitCon()); 00113 if (result.isConnected()) 00114 { 00115 result.prepare("SELECT lastrun FROM housekeeping WHERE tag = :TAG ;"); 00116 result.bindValue(":TAG", dbTag); 00117 00118 if (result.exec() && result.next()) 00119 { 00120 lastrun = result.value(0).toDateTime(); 00121 00122 if ((lastrun.secsTo(now) > longEnough) && 00123 (now.date().day() != lastrun.date().day())) 00124 { 00125 int hour = now.time().hour(); 00126 00127 if (((minhour > maxhour) && 00128 ((hour <= maxhour) || (hour >= minhour))) || 00129 ((hour >= minhour) && (hour <= maxhour))) 00130 { 00131 int minute = now.time().minute(); 00132 // Allow the job run if 00133 // a) we want to run now rather than at a random time 00134 // b) we have reached the last half hour of the window, or 00135 // c) we win a random draw with a probability of 1/N. 00136 // 00137 // N gets smaller the nearer we are to the end of the 00138 // window. The "(24 + ...) % 24" makes sure the calculation 00139 // is correct even for the case hour > minhour > maxhour. 00140 if ((nowIfPossible) || 00141 (hour == maxhour && minute > 30) || 00142 ((random()%((((24+maxhour-hour)%24)*12+(60-minute)/5 - 6) + 1)) == 0)) 00143 runOK = true; 00144 } 00145 } 00146 } 00147 else 00148 { 00149 result.prepare("INSERT INTO housekeeping(tag,lastrun) " 00150 "values(:TAG ,now());"); 00151 result.bindValue(":TAG", dbTag); 00152 if (!result.exec()) 00153 MythDB::DBError("HouseKeeper::wantToRun -- insert", result); 00154 00155 runOK = true; 00156 } 00157 } 00158 00159 return runOK; 00160 } 00161 00162 void HouseKeeper::updateLastrun(const QString &dbTag) 00163 { 00164 MSqlQuery result(MSqlQuery::InitCon()); 00165 if (result.isConnected()) 00166 { 00167 result.prepare("DELETE FROM housekeeping WHERE tag = :TAG ;"); 00168 result.bindValue(":TAG", dbTag); 00169 if (!result.exec()) 00170 MythDB::DBError("HouseKeeper::updateLastrun -- delete", result); 00171 00172 result.prepare("INSERT INTO housekeeping(tag,lastrun) " 00173 "values(:TAG ,now()) ;"); 00174 result.bindValue(":TAG", dbTag); 00175 if (!result.exec()) 00176 MythDB::DBError("HouseKeeper::updateLastrun -- insert", result); 00177 } 00178 } 00179 00180 QDateTime HouseKeeper::getLastRun(const QString &dbTag) 00181 { 00182 QDateTime lastRun; 00183 MSqlQuery result(MSqlQuery::InitCon()); 00184 00185 lastRun.setTime_t(0); 00186 00187 result.prepare("SELECT lastrun FROM housekeeping WHERE tag = :TAG ;"); 00188 result.bindValue(":TAG", dbTag); 00189 00190 if (result.exec() && result.next()) 00191 { 00192 lastRun = result.value(0).toDateTime(); 00193 } 00194 00195 return lastRun; 00196 } 00197 00198 void HouseKeeper::RunHouseKeeping(void) 00199 { 00200 // tell constructor that we've started.. 00201 { 00202 QMutexLocker locker(&houseKeepingLock); 00203 houseKeepingWait.wakeAll(); 00204 } 00205 00206 int period, maxhr, minhr; 00207 QString dbTag; 00208 bool initialRun = true; 00209 00210 // wait a little for main server to come up and things to settle down 00211 { 00212 QMutexLocker locker(&houseKeepingLock); 00213 houseKeepingWait.wait(locker.mutex(), 10 * 1000); 00214 } 00215 00216 RunStartupTasks(); 00217 00218 QMutexLocker locker(&houseKeepingLock); 00219 while (houseKeepingRun) 00220 { 00221 locker.unlock(); 00222 00223 LOG(VB_GENERAL, LOG_INFO, "Running housekeeping thread"); 00224 00225 // These tasks are only done from the master backend 00226 if (isMaster) 00227 { 00228 // Clean out old database logging entries 00229 if (wantToRun("LogClean", 1, 0, 24)) 00230 { 00231 LOG(VB_GENERAL, LOG_INFO, "Running LogClean"); 00232 flushDBLogs(); 00233 updateLastrun("LogClean"); 00234 } 00235 00236 // Run mythfilldatabase to grab the TV listings 00237 if (gCoreContext->GetNumSetting("MythFillEnabled", 1)) 00238 { 00239 if (fillDBThread && fillDBThread->isRunning()) 00240 { 00241 LOG(VB_GENERAL, LOG_INFO, 00242 "mythfilldatabase still running, skipping checks."); 00243 } 00244 else 00245 { 00246 period = 1; 00247 minhr = gCoreContext->GetNumSetting("MythFillMinHour", -1); 00248 if (minhr == -1) 00249 { 00250 minhr = 0; 00251 maxhr = 24; 00252 } 00253 else 00254 { 00255 maxhr = gCoreContext->GetNumSetting("MythFillMaxHour", 24); 00256 } 00257 00258 bool grabberSupportsNextTime = false; 00259 MSqlQuery result(MSqlQuery::InitCon()); 00260 if (result.isConnected()) 00261 { 00262 result.prepare("SELECT COUNT(*) FROM videosource " 00263 "WHERE xmltvgrabber IN " 00264 "( 'datadirect', 'technovera'," 00265 " 'schedulesdirect1' );"); 00266 00267 if ((result.exec()) && 00268 (result.next()) && 00269 (result.value(0).toInt() > 0)) 00270 grabberSupportsNextTime = true; 00271 } 00272 00273 bool runMythFill = false; 00274 if (grabberSupportsNextTime && 00275 gCoreContext->GetNumSetting("MythFillGrabberSuggestsTime", 1)) 00276 { 00277 QDateTime nextRun = QDateTime::fromString( 00278 gCoreContext->GetSetting("MythFillSuggestedRunTime", 00279 "1970-01-01T00:00:00"), Qt::ISODate); 00280 QDateTime lastRun = getLastRun("MythFillDB"); 00281 QDateTime now = QDateTime::currentDateTime(); 00282 00283 if ((nextRun < now) && 00284 (lastRun.secsTo(now) > (3 * 60 * 60))) 00285 runMythFill = true; 00286 } 00287 else if (wantToRun("MythFillDB", period, minhr, maxhr, 00288 initialRun)) 00289 { 00290 runMythFill = true; 00291 } 00292 00293 if (runMythFill) 00294 { 00295 LOG(VB_GENERAL, LOG_INFO, "Running mythfilldatabase"); 00296 StartMFD(); 00297 updateLastrun("MythFillDB"); 00298 } 00299 } 00300 } 00301 00302 if (wantToRun("DailyCleanup", 1, 0, 24)) { 00303 JobQueue::CleanupOldJobsInQueue(); 00304 CleanupAllOldInUsePrograms(); 00305 CleanupOrphanedLivetvChains(); 00306 CleanupRecordedTables(); 00307 CleanupProgramListings(); 00308 updateLastrun("DailyCleanup"); 00309 } 00310 00311 if ((gCoreContext->GetNumSetting("ThemeUpdateNofications", 1)) && 00312 (wantToRun("ThemeChooserInfoCacheUpdate", 1, 0, 24, true))) 00313 { 00314 UpdateThemeChooserInfoCache(); 00315 updateLastrun("ThemeChooserInfoCacheUpdate"); 00316 } 00317 00318 #if CONFIG_BINDINGS_PYTHON 00319 if ((gCoreContext->GetNumSetting("DailyArtworkUpdates", 0)) && 00320 (wantToRun("RecordedArtworkUpdate", 1, 0, 24, true))) 00321 { 00322 UpdateRecordedArtwork(); 00323 updateLastrun("RecordedArtworkUpdate"); 00324 } 00325 #endif 00326 } 00327 00328 dbTag = QString("JobQueueRecover-%1").arg(gCoreContext->GetHostName()); 00329 if (wantToRun(dbTag, 1, 0, 24)) 00330 { 00331 JobQueue::RecoverOldJobsInQueue(); 00332 updateLastrun(dbTag); 00333 } 00334 00335 if (wantToRun("DBCleanup", 1, 0, 24)) 00336 { 00337 gCoreContext->GetDBManager()->PurgeIdleConnections(); 00338 } 00339 00340 initialRun = false; 00341 00342 locker.relock(); 00343 if (houseKeepingRun) 00344 houseKeepingWait.wait(locker.mutex(), (300 + (random()%8)) * 1000); 00345 } 00346 } 00347 00348 void HouseKeeper::flushDBLogs() 00349 { 00350 int numdays = 14; 00351 uint64_t maxrows = 10000 * numdays; // likely high enough to keep numdays 00352 00353 MSqlQuery query(MSqlQuery::InitCon()); 00354 if (query.isConnected()) 00355 { 00356 // Remove less-important logging after 1/2 * numdays days 00357 QDateTime days = QDateTime::currentDateTime(); 00358 days = days.addDays(0 - (numdays / 2)); 00359 QString sql = "DELETE FROM logging " 00360 " WHERE application NOT IN (:MYTHBACKEND, :MYTHFRONTEND) " 00361 " AND msgtime < :DAYS ;"; 00362 query.prepare(sql); 00363 query.bindValue(":MYTHBACKEND", MYTH_APPNAME_MYTHBACKEND); 00364 query.bindValue(":MYTHFRONTEND", MYTH_APPNAME_MYTHFRONTEND); 00365 query.bindValue(":DAYS", days); 00366 LOG(VB_GENERAL, LOG_DEBUG, 00367 QString("Deleting helper application database log entries " 00368 "from before %1.") .arg(days.toString())); 00369 if (!query.exec()) 00370 MythDB::DBError("Delete helper application log entries", query); 00371 00372 // Remove backend/frontend logging after numdays days 00373 days = QDateTime::currentDateTime(); 00374 days = days.addDays(0 - numdays); 00375 sql = "DELETE FROM logging WHERE msgtime < :DAYS ;"; 00376 query.prepare(sql); 00377 query.bindValue(":DAYS", days); 00378 LOG(VB_GENERAL, LOG_DEBUG, 00379 QString("Deleting database log entries from before %1.") 00380 .arg(days.toString())); 00381 if (!query.exec()) 00382 MythDB::DBError("Delete old log entries", query); 00383 00384 sql = "SELECT COUNT(id) FROM logging;"; 00385 query.prepare(sql); 00386 if (query.exec()) 00387 { 00388 uint64_t totalrows = 0; 00389 while (query.next()) 00390 { 00391 totalrows = query.value(0).toLongLong(); 00392 LOG(VB_GENERAL, LOG_DEBUG, 00393 QString("Database has %1 log entries.").arg(totalrows)); 00394 } 00395 if (totalrows > maxrows) 00396 { 00397 sql = "DELETE FROM logging ORDER BY msgtime LIMIT :ROWS;"; 00398 query.prepare(sql); 00399 quint64 extrarows = totalrows - maxrows; 00400 query.bindValue(":ROWS", extrarows); 00401 LOG(VB_GENERAL, LOG_DEBUG, 00402 QString("Deleting oldest %1 database log entries.") 00403 .arg(extrarows)); 00404 if (!query.exec()) 00405 MythDB::DBError("Delete excess log entries", query); 00406 } 00407 } 00408 else 00409 MythDB::DBError("Query logging table size", query); 00410 } 00411 } 00412 00413 void HouseKeeper::RunMFD(void) 00414 { 00415 { 00416 QMutexLocker locker(&fillDBLock); 00417 fillDBStarted = true; 00418 fillDBWait.wakeAll(); 00419 } 00420 00421 QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath", 00422 "mythfilldatabase"); 00423 QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", ""); 00424 00425 if (mfpath == "mythfilldatabase") 00426 mfpath = GetInstallPrefix() + "/bin/mythfilldatabase"; 00427 00428 QString command = QString("%1 %2 %3").arg(mfpath).arg(logPropagateArgs) 00429 .arg(mfarg); 00430 00431 { 00432 QMutexLocker locker(&fillDBLock); 00433 fillDBMythSystem = new MythSystem(command, kMSRunShell | 00434 kMSAutoCleanup); 00435 fillDBMythSystem->Run(0); 00436 fillDBWait.wakeAll(); 00437 } 00438 00439 MythFillDatabaseThread::setTerminationEnabled(true); 00440 00441 uint result = fillDBMythSystem->Wait(0); 00442 00443 MythFillDatabaseThread::setTerminationEnabled(false); 00444 00445 { 00446 QMutexLocker locker(&fillDBLock); 00447 fillDBMythSystem->deleteLater(); 00448 fillDBMythSystem = NULL; 00449 fillDBWait.wakeAll(); 00450 } 00451 00452 if (result != GENERIC_EXIT_OK) 00453 { 00454 LOG(VB_GENERAL, LOG_ERR, QString("MythFillDatabase command '%1' failed") 00455 .arg(command)); 00456 } 00457 } 00458 00459 void HouseKeeper::StartMFD(void) 00460 { 00461 if (fillDBThread) 00462 { 00463 KillMFD(); 00464 delete fillDBThread; 00465 fillDBThread = NULL; 00466 fillDBStarted = false; 00467 } 00468 00469 fillDBThread = new MythFillDatabaseThread(this); 00470 fillDBThread->start(); 00471 00472 QMutexLocker locker(&fillDBLock); 00473 while (!fillDBStarted) 00474 fillDBWait.wait(locker.mutex()); 00475 } 00476 00477 void HouseKeeper::KillMFD(void) 00478 { 00479 if (!fillDBThread->isRunning()) 00480 return; 00481 00482 QMutexLocker locker(&fillDBLock); 00483 if (fillDBMythSystem && fillDBThread->isRunning()) 00484 { 00485 fillDBMythSystem->Term(false); 00486 fillDBWait.wait(locker.mutex(), 50); 00487 } 00488 00489 if (fillDBMythSystem && fillDBThread->isRunning()) 00490 { 00491 fillDBMythSystem->Term(true); 00492 fillDBWait.wait(locker.mutex(), 50); 00493 } 00494 00495 if (fillDBThread->isRunning()) 00496 { 00497 fillDBThread->terminate(); 00498 usleep(5000); 00499 } 00500 00501 if (fillDBThread->isRunning()) 00502 { 00503 locker.unlock(); 00504 fillDBThread->wait(); 00505 } 00506 } 00507 00508 void HouseKeeper::CleanupMyOldRecordings(void) 00509 { 00510 MSqlQuery query(MSqlQuery::InitCon()); 00511 00512 query.prepare("DELETE FROM inuseprograms " 00513 "WHERE hostname = :HOSTNAME AND " 00514 "( recusage = 'recorder' OR recusage LIKE 'Unknown %' );"); 00515 query.bindValue(":HOSTNAME", gCoreContext->GetHostName()); 00516 if (!query.exec()) 00517 MythDB::DBError("HouseKeeper::CleanupMyOldRecordings", query); 00518 } 00519 00520 void HouseKeeper::CleanupAllOldInUsePrograms(void) 00521 { 00522 QDateTime fourHoursAgo = QDateTime::currentDateTime().addSecs(-4 * 60 * 60); 00523 MSqlQuery query(MSqlQuery::InitCon()); 00524 00525 query.prepare("DELETE FROM inuseprograms " 00526 "WHERE lastupdatetime < :FOURHOURSAGO ;"); 00527 query.bindValue(":FOURHOURSAGO", fourHoursAgo); 00528 if (!query.exec()) 00529 MythDB::DBError("HouseKeeper::CleanupAllOldInUsePrograms", query); 00530 } 00531 00532 void HouseKeeper::CleanupOrphanedLivetvChains(void) 00533 { 00534 QDateTime fourHoursAgo = QDateTime::currentDateTime().addSecs(-4 * 60 * 60); 00535 MSqlQuery query(MSqlQuery::InitCon()); 00536 MSqlQuery deleteQuery(MSqlQuery::InitCon()); 00537 00538 // Keep these tvchains, they may be in use. 00539 query.prepare("SELECT DISTINCT chainid FROM tvchain " 00540 "WHERE endtime > :FOURHOURSAGO ;"); 00541 query.bindValue(":FOURHOURSAGO", fourHoursAgo); 00542 00543 if (!query.exec() || !query.isActive()) 00544 { 00545 MythDB::DBError("HouseKeeper Cleaning TVChain Table", query); 00546 return; 00547 } 00548 00549 QString msg, keepChains; 00550 while (query.next()) 00551 if (keepChains.isEmpty()) 00552 keepChains = "'" + query.value(0).toString() + "'"; 00553 else 00554 keepChains += ", '" + query.value(0).toString() + "'"; 00555 00556 if (keepChains.isEmpty()) 00557 msg = "DELETE FROM tvchain WHERE endtime < now();"; 00558 else 00559 { 00560 msg = QString("DELETE FROM tvchain " 00561 "WHERE chainid NOT IN ( %1 ) AND endtime < now();") 00562 .arg(keepChains); 00563 } 00564 deleteQuery.prepare(msg); 00565 if (!deleteQuery.exec()) 00566 MythDB::DBError("HouseKeeper Cleaning TVChain Table", deleteQuery); 00567 } 00568 00569 void HouseKeeper::CleanupRecordedTables(void) 00570 { 00571 MSqlQuery query(MSqlQuery::InitCon()); 00572 MSqlQuery deleteQuery(MSqlQuery::InitCon()); 00573 int tableIndex = 0; 00574 // tables[tableIndex][0] is the table name 00575 // tables[tableIndex][1] is the name of the column on which the join is 00576 // performed 00577 QString tables[][2] = { 00578 { "recordedprogram", "progstart" }, 00579 { "recordedrating", "progstart" }, 00580 { "recordedcredits", "progstart" }, 00581 { "recordedmarkup", "starttime" }, 00582 { "recordedseek", "starttime" }, 00583 { "", "" } }; // This blank entry must exist, do not remove. 00584 QString table = tables[tableIndex][0]; 00585 QString column = tables[tableIndex][1]; 00586 00587 // Because recordedseek can have millions of rows, we don't want to JOIN it 00588 // with recorded. Instead, pull out DISTINCT chanid and starttime into a 00589 // temporary table (resulting in tens, hundreds, or--at most--a few 00590 // thousand rows) for the JOIN 00591 QString querystr; 00592 querystr = "CREATE TEMPORARY TABLE IF NOT EXISTS temprecordedcleanup ( " 00593 "chanid int(10) unsigned NOT NULL default '0', " 00594 "starttime datetime NOT NULL default '0000-00-00 00:00:00' " 00595 ");"; 00596 00597 if (!query.exec(querystr)) 00598 { 00599 MythDB::DBError("Housekeeper Creating Temporary Table", query); 00600 return; 00601 } 00602 00603 while (!table.isEmpty()) 00604 { 00605 query.prepare(QString("TRUNCATE TABLE temprecordedcleanup;")); 00606 if (!query.exec() || !query.isActive()) 00607 { 00608 MythDB::DBError("Housekeeper Truncating Temporary Table", query); 00609 return; 00610 } 00611 00612 query.prepare(QString("INSERT INTO temprecordedcleanup " 00613 "( chanid, starttime ) " 00614 "SELECT DISTINCT chanid, starttime " 00615 "FROM %1;") 00616 .arg(table)); 00617 00618 if (!query.exec() || !query.isActive()) 00619 { 00620 MythDB::DBError("HouseKeeper Cleaning Recorded Tables", query); 00621 return; 00622 } 00623 00624 query.prepare(QString("SELECT DISTINCT p.chanid, p.starttime " 00625 "FROM temprecordedcleanup p " 00626 "LEFT JOIN recorded r " 00627 "ON p.chanid = r.chanid " 00628 "AND p.starttime = r.%1 " 00629 "WHERE r.chanid IS NULL;").arg(column)); 00630 if (!query.exec() || !query.isActive()) 00631 { 00632 MythDB::DBError("HouseKeeper Cleaning Recorded Tables", query); 00633 return; 00634 } 00635 00636 deleteQuery.prepare(QString("DELETE FROM %1 " 00637 "WHERE chanid = :CHANID " 00638 "AND starttime = :STARTTIME;") 00639 .arg(table)); 00640 while (query.next()) 00641 { 00642 deleteQuery.bindValue(":CHANID", query.value(0).toString()); 00643 deleteQuery.bindValue(":STARTTIME", query.value(1).toDateTime()); 00644 if (!deleteQuery.exec()) 00645 MythDB::DBError("HouseKeeper Cleaning Recorded Tables", 00646 deleteQuery); 00647 } 00648 00649 tableIndex++; 00650 table = tables[tableIndex][0]; 00651 column = tables[tableIndex][1]; 00652 } 00653 00654 if (!query.exec("DROP TABLE temprecordedcleanup;")) 00655 MythDB::DBError("Housekeeper Dropping Temporary Table", query); 00656 00657 } 00658 00659 void HouseKeeper::CleanupProgramListings(void) 00660 { 00661 00662 MSqlQuery query(MSqlQuery::InitCon()); 00663 QString querystr; 00664 // Keep as many days of listings data as we keep matching, non-recorded 00665 // oldrecorded entries to allow for easier post-mortem analysis 00666 int offset = gCoreContext->GetNumSetting( "CleanOldRecorded", 10); 00667 00668 query.prepare("DELETE FROM oldprogram WHERE airdate < " 00669 "DATE_SUB(CURRENT_DATE, INTERVAL 320 DAY);"); 00670 if (!query.exec()) 00671 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00672 00673 query.prepare("REPLACE INTO oldprogram (oldtitle,airdate) " 00674 "SELECT title,starttime FROM program " 00675 "WHERE starttime < NOW() AND manualid = 0 " 00676 "GROUP BY title;"); 00677 if (!query.exec()) 00678 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00679 00680 query.prepare("DELETE FROM program WHERE starttime <= " 00681 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);"); 00682 query.bindValue(":OFFSET", offset); 00683 if (!query.exec()) 00684 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00685 00686 query.prepare("DELETE FROM programrating WHERE starttime <= " 00687 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);"); 00688 query.bindValue(":OFFSET", offset); 00689 if (!query.exec()) 00690 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00691 00692 query.prepare("DELETE FROM programgenres WHERE starttime <= " 00693 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);"); 00694 query.bindValue(":OFFSET", offset); 00695 if (!query.exec()) 00696 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00697 00698 query.prepare("DELETE FROM credits WHERE starttime <= " 00699 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);"); 00700 query.bindValue(":OFFSET", offset); 00701 if (!query.exec()) 00702 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00703 00704 query.prepare("DELETE FROM record WHERE (type = :SINGLE " 00705 "OR type = :OVERRIDE OR type = :DONTRECORD) " 00706 "AND enddate < CURDATE();"); 00707 query.bindValue(":SINGLE", kSingleRecord); 00708 query.bindValue(":OVERRIDE", kOverrideRecord); 00709 query.bindValue(":DONTRECORD", kDontRecord); 00710 if (!query.exec()) 00711 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00712 00713 MSqlQuery findq(MSqlQuery::InitCon()); 00714 findq.prepare("SELECT record.recordid FROM record " 00715 "LEFT JOIN oldfind ON oldfind.recordid = record.recordid " 00716 "WHERE type = :FINDONE AND oldfind.findid IS NOT NULL;"); 00717 findq.bindValue(":FINDONE", kFindOneRecord); 00718 00719 if (findq.exec()) 00720 { 00721 query.prepare("DELETE FROM record WHERE recordid = :RECORDID;"); 00722 while (findq.next()) 00723 { 00724 query.bindValue(":RECORDID", findq.value(0).toInt()); 00725 if (!query.exec()) 00726 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00727 } 00728 } 00729 query.prepare("DELETE FROM oldfind WHERE findid < TO_DAYS(NOW()) - 14;"); 00730 if (!query.exec()) 00731 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00732 00733 query.prepare("DELETE FROM oldrecorded WHERE " 00734 "recstatus <> :RECORDED AND duplicate = 0 AND " 00735 "endtime < DATE_SUB(CURRENT_DATE, INTERVAL :CLEAN DAY);"); 00736 query.bindValue(":RECORDED", rsRecorded); 00737 query.bindValue(":CLEAN", offset); 00738 if (!query.exec()) 00739 MythDB::DBError("HouseKeeper Cleaning Program Listings", query); 00740 00741 } 00742 00743 void HouseKeeper::UpdateThemeChooserInfoCache(void) 00744 { 00745 QString MythVersion = MYTH_SOURCE_PATH; 00746 00747 // FIXME: For now, treat git master the same as svn trunk 00748 if (MythVersion == "master") 00749 MythVersion = "trunk"; 00750 00751 if (MythVersion != "trunk") 00752 { 00753 MythVersion = MYTH_BINARY_VERSION; // Example: 0.25.20101017-1 00754 MythVersion.replace(QRegExp("\\.[0-9]{8,}.*"), ""); 00755 } 00756 00757 QString remoteThemesDir = GetConfDir(); 00758 remoteThemesDir.append("/tmp/remotethemes"); 00759 00760 QDir dir(remoteThemesDir); 00761 if (!dir.exists() && !dir.mkpath(remoteThemesDir)) 00762 { 00763 LOG(VB_GENERAL, LOG_ERR, 00764 QString("HouseKeeper: Error creating %1" 00765 "directory for remote themes info cache.") 00766 .arg(remoteThemesDir)); 00767 return; 00768 } 00769 00770 QString remoteThemesFile = remoteThemesDir; 00771 remoteThemesFile.append("/themes.zip"); 00772 00773 QString url = QString("%1/%2/themes.zip") 00774 .arg(gCoreContext->GetSetting("ThemeRepositoryURL", 00775 "http://themes.mythtv.org/themes/repository")).arg(MythVersion); 00776 00777 bool result = GetMythDownloadManager()->download(url, remoteThemesFile); 00778 00779 if (!result) 00780 { 00781 LOG(VB_GENERAL, LOG_ERR, 00782 QString("HouseKeeper: Error downloading %1" 00783 "remote themes info package.").arg(url)); 00784 return; 00785 } 00786 00787 if (!extractZIP(remoteThemesFile, remoteThemesDir)) 00788 { 00789 LOG(VB_GENERAL, LOG_ERR, 00790 QString("HouseKeeper: Error extracting %1" 00791 "remote themes info package.").arg(remoteThemesFile)); 00792 QFile::remove(remoteThemesFile); 00793 return; 00794 } 00795 } 00796 00797 void HouseKeeper::UpdateRecordedArtwork(void) 00798 { 00799 QString command = GetInstallPrefix() + "/bin/mythmetadatalookup"; 00800 QStringList args; 00801 args << "--refresh-all-artwork"; 00802 args << logPropagateArgs; 00803 00804 LOG(VB_GENERAL, LOG_INFO, QString("Performing Artwork Refresh: %1 %2") 00805 .arg(command).arg(args.join(" "))); 00806 00807 MythSystem artupd(command, args, kMSRunShell | kMSAutoCleanup); 00808 00809 artupd.Run(); 00810 artupd.Wait(); 00811 00812 LOG(VB_GENERAL, LOG_INFO, QString("Artwork Refresh Complete")); 00813 } 00814 00815 void HouseKeeper::RunStartupTasks(void) 00816 { 00817 if (isMaster) 00818 EITCache::ClearChannelLocks(); 00819 } 00820 00821 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1