From f2167b1467eb98325f64300f96318391077c688b Mon Sep 17 00:00:00 2001 From: louis Date: Sat, 25 Oct 2014 05:55:19 +0200 Subject: [PATCH] Version 0.1.5 - introduced new DB API --- HISTORY | 3 ++ lib/common.h | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/config.h | 2 + lib/db.c | 1 + lib/db.h | 94 +++++++++++++++++++++++--------- lib/demo.c | 2 +- lib/tabledef.c | 6 +-- lib/tabledef.h | 6 +-- lib/test.c | 2 +- scraper2vdr.c | 5 +- scraper2vdr.h | 2 +- scrapmanager.c | 4 +- update.c | 3 +- 13 files changed, 236 insertions(+), 37 deletions(-) diff --git a/HISTORY b/HISTORY index 016de5a..183bd2b 100644 --- a/HISTORY +++ b/HISTORY @@ -33,3 +33,6 @@ Version 0.1.3 Version 0.1.4 - added ScraperGetPosterBannerV2 Service + +Versionn 0.1.5 +- introduced new DB API diff --git a/lib/common.h b/lib/common.h index 5aa4819..e757e3d 100644 --- a/lib/common.h +++ b/lib/common.h @@ -11,6 +11,7 @@ #include // uint_64_t #include #include +#include #include #include // MD5_* @@ -280,5 +281,147 @@ class LogDuration int logLevel; }; +//*************************************************************************** +// Semaphore +//*************************************************************************** + +#include + +class Sem +{ + public: + + Sem(key_t aKey) + { + locked = no; + key = aKey; + + if ((id = semget(key, 1, 0666 | IPC_CREAT)) == -1) + tell(0, "Error: Can't get semaphore, errno (%d) '%s'", + errno, strerror(errno)); + } + + ~Sem() + { + if (locked) + v(); + } + + // ---------------------- + // get lock + + int p() + { + sembuf sops[2]; + + sops[0].sem_num = 0; + sops[0].sem_op = 0; // wait for lock + sops[0].sem_flg = SEM_UNDO; + + sops[1].sem_num = 0; + sops[1].sem_op = 1; // increment + sops[1].sem_flg = SEM_UNDO | IPC_NOWAIT; + + if (semop(id, sops, 2) == -1) + { + tell(0, "Error: Can't lock semaphore, errno (%d) '%s'", + errno, strerror(errno)); + + return fail; + } + + locked = yes; + + return success; + } + + // ---------------------- + // increment + + int inc() + { + sembuf sops[1]; + + sops[0].sem_num = 0; + sops[0].sem_op = 1; // increment + sops[0].sem_flg = SEM_UNDO | IPC_NOWAIT; + + if (semop(id, sops, 1) == -1) + { + if (errno != EAGAIN) + tell(0, "Error: Can't lock semaphore, errno was (%d) '%s'", + errno, strerror(errno)); + + return fail; + } + + locked = yes; + + return success; + } + + // ---------------------- + // decrement + + int dec() + { + return v(); + } + + // ---------------------- + // check + + int check() + { + sembuf sops[1]; + + sops[0].sem_num = 0; + sops[0].sem_op = 0; + sops[0].sem_flg = SEM_UNDO | IPC_NOWAIT; + + if (semop(id, sops, 1) == -1) + { + if (errno != EAGAIN) + tell(0, "Error: Can't lock semaphore, errno was (%d) '%s'", + errno, strerror(errno)); + + return fail; + } + + return success; + } + + // ---------------------- + // release lock + + int v() + { + sembuf sops; + + sops.sem_num = 0; + sops.sem_op = -1; // release control + sops.sem_flg = SEM_UNDO | IPC_NOWAIT; + + if (semop(id, &sops, 1) == -1) + { + if (errno != EAGAIN) + tell(0, "Error: Can't unlock semaphore, errno (%d) '%s'", + errno, strerror(errno)); + + return fail; + } + + locked = no; + + return success; + } + + private: + + key_t key; + int id; + int locked; +}; + //*************************************************************************** #endif //___COMMON_H diff --git a/lib/config.h b/lib/config.h index 4389c58..f32877a 100644 --- a/lib/config.h +++ b/lib/config.h @@ -11,6 +11,8 @@ #include "common.h" +#define EPG_PLUGIN_SEM_KEY 0x3db00001 + //*************************************************************************** // Config //*************************************************************************** diff --git a/lib/db.c b/lib/db.c index 6ee2c71..d08a82d 100644 --- a/lib/db.c +++ b/lib/db.c @@ -512,6 +512,7 @@ int cDbConnection::dbPort = 3306; char* cDbConnection::dbUser = 0; char* cDbConnection::dbPass = 0; char* cDbConnection::dbName = 0; +Sem* cDbConnection::sem = 0; //*************************************************************************** // Object diff --git a/lib/db.h b/lib/db.h index 5f44c14..4c3bc08 100644 --- a/lib/db.h +++ b/lib/db.h @@ -8,11 +8,15 @@ #ifndef __DB_H #define __DB_H +#include + +#include #include #include #include #include #include + #include #include @@ -550,13 +554,11 @@ class cDbConnection virtual ~cDbConnection() { - if (mysql) - { - mysql_close(mysql); - mysql_thread_end(); - } + close(); } + int isConnected() { return getMySql() > 0; } + int attachConnection() { static int first = yes; @@ -565,14 +567,16 @@ class cDbConnection { connectDropped = yes; + tell(0, "Calling mysql_init(%ld)", syscall(__NR_gettid)); + if (!(mysql = mysql_init(0))) return errorSql(this, "attachConnection(init)"); if (!mysql_real_connect(mysql, dbHost, dbUser, dbPass, dbName, dbPort, 0, 0)) { - mysql_close(mysql); - mysql = 0; + close(); + tell(0, "Error, connecting to database at '%s' on port (%d) failed", dbHost, dbPort); @@ -601,19 +605,25 @@ class cDbConnection return success; } - void detachConnection() - { - attached--; - - if (!attached) + void close() + { + if (mysql) { + tell(0, "Closing mysql connection and calling mysql_thread_end(%ld)", syscall(__NR_gettid)); + mysql_close(mysql); mysql_thread_end(); mysql = 0; } } - int isConnected() { return getMySql() > 0; } + void detachConnection() + { + attached--; + + if (!attached) + close(); + } int check() { @@ -724,12 +734,7 @@ class cDbConnection MYSQL* getMySql() { if (connectDropped && mysql) - { - mysql_close(mysql); - mysql_thread_end(); - mysql = 0; - attached = 0; - } + close(); return mysql; } @@ -756,22 +761,59 @@ class cDbConnection int errorSql(cDbConnection* mysql, const char* prefix, MYSQL_STMT* stmt = 0, const char* stmtTxt = 0); - void showStat(const char* name = "") { statements.showStat(name); } + void showStat(const char* name = "") { statements.showStat(name); } - static int init() + // ----------------------------------------------------------- + // init() and exit() must exactly called 'once' per process + + static int init(key_t semKey) { - if (mysql_library_init(0, 0, 0)) + if (semKey && !sem) + sem = new Sem(semKey); + + if (!sem || sem->check() == success) { - tell(0, "Error: mysql_library_init failed"); - return fail; // return errorSql(0, "init(library_init)"); + // call only once per process + + if (sem) + tell(1, "Info: Calling mysql_library_init()"); + + if (mysql_library_init(0, 0, 0)) + { + tell(0, "Error: mysql_library_init() failed"); + return fail; + } } + else if (sem) + { + tell(1, "Info: Skipping calling mysql_library_init(), it's already done!"); + } + + if (sem) + sem->inc(); // count usage per process return success; } static int exit() { - mysql_library_end(); + mysql_thread_end(); + + if (sem) + sem->dec(); + + if (!sem || sem->check() == success) + { + if (sem) + tell(1, "Info: Released the last usage of mysql_lib, calling mysql_library_end() now"); + + mysql_library_end(); + } + else if (sem) + { + tell(1, "Info: The mysql_lib is still in use, skipping mysql_library_end() call"); + } + free(dbHost); free(dbUser); free(dbPass); @@ -792,6 +834,8 @@ class cDbConnection int inTact; int connectDropped; + static Sem* sem; + static char* encoding; // connecting data diff --git a/lib/demo.c b/lib/demo.c index 1d6ee10..b8a6592 100644 --- a/lib/demo.c +++ b/lib/demo.c @@ -15,7 +15,7 @@ const char* logPrefix = "demo"; void initConnection() { - cDbConnection::init(); + cDbConnection::init(0x3db00012); cDbConnection::setEncoding("utf8"); cDbConnection::setHost("localhost"); diff --git a/lib/tabledef.c b/lib/tabledef.c index d9826f5..3ea28c1 100644 --- a/lib/tabledef.c +++ b/lib/tabledef.c @@ -117,9 +117,9 @@ cDbService::FieldDef cTableEvents::fields[] = // episodes (constable) - { "episode", ffAscii, 250, fiEpisode, ftData }, - { "episodepart", ffAscii, 250, fiEpisodePart, ftData }, - { "episodelang", ffAscii, 3, fiEpisodeLang, ftData }, +// { "episodecompname", ffAscii, 250, fiEpisode, ftData }, +// { "episodecomppartname", ffAscii, 250, fiEpisodePart, ftData }, +// { "episodelang", ffAscii, 3, fiEpisodeLang, ftData }, // tv scraper diff --git a/lib/tabledef.h b/lib/tabledef.h index 9936f4e..9e6e83d 100644 --- a/lib/tabledef.h +++ b/lib/tabledef.h @@ -251,9 +251,9 @@ class cTableEvents : public cDbTable fiExtEpNum, fiImageCount, - fiEpisode, - fiEpisodePart, - fiEpisodeLang, +// fiEpisode, +// fiEpisodePart, +// fiEpisodeLang, fiScrSeriesId, fiScrSeriesEpisode, diff --git a/lib/test.c b/lib/test.c index fa85c70..e514aae 100644 --- a/lib/test.c +++ b/lib/test.c @@ -21,7 +21,7 @@ const char* logPrefix = "test"; void initConnection() { - cDbConnection::init(); + cDbConnection::init(0x3db00011); cDbConnection::setEncoding("utf8"); cDbConnection::setHost("localhost"); diff --git a/scraper2vdr.c b/scraper2vdr.c index 8f81c50..e21d234 100644 --- a/scraper2vdr.c +++ b/scraper2vdr.c @@ -6,7 +6,10 @@ * $Id$ */ +#include "lib/config.h" + #include "scraper2vdr.h" + const char* logPrefix = LOG_PREFIX; #if defined (APIVERSNUM) && (APIVERSNUM < 10600) @@ -80,7 +83,7 @@ eOSState cScraper2VdrPluginMenu::ProcessKey(eKeys key) { //*************************************************************************** cPluginScraper2vdr::cPluginScraper2vdr(void) { - cDbConnection::init(); + cDbConnection::init(EPG_PLUGIN_SEM_KEY); } cPluginScraper2vdr::~cPluginScraper2vdr() { diff --git a/scraper2vdr.h b/scraper2vdr.h index 7346edf..30c63cd 100644 --- a/scraper2vdr.h +++ b/scraper2vdr.h @@ -13,7 +13,7 @@ //*************************************************************************** // Constants //*************************************************************************** -static const char *VERSION = "0.1.4"; +static const char *VERSION = "0.1.5"; static const char *DESCRIPTION = "'scraper2vdr' plugin"; static const char *MAINMENUENTRY = "Scraper2Vdr"; diff --git a/scrapmanager.c b/scrapmanager.c index 4b07ff3..2df3c65 100644 --- a/scrapmanager.c +++ b/scrapmanager.c @@ -354,7 +354,7 @@ void cScrapManager::DumpMovies(void) { } void cScrapManager::DumpRecordings(void) { - tell(0, "%d recordings in memory:", recordings.size()); + tell(0, "%ld recordings in memory:", recordings.size()); for (map::iterator it = recordings.begin(); it != recordings.end(); it++) { sRecordingsKey key = it->first; sEventsValue val = it->second; @@ -481,6 +481,7 @@ bool cScrapManager::GetMovie(cMovie *m) { bool cScrapManager::GetPosterBanner(ScraperGetPosterBanner *call) { sEventsValue v; + v.episodeId = 0; if (call->event) { sEventsKey k; k.eventId = call->event->EventID(); @@ -516,6 +517,7 @@ bool cScrapManager::GetPosterBanner(ScraperGetPosterBanner *call) { bool cScrapManager::GetPosterBannerV2(ScraperGetPosterBannerV2 *call) { sEventsValue v; + v.episodeId = 0; if (call->event) { sEventsKey k; k.eventId = call->event->EventID(); diff --git a/update.c b/update.c index 09b27b1..9fdc358 100644 --- a/update.c +++ b/update.c @@ -77,7 +77,6 @@ cUpdate::cUpdate(cScrapManager *manager) : cThread("update thread started", true cUpdate::~cUpdate() { if (loopActive) Stop(); - exitDb(); } // global field definitions @@ -1356,6 +1355,8 @@ void cUpdate::Action() worked = no; } + + exitDb(); // don't call exit in dtor, outside from thread!! loopActive = no; tell(0, "Update thread ended (pid=%d)", getpid()); }