MythTV  0.26-pre
programinfocache.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 // vim:set sw=4 ts=4 expandtab:
00003 // Copyright (c) 2009, Daniel Thor Kristjansson
00004 // Distributed as part of MythTV under GPL version 2
00005 // (or at your option a later version)
00006 
00007 #include <QCoreApplication>
00008 #include <QRunnable>
00009 
00010 #include "programinfocache.h"
00011 #include "mthreadpool.h"
00012 #include "mythlogging.h"
00013 #include "programinfo.h"
00014 #include "remoteutil.h"
00015 #include "mythevent.h"
00016 
00017 typedef vector<ProgramInfo*> *VPI_ptr;
00018 static void free_vec(VPI_ptr &v)
00019 {
00020     if (v)
00021     {
00022         vector<ProgramInfo*>::iterator it = v->begin();
00023         for (; it != v->end(); ++it)
00024             delete *it;
00025         delete v;
00026         v = NULL;
00027     }
00028 }
00029 
00030 class ProgramInfoLoader : public QRunnable
00031 {
00032   public:
00033     ProgramInfoLoader(ProgramInfoCache &c, const bool updateUI)
00034       : m_cache(c), m_updateUI(updateUI) {}
00035 
00036     void run(void) 
00037     { 
00038         m_cache.Load(m_updateUI); 
00039     }
00040 
00041     ProgramInfoCache &m_cache;
00042     bool              m_updateUI;
00043 };
00044 
00045 ProgramInfoCache::ProgramInfoCache(QObject *o) :
00046     m_next_cache(NULL), m_listener(o),
00047     m_load_is_queued(false), m_loads_in_progress(0)
00048 {
00049 }
00050 
00051 ProgramInfoCache::~ProgramInfoCache()
00052 {
00053     QMutexLocker locker(&m_lock);
00054 
00055     while (m_loads_in_progress)
00056         m_load_wait.wait(&m_lock);
00057 
00058     Clear();
00059     free_vec(m_next_cache);
00060 }
00061 
00062 void ProgramInfoCache::ScheduleLoad(const bool updateUI)
00063 {
00064     QMutexLocker locker(&m_lock);
00065     if (!m_load_is_queued)
00066     {
00067         m_load_is_queued = true;
00068         m_loads_in_progress++;
00069         MThreadPool::globalInstance()->start(
00070             new ProgramInfoLoader(*this, updateUI), "ProgramInfoLoader");
00071     }
00072 }
00073 
00074 void ProgramInfoCache::Load(const bool updateUI)
00075 {
00076     QMutexLocker locker(&m_lock);
00077     m_load_is_queued = false;
00078 
00079     locker.unlock();
00080     
00081     // Get an unsorted list (sort = 0) from RemoteGetRecordedList
00082     // we sort the list later anyway.
00083     vector<ProgramInfo*> *tmp = RemoteGetRecordedList(0);
00084     
00085     locker.relock();
00086 
00087     free_vec(m_next_cache);
00088     m_next_cache = tmp;
00089 
00090     if (updateUI)
00091         QCoreApplication::postEvent(
00092             m_listener, new MythEvent("UPDATE_UI_LIST"));
00093     
00094     m_loads_in_progress--;
00095     m_load_wait.wakeAll();
00096 }
00097 
00098 bool ProgramInfoCache::IsLoadInProgress(void) const
00099 {
00100     QMutexLocker locker(&m_lock);
00101     return m_loads_in_progress;
00102 }
00103 
00104 void ProgramInfoCache::WaitForLoadToComplete(void) const
00105 {
00106     QMutexLocker locker(&m_lock);
00107     while (m_loads_in_progress)
00108         m_load_wait.wait(&m_lock);
00109 }
00110 
00121 void ProgramInfoCache::Refresh(void)
00122 {
00123     QMutexLocker locker(&m_lock);
00124     if (m_next_cache)
00125     {
00126         Clear();
00127         vector<ProgramInfo*>::iterator it = m_next_cache->begin();
00128         for (; it != m_next_cache->end(); ++it)
00129         {
00130             if (!(*it)->GetChanID())
00131                 continue;
00132 
00133             PICKey k((*it)->GetChanID(), (*it)->GetRecordingStartTime());
00134             m_cache[k] = *it;
00135         }
00136         delete m_next_cache;
00137         m_next_cache = NULL;
00138         return;
00139     }
00140     locker.unlock();
00141 
00142     Cache::iterator it = m_cache.begin();
00143     Cache::iterator nit = it;
00144     for (; it != m_cache.end(); it = nit)
00145     {
00146         nit = it;
00147         ++nit;
00148 
00149         if (it->second->GetAvailableStatus() == asDeleted)
00150         {
00151             delete it->second;
00152             m_cache.erase(it);
00153         }
00154     }
00155 }
00156 
00161 bool ProgramInfoCache::Update(const ProgramInfo &pginfo)
00162 {
00163     QMutexLocker locker(&m_lock);
00164 
00165     Cache::iterator it = m_cache.find(
00166         PICKey(pginfo.GetChanID(),pginfo.GetRecordingStartTime()));
00167 
00168     if (it != m_cache.end())
00169         it->second->clone(pginfo, true);
00170 
00171     return it != m_cache.end();
00172 }
00173 
00178 bool ProgramInfoCache::UpdateFileSize(
00179     uint chanid, const QDateTime &recstartts, uint64_t filesize)
00180 {
00181     QMutexLocker locker(&m_lock);
00182 
00183     Cache::iterator it = m_cache.find(PICKey(chanid,recstartts));
00184 
00185     if (it != m_cache.end())
00186     {
00187         it->second->SetFilesize(filesize);
00188         if (filesize)
00189             it->second->SetAvailableStatus(asAvailable, "PIC::UpdateFileSize");
00190     }
00191 
00192     return it != m_cache.end();
00193 }
00194 
00198 QString ProgramInfoCache::GetRecGroup(
00199     uint chanid, const QDateTime &recstartts) const
00200 {
00201     QMutexLocker locker(&m_lock);
00202 
00203     Cache::const_iterator it = m_cache.find(PICKey(chanid,recstartts));
00204 
00205     QString recgroup;
00206     if (it != m_cache.end())
00207         recgroup = it->second->GetRecordingGroup();
00208 
00209     return recgroup;
00210 }
00211 
00215 void ProgramInfoCache::Add(const ProgramInfo &pginfo)
00216 {
00217     if (!pginfo.GetChanID() || Update(pginfo))
00218         return;
00219 
00220     PICKey key(pginfo.GetChanID(),pginfo.GetRecordingStartTime());
00221     m_cache[key] = new ProgramInfo(pginfo);
00222 }
00223 
00229 bool ProgramInfoCache::Remove(uint chanid, const QDateTime &recstartts)
00230 {
00231     Cache::iterator it = m_cache.find(PICKey(chanid,recstartts));
00232 
00233     if (it != m_cache.end())
00234         it->second->SetAvailableStatus(asDeleted, "PIC::Remove");
00235 
00236     return it != m_cache.end();
00237 }
00238 
00239 void ProgramInfoCache::GetOrdered(vector<ProgramInfo*> &list, bool newest_first)
00240 {
00241     if (newest_first)
00242     {
00243         Cache::reverse_iterator it = m_cache.rbegin();
00244         for (; it != m_cache.rend(); ++it)
00245             list.push_back(it->second);
00246     }
00247     else
00248     {
00249         for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
00250             list.push_back(it->second);
00251     }
00252 }
00253 
00254 ProgramInfo *ProgramInfoCache::GetProgramInfo(
00255     uint chanid, const QDateTime &recstartts) const
00256 {
00257     Cache::const_iterator it = m_cache.find(PICKey(chanid,recstartts));
00258     
00259     if (it != m_cache.end())
00260         return it->second;
00261 
00262     return NULL;
00263 }
00264 
00265 ProgramInfo *ProgramInfoCache::GetProgramInfo(const QString &piKey) const
00266 {
00267     uint      chanid;
00268     QDateTime recstartts;
00269     if (ProgramInfo::ExtractKey(piKey, chanid, recstartts))
00270         return GetProgramInfo(chanid, recstartts);
00271     return NULL;
00272 }
00273 
00275 void ProgramInfoCache::Clear(void)
00276 {
00277     for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
00278         delete it->second;
00279     m_cache.clear();
00280 }
00281 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends