summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormethodus <methodus@web.de>2013-05-05 18:04:13 +0200
committermethodus <methodus@web.de>2013-05-05 18:04:13 +0200
commit001751f2d9ec3e13f5c4c36e8361ce1e4db43871 (patch)
tree1343028f7baa1a4f3412384cc4d384cbfcaf0b1b
parentd260e7cb971bfeb031f40c3d61e4778dd326083d (diff)
downloadvdr-plugin-upnp-001751f2d9ec3e13f5c4c36e8361ce1e4db43871.tar.gz
vdr-plugin-upnp-001751f2d9ec3e13f5c4c36e8361ce1e4db43871.tar.bz2
Fixed segfault in vdrProvider
-rw-r--r--include/media/mediaManager.h5
-rw-r--r--include/server.h4
-rw-r--r--media/mediaManager.cpp307
-rw-r--r--plugins/provider/vdrProvider/vdrProvider.cpp2
-rw-r--r--server/server.cpp20
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());