Ticket #1660: asyncdb.12546.patch
File asyncdb.12546.patch, 14.2 KB (added by , 19 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
5242 5242 using_null_videoout = true; 5243 5243 5244 5244 // clear out any existing seektables 5245 m_playbackinfo->ClearPositionMap(MARK_KEYFRAME );5246 m_playbackinfo->ClearPositionMap(MARK_GOP_START );5247 m_playbackinfo->ClearPositionMap(MARK_GOP_BYFRAME );5245 m_playbackinfo->ClearPositionMap(MARK_KEYFRAME,true); 5246 m_playbackinfo->ClearPositionMap(MARK_GOP_START,true); 5247 m_playbackinfo->ClearPositionMap(MARK_GOP_BYFRAME,true); 5248 5248 5249 5249 if (OpenFile() < 0) 5250 5250 return(0); -
libs/libmythtv/programinfo.h
220 220 // Keyframe positions Map 221 221 void GetPositionMap(frm_pos_map_t &, int type) const; 222 222 void ClearPositionMap(int type) const; 223 void ClearPositionMap(int type, bool sync) const; 223 224 void SetPositionMap(frm_pos_map_t &, int type, 224 225 long long min_frm = -1, long long max_frm = -1) const; 225 void SetPositionMapDelta(frm_pos_map_t &, int type) const;226 void SetPositionMapDelta(frm_pos_map_t &, int type); 226 227 227 228 228 // GUI stuff 229 229 void showDetails(void) const; 230 230 void EditRecording(void); … … 322 322 private: 323 323 bool ignoreBookmark; 324 324 mutable class ScheduledRecording* record; 325 326 QString inUseForWhat; 325 327 326 QString inUseForWhat;327 328 }; 328 329 329 330 /** \class ProgramList -
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/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 typedef struct adb_cmd_list { 16 struct adb_cmd_list *next; 17 QString cmd; 18 } adb_cmd_list_t; 19 20 class AsyncDB 21 { 22 public: 23 AsyncDB(void); 24 ~AsyncDB(); 25 bool Init(void); 26 void AddCommand(QString); 27 28 private: 29 pthread_t thread; 30 bool threadRunning; 31 QStringList list; 32 // adb_cmd_list_t *list; 33 QMutex listLock; 34 MSqlQuery query; 35 bool ListRunner(adb_cmd_list_t *); 36 37 protected: 38 static void *StartThread(void *); 39 void Worker(void); 40 }; 41 42 extern AsyncDB *gAsyncDB; 43 #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 // adb_cmd_list_t *item = new adb_cmd_list_t; 69 // item->cmd = cmd; 70 // listLock.lock(); 71 // item->next = list; 72 // list = item; 73 // listLock.unlock(); 74 } 75 76 /** \fn ~AsyncDB 77 * \brief Shut down the thread 78 * 79 * Add a "done" command to the list to make the thread 80 * shutdown and reap it. 81 */ 82 AsyncDB::~AsyncDB(void) 83 { 84 AddCommand(QString("done")); 85 pthread_join(thread, NULL); 86 VERBOSE(VB_IMPORTANT,QString("Ending async db thread")); 87 } 88 89 /** \fn Worker() 90 * \brief Run the lists of commands 91 * 92 * Swap the list for an empty one and call ListRunner 93 * to execute the commands. 94 */ 95 void AsyncDB::Worker(void) 96 { 97 bool done = false; 98 99 while( ! done ) { 100 if( list.empty() ) { 101 sleep(1); 102 } else { 103 listLock.lock(); 104 QStringList mylist = list; 105 list.clear(); 106 listLock.unlock(); 107 for ( QStringList::Iterator it = mylist.begin(); it != mylist.end(); ++it ) { 108 if( *it == QString("done") ) { 109 done = true; 110 break; 111 } 112 query.prepare(*it); 113 if (!query.exec() || !query.isActive()) 114 MythContext::DBError("delta position map insert", 115 query); 116 } 117 mylist.clear(); 118 } 119 } 120 // while( ! done ) { 121 // if( list == NULL ) { 122 // sleep(1); 123 // } else { 124 // listLock.lock(); 125 // adb_cmd_list_t *mylist = list; 126 // list = NULL; 127 // listLock.unlock(); 128 // done = ListRunner(mylist); 129 // } 130 // } 131 } 132 133 /** \fn ListRunner( adb_cmd_list_t * ) 134 * \brief Execute the accumulated commands 135 * 136 * Standard recursive routine. Shoot down to the end of the 137 * list and as we return back execute the commands and clean 138 * up the objects. This maintains order, since the newest 139 * commands are at the head of the list. 140 * 141 * If we find the command "done" return true. 142 * 143 * \param adb_cmd_list_t* The rest of the list 144 */ 145 bool AsyncDB::ListRunner( adb_cmd_list_t *list ) { 146 bool done = false; 147 if( list != NULL ) { 148 done = ListRunner(list->next); 149 if( list->cmd == QString("done") ) { 150 done = true; 151 } else { 152 query.prepare(list->cmd); 153 if (!query.exec() || !query.isActive()) 154 MythContext::DBError("async command failed", 155 query); 156 } 157 delete list->cmd; 158 delete list; 159 } 160 return( done ); 161 } 162 -
programs/mythtranscode/main.cpp
540 545 { 541 546 if (pginfo && ! mapfile) 542 547 { 543 pginfo->ClearPositionMap(MARK_KEYFRAME );544 pginfo->ClearPositionMap(MARK_GOP_START );548 pginfo->ClearPositionMap(MARK_KEYFRAME, true); 549 pginfo->ClearPositionMap(MARK_GOP_START, true); 545 550 pginfo->SetPositionMap(posMap, MARK_GOP_BYFRAME); 546 551 } 547 552 else if (mapfile) -
programs/mythbackend/main.cpp
35 35 #include "libmythtv/dbcheck.h" 36 36 #include "libmythtv/jobqueue.h" 37 37 #include "libmythupnp/upnp.h" 38 #include "libmyth/asyncdb.h" 38 39 39 40 #include "upnpcdstv.h" 40 41 #include "upnpcdsmusic.h" … … 202 203 203 204 void cleanup(void) 204 205 { 206 delete gAsyncDB; 205 207 delete gContext; 206 208 207 209 if (sched) … … 497 499 } 498 500 gContext->ActivateSettingsCache(true); 499 501 502 gAsyncDB = new AsyncDB(); 503 if( gAsyncDB->Init() == false ) 504 { 505 VERBOSE(VB_IMPORTANT, "Couldn't start async database thread"); 506 return BACKEND_EXIT_ASYNCDB_ERROR; 507 } 508 500 509 if (printsched || testsched) 501 510 { 502 511 gContext->SetBackend(false); -
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; 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 = " "; 2719 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/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