source: trunk/src/halTorrentInternal.cpp @ 739

Revision 739, 12.6 KB checked in by Eoin, 11 years ago (diff)

Cleaning up torrent removal code.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2009.
3// Distributed under the Boost Software License, Version 1.0.
4//    (See accompanying file LICENSE_1_0.txt or copy at
5//          http://www.boost.org/LICENSE_1_0.txt)
6
7#include "stdAfx.hpp"
8
9#include "halTorrentInternal.hpp"
10
11namespace hal
12{
13
14void torrent_internal::adjust_queue_position(bit::queue_adjustments adjust)
15{
16        if (in_session() && is_managed())
17        {
18                switch (adjust)
19                {
20                case bit::move_up:
21                        handle_.queue_position_up();
22                        break;
23                case bit::move_down:
24                        handle_.queue_position_down();
25                        break;
26                case bit::move_to_top:
27                        handle_.queue_position_top();
28                        break;
29                case bit::move_to_bottom:
30                        handle_.queue_position_bottom();
31                        break;
32                };
33        }
34}
35
36void torrent_internal::add_to_session(bool paused)
37{
38        try
39        {
40        HAL_DEV_MSG(hal::wform(L"add_to_session() paused=%1%") % paused);
41
42        mutex_t::scoped_lock l(mutex_); 
43
44        process_event(ev_add_to_session(paused));
45        assert(in_session());
46
47        }
48        catch(std::exception& e)
49        {
50                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
51                        new hal::EventStdException(event_logger::critical, e, L"add_to_session"))); 
52        }
53}
54
55bool torrent_internal::remove_from_session(bool write_data)
56{
57        try
58        {
59        HAL_DEV_MSG(hal::wform(L"remove_from_session() write_data=%1%") % write_data);
60
61        mutex_t::scoped_lock l(mutex_);
62       
63        process_event(ev_remove_from_session(write_data));
64        assert(in_session());
65
66        }
67        catch(std::exception& e)
68        {
69                hal::event_log.post(boost::shared_ptr<hal::EventDetail>(
70                        new hal::EventStdException(event_logger::critical, e, L"remove_from_session()"))); 
71                return false;
72        }
73
74        return true;
75}
76
77torrent_details_ptr torrent_internal::get_torrent_details_ptr()
78{       
79        mutex_t::scoped_lock l(mutex_);
80
81        try
82        {
83
84        if (in_session())
85        {
86                status_memory_ = handle_.status();
87                progress_ = status_memory_.progress;
88
89                queue_position_ = handle_.queue_position();
90        }
91        else
92        {
93                // Wipe these cause they don't make sense for a non-active torrent.
94               
95                status_memory_.download_payload_rate = 0;
96                status_memory_.upload_payload_rate = 0;
97                status_memory_.next_announce = boost::posix_time::seconds(0);           
98        }
99       
100        wstring state_str;
101       
102        switch (state())
103        {
104        case torrent_details::torrent_paused:
105                state_str = app().res_wstr(HAL_TORRENT_PAUSED);
106                break;
107               
108        case torrent_details::torrent_pausing:
109                state_str = app().res_wstr(HAL_TORRENT_PAUSING);
110                break;
111               
112        case torrent_details::torrent_stopped:
113                state_str = app().res_wstr(HAL_TORRENT_STOPPED);
114                break;
115               
116        case torrent_details::torrent_stopping:
117                state_str = app().res_wstr(HAL_TORRENT_STOPPING);
118                break;
119               
120        case torrent_details::torrent_in_error:
121                state_str = app().res_wstr(HAL_TORRENT_IN_ERROR);
122                break;
123               
124        default:
125                switch (status_memory_.state)
126                {
127                case libt::torrent_status::queued_for_checking:
128                        state_str = app().res_wstr(HAL_TORRENT_QUEUED_CHECKING);
129                        break;
130                case libt::torrent_status::checking_files:
131                        state_str = app().res_wstr(HAL_TORRENT_CHECKING_FILES);
132                        break;
133//                      case libt::torrent_status::connecting_to_tracker:
134//                              state = app().res_wstr(HAL_TORRENT_CONNECTING);
135//                              break;
136                case libt::torrent_status::downloading_metadata:
137                        state_str = app().res_wstr(HAL_TORRENT_METADATA);
138                        break;
139                case libt::torrent_status::downloading:
140                        state_str = app().res_wstr(HAL_TORRENT_DOWNLOADING);
141                        break;
142                case libt::torrent_status::finished:
143                        state_str = app().res_wstr(HAL_TORRENT_FINISHED);
144                        break;
145                case libt::torrent_status::seeding:
146                        state_str = app().res_wstr(HAL_TORRENT_SEEDING);
147                        break;
148                case libt::torrent_status::allocating:
149                        state_str = app().res_wstr(HAL_TORRENT_ALLOCATING);
150                        break;
151                }       
152        }
153       
154        pt::time_duration td(pt::pos_infin);
155       
156        if (status_memory_.download_payload_rate != 0)
157        {
158                td = boost::posix_time::seconds(       
159                        long(float(status_memory_.total_wanted-status_memory_.total_wanted_done) / status_memory_.download_payload_rate));
160        }
161       
162        total_uploaded_ += (status_memory_.total_payload_upload - total_base_);
163        total_base_ = status_memory_.total_payload_upload;
164       
165        uploaded_.update(status_memory_.total_upload);
166        payload_uploaded_.update(status_memory_.total_payload_upload);
167        downloaded_.update(status_memory_.total_download);
168        payload_downloaded_.update(status_memory_.total_payload_download);
169       
170        if (is_active())
171        {
172                active_duration_.update();
173               
174                if (libt::torrent_status::seeding == status_memory_.state)
175                        seeding_duration_.update();
176        }       
177       
178        boost::tuple<size_t, size_t, size_t, size_t> connections = update_peers();     
179
180        return torrent_details_ptr(new torrent_details(
181                name_, filename_, 
182                save_directory().string(), 
183                state_str, 
184                hal::from_utf8(status_memory_.current_tracker), 
185                std::pair<float, float>(
186                        status_memory_.download_payload_rate, 
187                        status_memory_.upload_payload_rate),
188                progress_, 
189                status_memory_.distributed_copies, 
190                status_memory_.total_wanted_done, 
191                status_memory_.total_wanted, 
192                uploaded_, payload_uploaded_,
193                downloaded_, payload_downloaded_, 
194                connections, 
195                ratio_, 
196                td, 
197                status_memory_.next_announce, 
198                active_duration_, seeding_duration_, 
199                start_time_, finish_time_, 
200                queue_position_,
201                is_managed()));
202
203        }
204        catch (const libt::invalid_handle&)
205        {
206                event_log.post(shared_ptr<EventDetail>(
207                        new EventInvalidTorrent(event_logger::critical, 
208                                event_logger::invalid_torrent, to_utf8(name_), "get_torrent_details_ptr")));
209        }
210        catch (const std::exception& e)
211        {
212                event_log.post(shared_ptr<EventDetail>(
213                        new EventTorrentException(event_logger::critical, 
214                                event_logger::torrentException, e.what(), to_utf8(name_), "get_torrent_details_ptr")));
215        }
216       
217        return torrent_details_ptr(new torrent_details(
218                name_, filename_, 
219                save_directory().string(), 
220                app().res_wstr(HAL_TORRENT_STOPPED), 
221                app().res_wstr(HAL_NA)));
222}
223
224file_details_vec torrent_internal::get_file_details()
225{
226        file_details_vec files;
227        get_file_details(files);
228
229        return files;
230}
231
232void torrent_internal::get_file_details(file_details_vec& files)
233{
234        if (file_details_memory_.empty())
235        {
236                boost::intrusive_ptr<libt::torrent_info> info = info_memory();
237                std::vector<libt::file_entry> files;
238               
239                std::copy(info->begin_files(), info->end_files(), 
240                        std::back_inserter(files));                                     
241                       
242                if (file_priorities_.size() != files.size())
243                {
244                        file_priorities_.clear();
245                        file_priorities_.assign(files.size(), 1);
246                }
247               
248                for(size_t i=0, e=files.size(); i<e; ++i)
249                {
250                        wstring fullPath = hal::from_utf8(files[i].path.string());
251                        boost::int64_t size = static_cast<boost::int64_t>(files[i].size);
252                       
253                        file_details_memory_.push_back(file_details(fullPath, size, 0, file_priorities_[i], i));
254                }       
255        }               
256       
257        if (in_session())
258        {                       
259                std::vector<libt::size_type> fileProgress;                     
260                handle_.file_progress(fileProgress);
261               
262                for(size_t i=0, e=file_details_memory_.size(); i<e; ++i)
263                        file_details_memory_[i].progress =  fileProgress[i];                   
264        }
265
266        for(size_t i=0, e=file_details_memory_.size(); i<e; ++i)
267                file_details_memory_[i].priority =  file_priorities_[i];
268       
269        files = file_details_memory_;
270}
271
272void torrent_internal::prepare(wpath filename)
273{
274        mutex_t::scoped_lock l(mutex_);
275       
276        if (fs::exists(filename)) 
277                info_memory_ = new libt::torrent_info(path_to_utf8(filename));
278       
279        extract_names(info_memory());                   
280       
281        const wpath resumeFile = hal::app().get_working_directory()/L"resume"/filename_;
282        const wpath torrentFile = hal::app().get_working_directory()/L"torrents"/filename_;
283       
284        event_log.post(shared_ptr<EventDetail>(new EventMsg(
285                hal::wform(L"File: %1%, %2%.") % resumeFile % torrentFile)));
286       
287//      if (exists(resumeFile))
288//              resumedata_ = haldecode(resumeFile);
289
290        if (!exists(hal::app().get_working_directory()/L"torrents"))
291                create_directory(hal::app().get_working_directory()/L"torrents");
292
293        if (!exists(torrentFile))
294                copy_file(filename.string(), torrentFile);
295
296        if (!fs::exists(save_directory_))
297                fs::create_directory(save_directory_);
298
299        // These here should not make state changes based on torrent
300        // session status since it has not been initialized yet.
301        if (state_ == torrent_details::torrent_stopping)
302                state(torrent_details::torrent_stopped);
303        else if (state_ == torrent_details::torrent_pausing)
304                state(torrent_details::torrent_paused);
305}
306
307void torrent_internal::extract_names(boost::intrusive_ptr<libt::torrent_info> metadata)
308{
309        mutex_t::scoped_lock l(mutex_);
310                       
311        name_ = hal::from_utf8_safe(metadata->name());
312       
313        filename_ = name_;
314        if (!boost::find_last(filename_, L".torrent")) 
315                        filename_ += L".torrent";
316       
317        event_log.post(shared_ptr<EventDetail>(new EventMsg(
318                hal::wform(L"Loaded names: %1%, %2%") % name_ % filename_)));
319}
320
321boost::tuple<size_t, size_t, size_t, size_t> torrent_internal::update_peers()
322{
323        if (in_session())
324                handle_.get_peer_info(peers_);
325       
326        size_t totalPeers = 0;
327        size_t peersConnected = 0;
328        size_t totalSeeds = 0;
329        size_t seedsConnected = 0;
330       
331        foreach (libt::peer_info& peer, peers_) 
332        {
333                float speedSum = peer.down_speed + peer.up_speed;
334               
335                if (!(peer.flags & libt::peer_info::seed))
336                {
337                        ++totalPeers;
338                       
339                        if (speedSum > 0)
340                                ++peersConnected;
341                }
342                else
343                {
344                        ++totalSeeds;
345                       
346                        if (speedSum > 0)
347                                ++seedsConnected;
348                }
349        }       
350       
351        return boost::make_tuple(totalPeers, peersConnected, totalSeeds, seedsConnected);
352}
353
354// ----------------- private -----------------
355
356void torrent_internal::apply_settings()
357{               
358        apply_transfer_speed();
359        apply_connection_limit();
360        apply_ratio();
361        apply_trackers();
362        apply_tracker_login();
363        apply_file_priorities();
364        apply_resolve_countries();
365}
366
367void torrent_internal::apply_transfer_speed()
368{
369        mutex_t::scoped_lock l(mutex_);
370        if (in_session())
371        {
372                int down = (transfer_limit_.first > 0) ? static_cast<int>(transfer_limit_.first*1024) : -1;
373                handle_.set_download_limit(down);
374               
375                int up = (transfer_limit_.second > 0) ? static_cast<int>(transfer_limit_.second*1024) : -1;
376                handle_.set_upload_limit(up);
377
378                HAL_DEV_MSG(hal::wform(L"Applying Transfer Speed %1% - %2%") % down % up);
379        }
380}
381
382void torrent_internal::apply_connection_limit()
383{
384        mutex_t::scoped_lock l(mutex_);
385        if (in_session())
386        {
387                handle_.set_max_connections(connections_);
388                handle_.set_max_uploads(uploads_);
389
390                HAL_DEV_MSG(hal::wform(L"Applying Connection Limit %1% - %2%") % connections_ % uploads_);
391        }
392}
393
394void torrent_internal::apply_ratio()
395{ 
396        mutex_t::scoped_lock l(mutex_);
397        if (in_session())
398        {
399                handle_.set_ratio(ratio_);
400
401                HAL_DEV_MSG(hal::wform(L"Applying Ratio %1%") % ratio_);
402        }
403}
404
405void torrent_internal::apply_trackers()
406{
407        mutex_t::scoped_lock l(mutex_);
408        if (in_session())
409        {
410                if (torrent_trackers_.empty())
411                        torrent_trackers_ = handle_.trackers();
412               
413                if (!trackers_.empty())
414                {
415                        std::vector<libt::announce_entry> trackers;
416                       
417                        foreach (const tracker_detail& tracker, trackers_)
418                        {
419                                trackers.push_back(
420                                        libt::announce_entry(hal::to_utf8(tracker.url)));
421                                trackers.back().tier = tracker.tier;
422                        }
423                        handle_.replace_trackers(trackers);
424                }
425               
426                HAL_DEV_MSG(L"Applying Trackers");
427        }
428}
429
430void torrent_internal::apply_tracker_login()
431{
432        mutex_t::scoped_lock l(mutex_);
433        if (in_session())
434        {
435                if (tracker_username_ != L"")
436                {
437                        handle_.set_tracker_login(hal::to_utf8(tracker_username_),
438                                hal::to_utf8(tracker_password_));
439                }
440
441                HAL_DEV_MSG(hal::wform(L"Applying Tracker Login User: %1%, Pass: %2%")
442                        % tracker_username_ % tracker_password_ );
443        }
444}
445
446void torrent_internal::apply_file_priorities()
447{               
448        mutex_t::scoped_lock l(mutex_);
449        if (in_session()) 
450        {
451                if (!file_priorities_.empty())
452                        handle_.prioritize_files(file_priorities_);
453               
454                HAL_DEV_MSG(L"Applying File Priorities");
455        }
456}       
457
458void torrent_internal::apply_resolve_countries()
459{
460        mutex_t::scoped_lock l(mutex_);
461        if (in_session())
462        {
463                handle_.resolve_countries(resolve_countries_);
464               
465                HAL_DEV_MSG(hal::wform(L"Applying Resolve Countries %1%") % resolve_countries_);
466        }
467}
468
469void torrent_internal::state(unsigned s)
470{
471        switch (s)
472        {
473        case torrent_details::torrent_stopped:
474                HAL_DEV_MSG(L"state() - stopped");
475                break;
476        case torrent_details::torrent_stopping:
477                HAL_DEV_MSG(L"state() - stopping");
478                break;
479        case torrent_details::torrent_pausing:
480                HAL_DEV_MSG(L"state() - pausing");
481                break;
482        case torrent_details::torrent_active:
483                HAL_DEV_MSG(L"state() - active");
484                break;
485        case torrent_details::torrent_paused:
486                HAL_DEV_MSG(L"state() - paused");
487                break;
488        case torrent_details::torrent_in_error:
489                HAL_DEV_MSG(L"state() - in error");
490                break;
491        default:
492                HAL_DEV_MSG(L"state() - unknown");
493                break;
494        };
495        state_ = s;
496}
497
498};
Note: See TracBrowser for help on using the repository browser.