Ticket #7691: 7691-event-reduction-v1.patch

File 7691-event-reduction-v1.patch, 13.6 KB (added by danielk, 10 years ago)

Reduces event frequency by combining events.

  • libs/libmyth/programinfoupdater.h

     
     1#ifndef _PROGRAM_INFO_UPDATER_H_
     2#define _PROGRAM_INFO_UPDATER_H_
     3
     4#include <vector>
     5using namespace std;
     6
     7#include <QThreadPool>
     8#include <QDateTime>
     9#include <QMutex>
     10#include <QHash>
     11
     12typedef enum PIAction {
     13    kPIAdd,
     14    kPIDelete,
     15    kPIUpdate,
     16    kPIUpdateFileSize,
     17} PIAction;
     18
     19class PIKey
     20{
     21  public:
     22    PIKey(uint c, const QDateTime &r) : chanid(c), recstartts(r) {}
     23
     24    uint      chanid;
     25    QDateTime recstartts;
     26
     27    bool operator==(const PIKey &other) const
     28    {
     29        return (chanid     == other.chanid &&
     30                recstartts == other.recstartts);
     31    }
     32};
     33uint qHash(const PIKey &k);
     34
     35class PIKeyAction : public PIKey
     36{
     37  public:
     38    PIKeyAction(uint c, const QDateTime &r, PIAction a) :
     39        PIKey(c, r), action(a) { }
     40
     41    PIAction action;
     42};
     43
     44class PIKeyData
     45{
     46  public:
     47    PIKeyData(PIAction a, long long f) : action(a), filesize(f) { }
     48    PIAction action;
     49    long long filesize;
     50};
     51
     52class ProgramInfoUpdater : public QRunnable
     53{
     54  public:
     55    ProgramInfoUpdater() : isQueued(false) { setAutoDelete(false); }
     56
     57    void insert(uint     chanid, const QDateTime &recstartts,
     58                PIAction action, long long        filesize = 0LL);
     59    void run(void);
     60
     61  private:
     62    QMutex        lock;
     63    bool          isQueued;
     64    vector<PIKeyAction>    needsAddDelete;
     65    QHash<PIKey,PIKeyData> needsUpdate;
     66};
     67
     68#endif // _PROGRAM_INFO_UPDATER_H_
  • libs/libmyth/programinfo.h

     
    221221
    222222class MSqlQuery;
    223223class ProgramList;
     224class ProgramInfoUpdater;
    224225
    225226class MPUBLIC ProgramInfo
    226227{
     
    485486
    486487    static QMutex staticDataLock;
    487488    static QString unknownTitle;
     489    static ProgramInfoUpdater *updater;
    488490};
    489491
    490492Q_DECLARE_METATYPE(ProgramInfo*)
  • libs/libmyth/programinfo.cpp

     
    2727#include "mythverbose.h"
    2828#include "storagegroup.h"
    2929#include "programlist.h"
     30#include "programinfoupdater.h"
    3031
    3132#define LOC QString("ProgramInfo: ")
    3233#define LOC_ERR QString("ProgramInfo, Error: ")
     
    4041
    4142QMutex ProgramInfo::staticDataLock;
    4243QString ProgramInfo::unknownTitle;
     44ProgramInfoUpdater *ProgramInfo::updater;
    4345
    4446static void set_flag(uint32_t &flags, int flag_to_set, bool is_set)
    4547{
     
    138140    inUseForWhat(""),
    139141    positionMapDBReplacement(NULL)
    140142{
     143    QMutexLocker locker(&staticDataLock);
     144    if (!updater)
     145        updater = new ProgramInfoUpdater();
    141146}
    142147
    143148/** \fn ProgramInfo::ProgramInfo(const ProgramInfo &other)
     
    17821787    if (!query.exec())
    17831788        MythDB::DBError("File size update", query);
    17841789
    1785     QString msg = QString("UPDATE_FILE_SIZE %1 %2 %3")
    1786         .arg(chanid).arg(recstartts.toString(Qt::ISODate)).arg(fsize);
    1787     RemoteSendMessage(msg);
     1790    updater->insert(chanid.toUInt(), recstartts, kPIUpdateFileSize, fsize);
    17881791}
    17891792
    17901793/** \fn ProgramInfo::GetFilesize(void)
     
    18771880
    18781881void ProgramInfo::SendUpdateEvent(void)
    18791882{
    1880     // Make sure we are up to date first..
    1881     if (LoadProgramFromRecorded(chanid.toUInt(), recstartts))
    1882     {
    1883         // if we successfully loaded the program from the recorded
    1884         // table send an update event..
    1885         QStringList list;
    1886         ToStringList(list);
    1887         RemoteSendEvent(MythEvent(QString("MASTER_UPDATE_PROG_INFO"), list));
    1888     }
     1883    updater->insert(chanid.toUInt(), recstartts, kPIUpdate);
    18891884}
    18901885
    18911886void ProgramInfo::SendAddedEvent(void) const
    18921887{
    1893     QStringList list;
    1894     ToStringList(list);
    1895     RemoteSendEvent(MythEvent(QString("RECORDING_LIST_CHANGE ADD"), list));
     1888    updater->insert(chanid.toUInt(), recstartts, kPIAdd);
    18961889}
    18971890
    18981891void ProgramInfo::SendDeletedEvent(void) const
    18991892{
    1900     QString msg = QString("RECORDING_LIST_CHANGE DELETE %1 %2")
    1901         .arg(chanid).arg(recstartts.toString(Qt::ISODate));
    1902     RemoteSendEvent(MythEvent(msg));
     1893    updater->insert(chanid.toUInt(), recstartts, kPIDelete);
    19031894}
    19041895
    19051896/** \brief Queries Latest bookmark timestamp from the database.
  • libs/libmyth/libmyth.pro

     
    2828HEADERS += mythcommandlineparser.h mythterminal.h
    2929HEADERS += mythhttppool.h mythhttphandler.h
    3030HEADERS += audiopulseutil.h
    31 HEADERS += programinfo.h programlist.h recordingtypes.h remoteutil.h
     31HEADERS += programinfo.h programlist.h programinfoupdater.h
     32HEADERS += recordingtypes.h remoteutil.h
    3233
    3334# remove when everything is switched to mythui
    3435HEADERS += virtualkeyboard_qt.h
     
    5051SOURCES += mythcommandlineparser.cpp mythterminal.cpp
    5152SOURCES += mythhttppool.cpp mythhttphandler.cpp
    5253SOURCES += audiopulseutil.cpp
    53 SOURCES += programinfo.cpp programlist.cpp recordingtypes.cpp remoteutil.cpp
     54SOURCES += programinfo.cpp programlist.cpp programinfoupdater.cpp
     55SOURCES += recordingtypes.cpp remoteutil.cpp
    5456
    5557# remove when everything is switched to mythui
    5658SOURCES += virtualkeyboard_qt.cpp
  • libs/libmyth/programinfoupdater.cpp

     
     1#include "programinfoupdater.h"
     2#include "remoteutil.h"
     3
     4uint qHash(const PIKey &k)
     5{
     6    return qHash(k.chanid) ^ qHash(k.recstartts.toTime_t());
     7}
     8
     9void ProgramInfoUpdater::insert(
     10    uint     chanid, const QDateTime &recstartts,
     11    PIAction action, long long        filesize)
     12{
     13    QMutexLocker locker(&lock);
     14    if (kPIUpdate == action || kPIUpdateFileSize == action)
     15    {
     16        PIKey key = PIKey(chanid, recstartts);
     17        QHash<PIKey,PIKeyData>::iterator it = needsUpdate.find(key);
     18        // If there is no action in the set we can insert
     19        // If it is the same type of action we can overwrite,
     20        // If it the new action is a full update we can overwrite
     21        if (it == needsUpdate.end())
     22            needsUpdate.insert(key, PIKeyData(action, filesize));
     23        else if (((*it).action == action) || (kPIUpdate == action))
     24            (*it) = PIKeyData(action, filesize);
     25    }
     26    else
     27    {
     28        needsAddDelete.push_back(PIKeyAction(chanid, recstartts, action));
     29    }
     30
     31    // Start a new run() if one isn't already running..
     32    // The lock prevents anything from getting stuck on a queue.
     33    if (!isQueued)
     34    {
     35        isQueued = true;
     36        QThreadPool::globalInstance()->start(this);
     37    }
     38}
     39
     40void ProgramInfoUpdater::run(void)
     41{
     42    // we don't need instant updates allow a few to queue up
     43    // if they come in quick succession, this allows multiple
     44    // updates to be consolidated into one update...
     45    usleep(50 * 1000);
     46
     47    QMutexLocker locker(&lock);
     48    isQueued = false;
     49
     50    // send adds and deletes in the order they were queued
     51    vector<PIKeyAction>::iterator ita = needsAddDelete.begin();
     52    for (; ita != needsAddDelete.end(); ++ita)
     53    {
     54        if (kPIAdd != (*ita).action && kPIDelete != (*ita).action)
     55            continue;
     56
     57        QString type = (kPIAdd == (*ita).action) ? "ADD" : "DELETE";
     58        QString msg = QString("RECORDING_LIST_CHANGE %1 %2 %3")
     59            .arg(type).arg((*ita).chanid)
     60            .arg((*ita).recstartts.toString(Qt::ISODate));
     61
     62        RemoteSendMessage(msg);
     63    }
     64    needsAddDelete.clear();
     65
     66    // Send updates in any old order, we just need
     67    // one per updated ProgramInfo.
     68    QHash<PIKey,PIKeyData>::iterator itu = needsUpdate.begin();
     69    for (; itu != needsUpdate.end(); ++itu)
     70    {
     71        QString msg;
     72
     73        if (kPIUpdateFileSize == (*itu).action)
     74        {
     75            msg = QString("UPDATE_FILE_SIZE %1 %2 %3")
     76                .arg(itu.key().chanid)
     77                .arg(itu.key().recstartts.toString(Qt::ISODate))
     78                .arg((*itu).filesize);
     79        }
     80        else
     81        {
     82            msg = QString("MASTER_UPDATE_PROG_INFO %1 %2")
     83                .arg(itu.key().chanid)
     84                .arg(itu.key().recstartts.toString(Qt::ISODate));
     85        }
     86
     87        RemoteSendMessage(msg);
     88    }
     89    needsUpdate.clear();
     90}
  • libs/libmyth/mythcontext.cpp

     
    155155    MythDB *m_database;
    156156    MythUIHelper *m_ui;
    157157    MythContextSlotHandler *m_sh;
     158
     159    QThread *m_UIThread;
    158160};
    159161
    160162static void exec_program_cb(const QString &cmd)
     
    260262      pluginmanager(NULL),
    261263      m_logenable(-1), m_logmaxcount(-1), m_logprintlevel(-1),
    262264      m_database(GetMythDB()), m_ui(NULL),
    263       m_sh(new MythContextSlotHandler(this))
     265      m_sh(new MythContextSlotHandler(this)),
     266      m_UIThread(QThread::currentThread())
    264267{
    265268    InitializeMythDirs();
    266269}
     
    20262029bool MythContext::SendReceiveStringList(QStringList &strlist,
    20272030                                        bool quickTimeout, bool block)
    20282031{
     2032    if (!IsBackend() && QThread::currentThread() == d->m_UIThread)
     2033    {
     2034        QString msg = "SendReceiveStringList(";
     2035        for (uint i=0; i<(uint)strlist.size() && i<2; i++)
     2036            msg += (i?",":"") + strlist[i];
     2037        msg += (strlist.size() > 2) ? "...)" : ")";
     2038        msg += " called from UI thread";
     2039        VERBOSE(VB_IMPORTANT, msg);
     2040    }
     2041
    20292042    QString query_type = "UNKNOWN";
    20302043
    20312044    if (!strlist.isEmpty())
  • programs/mythfrontend/playbackbox.cpp

     
    37603760        if (message.left(21) == "RECORDING_LIST_CHANGE")
    37613761        {
    37623762            QStringList tokens = message.simplified().split(" ");
    3763             if ((tokens.size() == 4) && (tokens[1] == "ADD"))
     3763            uint chanid = 0;
     3764            QDateTime recstartts;
     3765            if (tokens.size() >= 4)
    37643766            {
     3767                chanid = tokens[2].toUInt();
     3768                recstartts = QDateTime::fromString(tokens[3]);
     3769            }
     3770
     3771            if ((tokens.size() >= 2) && tokens[1] == "UPDATE")
     3772            {
    37653773                ProgramInfo evinfo;
    37663774                if (evinfo.FromStringList(me->ExtraDataList(), 0))
     3775                    HandleUpdateProgramInfoEvent(evinfo);
     3776            }
     3777            else if (chanid && recstartts.isValid() && (tokens[1] == "ADD"))
     3778            {
     3779                ProgramInfo evinfo;
     3780                if (evinfo.LoadProgramFromRecorded(chanid, recstartts))
     3781                {
     3782                    evinfo.recstatus = rsRecording;
    37673783                    HandleRecordingAddEvent(evinfo);
     3784                }
    37683785            }
    3769             if ((tokens.size() == 4) && (tokens[1] == "DELETE"))
     3786            else if (chanid && recstartts.isValid() && (tokens[1] == "DELETE"))
    37703787            {
    3771                 uint chanid = tokens[2].toUInt();
    3772                 QDateTime recstartts = QDateTime::fromString(tokens[3]);
    37733788                if (chanid && recstartts.isValid())
    37743789                    HandleRecordingRemoveEvent(chanid, recstartts);
    37753790            }
     
    38133828            if (evinfo.FromStringList(me->ExtraDataList(), 0))
    38143829                HandlePreviewEvent(evinfo);
    38153830        }
    3816         else if (message == "UPDATE_PROG_INFO")
    3817         {
    3818             ProgramInfo evinfo;
    3819             if (evinfo.FromStringList(me->ExtraDataList(), 0))
    3820                 HandleUpdateProgramInfoEvent(evinfo);
    3821         }
    38223831        else if (message.left(17) == "UPDATE_FILE_SIZE")
    38233832        {
    38243833            QStringList tokens = message.simplified().split(" ");
  • programs/mythbackend/mainserver.cpp

     
    875875            return;
    876876
    877877        MythEvent mod_me("");
    878         if (me->Message() == "MASTER_UPDATE_PROG_INFO" && m_sched)
     878        if (me->Message().left(23) == "MASTER_UPDATE_PROG_INFO")
    879879        {
     880            QStringList tokens = me->Message().simplified().split(" ");
     881            uint chanid = 0;
     882            QDateTime recstartts;
     883            if (tokens.size() >= 3)
     884            {
     885                chanid     = tokens[1].toUInt();
     886                recstartts = QDateTime::fromString(tokens[2], Qt::ISODate);
     887            }
     888
    880889            ProgramInfo evinfo;
    881             if (evinfo.FromStringList(me->ExtraDataList(), 0))
     890            if (chanid && recstartts.isValid() &&
     891                evinfo.LoadProgramFromRecorded(chanid, recstartts))
    882892            {
    883893                QDateTime rectime = QDateTime::currentDateTime().addSecs(
    884894                    -gContext->GetNumSetting("RecordOverTime"));
    885895
    886                 if (evinfo.recendts > rectime)
     896                if (m_sched && evinfo.recendts > rectime)
    887897                    evinfo.recstatus = m_sched->GetRecStatus(evinfo);
    888898
    889899                QStringList list;
    890900                evinfo.ToStringList(list);
    891                 mod_me = MythEvent("UPDATE_PROG_INFO", list);
     901                mod_me = MythEvent("RECORDING_LIST_CHANGE UPDATE", list);
    892902                me = &mod_me;
    893903            }
    894904            else