Ticket #1660: asyncdb.12694.patch
File asyncdb.12694.patch, 12.8 KB (added by , 17 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
5378 5378 using_null_videoout = true; 5379 5379 5380 5380 // 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); 5384 5384 5385 5385 if (OpenFile() < 0) 5386 5386 return(0); -
libs/libmythtv/programinfo.h
237 237 // Keyframe positions Map 238 238 void GetPositionMap(frm_pos_map_t &, int type) const; 239 239 void ClearPositionMap(int type) const; 240 void ClearPositionMap(int type, bool sync) const; 240 241 void SetPositionMap(frm_pos_map_t &, int type, 241 242 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); 243 244 244 245 245 // GUI stuff 246 246 void showDetails(void) const; 247 247 void EditRecording(void); … … 344 344 private: 345 345 bool ignoreBookmark; 346 346 mutable class ScheduledRecording* record; 347 348 QString inUseForWhat; 347 349 348 QString inUseForWhat;349 350 }; 350 351 351 352 /** \class ProgramList -
libs/libmythtv/programinfo.cpp
17 17 #include "util.h" 18 18 #include "mythcontext.h" 19 19 #include "dialogbox.h" 20 #include "asyncdb.h" 20 21 #include "remoteutil.h" 21 22 #include "jobqueue.h" 22 23 #include "mythdbcon.h" … … 1812 1813 { 1813 1814 filesize = fsize; 1814 1815 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")); 1822 1822 1823 if (!query.exec() || !query.isActive()) 1824 MythContext::DBError("File size update", 1825 query); 1823 gAsyncDB->AddCommand(query); 1826 1824 } 1827 1825 1828 1826 /** \fn ProgramInfo::GetFilesize(void) … … 2595 2593 2596 2594 void ProgramInfo::ClearPositionMap(int type) const 2597 2595 { 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 2618 void ProgramInfo::ClearPositionMap(int type, bool sync) const 2619 { 2598 2620 MSqlQuery query(MSqlQuery::InitCon()); 2599 2621 2600 2622 if (isVideo) … … 2712 2734 } 2713 2735 2714 2736 void ProgramInfo::SetPositionMapDelta(frm_pos_map_t &posMap, 2715 int type) const2737 int type) 2716 2738 { 2717 2739 QMap<long long, long long>::Iterator i; 2718 MSqlQuery query(MSqlQuery::InitCon());2740 QString insert; 2719 2741 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 */ 2720 2761 for (i = posMap.begin(); i != posMap.end(); ++i) 2721 2762 { 2722 2763 long long frame = i.key(); … … 2731 2772 QString offset_str = tempc; 2732 2773 2733 2774 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); 2758 2791 } 2759 2792 2760 2793 /** \fn ProgramInfo::ReactivateRecording(void) -
libs/libmyth/exitcodes.h
57 57 #define BACKEND_BUGGY_EXIT_NO_CAP_CARD GENERIC_EXIT_START-11 58 58 #define BACKEND_BUGGY_EXIT_NO_CHAN_DATA GENERIC_EXIT_START-12 59 59 #define BACKEND_EXIT_START GENERIC_EXIT_START-12 60 #define BACKEND_EXIT_ASYNCDB_ERROR GENERIC_EXIT_START-13 60 61 61 62 // mythtranscode 62 63 #define TRANSCODE_EXIT_OK GENERIC_EXIT_OK -
libs/libmyth/libmyth.pro
20 20 HEADERS += langsettings.h audiooutputnull.h mythsocket.h 21 21 HEADERS += DisplayResScreen.h util-x11.h mythdeque.h qmdcodec.h 22 22 HEADERS += exitcodes.h virtualkeyboard.h mythobservable.h mythevent.h 23 HEADERS += asyncdb.h 23 24 HEADERS += mythexp.h mythpluginapi.h 24 25 25 26 SOURCES += dialogbox.cpp lcddevice.cpp mythcontext.cpp mythwidgets.cpp … … 33 34 SOURCES += langsettings.cpp mythdbcon.cpp audiooutputnull.cpp 34 35 SOURCES += DisplayResScreen.cpp util-x11.cpp qmdcodec.cpp 35 36 SOURCES += virtualkeyboard.cpp mythobservable.cpp mythsocket.cpp 37 SOURCES += asyncdb.cpp 36 38 37 39 INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../.. ../ 38 40 DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch ../ ../libmythui … … 59 61 inc.files += visual.h volumebase.h output.h langsettings.h qmdcodec.h 60 62 inc.files += exitcodes.h mythconfig.h mythconfig.mak virtualkeyboard.h 61 63 inc.files += mythevent.h mythobservable.h mythsocket.h 64 inc.files += asyncdb.h 62 65 inc.files += mythexp.h mythpluginapi.h 63 66 64 67 cygwin: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 13 using namespace std; 14 15 class 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 35 extern 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 7 AsyncDB *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 */ 21 AsyncDB::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 */ 32 bool 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 */ 48 void *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 */ 63 void 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 */ 76 AsyncDB::~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 */ 89 void 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
553 553 { 554 554 if (pginfo && ! mapfile) 555 555 { 556 pginfo->ClearPositionMap(MARK_KEYFRAME );557 pginfo->ClearPositionMap(MARK_GOP_START );556 pginfo->ClearPositionMap(MARK_KEYFRAME, true); 557 pginfo->ClearPositionMap(MARK_GOP_START, true); 558 558 pginfo->SetPositionMap(posMap, MARK_GOP_BYFRAME); 559 559 } 560 560 else if (mapfile) -
programs/mythbackend/main.cpp
36 36 #include "libmythtv/jobqueue.h" 37 37 #include "libmythtv/storagegroup.h" 38 38 #include "libmythupnp/mediaserver.h" 39 #include "libmyth/asyncdb.h" 39 40 40 41 #include "upnpcdstv.h" 41 42 #include "upnpcdsmusic.h" … … 203 204 204 205 void cleanup(void) 205 206 { 207 delete gAsyncDB; 206 208 delete gContext; 207 209 208 210 if (sched) … … 525 527 } 526 528 gContext->ActivateSettingsCache(true); 527 529 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 528 537 if (printsched || testsched) 529 538 { 530 539 gContext->SetBackend(false);