source: trunk/src/halTorrentInternal.hpp @ 723

Revision 723, 24.7 KB checked in by Eoin, 11 years ago (diff)
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#pragma once
8
9#include "halTorrentDefines.hpp"
10
11#ifndef HAL_TORRENT_STATE_LOGGING
12#       define TORRENT_STATE_LOG(s)
13#else
14#       include "../halEvent.hpp"
15#       define TORRENT_STATE_LOG(msg) \
16        hal::event_log.post(boost::shared_ptr<hal::EventDetail>( \
17                        new hal::EventMsg(msg, hal::event_logger::torrent_dev)))
18#endif
19
20#pragma warning (push, 1)
21#       include <libtorrent/file.hpp>
22#       include <libtorrent/hasher.hpp>
23#       include <libtorrent/storage.hpp>
24#       include <libtorrent/file_pool.hpp>
25#       include <libtorrent/alert_types.hpp>
26#       include <libtorrent/entry.hpp>
27#       include <libtorrent/bencode.hpp>
28#       include <libtorrent/session.hpp>
29#       include <libtorrent/ip_filter.hpp>
30#       include <libtorrent/torrent_handle.hpp>
31#       include <libtorrent/peer_connection.hpp>
32#       include <libtorrent/extensions/metadata_transfer.hpp>
33#       include <libtorrent/extensions/ut_pex.hpp>
34#pragma warning (pop)
35
36#include <boost/tuple/tuple.hpp>
37#include <boost/enable_shared_from_this.hpp>
38#include <boost/multi_index_container.hpp>
39#include <boost/multi_index/ordered_index.hpp>
40#include <boost/multi_index/indexed_by.hpp>
41#include <boost/multi_index/identity.hpp>
42#include <boost/multi_index/member.hpp>
43#include <boost/multi_index/tag.hpp>
44
45#include <boost/statechart/event.hpp>
46#include <boost/statechart/state_machine.hpp>
47#include <boost/statechart/simple_state.hpp>
48#include <boost/statechart/transition.hpp>
49#include <boost/statechart/state.hpp>
50#include <boost/statechart/custom_reaction.hpp>
51
52#include <boost/mpl/list.hpp>
53
54#include "halIni.hpp"
55#include "halTypes.hpp"
56#include "halSignaler.hpp"
57#include "halTorrentIntEvents.hpp"
58
59namespace hal
60{
61class TorrentInternalOld;
62class torrent_internal;
63}
64
65BOOST_CLASS_VERSION(hal::TorrentInternalOld, 9)
66BOOST_CLASS_VERSION(hal::torrent_internal, 2)
67
68namespace hal
69{
70
71namespace libt = libtorrent;
72namespace sc = boost::statechart;
73namespace mpl = boost::mpl;
74
75
76inline libt::entry haldecode(const wpath &file) 
77{
78        fs::ifstream ifs(file, fs::ifstream::binary);
79        if (ifs.is_open()) 
80        {
81                ifs.unsetf(fs::ifstream::skipws);
82                return libt::bdecode(std::istream_iterator<char>(ifs), std::istream_iterator<char>());
83        }
84        else return libt::entry();
85}
86
87inline bool halencode(const wpath &file, const libt::entry &e) 
88{
89        fs::ofstream ofs(file, fs::ofstream::binary);
90
91        if (!ofs.is_open()) 
92                return false;
93       
94        libt::bencode(std::ostream_iterator<char>(ofs), e);
95        return true;
96}
97
98inline path path_to_utf8(const wpath& wp)
99{
100        return path(to_utf8(wp.string()));
101}
102
103inline wpath path_from_utf8(const path& p)
104{
105        return wpath(from_utf8(p.string()));
106}
107
108inline std::pair<std::string, std::string> extract_names(const wpath &file)
109{
110        if (fs::exists(file)) 
111        {       
112                libt::torrent_info info(path_to_utf8(file));
113
114                std::string name = info.name(); 
115                std::string filename = name;
116
117                if (!boost::find_last(filename, ".torrent")) 
118                                filename += ".torrent";
119               
120                event_log.post(shared_ptr<EventDetail>(new EventMsg(
121                        hal::wform(L"Loaded names: %1%, %2%") % from_utf8(name) % from_utf8(filename))));
122
123                return std::make_pair(name, filename);
124        }
125        else
126                return std::make_pair("", "");
127}
128
129inline libt::storage_mode_t hal_allocation_to_libt(bit::allocations alloc)
130{
131        switch (alloc)
132        {
133        case bit::full_allocation:
134                return libt::storage_mode_allocate;
135        case bit::compact_allocation:
136                return libt::storage_mode_compact;
137        case bit::sparse_allocation:
138        default:
139                return libt::storage_mode_sparse;
140        }
141}
142
143class invalid_torrent : public std::exception
144{
145public:
146        invalid_torrent(const wstring& who) :
147                who_(who)
148        {}
149       
150        virtual ~invalid_torrent() throw () {}
151
152        wstring who() const throw ()
153        {
154                return who_;
155        }       
156       
157private:
158        wstring who_;   
159};
160       
161template<typename T>
162class transfer_tracker
163{
164public:
165        transfer_tracker() :
166                total_(0),
167                total_offset_(0)
168        {}
169       
170        transfer_tracker(T total) :
171                total_(total),
172                total_offset_(0)
173        {}
174       
175        transfer_tracker(T total, T offset) :
176                total_(total),
177                total_offset_(offset)
178        {}
179       
180        void reset(T total) const
181        {
182                total_ = total;
183                total_offset_ = 0;
184        }
185       
186        T update(T rel_total) const
187        {
188                total_ += (rel_total - total_offset_);
189                total_offset_ = rel_total;
190               
191                return total_;
192        }
193       
194        void setOffset(T offset) const
195        {
196                total_offset_ = offset;
197        }
198       
199        operator T() const { return total_; }
200       
201        friend class boost::serialization::access;
202        template<class Archive>
203        void serialize(Archive& ar, const unsigned int version)
204        {
205                ar & boost::serialization::make_nvp("total", total_);
206        }
207       
208private:
209        mutable T total_;
210        mutable T total_offset_;
211};
212
213class duration_tracker
214{
215public:
216        duration_tracker() :
217                total_(boost::posix_time::time_duration(0,0,0,0), 
218                        boost::posix_time::time_duration(0,0,0,0))
219        {}
220       
221        boost::posix_time::time_duration update() const
222        {
223                if (start_.is_not_a_date_time()) 
224                        start_ = boost::posix_time::second_clock::universal_time();
225
226                if (static_cast<boost::posix_time::time_duration>(total_).is_special()) 
227                        total_.setOffset(boost::posix_time::time_duration(0,0,0,0));
228               
229                return total_.update(boost::posix_time::second_clock::universal_time() - start_);
230        }
231       
232        void reset() const
233        {
234                total_.setOffset(boost::posix_time::time_duration(0,0,0,0));
235                start_ = boost::posix_time::second_clock::universal_time();
236        }
237       
238        friend class boost::serialization::access;
239        template<class Archive>
240        void serialize(Archive& ar, const unsigned int version)
241        {
242                ar & boost::serialization::make_nvp("total", total_);
243        }
244       
245        operator boost::posix_time::time_duration() const { return total_; }
246       
247private:
248        transfer_tracker<boost::posix_time::time_duration> total_;     
249        mutable boost::posix_time::ptime start_;               
250};
251       
252struct signalers
253{
254        signaler<> torrent_finished;
255
256        boost::signal<void ()> torrent_paused;
257        boost::signal<void ()> resume_data;
258};
259
260class torrent_internal;
261typedef shared_ptr<torrent_internal> torrent_internal_ptr;
262
263struct torrent_standalone :
264        public hal::IniBase<torrent_standalone>
265{
266        typedef torrent_standalone thisClass;
267        typedef hal::IniBase<thisClass> iniClass;
268
269        torrent_standalone() :
270                iniClass("torrent")
271        {}
272
273        torrent_standalone(torrent_internal_ptr t) :
274                iniClass("torrent"),
275                torrent(t),
276                save_time(pt::second_clock::universal_time())
277        {}
278
279        torrent_internal_ptr torrent;
280        pt::ptime save_time;
281
282    friend class boost::serialization::access;
283    template<class Archive>
284    void serialize(Archive& ar, const unsigned int version)
285    {
286                ar & boost::serialization::make_nvp("torrent", torrent);
287                ar & boost::serialization::make_nvp("save_time", save_time);
288    }
289};
290
291struct out_of_session;
292
293class torrent_internal :
294        public boost::enable_shared_from_this<torrent_internal>,
295        public sc::state_machine<torrent_internal, out_of_session>
296{
297        friend class bit::torrent::exec_around_ptr::proxy;
298
299        friend struct out_of_session;   
300        friend struct in_the_session;
301       
302        friend struct active;
303        friend struct pausing;
304        friend struct paused;
305        friend struct stopping;
306        friend struct stopped;
307        friend struct in_error;
308        friend struct resume_data_waiting;
309        friend struct resume_data_idling;
310
311public:
312        #define TORRENT_INTERNALS_DEFAULTS \
313                original_filename_(L""), \
314                transfer_limit_(std::pair<float, float>(-1, -1)), \
315                connections_(-1), \
316                uploads_(-1), \
317                ratio_(0), \
318                awaiting_resume_data_(false), \
319                resolve_countries_(true), \
320                total_uploaded_(0), \
321                total_base_(0), \
322                progress_(0), \
323                managed_(false), \
324                start_time_(boost::posix_time::second_clock::universal_time()), \
325                in_session_(false), \
326                queue_position_(0)
327               
328        torrent_internal() :   
329                TORRENT_INTERNALS_DEFAULTS,
330                allocation_(bit::sparse_allocation)
331        {
332                state(torrent_details::torrent_stopped);
333                TORRENT_STATE_LOG(L"Torrent state machine initiate");
334                initiate();
335        }
336       
337        torrent_internal(wpath filename, wpath saveDirectory, bit::allocations alloc, wpath move_to_directory=L"") :
338                TORRENT_INTERNALS_DEFAULTS,
339                save_directory_(saveDirectory.string()),
340                move_to_directory_(move_to_directory.string()),
341                allocation_(alloc)
342        {
343                state(torrent_details::torrent_stopped);
344                assert(the_session_);   
345               
346                TORRENT_STATE_LOG(L"Torrent state machine initiate");
347                initiate();
348
349                prepare(filename);
350        }
351
352        #undef TORRENT_INTERNALS_DEFAULTS
353
354        void locked_process_event(const sc::event_base & e)
355        {
356                mutex_t::scoped_lock l(mutex_);
357                process_event(e);
358        }
359
360        ~torrent_internal()
361        {
362                terminate();
363        }
364       
365        torrent_details_ptr get_torrent_details_ptr();
366
367        void adjust_queue_position(bit::queue_adjustments adjust);
368
369        void set_transfer_speed(float down, float up)
370        {       
371                mutex_t::scoped_lock l(mutex_);
372
373                transfer_limit_ = std::make_pair(down, up);
374               
375                apply_transfer_speed();
376        }
377
378        void set_connection_limit(int maxConn, int maxUpload)           
379        {
380                mutex_t::scoped_lock l(mutex_);
381
382                connections_ = maxConn;
383                uploads_ = maxUpload;
384               
385                apply_connection_limit();
386        }
387
388        std::pair<float, float> get_transfer_speed()
389        {
390                return transfer_limit_;
391        }
392
393        std::pair<int, int> get_connection_limit()
394        {
395                return std::make_pair(connections_, uploads_);
396        }
397       
398        const wstring& name() const { return name_; }
399       
400        void set_ratio(float ratio) 
401        { 
402                if (ratio < 0) ratio = 0;
403                ratio_ = ratio; 
404               
405                apply_ratio();
406        }
407       
408        float get_ratio()
409        {
410                return ratio_;
411        }
412
413        void set_managed(bool m)
414        {
415                mutex_t::scoped_lock l(mutex_);
416                managed_ = m;
417               
418                if (in_session()) handle_.auto_managed(managed_);
419        }
420
421        bool is_managed()
422        {
423                if (in_session())
424                {
425                        managed_ = handle_.is_auto_managed();
426                }
427
428                return managed_;
429        }
430       
431        void add_to_session(bool paused = false);
432       
433        bool remove_from_session(bool write_data=true);
434
435        bool in_session() const
436        { 
437                mutex_t::scoped_lock l(mutex_);
438
439                return (in_session_ && the_session_ != 0 && handle_.is_valid());
440        }
441
442        void resume()
443        {
444                mutex_t::scoped_lock l(mutex_);
445                HAL_DEV_MSG(hal::wform(L"resume() - %1%") % name_);
446               
447                process_event(ev_resume());
448        }
449       
450        void pause()
451        {
452                mutex_t::scoped_lock l(mutex_);
453                HAL_DEV_MSG(hal::wform(L"pause() - %1%") % name_);
454               
455                process_event(ev_pause());             
456        }
457       
458        void stop()
459        {
460                mutex_t::scoped_lock l(mutex_);
461                HAL_DEV_MSG(hal::wform(L"stop() - %1%") % name_);
462               
463                process_event(ev_stop());
464        }
465
466        void set_state_stopped()
467        {
468                state(torrent_details::torrent_stopped);
469        }
470
471        void force_recheck()
472        {
473                mutex_t::scoped_lock l(mutex_);
474                HAL_DEV_MSG(hal::wform(L"force_recheck() - %1%") % name_);
475               
476                process_event(ev_force_recheck());     
477        }
478       
479        void write_resume_data(const libt::entry& ent)
480        {                                       
481                HAL_DEV_MSG(L"write_resume_data()");
482
483                wpath resume_dir = hal::app().get_working_directory()/L"resume";
484               
485                if (!exists(resume_dir))
486                        create_directory(resume_dir);
487
488                boost::filesystem::ofstream out(resume_dir/(name_ + L".fastresume"), std::ios_base::binary);
489                out.unsetf(std::ios_base::skipws);
490                bencode(std::ostream_iterator<char>(out), ent);
491
492                HAL_DEV_MSG(L"Written!");
493        }
494
495        void save_resume_data()
496        {
497                handle_.save_resume_data();
498        }
499       
500        void clear_resume_data()
501        {
502                wpath resume_file = hal::app().get_working_directory()/L"resume"/filename_;
503               
504                if (exists(resume_file))
505                        remove(resume_file);
506        }
507
508        const wpath get_save_directory()
509        {
510                return save_directory_;
511        }
512
513        void set_save_directory(wpath s, bool force=false)
514        {
515                if (in_session() && !is_finished() &&
516                                s != path_from_utf8(handle_.save_path()))
517                {
518                        handle_.move_storage(path_to_utf8(s));
519                        save_directory_ = s;
520                }
521                else if (!in_session() && force)
522                {
523                        save_directory_ = s;
524                }
525        }
526
527        const wpath get_move_to_directory()
528        {
529                return move_to_directory_;
530        }
531       
532        void set_move_to_directory(wpath m)
533        {
534                if (is_finished() && !m.empty())
535                {
536                        if (m != path_from_utf8(handle_.save_path()))
537                        {
538                                handle_.move_storage(path_to_utf8(m));
539                                save_directory_ = move_to_directory_ = m;
540                        }
541                }
542                else
543                {
544                        move_to_directory_ = m;
545                }
546        }
547
548        bool is_finished()
549        {
550                if (in_session())
551                {
552                        libt::torrent_status::state_t s = handle_.status().state;
553
554                        return (s == libt::torrent_status::seeding ||
555                                                s == libt::torrent_status::finished);
556                }
557                else 
558                        return false;
559        }
560       
561        void finished()
562        {
563                if (finish_time_.is_special())
564                        finish_time_ = boost::posix_time::second_clock::universal_time();
565
566                if (is_finished())
567                {
568                        if (!move_to_directory_.empty() && 
569                                        move_to_directory_ !=  path_from_utf8(handle_.save_path()))
570                        {
571                                handle_.move_storage(path_to_utf8(move_to_directory_));
572                                save_directory_ = move_to_directory_;
573                        }
574                }
575        }
576       
577        bool is_active() const { return state() == torrent_details::torrent_active; }
578
579        unsigned get_state()
580        {
581                return state_;
582        }
583       
584        void set_tracker_login(wstring username, wstring password)
585        {
586                tracker_username_ = username;
587                tracker_password_ = password;
588               
589                apply_tracker_login();
590        }       
591       
592        std::pair<wstring, wstring> get_tracker_login() const
593        {
594                return make_pair(tracker_username_, tracker_password_);
595        }
596       
597        const wstring& filename() const { return filename_; }
598       
599        const wstring& original_filename() const { return original_filename_; }
600       
601        const libt::torrent_handle& handle() const { return handle_; }
602
603        void reset_trackers()
604        {
605                if (in_session())
606                {
607                        handle_.replace_trackers(torrent_trackers_);           
608                        trackers_.clear();
609                }
610        }
611       
612        void set_trackers(const std::vector<tracker_detail>& tracker_details)
613        {
614                trackers_.clear();
615                trackers_.assign(tracker_details.begin(), tracker_details.end());
616               
617                apply_trackers();
618        }
619       
620        const std::vector<tracker_detail>& get_trackers()
621        {
622                if (trackers_.empty() && info_memory_)
623                {
624                        std::vector<libt::announce_entry> trackers = info_memory_->trackers();
625                       
626                        foreach (const libt::announce_entry& entry, trackers)
627                        {
628                                trackers_.push_back(
629                                        tracker_detail(hal::from_utf8(entry.url), entry.tier));
630                        }
631                }               
632                return trackers_;
633        }
634       
635        void set_file_priorities(std::vector<int> fileIndices, int priority)
636        {
637                if (!file_priorities_.empty())
638                {
639                        foreach(int i, fileIndices)
640                                file_priorities_[i] = priority;
641                               
642                        apply_file_priorities();
643                }
644        }
645
646        const wpath& save_directory() { return save_directory_; }
647       
648    friend class boost::serialization::access;
649    template<class Archive>
650    void serialize(Archive& ar, const unsigned int version)
651        {
652                using boost::serialization::make_nvp;
653
654                if (version > 1) {
655                        ar & make_nvp("transfer_limits", transfer_limit_);
656                        ar & make_nvp("connection_limits", connections_);
657                        ar & make_nvp("upload_limits", uploads_);       
658
659                        ar & make_nvp("name", name_);
660                        ar & make_nvp("filename", filename_);   
661
662                        ar & make_nvp("ratio", ratio_); 
663                        ar & make_nvp("progress", progress_);
664                        ar & make_nvp("state", state_);
665        //                      ar & make_nvp("compact_storage", compact_storage_);     
666                        ar & make_nvp("allocation_type", allocation_); 
667                        ar & make_nvp("resolve_countries", resolve_countries_); 
668
669                        ar & make_nvp("tracker_username", tracker_username_);
670                        ar & make_nvp("tracker_password", tracker_password_);
671                        ar & make_nvp("trackers", trackers_);
672
673                        ar & make_nvp("save_directory", save_directory_);
674                        ar & make_nvp("move_to_directory", move_to_directory_);
675                       
676                        ar & make_nvp("payload_uploaded", payload_uploaded_);
677                        ar & make_nvp("payload_downloaded", payload_downloaded_);
678                        ar & make_nvp("uploaded", uploaded_);
679                        ar & make_nvp("downloaded", downloaded_);                       
680                                       
681                        ar & make_nvp("file_priorities", file_priorities_);
682                       
683                        ar & make_nvp("start_time", start_time_);
684                        ar & make_nvp("finish_time", finish_time_);
685                        ar & make_nvp("active_duration", active_duration_);
686                        ar & make_nvp("seeding_duration", seeding_duration_);
687                        ar & make_nvp("managed", managed_);                             
688                } 
689                else 
690                {
691                        ar & make_nvp("transferLimit", transfer_limit_);
692                        ar & make_nvp("connections", connections_);
693                        ar & make_nvp("uploads", uploads_);                     
694                        ar & make_nvp("filename", filename_);   
695
696                        wstring s;
697                        ar & make_nvp("saveDirectory", s);
698                        save_directory_ = s;
699
700                        if (version == 2) {
701                                wstring m;
702                                ar & make_nvp("moveToDirectory", m);
703                                move_to_directory_ = m;
704                        } else {
705                                move_to_directory_ = save_directory_;
706                        }
707                       
708                        ar & make_nvp("payload_uploaded_", payload_uploaded_);
709                        ar & make_nvp("payload_downloaded_", payload_downloaded_);
710                        ar & make_nvp("uploaded_", uploaded_);
711                        ar & make_nvp("downloaded_", downloaded_);     
712                        ar & make_nvp("ratio", ratio_); 
713                        ar & make_nvp("trackerUsername", tracker_username_);
714                        ar & make_nvp("trackerPassword", tracker_password_);
715                       
716                        ar & make_nvp("state", state_);
717                        ar & make_nvp("trackers", trackers_);
718                       
719                        ar & make_nvp("resolve_countries", resolve_countries_);
720                       
721                        ar & make_nvp("file_priorities", file_priorities_);
722                       
723                        ar & make_nvp("start_time", start_time_);
724                        ar & make_nvp("activeDuration", active_duration_);
725                        ar & make_nvp("seedingDuration", seeding_duration_);
726                       
727                        ar & make_nvp("name", name_);
728                        ar & make_nvp("compactStorage", compact_storage_);
729                        ar & make_nvp("finish_time", finish_time_);
730                       
731                        ar & make_nvp("progress", progress_);
732                }
733        }
734
735        void set_entry_data(boost::intrusive_ptr<libt::torrent_info> metadata, libtorrent::entry resumedata)
736        {               
737                info_memory_ = metadata;
738        }
739
740        std::vector<libt::peer_info>& peers() { return peers_; }
741       
742        boost::tuple<size_t, size_t, size_t, size_t> update_peers();
743       
744        void get_peer_details(peer_details_vec& peer_details) const
745        {
746                if (in_session())
747                {
748                        foreach (libt::peer_info peer, peers_) 
749                        {
750                                peer_details.insert(peer);
751                        }       
752                }
753        }
754
755        void get_file_details(file_details_vec& files);
756       
757        void prepare(wpath filename);
758
759        void set_resolve_countries(bool b)
760        {
761                resolve_countries_ = b;
762                apply_resolve_countries();
763        }
764       
765        void extract_names(boost::intrusive_ptr<libt::torrent_info> metadata);
766       
767        boost::intrusive_ptr<libt::torrent_info> info_memory()
768        {
769                if (!info_memory_) 
770                        info_memory_ = boost::intrusive_ptr<libt::torrent_info>
771                                (new libt::torrent_info(path_to_utf8(filename())));
772               
773                return info_memory_;
774        }
775       
776        signalers& signals()
777        {
778                mutex_t::scoped_lock l(mutex_);
779                return signals_;
780        }       
781       
782        unsigned state() const 
783        { 
784                if (!in_session())
785                {
786                        if (state_ != torrent_details::torrent_stopped)
787                        {                       
788                                HAL_DEV_MSG(L"Should really be stopped!");
789                                state_ = torrent_details::torrent_stopped;
790                        }
791                }
792               
793                return state_; 
794        }
795
796        wstring check_error() 
797        {               
798                if (in_session())
799                {
800                        status_memory_ = handle_.status();
801                        return from_utf8(status_memory_.error);
802                }
803                else
804                        return L"";
805        }
806
807        bool awaiting_resume_data() { return awaiting_resume_data_; }
808
809        void output_torrent_debug_details()
810        {
811                HAL_DEV_MSG(wform(L"Name %1%") % name_);
812                HAL_DEV_MSG(wform(L" >> In session       %1%") % in_session());
813
814                if (in_session())
815                {
816
817                wstring state_str;
818
819                switch (state())
820                {
821                case torrent_details::torrent_active:
822                        state_str = L"Active";
823                        break;
824
825                case torrent_details::torrent_paused:
826                        state_str = app().res_wstr(HAL_TORRENT_PAUSED);
827                        break;
828                       
829                case torrent_details::torrent_pausing:
830                        state_str = app().res_wstr(HAL_TORRENT_PAUSING);
831                        break;
832                       
833                case torrent_details::torrent_stopped:
834                        state_str = app().res_wstr(HAL_TORRENT_STOPPED);
835                        break;
836                       
837                case torrent_details::torrent_stopping:
838                        state_str = app().res_wstr(HAL_TORRENT_STOPPING);
839                        break;
840                       
841                case torrent_details::torrent_in_error:
842                        state_str = app().res_wstr(HAL_TORRENT_IN_ERROR);
843                        break;
844                };
845               
846                HAL_DEV_MSG(wform(L" >> State            %1%") % state_str);
847                HAL_DEV_MSG(wform(L" >> Session Paused   %1%") % handle_.is_paused());
848                HAL_DEV_MSG(wform(L" >> Error state      %1%") % check_error());
849
850                }
851        }
852
853        static libt::session* the_session_;     
854
855private:
856        void apply_settings(); 
857        void apply_transfer_speed();
858        void apply_connection_limit(); 
859        void apply_ratio();     
860        void apply_trackers(); 
861        void apply_tracker_login();     
862        void apply_file_priorities();   
863        void apply_resolve_countries();
864        void state(unsigned s);
865
866        mutable mutex_t mutex_;
867        signalers signals_;
868       
869        std::pair<float, float> transfer_limit_;
870       
871        mutable unsigned state_;
872        bool awaiting_resume_data_;
873        int connections_;
874        int uploads_;
875        bool in_session_;
876        float ratio_;
877        bool resolve_countries_;
878       
879        wstring filename_;
880        wstring name_;
881        wpath save_directory_;
882        wpath move_to_directory_;
883        wstring original_filename_;
884        libt::torrent_handle handle_;   
885        wstring tracker_username_;     
886        wstring tracker_password_;
887       
888        boost::int64_t total_uploaded_;
889        boost::int64_t total_base_;
890       
891        transfer_tracker<boost::int64_t> payload_uploaded_;
892        transfer_tracker<boost::int64_t> payload_downloaded_;
893        transfer_tracker<boost::int64_t> uploaded_;
894        transfer_tracker<boost::int64_t> downloaded_;
895       
896        pt::ptime start_time_;
897        pt::ptime finish_time_;
898        duration_tracker active_duration_;
899        duration_tracker seeding_duration_;
900       
901        std::vector<tracker_detail> trackers_;
902        std::vector<libt::announce_entry> torrent_trackers_;
903        std::vector<libt::peer_info> peers_;   
904        std::vector<int> file_priorities_;
905       
906        float progress_;       
907        int queue_position_;
908        bool compact_storage_;
909        bool managed_;
910        bit::allocations allocation_;
911       
912        boost::intrusive_ptr<libt::torrent_info> info_memory_;
913        libt::torrent_status status_memory_;
914        file_details_vec file_details_memory_;
915};
916
917typedef std::map<std::string, TorrentInternalOld> TorrentMap;
918typedef std::pair<std::string, TorrentInternalOld> TorrentPair;
919
920class torrent_manager : 
921        public hal::IniBase<torrent_manager>
922{
923        typedef torrent_manager thisClass;
924        typedef hal::IniBase<thisClass> iniClass;
925
926        struct torrent_holder
927        {
928                mutable torrent_internal_ptr torrent;
929               
930                wstring filename;
931                wstring name;           
932               
933                torrent_holder()
934                {}
935               
936                explicit torrent_holder(torrent_internal_ptr t) :
937                        torrent(t), filename(torrent->filename()), name(torrent->name())
938                {}
939                                               
940                friend class boost::serialization::access;
941                template<class Archive>
942                void serialize(Archive& ar, const unsigned int version)
943                {
944                        using boost::serialization::make_nvp;
945
946                        ar & make_nvp("torrent", torrent);
947                        ar & make_nvp("filename", filename);
948                        ar & make_nvp("name", name);
949                }
950        };
951       
952        struct by_filename{};
953        struct by_name{};
954       
955        typedef boost::multi_index_container<
956                torrent_holder,
957                boost::multi_index::indexed_by<
958                        boost::multi_index::ordered_unique<
959                                boost::multi_index::tag<by_filename>,
960                                boost::multi_index::member<
961                                        torrent_holder, wstring, &torrent_holder::filename> 
962                                >,
963                        boost::multi_index::ordered_unique<
964                                boost::multi_index::tag<by_name>,
965                                boost::multi_index::member<
966                                        torrent_holder, wstring, &torrent_holder::name> 
967                                >
968                >
969        > torrent_multi_index;
970       
971public:
972        typedef torrent_multi_index::index<by_filename>::type torrent_by_filename;
973        typedef torrent_multi_index::index<by_name>::type torrent_by_name;
974       
975        torrent_manager(ini_file& ini) :
976                iniClass("bittorrent", "torrent_manager", ini)
977        {}
978
979        std::pair<torrent_by_name::iterator, bool> insert(const torrent_holder& h)
980        {
981                return torrents_.get<by_name>().insert(h);
982        }
983       
984        std::pair<torrent_by_name::iterator, bool> insert(torrent_internal_ptr t)
985        {
986                return insert(torrent_holder(t));
987        }
988
989        torrent_internal_ptr get_by_file(const wstring& filename)
990        {
991                torrent_by_filename::iterator it = torrents_.get<by_filename>().find(filename);
992               
993                if (it != torrents_.get<by_filename>().end() && (*it).torrent)
994                {
995                        return (*it).torrent;
996                }
997               
998                throw invalid_torrent(filename);
999        }
1000       
1001        torrent_internal_ptr get(const wstring& name)
1002        {
1003                torrent_by_name::iterator it = torrents_.get<by_name>().find(name);
1004               
1005                if (it != torrents_.get<by_name>().end() && (*it).torrent)
1006                {
1007                        return (*it).torrent;
1008                }
1009               
1010                throw invalid_torrent(name);
1011        }
1012       
1013        torrent_by_name::iterator erase(torrent_by_name::iterator where)
1014        {
1015                return torrents_.get<by_name>().erase(where);
1016        }
1017       
1018        size_t size()
1019        {
1020                return torrents_.size();
1021        }
1022       
1023        size_t erase(const wstring& name)
1024        {
1025                return torrents_.get<by_name>().erase(name);
1026        }
1027       
1028        bool exists(const wstring& name)
1029        {
1030                torrent_by_name::iterator it = torrents_.get<by_name>().find(name);
1031               
1032                if (it != torrents_.get<by_name>().end())
1033                        return true;
1034                else
1035                        return false;
1036        }
1037       
1038        torrent_by_name::iterator begin() { return torrents_.get<by_name>().begin(); }
1039        torrent_by_name::iterator end() { return torrents_.get<by_name>().end(); }
1040       
1041        friend class boost::serialization::access;
1042        template<class Archive>
1043        void serialize(Archive& ar, const unsigned int version)
1044        {
1045                ar & boost::serialization::make_nvp("torrents", torrents_);
1046        }       
1047       
1048private:
1049        torrent_multi_index torrents_;
1050};
1051
1052} // namespace hal
1053
1054#include "halTorrentIntStates.hpp"
1055
1056BOOST_CLASS_VERSION(hal::torrent_manager::torrent_holder, 1)
Note: See TracBrowser for help on using the repository browser.