Rasterbar Libtorrent 的简单分析

  最近在做的一个P2P项目需要使用到一些基础的IO,网络通信的模块,自己写的话短时间内很难达到产品级的健壮性,所以就从现有的开源项目里面抽取模块了,看了看eMule的,这东西和MFC结合紧密,而且整个项目大的可怕,要编译成功都很麻烦,更不要说去抽取它的模块了。不大靠谱。于是就研究了一下LibTorrent,不过这东西有两个。我研究的是Rasterbar的版本。现在的版本是0.15.0。不过这东西整了个openssl的功能。openssl在windows下编译麻烦死了,关键还得装个perl还是python忘了,代码也复杂了。所以我花了点时间把openssl给剥离出去。还好作者写的代码思路清晰,都用宏定义划分了不同功能的分支。

 

 

  libtorrent的类结构中最大的一个结构就是alert结构了(点击看大图).

 

 

alert

 

Rasterbar Libtorrent 的简单分析_第1张图片

  对于外部程序来说,libtorrent的pop_alert()函数正是外部程序用来从libtorrent中获取各种消息、警告、错误等信息的接口。按照官方文档的说明,如果没有任何可用的这些信息的话,就自动返回一个默认构造的auto_ptr对象。由此可见。这个alert的继承树中的各种具体的对象,就分别代表了不同的信息了。对于libtorrent来说,它内部维护了一个alert的队列。此外,libtorrent默认是只保存错误消息的。可以使用set_alert_mask来设置。当然,获得了一个auto_ptr对象的话自然还必须知道具体是哪一个,所以libtorrent就使用alert_cast<>来获得具体的详细类型。alert的具体类型都定义在libtorrent/alert_types.hpp文件中。

  alert的代码是这样的:

 


class TORRENT_EXPORT alert { public: // only here for backwards compatibility enum severity_t { debug, info, warning, critical, fatal, none }; enum category_t { error_notification = 0x1, peer_notification = 0x2, port_mapping_notification = 0x4, storage_notification = 0x8, tracker_notification = 0x10, debug_notification = 0x20, status_notification = 0x40, progress_notification = 0x80, ip_block_notification = 0x100, performance_warning = 0x200, dht_notification = 0x400, stats_notification = 0x800, all_categories = 0xffffffff }; alert(); virtual ~alert(); // a timestamp is automatically created in the constructor ptime timestamp() const; virtual char const* what() const = 0; virtual std::string message() const = 0; virtual int category() const = 0; #ifndef TORRENT_NO_DEPRECATE TORRENT_DEPRECATED_PREFIX severity_t severity() const TORRENT_DEPRECATED { return warning; } #endif virtual std::auto_ptr<alert> clone() const = 0; private: ptime m_timestamp; }; 

   关于每个alert的具体描述,官方文档这里有说明。

 

 

 

 

 

libtorrent_exception

 

  libtorrent中的不少函数有两个版本,一个会抛出异常,一个是接受一个引用,返回异常代码。因为直接使用了boost的error code来表示错误,所以结构比较简单。

Rasterbar Libtorrent 的简单分析_第2张图片

 

 

 

 

storage_interface

  storage_interface是libtorrent中我最关心的一部分了,这个接口是个纯虚函数,目的是可以让开发者定制特定的种子对应的文件保存位置,默认使用一个代表存储在本地磁盘的文件的实现。storage_interface是基于槽实现的,每个槽有piece_size个字节。所有对磁盘的读写都是基于完整的或者部分的槽。

 

 

struct TORRENT_EXPORT storage_interface { storage_interface(): m_disk_pool(0), m_settings(0) {} // create directories and set file sizes // if allocate_files is true. // allocate_files is true if allocation mode // is set to full and sparse files are supported // false return value indicates an error virtual bool initialize(bool allocate_files) = 0; // 此函数在第一次检查(重检查)种子所对应的文件时调用,如果文件已存在应该返回true。 // 并且,这种情况下这个文件已有的片段应该在下载开始前被检查 virtual bool has_any_file() = 0; // 以下两个函数用于从给定的offset处的给定的slot中读写数据。此方法将连续读写 // num_bufs个buffer的内容,其中每个buffer的大小都将在bufs数组中定义。 // file::iovec_t类型是这样定义的: // struct iovec_t // { // void* iov_base; // size_t iov_len; // }; // 返回值则是实际读写的字节数。或者返回-1表示失败。 // 每个bufs中的buffer都能被假定为是按页及页大小对准的,当然,除了种子中的最后一个buffer。 virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs); virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs); // negative return value indicates an error virtual int read(char* buf, int slot, int offset, int size) = 0; // negative return value indicates an error virtual int write(const char* buf, int slot, int offset, int size) = 0; virtual size_type physical_offset(int slot, int offset) = 0; // returns the end of the sparse region the slot 'start' // resides in i.e. the next slot with content. If start // is not in a sparse region, start itself is returned virtual int sparse_end(int start) const { return start; } // non-zero return value indicates an error virtual bool move_storage(fs::path save_path) = 0; // verify storage dependent fast resume entries virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) = 0; // write storage dependent fast resume entries virtual bool write_resume_data(entry& rd) const = 0; // moves (or copies) the content in src_slot to dst_slot virtual bool move_slot(int src_slot, int dst_slot) = 0; // swaps the data in slot1 and slot2 virtual bool swap_slots(int slot1, int slot2) = 0; // swaps the puts the data in slot1 in slot2, the data in slot2 // in slot3 and the data in slot3 in slot1 virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0; // this will close all open files that are opened for // writing. This is called when a torrent has finished // downloading. // non-zero return value indicates an error virtual bool release_files() = 0; // this will rename the file specified by index. virtual bool rename_file(int index, std::string const& new_filename) = 0; // this will close all open files and delete them // non-zero return value indicates an error virtual bool delete_files() = 0; disk_buffer_pool* disk_pool() { return m_disk_pool; } session_settings const& settings() const { return *m_settings; } void set_error(boost::filesystem::path const& file, error_code const& ec) const { m_error_file = file.string(); m_error = ec; } error_code const& error() const { return m_error; } std::string const& error_file() const { return m_error_file; } void clear_error() { m_error = error_code(); m_error_file.clear(); } mutable error_code m_error; mutable std::string m_error_file; virtual ~storage_interface() {} disk_buffer_pool* m_disk_pool; session_settings* m_settings; }; 

 

 

  文件是分片了,但是关于文件分片在程序中的读取优先级,则主要在torrent_handle中处理

torrent_handle

 

torrent_handle中对文件下载顺序影响最大的一个函数就是set_piece_deadline()函数了,这个函数给每个片段设置一个截止期限,libtorrent会在截止期限终止之前去尝试下载这个片段.而piece_priority() prioritize_pieces() piece_priorities()则设置了每个片段的优先级(注意是和其available有关的).

 

你可能感兴趣的:(String,File,buffer,interface,deprecated,disk)