void MythUIHelper::RemoveFromCacheByURL(const QString &url) { QMutexLocker locker(d->m_cacheLock); QMap<QString, MythImage *>::iterator it = d->imageCache.find(url); if (it != d->imageCache.end()) { d->imageCache[url]->SetIsInCache(false); d->imageCache[url]->DecrRef(); d->imageCache.remove(url); d->CacheTrack.remove(url); } QString dstfile; dstfile = GetThemeCacheDir() + '/' + url; LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("RemoveFromCacheByURL removed :%1: from cache").arg(dstfile)); QFile::remove(dstfile); }
void MythUIHelper::RemoveFromCacheByFile(const QString &fname) { QList<QString>::iterator it; QString partialKey = fname; partialKey.replace('/', '-'); d->m_cacheLock->lock(); QList<QString> imageCacheKeys = d->imageCache.keys(); d->m_cacheLock->unlock(); for (it = imageCacheKeys.begin(); it != imageCacheKeys.end(); ++it) { if ((*it).contains(partialKey)) RemoveFromCacheByURL(*it); } // Loop through files to cache any that were not caught by // RemoveFromCacheByURL QDir dir(GetThemeCacheDir()); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); if (fileInfo.fileName().contains(partialKey)) { LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("RemoveFromCacheByFile removed: %1: from cache") .arg(fileInfo.fileName())); if (!dir.remove(fileInfo.fileName())) LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to delete %1 from the theme cache") .arg(fileInfo.fileName())); } } }
void MythUIHelper::ClearOldImageCache(void) { QString cachedirname = GetConfDir() + "/cache/themecache/"; d->themecachedir = GetThemeCacheDir(); QDir dir(cachedirname); if (!dir.exists()) dir.mkdir(cachedirname); QString themecachedir = d->themecachedir; d->themecachedir += '/'; dir.setPath(themecachedir); if (!dir.exists()) dir.mkdir(themecachedir); dir.setPath(cachedirname); dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); QFileInfoList list = dir.entryInfoList(); QFileInfoList::const_iterator it = list.begin(); QMap<QDateTime, QString> dirtimes; const QFileInfo *fi; while (it != list.end()) { fi = &(*it++); if (fi->isDir() && !fi->isSymLink()) { if (fi->absoluteFilePath() == themecachedir) continue; dirtimes[fi->lastModified()] = fi->absoluteFilePath(); } } // Cache two themes/resolutions to allow sampling other themes without // incurring a penalty. Especially for those writing new themes or testing // changes of an existing theme. The space used is neglible when compared // against the average video while ((size_t)dirtimes.size() >= 2) { LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Removing cache dir: %1") .arg(dirtimes.begin().value())); RemoveCacheDir(dirtimes.begin().value()); dirtimes.erase(dirtimes.begin()); } QMap<QDateTime, QString>::const_iterator dit = dirtimes.begin(); for (; dit != dirtimes.end(); ++dit) { LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Keeping cache dir: %1").arg(*dit)); } }
MythImage *MythUIHelper::LoadCacheImage(QString srcfile, QString label, MythPainter *painter, ImageCacheMode cacheMode) { LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("LoadCacheImage(%1,%2)").arg(srcfile).arg(label)); if (srcfile.isEmpty() || label.isEmpty()) return NULL; if (!(kCacheForceStat & cacheMode)) { // Some screens include certain images dozens or even hundreds of // times. Even if the image is in the cache, there is still a // stat system call on the original file to see if it has changed. // This code relaxes the original-file check so that the check // isn't repeated if it was already done within kImageCacheTimeout // seconds. // This only applies to the MEMORY cache const uint kImageCacheTimeout = 60; uint now = MythDate::current().toTime_t(); QMutexLocker locker(d->m_cacheLock); if (d->imageCache.contains(label) && d->CacheTrack[label] + kImageCacheTimeout > now) { d->imageCache[label]->IncrRef(); return d->imageCache[label]; } } MythImage *ret = NULL; // Check Memory Cache ret = GetImageFromCache(label); // If the image is in the memory or we are not ignoring the disk cache // then proceed to check whether the source file is newer than our cached // copy if (ret || !(cacheMode & kCacheIgnoreDisk)) { // Create url to image in disk cache QString cachefilepath = GetThemeCacheDir() + '/' + label; QFileInfo cacheFileInfo(cachefilepath); // If the file isn't in the disk cache, then we don't want to bother // checking the last modified times of the original if (!cacheFileInfo.exists()) return NULL; // Now compare the time on the source versus our cached copy QDateTime srcLastModified; // For internet images this involves querying the headers of the remote // image. This is slow even without redownloading the whole image if ((srcfile.startsWith("http://")) || (srcfile.startsWith("https://")) || (srcfile.startsWith("ftp://"))) { // If the image is in the memory cache then skip the last modified // check, since memory cached images are loaded in the foreground // this can cause an intolerable delay. The images won't stay in // the cache forever and so eventually they will be checked. if (ret) srcLastModified = cacheFileInfo.lastModified(); else { srcLastModified = GetMythDownloadManager()->GetLastModified(srcfile); } } else if (srcfile.startsWith("myth://")) srcLastModified = RemoteFile::LastModified(srcfile); else { if (!FindThemeFile(srcfile)) return NULL; QFileInfo original(srcfile); if (original.exists()) srcLastModified = original.lastModified(); } // Now compare the timestamps, if the cached image is newer than the // source image we can use it, otherwise we want to remove it from the // cache if (cacheFileInfo.lastModified() >= srcLastModified) { // If we haven't already loaded the image from the memory cache // and we're not ignoring the disk cache, then it's time to load // it from there instead if (!ret && (cacheMode == kCacheNormal)) { if (painter) ret = painter->GetFormatImage(); // Load file from disk cache to memory cache if (ret->Load(cachefilepath)) { // Add to ram cache, and skip saving to disk since that is // where we found this in the first place. CacheImage(label, ret, true); } else { LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC + QString("LoadCacheImage: Could not load :%1") .arg(cachefilepath)); ret->SetIsInCache(false); ret->DecrRef(); ret = NULL; } } } else { ret = NULL; // If file has changed on disk, then remove it from the memory // and disk cache RemoveFromCacheByURL(label); } } return ret; }
MythImage *MythUIHelper::LoadCacheImage(QString srcfile, QString label, MythPainter *painter, ImageCacheMode cacheMode) { LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("LoadCacheImage(%1,%2)").arg(srcfile).arg(label)); if (srcfile.isEmpty() || label.isEmpty()) return NULL; if (!(kCacheForceStat & cacheMode)) { // Some screens include certain images dozens or even hundreds of // times. Even if the image is in the cache, there is still a // stat system call on the original file to see if it has changed. // This code relaxes the original-file check so that the check // isn't repeated if it was already done within kImageCacheTimeout // seconds. const uint kImageCacheTimeout = 5; uint now = MythDate::current().toTime_t(); QMutexLocker locker(d->m_cacheLock); if (d->imageCache.contains(label) && d->CacheTrack[label] + kImageCacheTimeout > now) { d->imageCache[label]->IncrRef(); return d->imageCache[label]; } } QString cachefilepath = GetThemeCacheDir() + '/' + label; QFileInfo fi(cachefilepath); MythImage *ret = NULL; if (!!(cacheMode & kCacheIgnoreDisk) || fi.exists()) { // Now compare the time on the source versus our cached copy if (!(cacheMode & kCacheIgnoreDisk)) FindThemeFile(srcfile); QDateTime srcLastModified; QFileInfo original(srcfile); if ((srcfile.startsWith("http://")) || (srcfile.startsWith("https://")) || (srcfile.startsWith("ftp://"))) { srcLastModified = GetMythDownloadManager()->GetLastModified(srcfile); } else if (srcfile.startsWith("myth://")) srcLastModified = RemoteFile::LastModified(srcfile); else if (original.exists()) srcLastModified = original.lastModified(); if (!!(cacheMode & kCacheIgnoreDisk) || (fi.lastModified() > srcLastModified)) { // Check Memory Cache ret = GetImageFromCache(label); if (!ret && (cacheMode == kCacheNormal) && painter) { // Load file from disk cache to memory cache ret = painter->GetFormatImage(); if (!ret->Load(cachefilepath, false)) { LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC + QString("LoadCacheImage: Could not load :%1") .arg(cachefilepath)); ret->SetIsInCache(false); ret->DecrRef(); ret = NULL; } else { // Add to ram cache, and skip saving to disk since that is // where we found this in the first place. CacheImage(label, ret, true); } } } else { // If file has changed on disk, then remove it from the memory // and disk cache RemoveFromCacheByURL(label); } } return ret; }