Server session persistence is implemented
authordeztructor <denis.zalewsky@gmail.com>
Wed, 18 Nov 2009 12:28:48 +0000 (12:28 +0000)
committerdeztructor <denis.zalewsky@gmail.com>
Wed, 18 Nov 2009 12:28:48 +0000 (12:28 +0000)
Now only SQLite database is used as the backend to store session
information. Only session information is stored there, common settings
(including sqlite db name, download directory etc.) are stored using
standard Qt QSettings

git-svn-id: file:///svnroot/qtrapids/trunk@37 42ac0dd5-4c8c-4c71-bb3e-ecdfe252ffda

dbus/com.ixonos.qtrapids.xml
src/include/qtrapids/dbus.hpp
src/include/qtrapids/info.hpp
src/server/CMakeLists.txt
src/server/ServerDb.hpp
src/server/TorrentSession.cpp
src/server/TorrentSession.hpp

index 5c25e77..1496a78 100644 (file)
                   value="qtrapids::ParamsMap_t"/>
     </signal>
 
                   value="qtrapids::ParamsMap_t"/>
     </signal>
 
+    <method name="getOptions">
+      <arg type="a{ss}" direction="out" name="options"/>
+      <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" 
+                  value="qtrapids::ParamsMap_t"/>
+    </method>
+
+    <method name="setOption">
+      <arg type="s" direction="in" name="name"/>
+      <arg type="s" direction="in" name="value"/>
+    </method>
+
   </interface>
 
 </node>
   </interface>
 
 </node>
index 79d1cd5..bb3671b 100644 (file)
@@ -46,8 +46,8 @@ struct TorrentState {
 
 typedef QHash<QString, QString> ParamsMap_t;
 typedef QHash<QString, QString> const ParamsMapConst_t;
 
 typedef QHash<QString, QString> ParamsMap_t;
 typedef QHash<QString, QString> const ParamsMapConst_t;
-typedef QHash<QString, QString>::iterator ParamsMapIterator_t;
-typedef QHash<QString, QString>::const_iterator ParamsMapConstIterator_t;
+typedef ParamsMap_t::iterator ParamsMapIterator_t;
+typedef ParamsMap_t::const_iterator ParamsMapConstIterator_t;
 
 static inline QDBusArgument& operator << (QDBusArgument& argument
         , TorrentState const& state)
 
 static inline QDBusArgument& operator << (QDBusArgument& argument
         , TorrentState const& state)
index 81c7017..20d7d6c 100644 (file)
@@ -3,8 +3,10 @@
 
 #include <libtorrent/torrent_handle.hpp>
 
 
 #include <libtorrent/torrent_handle.hpp>
 
-#include <limits>
-#include <stdint.h>
+//#include <limits>
+//#include <stdint.h>
+
+#include <QString>
 
 namespace qtrapids
 {
 
 namespace qtrapids
 {
@@ -30,7 +32,14 @@ struct TorrentStatus {
        };
 };
 
        };
 };
 
-}
+struct TorrentDownloadInfo {
+       QString hash;
+       QString path;
+       QString download_path;
+};
+
+
+} // namespace qtrapids
 
 #endif // _QTRAPIDS_INFO_HPP_
 
 
 #endif // _QTRAPIDS_INFO_HPP_
 
index aee8f2e..60bb5d0 100644 (file)
@@ -17,7 +17,6 @@ SET_SOURCE_FILES_PROPERTIES(./server.cpp ./server.h PROPERTIES GENERATED 1)
 
 SET(MOC_HEADERS
   ./AlertWaiterThread.hpp
 
 SET(MOC_HEADERS
   ./AlertWaiterThread.hpp
-  ./TorrentHandle.hpp
   ./TorrentSession.hpp
   ./server.h
 )
   ./TorrentSession.hpp
   ./server.h
 )
@@ -26,13 +25,18 @@ SET(SRC
   ./AlertWaiterThread.cpp
   ./main.cpp
   ./server.cpp
   ./AlertWaiterThread.cpp
   ./main.cpp
   ./server.cpp
-  ./TorrentHandle.cpp
   ./TorrentSession.cpp
 )
 
 QT4_WRAP_CPP(SRC ${MOC_HEADERS} )
 
   ./TorrentSession.cpp
 )
 
 QT4_WRAP_CPP(SRC ${MOC_HEADERS} )
 
