Server session persistence is implemented
[qtrapids] / src / server / TorrentSession.cpp
1 #include "TorrentSession.hpp"
2 #include "TorrentHandle.hpp"
3 #include "AlertWaiterThread.hpp"
4 #include "ServerDb.hpp"
5 #include <qtrapids/error.hpp>
6
7 namespace qtrapids
8 {
9
10
11
12 TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
13                 : QObject(parent)
14                 , btSession_()
15                 , alertWaiter_(new AlertWaiterThread(&btSession_, this))
16                 , settings_(new ServerSettings(*settings))
17                 , db_(new ServerDb(settings_.get()))
18 {
19         qDBusRegisterMetaType<qtrapids::TorrentState>();
20         qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
21         new QtRapidsServer(this);
22
23         QDBusConnection dbus = QDBusConnection::sessionBus();
24         dbus.registerObject("/qtrapids", this);
25         dbus.registerService("com.ixonos.qtrapids");
26
27         alertWaiter_->allAlerts();
28         connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
29         alertWaiter_->start();
30
31         loadState();
32 }
33
34 void TorrentSession::loadState()
35 {
36         TorrentDownloadInfo info;
37         TorrentsStorage storage(*db_);
38         while (storage.nextTorrent(info)) {
39                 qDebug() << "adding " << info.path;
40                 addTorrent_(info.path, info.download_path, ParamsMap_t(), true);
41         }
42 }
43
44 void TorrentSession::on_alert()
45 {
46         std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
47
48         if (alertPtr.get() != NULL) {
49
50                 torrent_alert_t *ta = dynamic_cast<torrent_alert_t*> (alertPtr.get());
51
52                 qDebug()
53                 << "QBittorrentSession::on_alert(): "
54                 << QString::fromStdString(alertPtr->message());
55
56                 if (ta) {
57                         if (!ta->handle.is_valid()) {
58                                 qDebug() << "handle is invalid";
59                                 return;
60                         }
61
62                         TorrentHandle handle(ta->handle);
63                         TorrentState state;
64
65                         state.hash = Hash2QStr(handle.hash());
66                         state.action = TorrentState::action_update;
67                         state.state = handle.state();
68                         state.progress = handle.progress() * torrent_progress_max;
69                         state.down_rate = handle.downloadRate();
70                         state.up_rate = handle.uploadRate();
71                         state.seeds = handle.numSeeds();
72                         state.leeches = handle.numLeeches();
73
74                         ParamsMap_t params;
75                         emit alert(state, params);
76                 }
77
78         }
79 }
80
81 void TorrentSession::getState()
82 {
83         torrents_t::const_iterator p;
84         for (p = torrents_.constBegin(); p != torrents_.constEnd(); ++p) {
85                 TorrentHandlePtr handle = *p;
86                 TorrentState state;
87                 QString hash = Hash2QStr(handle->hash());
88
89                 state.hash = hash;
90                 state.name = handle->name();
91                 state.action = TorrentState::action_add;
92                 state.state = handle->state();
93                 state.progress = handle->progress() * torrent_progress_max;
94                 state.down_rate = handle->downloadRate();
95                 state.up_rate = handle->uploadRate();
96                 state.seeds = handle->numSeeds();
97                 state.leeches = handle->numLeeches();
98                 state.total_size = handle->getTotalSize();
99
100                 emit alert(state, ParamsMap_t());
101         }
102 }
103
104 void TorrentSession::addTorrent(const QString &path, const QString &save_path
105                                 , qtrapids::ParamsMap_t other_params)
106 {
107         return addTorrent_(path, save_path, other_params, false);
108 }
109
110 void TorrentSession::addTorrent_(const QString &path, const QString &save_path
111                                  , const qtrapids::ParamsMap_t &other_params
112                                  , bool is_restore_session)
113 {
114         add_torrent_params_t addParams;
115         QFile torrent_file(path);
116         QDir::home().mkdir(settings_->getTorrentsSubDir());
117
118         if (!torrent_file.exists()) {
119                 qWarning() << "Torrent file " << path << "doesn't exist";
120                 return;
121         }
122
123         QString new_torrent_fname(QDir(settings_->getTorrentsDir())
124                                   .filePath(QFileInfo(path).fileName()));
125         qDebug() << "copy to " << new_torrent_fname;
126         torrent_file.copy(new_torrent_fname);
127
128         qDebug() << "addTorrent: " << path << " save to " << save_path;
129         boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
130         = new libtorrent::torrent_info
131         (boost::filesystem::path(new_torrent_fname.toStdString()));
132         addParams.ti = tiTmp;
133
134         QString download_dir;
135         if (!save_path.isEmpty()) {
136                 download_dir = save_path;
137         } else {
138                 download_dir = settings_->getDownloadDir();
139         }
140         // save_path is the only mandatory parameter, rest are optional.
141         addParams.save_path = boost::filesystem::path(download_dir.toStdString());
142         //addParams.storage_mode = libtorrent::storage_mode_allocate;
143
144         TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
145         QString hash = Hash2QStr(handle->hash());
146
147         if (!is_restore_session) {
148                 db_->addTorrent(hash, path, save_path);
149         }
150
151         TorrentState state;
152
153         state.hash = hash;
154         state.name = handle->name();
155         state.action = TorrentState::action_add;
156         state.state = handle->state();
157         state.progress = handle->progress() * torrent_progress_max;
158         state.down_rate = handle->downloadRate();
159         state.up_rate = handle->uploadRate();
160         state.seeds = handle->numSeeds();
161         state.leeches = handle->numLeeches();
162         state.total_size = handle->getTotalSize();
163
164         torrents_[hash] = handle;
165
166         emit alert(state, ParamsMap_t());
167 }
168
169 void TorrentSession::removeTorrent(const QString &hash)
170 {
171         torrents_t::iterator p = torrents_.find(hash);
172
173         if (p == torrents_.end()) {
174                 qDebug() << "Invalid request to remove torrent with hash " << hash;
175                 return;
176         }
177         try {
178                 btSession_.remove_torrent(p.value()->getHandle());
179         } catch (torrent_exception_t e) {
180                 qDebug() << // e.what()
181                 "exception catched"
182                 ;
183         }
184
185         TorrentState state;
186         state.hash = hash;
187         state.action = TorrentState::action_remove;
188         emit alert(state, ParamsMap_t());
189         torrents_.erase(p);
190         db_->removeTorrent(hash);
191 }
192
193
194 } // namespace qtrapids