source: trunk/src/halTorrentInternal.hpp @ 739

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