-ADD_EXECUTABLE(qtrapids-server ${SRC} ${MOC_HEADERS})
+SET(SRC_NOMOC
+  ./TorrentHandle.cpp
+  ./TorrentHandle.hpp
+  ./ServerDb.hpp
+)
+
+ADD_EXECUTABLE(qtrapids-server ${SRC} ${MOC_HEADERS} ${SRC_NOMOC})
 
 ADD_DEFINITIONS(-DQT_SHARED)
 TARGET_LINK_LIBRARIES(qtrapids-server
 
 ADD_DEFINITIONS(-DQT_SHARED)
 TARGET_LINK_LIBRARIES(qtrapids-server
index 342d26a..9bda677 100644 (file)
@@ -5,6 +5,8 @@
 #include <QtSql>
 #include <QDir>
 
 #include <QtSql>
 #include <QDir>
 
+#include <qtrapids/settings.hpp>
+
 namespace qtrapids
 {
 
 namespace qtrapids
 {
 
@@ -12,12 +14,10 @@ class ServerSettings
 {
 
 public:
 {
 
 public:
-       ServerSettings(QSettings *settings)
+       ServerSettings(QSettings &settings)
                        : settings_(settings) { }
 
                        : settings_(settings) { }
 
-       ~ServerSettings() {
-
-       }
+       ~ServerSettings() { }
 
        QString getDbEngine() const {
                return getParamAndStore("db_engine", getDefaultDbEngine()).toString();
 
        QString getDbEngine() const {
                return getParamAndStore("db_engine", getDefaultDbEngine()).toString();
@@ -29,11 +29,26 @@ public:
        }
 
        QString getTorrentsDir() const {
        }
 
        QString getTorrentsDir() const {
-               QString default_dir(QDir::home().filePath(QString(".") + appName()));
-               return getParamAndStore("db", default_dir).toString();
+               QString default_dir(QDir::home().filePath(getTorrentsSubDir()));
+               return getParamAndStore("torrents_dir", default_dir).toString();
 
        }
 
 
        }
 
+       QString getDownloadDir() const {
+               QString default_dir(QDir::home().absolutePath());
+               QString v = getParamAndStore("download/directory", default_dir).toString();
+               if (!v.isEmpty()) {
+                       return v;
+               } else {
+                       settings_.setValue("download/directory", default_dir);
+                       return default_dir;
+               }
+       }
+
+       static QString getTorrentsSubDir() {
+               return QString(".") + appName();
+       }
+
 private:
 
        ServerSettings(ServerSettings const&);
 private:
 
        ServerSettings(ServerSettings const&);
@@ -51,18 +66,34 @@ private:
        }
 
        QVariant getParamAndStore(QString const& name, QVariant default_value) const {
        }
 
        QVariant getParamAndStore(QString const& name, QVariant default_value) const {
-               QVariant v(settings_->value(name));
-               if (!v.isNull()) {
-                       return v;
+               return GetSettingsStoreDefault(settings_, name, default_value);
+       }
+
+       mutable QSettings &settings_;
+};
+
+namespace {
+
+class DbAccessor
+{
+public:
+       DbAccessor(QSqlDatabase &db)
+                       : db_(db) {
+               if (!db_.open()) {
+                       qDebug() << "cant open db";
                }
                }
+       }
 
 
-               settings_->setValue(name, default_value);
-               return default_value;
+       ~DbAccessor() {
+               db_.close();
        }
 
        }
 
-       mutable QSettings *settings_;
+private:
+       QSqlDatabase &db_;
 };
 
 };
 
+}
+
 class ServerDb
 {
 
 class ServerDb
 {
 
@@ -72,6 +103,7 @@ public:
                QString db_name(settings->getDbName());
                db_.setDatabaseName(db_name);
 
                QString db_name(settings->getDbName());
                db_.setDatabaseName(db_name);
 
+               qDebug() << "opening db " << db_name;
                if (!db_.open()) {
                        qDebug() << "cant open db";
                        return;
                if (!db_.open()) {
                        qDebug() << "cant open db";
                        return;
@@ -89,9 +121,7 @@ public:
        }
 
        void addTorrent(const QString &hash, const QString &path, const QString &save_path) {
        }
 
        void addTorrent(const QString &hash, const QString &path, const QString &save_path) {
-               if (!db_.open()) {
-                       qDebug() << "cant open db";
-               }
+               DbAccessor dba(db_);
                QSqlQuery query_add_;
                query_add_.prepare("INSERT INTO torrents (hash, path, savepath) VALUES (?, ?, ?)");
                query_add_.bindValue(0, hash);
                QSqlQuery query_add_;
                query_add_.prepare("INSERT INTO torrents (hash, path, savepath) VALUES (?, ?, ?)");
                query_add_.bindValue(0, hash);
@@ -101,7 +131,15 @@ public:
                        qDebug() << "cant add torrent info into db: "
                        << query_add_.lastError().text();
                }
                        qDebug() << "cant add torrent info into db: "
                        << query_add_.lastError().text();
                }
-               db_.close();
+       }
+
+       void removeTorrent(const QString &hash) {
+               DbAccessor dba(db_);
+               QSqlQuery query(QString("DELETE FROM torrents WHERE hash='") + hash + "'");
+               if (!query.exec()) {
+                       qDebug() << "cant delete torrent info from db"
+                       << query.lastError().text();
+               }
        }
 
 private:
        }
 
 private:
@@ -112,6 +150,29 @@ private:
        QSqlDatabase db_;
 };
 
        QSqlDatabase db_;
 };
 
