diff options
author | methodus <methodus@web.de> | 2013-05-05 18:04:13 +0200 |
---|---|---|
committer | methodus <methodus@web.de> | 2013-05-05 18:04:13 +0200 |
commit | 001751f2d9ec3e13f5c4c36e8361ce1e4db43871 (patch) | |
tree | 1343028f7baa1a4f3412384cc4d384cbfcaf0b1b | |
parent | d260e7cb971bfeb031f40c3d61e4778dd326083d (diff) | |
download | vdr-plugin-upnp-001751f2d9ec3e13f5c4c36e8361ce1e4db43871.tar.gz vdr-plugin-upnp-001751f2d9ec3e13f5c4c36e8361ce1e4db43871.tar.bz2 |
Fixed segfault in vdrProvider
-rw-r--r-- | include/media/mediaManager.h | 5 | ||||
-rw-r--r-- | include/server.h | 4 | ||||
-rw-r--r-- | media/mediaManager.cpp | 307 | ||||
-rw-r--r-- | plugins/provider/vdrProvider/vdrProvider.cpp | 2 | ||||
-rw-r--r-- | server/server.cpp | 20 |
5 files changed, 165 insertions, 173 deletions
diff --git a/include/media/mediaManager.h b/include/media/mediaManager.h index 10cb9e9..36987ab 100644 --- a/include/media/mediaManager.h +++ b/include/media/mediaManager.h @@ -14,8 +14,6 @@ #include <list> #include <string> #include <stdint.h> -#include <tntdb/connect.h> -#include <tntdb/connection.h> namespace upnp { @@ -57,8 +55,6 @@ public: cMediaManager(); virtual ~cMediaManager(); - void SetDatabaseDir(const string& file); - bool Initialise(); void Housekeeping(); @@ -94,7 +90,6 @@ private: uint32_t systemUpdateID; IdList eventedContainerUpdateIDs; StringList scanTargets; - string databaseFile; tntdb::Connection connection; upnp::cPluginManager* pluginManager; diff --git a/include/server.h b/include/server.h index 6f52a1f..10be258 100644 --- a/include/server.h +++ b/include/server.h @@ -12,6 +12,8 @@ #include <map> #include <list> #include <upnp/upnp.h> +#include <tntdb/connect.h> +#include <tntdb/connection.h> #include "../include/config.h" using namespace std; @@ -67,6 +69,7 @@ public: const cWebserver& GetWebserver() const { return *mWebserver; } cMediaManager& GetManager() const { return *mMediaManager; } + tntdb::Connection& GetDatabase() const { return mConnection; } const string GetDeviceUUID() const { return string("uuid:") + mCurrentConfiguration.deviceUUID; } @@ -94,6 +97,7 @@ private: Description mServerDescription; iconList mServerIcons; upnp::cConfig mCurrentConfiguration; + tntdb::Connection mConnection; string mConfigDirectory; UpnpDevice_Handle mDeviceHandle; int mAnnounceMaxAge; diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp index c1b84a3..07afef2 100644 --- a/media/mediaManager.cpp +++ b/media/mediaManager.cpp @@ -107,16 +107,10 @@ cMediaManager::cMediaManager() : systemUpdateID(0) , pluginManager(NULL) { - SetDatabaseDir(string()); + connection = cMediaServer::GetInstance()->GetDatabase(); } cMediaManager::~cMediaManager(){ - try { - connection.execute("VACUUM"); - } catch (const std::exception& e) { - esyslog("UPnP\tFailed to vacuum database '%s': '%s'", databaseFile.c_str(), e.what()); - } - delete pluginManager; } @@ -491,127 +485,117 @@ void cMediaManager::Housekeeping(){ bool cMediaManager::Initialise(){ - try { - stringstream ss; - ss << "sqlite:" << databaseFile; + stringstream ss; - connection = tntdb::connect(ss.str()); + LOG(2, "Preparing database structure..."); - LOG(2, "Preparing database structure..."); + if(!CheckIntegrity()){ + try { - if(!CheckIntegrity()){ - try { + connection.beginTransaction(); - connection.beginTransaction(); - - ss.str(string()); - - ss << "CREATE TABLE " << db::Metadata - << "(" - << "`" << property::object::KEY_OBJECTID << "` TEXT PRIMARY KEY," - << "`" << property::object::KEY_PARENTID << "` TEXT NOT NULL," - << "`" << property::object::KEY_TITLE << "` TEXT NOT NULL," - << "`" << property::object::KEY_CLASS << "` TEXT NOT NULL," - << "`" << property::object::KEY_RESTRICTED << "` INTEGER NOT NULL," - << "`" << property::object::KEY_CREATOR << "` TEXT," - << "`" << property::object::KEY_DESCRIPTION << "` TEXT," - << "`" << property::object::KEY_LONG_DESCRIPTION << "` TEXT," - << "`" << property::object::KEY_DATE << "` TEXT," - << "`" << property::object::KEY_LANGUAGE << "` TEXT," - << "`" << property::object::KEY_CHANNEL_NR << "` INTEGER," - << "`" << property::object::KEY_CHANNEL_NAME << "` TEXT," - << "`" << property::object::KEY_SCHEDULED_START << "` TEXT," - << "`" << property::object::KEY_SCHEDULED_END << "` TEXT," - << "`" << property::object::KEY_OBJECT_UPDATE_ID << "` INTEGER" - << ")"; - - tntdb::Statement objectTable = connection.prepare(ss.str()); - - objectTable.execute(); - - ss.str(string()); - - ss << "CREATE TABLE " << db::Details - << "(" - << " `propertyID` INTEGER PRIMARY KEY," - << " `" << property::object::KEY_OBJECTID << "` TEXT " - << " REFERENCES metadata (`"<< property::object::KEY_OBJECTID <<"`) ON DELETE CASCADE ON UPDATE CASCADE," - << " `property` TEXT," - << " `value` TEXT" - << ")"; - - tntdb::Statement detailsTable = connection.prepare(ss.str()); - - detailsTable.execute(); - - ss.str(string()); - - ss << "CREATE TABLE " << db::Resources - << "(" - << "`" << property::object::KEY_OBJECTID << "` TEXT " - << "REFERENCES metadata (`"<< property::object::KEY_OBJECTID <<"`) ON DELETE CASCADE ON UPDATE CASCADE," - << "`" << property::resource::KEY_RESOURCE << "` TEXT," - << "`" << property::resource::KEY_PROTOCOL_INFO << "` TEXT NOT NULL," - << "`" << property::resource::KEY_SIZE << "` INTEGER," - << "`" << property::resource::KEY_DURATION << "` TEXT," - << "`" << property::resource::KEY_RESOLUTION << "` TEXT," - << "`" << property::resource::KEY_BITRATE << "` INTEGER," - << "`" << property::resource::KEY_SAMPLE_FREQUENCY << "` INTEGER," - << "`" << property::resource::KEY_BITS_PER_SAMPLE << "` INTEGER," - << "`" << property::resource::KEY_NR_AUDIO_CHANNELS << "` INTEGER," - << "`" << property::resource::KEY_COLOR_DEPTH << "` INTEGER," - << "PRIMARY KEY (" - << "`" << property::object::KEY_OBJECTID << "`," - << "`" << property::resource::KEY_RESOURCE << "`" - << ")" - << ")"; - - tntdb::Statement resourcesTable = connection.prepare(ss.str()); - - resourcesTable.execute(); - - ss.str(string()); - - ss << "INSERT INTO " << db::Metadata << " (" - << "`" << property::object::KEY_OBJECTID << "`, " - << "`" << property::object::KEY_PARENTID << "`, " - << "`" << property::object::KEY_TITLE << "`, " - << "`" << property::object::KEY_CLASS << "`, " - << "`" << property::object::KEY_RESTRICTED << "`, " - << "`" << property::object::KEY_CREATOR << "`, " - << "`" << property::object::KEY_DESCRIPTION << "`, " - << "`" << property::object::KEY_LONG_DESCRIPTION << "`) " - << " VALUES (:objectID, :parentID, :title, :class, :restricted, :creator, :description, :longDescription)"; - - tntdb::Statement rootContainer = connection.prepare(ss.str()); - - const cMediaServer::Description desc = cMediaServer::GetInstance()->GetServerDescription(); - - rootContainer.setString("objectID", "0") - .setString("parentID", "-1") - .setString("title", desc.friendlyName) - .setString("creator", desc.manufacturer) - .setString("class", "object.container") - .setBool("restricted", true) - .setString("description", desc.modelName) - .setString("longDescription", desc.modelDescription) - .execute(); - - connection.commitTransaction(); + ss.str(string()); - } catch (const std::exception& e) { - esyslog("UPnP\tException occurred while initializing database '%s': %s", databaseFile.c_str(), e.what()); - connection.rollbackTransaction(); + ss << "CREATE TABLE " << db::Metadata + << "(" + << "`" << property::object::KEY_OBJECTID << "` TEXT PRIMARY KEY," + << "`" << property::object::KEY_PARENTID << "` TEXT NOT NULL," + << "`" << property::object::KEY_TITLE << "` TEXT NOT NULL," + << "`" << property::object::KEY_CLASS << "` TEXT NOT NULL," + << "`" << property::object::KEY_RESTRICTED << "` INTEGER NOT NULL," + << "`" << property::object::KEY_CREATOR << "` TEXT," + << "`" << property::object::KEY_DESCRIPTION << "` TEXT," + << "`" << property::object::KEY_LONG_DESCRIPTION << "` TEXT," + << "`" << property::object::KEY_DATE << "` TEXT," + << "`" << property::object::KEY_LANGUAGE << "` TEXT," + << "`" << property::object::KEY_CHANNEL_NR << "` INTEGER," + << "`" << property::object::KEY_CHANNEL_NAME << "` TEXT," + << "`" << property::object::KEY_SCHEDULED_START << "` TEXT," + << "`" << property::object::KEY_SCHEDULED_END << "` TEXT," + << "`" << property::object::KEY_OBJECT_UPDATE_ID << "` INTEGER" + << ")"; + + tntdb::Statement objectTable = connection.prepare(ss.str()); + + objectTable.execute(); - return false; - } + ss.str(string()); - } + ss << "CREATE TABLE " << db::Details + << "(" + << " `propertyID` INTEGER PRIMARY KEY," + << " `" << property::object::KEY_OBJECTID << "` TEXT " + << " REFERENCES metadata (`"<< property::object::KEY_OBJECTID <<"`) ON DELETE CASCADE ON UPDATE CASCADE," + << " `property` TEXT," + << " `value` TEXT" + << ")"; - } catch (const std::exception& e) { - esyslog("UPnP\tException occurred while connecting to database '%s': %s", databaseFile.c_str(), e.what()); + tntdb::Statement detailsTable = connection.prepare(ss.str()); + + detailsTable.execute(); + + ss.str(string()); + + ss << "CREATE TABLE " << db::Resources + << "(" + << "`" << property::object::KEY_OBJECTID << "` TEXT " + << "REFERENCES metadata (`"<< property::object::KEY_OBJECTID <<"`) ON DELETE CASCADE ON UPDATE CASCADE," + << "`" << property::resource::KEY_RESOURCE << "` TEXT," + << "`" << property::resource::KEY_PROTOCOL_INFO << "` TEXT NOT NULL," + << "`" << property::resource::KEY_SIZE << "` INTEGER," + << "`" << property::resource::KEY_DURATION << "` TEXT," + << "`" << property::resource::KEY_RESOLUTION << "` TEXT," + << "`" << property::resource::KEY_BITRATE << "` INTEGER," + << "`" << property::resource::KEY_SAMPLE_FREQUENCY << "` INTEGER," + << "`" << property::resource::KEY_BITS_PER_SAMPLE << "` INTEGER," + << "`" << property::resource::KEY_NR_AUDIO_CHANNELS << "` INTEGER," + << "`" << property::resource::KEY_COLOR_DEPTH << "` INTEGER," + << "PRIMARY KEY (" + << "`" << property::object::KEY_OBJECTID << "`," + << "`" << property::resource::KEY_RESOURCE << "`" + << ")" + << ")"; + + tntdb::Statement resourcesTable = connection.prepare(ss.str()); + + resourcesTable.execute(); + + ss.str(string()); + + ss << "INSERT INTO " << db::Metadata << " (" + << "`" << property::object::KEY_OBJECTID << "`, " + << "`" << property::object::KEY_PARENTID << "`, " + << "`" << property::object::KEY_TITLE << "`, " + << "`" << property::object::KEY_CLASS << "`, " + << "`" << property::object::KEY_RESTRICTED << "`, " + << "`" << property::object::KEY_CREATOR << "`, " + << "`" << property::object::KEY_DESCRIPTION << "`, " + << "`" << property::object::KEY_LONG_DESCRIPTION << "`) " + << " VALUES (:objectID, :parentID, :title, :class, :restricted, :creator, :description, :longDescription)"; + + tntdb::Statement rootContainer = connection.prepare(ss.str()); + + const cMediaServer::Description desc = cMediaServer::GetInstance()->GetServerDescription(); + + rootContainer.setString("objectID", "0") + .setString("parentID", "-1") + .setString("title", desc.friendlyName) + .setString("creator", desc.manufacturer) + .setString("class", "object.container") + .setBool("restricted", true) + .setString("description", desc.modelName) + .setString("longDescription", desc.modelDescription) + .execute(); + + connection.commitTransaction(); + + } catch (const std::exception& e) { + esyslog("UPnP\tException occurred while initializing database: %s", e.what()); + connection.rollbackTransaction(); + + return false; + } - return false; } dsyslog("UPnP\tLoading Plugins..."); @@ -637,40 +621,45 @@ bool cMediaManager::Initialise(){ bool cMediaManager::CheckIntegrity(){ - connection.execute("PRAGMA foreign_keys = ON"); - connection.execute("PRAGMA page_size = 4096"); - connection.execute("PRAGMA cache_size = 16384"); - connection.execute("PRAGMA temp_store = MEMORY"); - connection.execute("PRAGMA synchronous = NORMAL"); - connection.execute("PRAGMA locking_mode = EXCLUSIVE"); - - tntdb::Statement checkTable = connection.prepare( - "SELECT name FROM sqlite_master WHERE type='table' AND name=:table;" - ); - - if( checkTable.setString("table", db::Metadata).select().empty() ){ - isyslog("UPnP\tTable '%s' does not exist", db::Metadata); - return false; - } - if( checkTable.setString("table", db::Details).select().empty() ){ - isyslog("UPnP\tTable '%s' does not exist", db::Details); - return false; - } - if( checkTable.setString("table", db::Resources).select().empty() ){ - isyslog("UPnP\tTable '%s' does not exist", db::Resources); - return false; - } + try { + connection.execute("PRAGMA foreign_keys = ON"); + connection.execute("PRAGMA page_size = 4096"); + connection.execute("PRAGMA cache_size = 16384"); + connection.execute("PRAGMA temp_store = MEMORY"); + connection.execute("PRAGMA synchronous = NORMAL"); + connection.execute("PRAGMA locking_mode = EXCLUSIVE"); + + tntdb::Statement checkTable = connection.prepare( + "SELECT name FROM sqlite_master WHERE type='table' AND name=:table;" + ); + + if( checkTable.setString("table", db::Metadata).select().empty() ){ + isyslog("UPnP\tTable '%s' does not exist", db::Metadata); + return false; + } + if( checkTable.setString("table", db::Details).select().empty() ){ + isyslog("UPnP\tTable '%s' does not exist", db::Details); + return false; + } + if( checkTable.setString("table", db::Resources).select().empty() ){ + isyslog("UPnP\tTable '%s' does not exist", db::Resources); + return false; + } - stringstream ss; + stringstream ss; - ss << "SELECT `" << property::object::KEY_OBJECTID << "` FROM " << db::Metadata << " WHERE `" - << property::object::KEY_OBJECTID << "` = '0' AND `" - << property::object::KEY_PARENTID << "` = '-1';"; + ss << "SELECT `" << property::object::KEY_OBJECTID << "` FROM " << db::Metadata << " WHERE `" + << property::object::KEY_OBJECTID << "` = '0' AND `" + << property::object::KEY_PARENTID << "` = '-1';"; - tntdb::Statement checkObject = connection.prepare(ss.str()); + tntdb::Statement checkObject = connection.prepare(ss.str()); - if( checkObject.select().size() != 1 ){ - isyslog("UPnP\tRoot item does not exist or more than one root item exist."); + if( checkObject.select().size() != 1 ){ + isyslog("UPnP\tRoot item does not exist or more than one root item exist."); + return false; + } + } catch (const std::exception& e) { + esyslog("UPnP\tException occurred while connecting to database: %s", e.what()); return false; } @@ -736,14 +725,6 @@ cUPnPResourceProvider* cMediaManager::CreateResourceProvider(const string& uri){ return pluginManager->CreateProvider(uri.substr(0, uri.find_first_of(':',0))); } -void cMediaManager::SetDatabaseDir(const string& file){ - if(file.empty()) - databaseFile = cPlugin::ConfigDirectory(PLUGIN_NAME_I18N); - else databaseFile = file; - - databaseFile += "/metadata.db"; -} - void cMediaManager::Action(){ string uri; while(!scanTargets.empty()){ @@ -812,8 +793,8 @@ bool cMediaManager::ScanURI(const string& uri, cUPnPResourceProvider* provider){ } } catch (const std::exception& e) { - esyslog("UPnP\tException occurred while getting objects from '%s' from database '%s': %s", - tools::GenerateUUIDFromURL(uri).c_str(), databaseFile.c_str(), e.what()); + esyslog("UPnP\tException occurred while getting objects from '%s' from database: %s", + tools::GenerateUUIDFromURL(uri).c_str(), e.what()); return false; } @@ -834,8 +815,8 @@ bool cMediaManager::ScanURI(const string& uri, cUPnPResourceProvider* provider){ tntdb::Statement objects = connection.prepare(ss.str()); objects.execute(); } catch (const std::exception& e) { - esyslog("UPnP\tException occurred while removing old object in '%s' from database '%s': %s", - tools::GenerateUUIDFromURL(uri).c_str(), databaseFile.c_str(), e.what()); + esyslog("UPnP\tException occurred while removing old object in '%s' from database: %s", + tools::GenerateUUIDFromURL(uri).c_str(), e.what()); return false; } @@ -1103,8 +1084,8 @@ bool cMediaManager::RefreshObject(cMetadata& metadata){ connection.commitTransaction(); } catch (const std::exception& e) { - esyslog("UPnP\tException occurred while storing object '%s' to database '%s': %s", - objectID.c_str(), databaseFile.c_str(), e.what()); + esyslog("UPnP\tException occurred while storing object '%s' to database: %s", + objectID.c_str(), e.what()); connection.rollbackTransaction(); diff --git a/plugins/provider/vdrProvider/vdrProvider.cpp b/plugins/provider/vdrProvider/vdrProvider.cpp index 9f893b6..3090583 100644 --- a/plugins/provider/vdrProvider/vdrProvider.cpp +++ b/plugins/provider/vdrProvider/vdrProvider.cpp @@ -217,7 +217,7 @@ public: break; } } else if(Schedule->Modified() > lastModified){ - targets.push_back(*event->ChannelID().ToString()); + targets.push_back(*Schedule->ChannelID().ToString()); modified = true; break; } diff --git a/server/server.cpp b/server/server.cpp index 0f7b323..61e723a 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -64,6 +64,12 @@ cMediaServer::~cMediaServer(){ delete mMediaManager; mMediaManager = NULL; } + + try { + mConnection.execute("VACUUM"); + } catch (const std::exception& e) { + esyslog("UPnP\tFailed to vacuum database: '%s'", e.what()); + } } bool cMediaServer::Start(){ @@ -210,6 +216,7 @@ bool cMediaServer::Initialize(){ mWebserver = new cWebserver(GetServerIPAddress()); mMediaManager = new cMediaManager(); + stringstream ss; if(mCurrentConfiguration.expertSettings){ @@ -226,8 +233,6 @@ bool cMediaServer::Initialize(){ if(!mCurrentConfiguration.presentationURL.empty()) mWebserver->SetPresentationUrl(mCurrentConfiguration.presentationURL); } else { - stringstream ss; - uint16_t port = mCurrentConfiguration.livePort ? mCurrentConfiguration.livePort : 8008; ss << "http://" << GetServerIPAddress() << ":" << port << "/"; @@ -241,8 +246,15 @@ bool cMediaServer::Initialize(){ if(mCurrentConfiguration.maxRequestTime) mWebserver->SetMaxRequestTime(mCurrentConfiguration.maxRequestTime); - if(!mCurrentConfiguration.databaseDir.empty()) - mMediaManager->SetDatabaseDir(mCurrentConfiguration.databaseDir); + } + + ss.str(); + ss << "sqlite:" << mCurrentConfiguration.databaseDir.empty() << "/metadata.db"; + try { + mConnection = tntdb::connect(ss.str()); + } catch (const std::exception& e) { + esyslog("UPnP\tException occurred while connecting to database '%s': %s", ss.str().c_str(), e.what()); + return false; } ret = UpnpSetMaxContentLength(GetMaxContentLength()); |