Ticket #1660: asyncdb.12694.patch

File asyncdb.12694.patch, 12.8 KB (added by ajlill@…, 19 years ago)

Updated to 12694 and cleaned as requested

  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    53785378    using_null_videoout = true;
    53795379
    53805380    // clear out any existing seektables
    5381     m_playbackinfo->ClearPositionMap(MARK_KEYFRAME);
    5382     m_playbackinfo->ClearPositionMap(MARK_GOP_START);
    5383     m_playbackinfo->ClearPositionMap(MARK_GOP_BYFRAME);
     5381    m_playbackinfo->ClearPositionMap(MARK_KEYFRAME,true);
     5382    m_playbackinfo->ClearPositionMap(MARK_GOP_START,true);
     5383    m_playbackinfo->ClearPositionMap(MARK_GOP_BYFRAME,true);
    53845384
    53855385    if (OpenFile() < 0)
    53865386        return(0);
  • libs/libmythtv/programinfo.h

     
    237237    // Keyframe positions Map
    238238    void GetPositionMap(frm_pos_map_t &, int type) const;
    239239    void ClearPositionMap(int type) const;
     240    void ClearPositionMap(int type, bool sync) const;
    240241    void SetPositionMap(frm_pos_map_t &, int type,
    241242                        long long min_frm = -1, long long max_frm = -1) const;
    242     void SetPositionMapDelta(frm_pos_map_t &, int type) const;
     243    void SetPositionMapDelta(frm_pos_map_t &, int type);
    243244
    244 
    245245    // GUI stuff
    246246    void showDetails(void) const;
    247247    void EditRecording(void);
     
    344344  private:
    345345    bool ignoreBookmark;
    346346    mutable class ScheduledRecording* record;
     347   
     348    QString inUseForWhat;
    347349
    348     QString inUseForWhat;
    349350};
    350351
    351352/** \class ProgramList
  • libs/libmythtv/programinfo.cpp

     
    1717#include "util.h"
    1818#include "mythcontext.h"
    1919#include "dialogbox.h"
     20#include "asyncdb.h"
    2021#include "remoteutil.h"
    2122#include "jobqueue.h"
    2223#include "mythdbcon.h"
     
    18121813{
    18131814    filesize = fsize;
    18141815
    1815     MSqlQuery query(MSqlQuery::InitCon());
    1816     query.prepare("UPDATE recorded SET filesize = :FILESIZE"
    1817                   " WHERE chanid = :CHANID"
    1818                   " AND starttime = :STARTTIME ;");
    1819     query.bindValue(":FILESIZE", longLongToString(fsize));
    1820     query.bindValue(":CHANID", chanid);
    1821     query.bindValue(":STARTTIME", recstartts);
     1816    QString query = QString("UPDATE recorded SET filesize = %1"
     1817                            " WHERE chanid = %2"
     1818                            " AND starttime = \"%3\" ;")
     1819      .arg(longLongToString(fsize))
     1820      .arg(chanid)
     1821      .arg(recstartts.toString("yyyyMMddhhmmss"));
    18221822   
    1823     if (!query.exec() || !query.isActive())
    1824         MythContext::DBError("File size update",
    1825                              query);
     1823    gAsyncDB->AddCommand(query);
    18261824}
    18271825
    18281826/** \fn ProgramInfo::GetFilesize(void)
     
    25952593
    25962594void ProgramInfo::ClearPositionMap(int type) const
    25972595{
     2596    QString query;
     2597 
     2598    if (isVideo)
     2599    {
     2600        query = QString("DELETE FROM filemarkup"
     2601                        " WHERE filename = \"%1\"")
     2602        .arg(pathname);
     2603    }
     2604    else
     2605    {
     2606        query = QString("DELETE FROM recordedseek"
     2607                      " WHERE chanid = %1"
     2608                      " AND starttime = \"%2\"")
     2609        .arg(chanid)
     2610        .arg(recstartts.toString("yyyyMMddhhmmss"));
     2611    }
     2612    query += QString(" AND type = %1 ;").arg(type);
     2613                               
     2614    /* Hand it to the async thread */
     2615    gAsyncDB->AddCommand(query);
     2616}
     2617
     2618void ProgramInfo::ClearPositionMap(int type, bool sync) const
     2619{
    25982620    MSqlQuery query(MSqlQuery::InitCon());
    25992621 
    26002622    if (isVideo)
     
    27122734}
    27132735
    27142736void ProgramInfo::SetPositionMapDelta(frm_pos_map_t &posMap,
    2715                                       int type) const
     2737                                      int type)
    27162738{
    27172739    QMap<long long, long long>::Iterator i;
    2718     MSqlQuery query(MSqlQuery::InitCon());
     2740    QString insert;
    27192741
     2742    if( posMap.isEmpty() )
     2743      return;
     2744
     2745    if (isVideo)
     2746      {
     2747        insert = QString("INSERT INTO filemarkup"
     2748                         " (filename, mark, type, offset)"
     2749                         " VALUES");
     2750      }
     2751    else
     2752      {
     2753        insert = QString("INSERT INTO recordedseek"
     2754                         " (chanid, starttime, mark, type, offset)"
     2755                         " VALUES");
     2756      }
     2757    QString sep = " ";
     2758
     2759    /* Assemble these these updates into a single multi-row insert
     2760     * statement -- much more efficient */
    27202761    for (i = posMap.begin(); i != posMap.end(); ++i)
    27212762    {
    27222763        long long frame = i.key();
     
    27312772        QString offset_str = tempc;
    27322773
    27332774        if (isVideo)
    2734         {
    2735             query.prepare("INSERT INTO filemarkup"
    2736                           " (filename, mark, type, offset)"
    2737                           " VALUES"
    2738                           " ( :PATH , :MARK , :TYPE , :OFFSET );");
    2739             query.bindValue(":PATH", pathname);
    2740         }
    2741         else
    2742         {
    2743             query.prepare("INSERT INTO recordedseek"
    2744                           " (chanid, starttime, mark, type, offset)"
    2745                           " VALUES"
    2746                           " ( :CHANID , :STARTTIME , :MARK , :TYPE , :OFFSET );");
    2747             query.bindValue(":CHANID", chanid);
    2748             query.bindValue(":STARTTIME", recstartts);
    2749         }
    2750         query.bindValue(":MARK", frame_str);
    2751         query.bindValue(":TYPE", type);
    2752         query.bindValue(":OFFSET", offset_str);
    2753        
    2754         if (!query.exec() || !query.isActive())
    2755             MythContext::DBError("delta position map insert",
    2756                                  query);
    2757     }
     2775          {
     2776            insert += sep + QString("( \"%1\", %2, %3, %4 )")
     2777              .arg(pathname).arg(i.key()).arg(type).arg(i.data());
     2778          }
     2779          else
     2780          {
     2781            insert += sep + QString("( %1 , \"%2\" , %3 , %4 , %5 )")
     2782              .arg(chanid).arg(recstartts.toString("yyyyMMddhhmmss"))
     2783              .arg(i.key()).arg(type).arg(i.data());
     2784          }
     2785        sep = ",";
     2786      }
     2787
     2788    insert += QString(";");
     2789    /* Hand it to the async thread */
     2790    gAsyncDB->AddCommand(insert);
    27582791}
    27592792
    27602793/** \fn ProgramInfo::ReactivateRecording(void)
  • libs/libmyth/exitcodes.h

     
    5757#define BACKEND_BUGGY_EXIT_NO_CAP_CARD            GENERIC_EXIT_START-11
    5858#define BACKEND_BUGGY_EXIT_NO_CHAN_DATA           GENERIC_EXIT_START-12
    5959#define BACKEND_EXIT_START                        GENERIC_EXIT_START-12
     60#define BACKEND_EXIT_ASYNCDB_ERROR                GENERIC_EXIT_START-13
    6061
    6162// mythtranscode
    6263#define TRANSCODE_EXIT_OK                         GENERIC_EXIT_OK
  • libs/libmyth/libmyth.pro

     
    2020HEADERS += langsettings.h audiooutputnull.h mythsocket.h
    2121HEADERS += DisplayResScreen.h util-x11.h mythdeque.h qmdcodec.h
    2222HEADERS += exitcodes.h virtualkeyboard.h mythobservable.h mythevent.h
     23HEADERS += asyncdb.h
    2324HEADERS += mythexp.h mythpluginapi.h
    2425
    2526SOURCES += dialogbox.cpp lcddevice.cpp mythcontext.cpp mythwidgets.cpp
     
    3334SOURCES += langsettings.cpp mythdbcon.cpp audiooutputnull.cpp
    3435SOURCES += DisplayResScreen.cpp util-x11.cpp qmdcodec.cpp
    3536SOURCES += virtualkeyboard.cpp mythobservable.cpp mythsocket.cpp
     37SOURCES += asyncdb.cpp
    3638
    3739INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../.. ../
    3840DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch ../ ../libmythui
     
    5961inc.files += visual.h volumebase.h output.h langsettings.h qmdcodec.h
    6062inc.files += exitcodes.h mythconfig.h mythconfig.mak virtualkeyboard.h
    6163inc.files += mythevent.h mythobservable.h mythsocket.h
     64inc.files += asyncdb.h
    6265inc.files += mythexp.h mythpluginapi.h
    6366
    6467cygwin:QMAKE_LFLAGS_SHLIB += -Wl,--noinhibit-exec
  • libs/libmyth/asyncdb.h

     
     1#ifndef ASYNCDB_H_
     2#define ASYNCDB_H_
     3
     4// ANSI C headers
     5#include <cstdio>
     6#include <cstdlib>
     7#include <cerrno>
     8
     9#include "mythdbcon.h"
     10
     11#include <qstring.h>
     12
     13using namespace std;
     14
     15class AsyncDB
     16{
     17 public:
     18    AsyncDB(void);
     19    ~AsyncDB();
     20    bool Init(void);
     21    void AddCommand(QString); 
     22
     23 private:
     24    pthread_t thread;
     25    QStringList list;
     26    QMutex listLock;
     27    MSqlQuery query;
     28    bool threadRunning;
     29
     30 protected:
     31    static void *StartThread(void *);
     32    void Worker(void);
     33};
     34
     35extern AsyncDB *gAsyncDB;
     36#endif
  • libs/libmyth/asyncdb.cpp

     
     1#include "asyncdb.h"
     2#include <unistd.h>
     3#include <sys/time.h>
     4#include <sys/resource.h>
     5#include <sys/mman.h>
     6
     7AsyncDB *gAsyncDB = NULL;
     8#define ADB QString("AsyncDB: ")
     9
     10/** \class AsyncDB
     11 *  \brief This class supports asynchronous database inserts.
     12 *
     13 *   This class allows us to toss those database queries for which
     14 *   we do not require values or status to be run by a separate thread.
     15 *   This helps the enocder threads to keep up with the datastream.
     16 */
     17
     18/** \fn AsyncDB
     19 *  \brief Initialize the class
     20 */
     21AsyncDB::AsyncDB(void):
     22  query(MSqlQuery::InitCon()), threadRunning(false)
     23{
     24  list.clear();
     25}
     26
     27/** \fn Init()
     28 *  \brief Starts the thread
     29 *
     30 *   Create a thread and return false if this fails
     31 */
     32bool AsyncDB::Init(void)
     33{
     34  int rv;
     35  if(  ( rv = pthread_create(&thread, NULL, StartThread, this) ) ) {
     36    VERBOSE(VB_IMPORTANT, ADB + QString("Can't start thread"));
     37    return false;
     38  }
     39  threadRunning = true;
     40  return(true);
     41}
     42
     43/** \fn StartThread(AsyncDB *)
     44 *  \brief Runs the worker function
     45 *
     46 *   Drop the priority on this thread and invoke the worker function
     47 */
     48void *AsyncDB::StartThread(void *wotzit)
     49{
     50  AsyncDB *pi = (AsyncDB *)wotzit;
     51  VERBOSE(VB_IMPORTANT,QString("Starting async db thread"));
     52  // Loser priority, to avoid problems with recordings.
     53  setpriority(PRIO_PROCESS, 0, 3);
     54  pi->Worker();
     55  return(NULL);
     56}
     57
     58/** \fn AddCommand(QString)
     59 *  \brief Adds a database command to the list
     60 *
     61 *  \param QString   The sql command
     62 */
     63void AsyncDB::AddCommand(QString cmd)
     64{
     65  listLock.lock();
     66  list.append(cmd);
     67  listLock.unlock();
     68}
     69
     70/** \fn ~AsyncDB
     71 *  \brief Shut down the thread
     72 *
     73 *   Add a "done" command to the list to make the thread
     74 *   shutdown and reap it.
     75 */
     76AsyncDB::~AsyncDB(void)
     77{
     78  AddCommand(QString("done"));
     79  pthread_join(thread, NULL);
     80  VERBOSE(VB_IMPORTANT,QString("Ending async db thread"));
     81}
     82
     83/** \fn Worker()
     84 *  \brief Run the lists of commands
     85 *
     86 *   Swap the list for an empty one and call ListRunner
     87 *   to execute the commands.
     88 */
     89void AsyncDB::Worker(void)
     90{
     91  bool done = false;
     92
     93  while( ! done ) {
     94    if( list.empty() ) {
     95      sleep(1);
     96    } else {
     97      listLock.lock();
     98      QStringList mylist = list;
     99      list.clear();
     100      listLock.unlock();
     101      for ( QStringList::Iterator it = mylist.begin(); it != mylist.end(); ++it ) {
     102        if( *it == QString("done") ) {
     103          done = true;
     104          break;
     105        }
     106        query.prepare(*it);
     107        if (!query.exec() || !query.isActive())
     108          MythContext::DBError("delta position map insert",
     109                               query);
     110      }
     111      mylist.clear();
     112    }
     113  }
     114}
  • programs/mythtranscode/main.cpp

     
    553553{
    554554    if (pginfo && ! mapfile)
    555555    {
    556         pginfo->ClearPositionMap(MARK_KEYFRAME);
    557         pginfo->ClearPositionMap(MARK_GOP_START);
     556        pginfo->ClearPositionMap(MARK_KEYFRAME, true);
     557        pginfo->ClearPositionMap(MARK_GOP_START, true);
    558558        pginfo->SetPositionMap(posMap, MARK_GOP_BYFRAME);
    559559    }
    560560    else if (mapfile)
  • programs/mythbackend/main.cpp

     
    3636#include "libmythtv/jobqueue.h"
    3737#include "libmythtv/storagegroup.h"
    3838#include "libmythupnp/mediaserver.h"
     39#include "libmyth/asyncdb.h"
    3940
    4041#include "upnpcdstv.h"
    4142#include "upnpcdsmusic.h"
     
    203204
    204205void cleanup(void)
    205206{
     207    delete gAsyncDB;
    206208    delete gContext;
    207209
    208210    if (sched)
     
    525527    }   
    526528    gContext->ActivateSettingsCache(true);
    527529
     530    gAsyncDB = new AsyncDB();
     531    if( gAsyncDB->Init() == false )
     532      {
     533        VERBOSE(VB_IMPORTANT, "Couldn't start async database thread");
     534        return BACKEND_EXIT_ASYNCDB_ERROR;
     535      }
     536
    528537    if (printsched || testsched)
    529538    {
    530539        gContext->SetBackend(false);