+class TorrentsStorage
+{
+public:
+
+       TorrentsStorage(ServerDb &db)
+                       : torrents_("SELECT hash, path, savepath from torrents") { }
+
+
+       bool nextTorrent(TorrentDownloadInfo &info) {
+               if (!torrents_.next()) {
+                       return false;
+               }
+               info.hash = torrents_.value(0).toString();
+               info.path = torrents_.value(1).toString();
+               info.download_path = torrents_.value(2).toString();
+               return true;
+       }
+
+
+private:
+       QSqlQuery torrents_;
+};
+
 } // namespace qtrapids
 
 #endif // _SERVERDB_HPP_
 } // namespace qtrapids
 
 #endif // _SERVERDB_HPP_
index c6d8b31..94c2465 100644 (file)
@@ -1,7 +1,8 @@
 #include "TorrentSession.hpp"
 #include "TorrentHandle.hpp"
 #include "AlertWaiterThread.hpp"
 #include "TorrentSession.hpp"
 #include "TorrentHandle.hpp"
 #include "AlertWaiterThread.hpp"
-
+#include "ServerDb.hpp"
+#include <qtrapids/error.hpp>
 
 namespace qtrapids
 {
 
 namespace qtrapids
 {
@@ -12,6 +13,8 @@ TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
                : QObject(parent)
                , btSession_()
                , alertWaiter_(new AlertWaiterThread(&btSession_, this))
                : QObject(parent)
                , btSession_()
                , alertWaiter_(new AlertWaiterThread(&btSession_, this))
+               , settings_(new ServerSettings(*settings))
+               , db_(new ServerDb(settings_.get()))
 {
        qDBusRegisterMetaType<qtrapids::TorrentState>();
        qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
 {
        qDBusRegisterMetaType<qtrapids::TorrentState>();
        qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
@@ -25,17 +28,21 @@ TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
        connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
        alertWaiter_->start();
 
        connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
        alertWaiter_->start();
 
+       loadState();
+}
 
 
+void TorrentSession::loadState()
+{
+       TorrentDownloadInfo info;
+       TorrentsStorage storage(*db_);
+       while (storage.nextTorrent(info)) {
+               qDebug() << "adding " << info.path;
+               addTorrent_(info.path, info.download_path, ParamsMap_t(), true);
+       }
 }
 
 void TorrentSession::on_alert()
 }
 
 void TorrentSession::on_alert()
-//NOTE: al parameter not necessarily needed here, as we pop_alert() now!
 {
 {
-
-       //qDebug() << "QBittorrentSession:on_alert(" << al << ")";
-       //      if (al)
-       //              qDebug() << "on_alert():" << QString::fromStdString(al->message());
-
        std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
 
        if (alertPtr.get() != NULL) {
        std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
 
        if (alertPtr.get() != NULL) {
@@ -46,9 +53,7 @@ void TorrentSession::on_alert()
                << "QBittorrentSession::on_alert(): "
                << QString::fromStdString(alertPtr->message());
 
                << "QBittorrentSession::on_alert(): "
                << QString::fromStdString(alertPtr->message());
 
-
                if (ta) {
                if (ta) {
-
                        if (!ta->handle.is_valid()) {
                                qDebug() << "handle is invalid";
                                return;
                        if (!ta->handle.is_valid()) {
                                qDebug() << "handle is invalid";
                                return;
@@ -99,26 +104,50 @@ void TorrentSession::getState()
 void TorrentSession::addTorrent(const QString &path, const QString &save_path
                                 , qtrapids::ParamsMap_t other_params)
 {
 void TorrentSession::addTorrent(const QString &path, const QString &save_path
                                 , qtrapids::ParamsMap_t other_params)
 {
+       return addTorrent_(path, save_path, other_params, false);
+}
+
+void TorrentSession::addTorrent_(const QString &path, const QString &save_path
+                                 , const qtrapids::ParamsMap_t &other_params
+                                 , bool is_restore_session)
+{
        add_torrent_params_t addParams;
        QFile torrent_file(path);
        add_torrent_params_t addParams;
        QFile torrent_file(path);
+       QDir::home().mkdir(settings_->getTorrentsSubDir());
+
        if (!torrent_file.exists()) {
                qWarning() << "Torrent file " << path << "doesn't exist";
                return;
        }
 
        if (!torrent_file.exists()) {
                qWarning() << "Torrent file " << path << "doesn't exist";
                return;
        }
 
+       QString new_torrent_fname(QDir(settings_->getTorrentsDir())
+                                 .filePath(QFileInfo(path).fileName()));
+       qDebug() << "copy to " << new_torrent_fname;
+       torrent_file.copy(new_torrent_fname);
+
        qDebug() << "addTorrent: " << path << " save to " << save_path;
        boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
        = new libtorrent::torrent_info
        qDebug() << "addTorrent: " << path << " save to " << save_path;
        boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
        = new libtorrent::torrent_info
-       (boost::filesystem::path(path.toStdString()));
+       (boost::filesystem::path(new_torrent_fname.toStdString()));
        addParams.ti = tiTmp;
 
        addParams.ti = tiTmp;
 
+       QString download_dir;
+       if (!save_path.isEmpty()) {
+               download_dir = save_path;
+       } else {
+               download_dir = settings_->getDownloadDir();
+       }
        // save_path is the only mandatory parameter, rest are optional.
        // save_path is the only mandatory parameter, rest are optional.
-       addParams.save_path = boost::filesystem::path(save_path.toStdString());
+       addParams.save_path = boost::filesystem::path(download_dir.toStdString());
        //addParams.storage_mode = libtorrent::storage_mode_allocate;
 
        TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
        QString hash = Hash2QStr(handle->hash());
 
        //addParams.storage_mode = libtorrent::storage_mode_allocate;
 
        TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
        QString hash = Hash2QStr(handle->hash());
 
+       if (!is_restore_session) {
+               db_->addTorrent(hash, path, save_path);
+       }
+
        TorrentState state;
 
        state.hash = hash;
        TorrentState state;
 
        state.hash = hash;
@@ -158,6 +187,7 @@ void TorrentSession::removeTorrent(const QString &hash)
        state.action = TorrentState::action_remove;
        emit alert(state, ParamsMap_t());
        torrents_.erase(p);
        state.action = TorrentState::action_remove;
        emit alert(state, ParamsMap_t());
        torrents_.erase(p);
+       db_->removeTorrent(hash);
 }
 
 
 }
 
 
index 6240024..1baffac 100644 (file)
@@ -63,9 +63,15 @@ private slots:
        void on_alert();
 
 private:
        void on_alert();
 
 private:
+
+       void loadState();
+       void addTorrent_(const QString &, const QString &, const qtrapids::ParamsMap_t &, bool);
+
        session_t btSession_;
        AlertWaiterThread *alertWaiter_;
        torrents_t torrents_;
        session_t btSession_;
        AlertWaiterThread *alertWaiter_;
        torrents_t torrents_;
+       std::auto_ptr<ServerSettings> settings_;
+       std::auto_ptr<ServerDb> db_;
 };
 
 } // namespace qtrapids
 };
 
 } // namespace qtrapids