forked from premiere/premiere-libtorrent
added custom storage example and regenerated html
This commit is contained in:
parent
5bbbf0cd41
commit
b0586eb47e
|
@ -313,7 +313,8 @@ typically the case on x86 64 bit systems.</li>
|
|||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">asserts</span></tt></td>
|
||||
<td><ul class="first last simple">
|
||||
<li><tt class="docutils literal"><span class="pre">on</span></tt> - asserts are on if in debug mode</li>
|
||||
<li><tt class="docutils literal"><span class="pre">auto</span></tt> - asserts are on if in debug mode</li>
|
||||
<li><tt class="docutils literal"><span class="pre">on</span></tt> - asserts are on, even in release mode</li>
|
||||
<li><tt class="docutils literal"><span class="pre">off</span></tt> - asserts are disabled</li>
|
||||
<li><tt class="docutils literal"><span class="pre">production</span></tt> - assertion failures are logged
|
||||
to <tt class="docutils literal"><span class="pre">asserts.log</span></tt> in the current working
|
||||
|
|
|
@ -57,22 +57,23 @@
|
|||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#libtorrent-plugins" id="id1">libtorrent plugins</a><ul>
|
||||
<li><a class="reference internal" href="#a-word-of-caution" id="id2">a word of caution</a></li>
|
||||
<li><a class="reference internal" href="#libtorrent-plugins" id="id2">libtorrent plugins</a><ul>
|
||||
<li><a class="reference internal" href="#a-word-of-caution" id="id3">a word of caution</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#plugin-interface" id="id3">plugin interface</a></li>
|
||||
<li><a class="reference internal" href="#plugin" id="id4">plugin</a></li>
|
||||
<li><a class="reference internal" href="#torrent-plugin" id="id5">torrent_plugin</a><ul>
|
||||
<li><a class="reference internal" href="#new-connection" id="id6">new_connection()</a></li>
|
||||
<li><a class="reference internal" href="#on-piece-pass-on-piece-fail" id="id7">on_piece_pass() on_piece_fail()</a></li>
|
||||
<li><a class="reference internal" href="#tick" id="id8">tick()</a></li>
|
||||
<li><a class="reference internal" href="#on-pause-on-resume" id="id9">on_pause() on_resume()</a></li>
|
||||
<li><a class="reference internal" href="#on-files-checked" id="id10">on_files_checked()</a></li>
|
||||
<li><a class="reference internal" href="#plugin-interface" id="id4">plugin interface</a></li>
|
||||
<li><a class="reference internal" href="#plugin" id="id5">plugin</a></li>
|
||||
<li><a class="reference internal" href="#torrent-plugin" id="id6">torrent_plugin</a><ul>
|
||||
<li><a class="reference internal" href="#new-connection" id="id7">new_connection()</a></li>
|
||||
<li><a class="reference internal" href="#on-piece-pass-on-piece-fail" id="id8">on_piece_pass() on_piece_fail()</a></li>
|
||||
<li><a class="reference internal" href="#tick" id="id9">tick()</a></li>
|
||||
<li><a class="reference internal" href="#on-pause-on-resume" id="id10">on_pause() on_resume()</a></li>
|
||||
<li><a class="reference internal" href="#on-files-checked" id="id11">on_files_checked()</a></li>
|
||||
<li><a class="reference internal" href="#id1" id="id12">on_files_checked()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#peer-plugin" id="id11">peer_plugin</a></li>
|
||||
<li><a class="reference internal" href="#disk-buffer-holder" id="id12">disk_buffer_holder</a></li>
|
||||
<li><a class="reference internal" href="#peer-plugin" id="id13">peer_plugin</a></li>
|
||||
<li><a class="reference internal" href="#disk-buffer-holder" id="id14">disk_buffer_holder</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>libtorrent has a plugin interface for implementing extensions to the protocol.
|
||||
|
@ -172,6 +173,16 @@ struct torrent_plugin
|
|||
virtual bool on_resume();
|
||||
|
||||
virtual void on_files_checked();
|
||||
|
||||
virtual void on_state(int s);
|
||||
|
||||
enum flags_t {
|
||||
first_time = 1,
|
||||
filtered = 2
|
||||
};
|
||||
|
||||
virtual void on_add_peer(tcp::endpoint const& ip
|
||||
, int src, int flags);
|
||||
};
|
||||
</pre>
|
||||
<p>This is the base class for a torrent_plugin. Your derived class is (if added
|
||||
|
@ -241,6 +252,41 @@ checked. If there are no files to check, this function is called immediately.</p
|
|||
<p>i.e. This function is always called when the torrent is in a state where it
|
||||
can start downloading.</p>
|
||||
</div>
|
||||
<div class="section" id="id1">
|
||||
<h2>on_files_checked()</h2>
|
||||
<pre class="literal-block">
|
||||
enum flags_t {
|
||||
first_time = 1,
|
||||
filtered = 2
|
||||
};
|
||||
|
||||
virtual void on_add_peer(tcp::endpoint const& ip
|
||||
, int src, int flags);
|
||||
</pre>
|
||||
<p>This function is called whenever we hear about a peer from any peer source,
|
||||
such as the tracker, PEX, DHT or Local peer discovery.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">src</span></tt> is a bitmask of <tt class="docutils literal"><span class="pre">peer_info::peer_source_flags</span></tt>:</p>
|
||||
<pre class="literal-block">
|
||||
enum peer_source_flags
|
||||
{
|
||||
tracker = 0x1,
|
||||
dht = 0x2,
|
||||
pex = 0x4,
|
||||
lsd = 0x8,
|
||||
resume_data = 0x10,
|
||||
incoming = 0x20
|
||||
};
|
||||
</pre>
|
||||
<p><tt class="docutils literal"><span class="pre">flags</span></tt> is a bitmask of:</p>
|
||||
<pre class="literal-block">
|
||||
enum flags_t {
|
||||
first_time = 1,
|
||||
filtered = 2
|
||||
};
|
||||
</pre>
|
||||
<p>If the <tt class="docutils literal"><span class="pre">filtered</span></tt> flag is set, it means the peer wasn't added to the
|
||||
peer list because of and IP filter, port filter, reserved ports filter.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="peer-plugin">
|
||||
<h1>peer_plugin</h1>
|
||||
|
|
182
docs/manual.html
182
docs/manual.html
|
@ -288,43 +288,45 @@
|
|||
<li><a class="reference internal" href="#storage-interface" id="id218">storage_interface</a><ul>
|
||||
<li><a class="reference internal" href="#initialize" id="id219">initialize()</a></li>
|
||||
<li><a class="reference internal" href="#has-any-file" id="id220">has_any_file()</a></li>
|
||||
<li><a class="reference internal" href="#readv-writev" id="id221">readv() writev()</a></li>
|
||||
<li><a class="reference internal" href="#sparse-end" id="id222">sparse_end()</a></li>
|
||||
<li><a class="reference internal" href="#id10" id="id223">move_storage()</a></li>
|
||||
<li><a class="reference internal" href="#verify-resume-data" id="id224">verify_resume_data()</a></li>
|
||||
<li><a class="reference internal" href="#write-resume-data" id="id225">write_resume_data()</a></li>
|
||||
<li><a class="reference internal" href="#move-slot" id="id226">move_slot()</a></li>
|
||||
<li><a class="reference internal" href="#swap-slots" id="id227">swap_slots()</a></li>
|
||||
<li><a class="reference internal" href="#swap-slots3" id="id228">swap_slots3()</a></li>
|
||||
<li><a class="reference internal" href="#id11" id="id229">rename_file()</a></li>
|
||||
<li><a class="reference internal" href="#release-files" id="id230">release_files()</a></li>
|
||||
<li><a class="reference internal" href="#delete-files" id="id231">delete_files()</a></li>
|
||||
<li><a class="reference internal" href="#finalize-file" id="id232">finalize_file()</a></li>
|
||||
<li><a class="reference internal" href="#hint-read" id="id221">hint_read()</a></li>
|
||||
<li><a class="reference internal" href="#readv-writev" id="id222">readv() writev()</a></li>
|
||||
<li><a class="reference internal" href="#sparse-end" id="id223">sparse_end()</a></li>
|
||||
<li><a class="reference internal" href="#id10" id="id224">move_storage()</a></li>
|
||||
<li><a class="reference internal" href="#verify-resume-data" id="id225">verify_resume_data()</a></li>
|
||||
<li><a class="reference internal" href="#write-resume-data" id="id226">write_resume_data()</a></li>
|
||||
<li><a class="reference internal" href="#move-slot" id="id227">move_slot()</a></li>
|
||||
<li><a class="reference internal" href="#swap-slots" id="id228">swap_slots()</a></li>
|
||||
<li><a class="reference internal" href="#swap-slots3" id="id229">swap_slots3()</a></li>
|
||||
<li><a class="reference internal" href="#id11" id="id230">rename_file()</a></li>
|
||||
<li><a class="reference internal" href="#release-files" id="id231">release_files()</a></li>
|
||||
<li><a class="reference internal" href="#delete-files" id="id232">delete_files()</a></li>
|
||||
<li><a class="reference internal" href="#finalize-file" id="id233">finalize_file()</a></li>
|
||||
<li><a class="reference internal" href="#example" id="id234">example</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#magnet-links" id="id233">magnet links</a></li>
|
||||
<li><a class="reference internal" href="#queuing" id="id234">queuing</a><ul>
|
||||
<li><a class="reference internal" href="#downloading" id="id235">downloading</a></li>
|
||||
<li><a class="reference internal" href="#seeding" id="id236">seeding</a></li>
|
||||
<li><a class="reference internal" href="#magnet-links" id="id235">magnet links</a></li>
|
||||
<li><a class="reference internal" href="#queuing" id="id236">queuing</a><ul>
|
||||
<li><a class="reference internal" href="#downloading" id="id237">downloading</a></li>
|
||||
<li><a class="reference internal" href="#seeding" id="id238">seeding</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#fast-resume" id="id237">fast resume</a><ul>
|
||||
<li><a class="reference internal" href="#file-format" id="id238">file format</a></li>
|
||||
<li><a class="reference internal" href="#fast-resume" id="id239">fast resume</a><ul>
|
||||
<li><a class="reference internal" href="#file-format" id="id240">file format</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#threads" id="id239">threads</a></li>
|
||||
<li><a class="reference internal" href="#storage-allocation" id="id240">storage allocation</a><ul>
|
||||
<li><a class="reference internal" href="#sparse-allocation" id="id241">sparse allocation</a></li>
|
||||
<li><a class="reference internal" href="#full-allocation" id="id242">full allocation</a></li>
|
||||
<li><a class="reference internal" href="#compact-allocation" id="id243">compact allocation</a></li>
|
||||
<li><a class="reference internal" href="#threads" id="id241">threads</a></li>
|
||||
<li><a class="reference internal" href="#storage-allocation" id="id242">storage allocation</a><ul>
|
||||
<li><a class="reference internal" href="#sparse-allocation" id="id243">sparse allocation</a></li>
|
||||
<li><a class="reference internal" href="#full-allocation" id="id244">full allocation</a></li>
|
||||
<li><a class="reference internal" href="#compact-allocation" id="id245">compact allocation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#extensions" id="id244">extensions</a><ul>
|
||||
<li><a class="reference internal" href="#metadata-from-peers" id="id245">metadata from peers</a></li>
|
||||
<li><a class="reference internal" href="#http-seeding" id="id246">HTTP seeding</a></li>
|
||||
<li><a class="reference internal" href="#extensions" id="id246">extensions</a><ul>
|
||||
<li><a class="reference internal" href="#metadata-from-peers" id="id247">metadata from peers</a></li>
|
||||
<li><a class="reference internal" href="#http-seeding" id="id248">HTTP seeding</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#filename-checks" id="id247">filename checks</a></li>
|
||||
<li><a class="reference internal" href="#filename-checks" id="id249">filename checks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="overview">
|
||||
|
@ -708,6 +710,10 @@ struct add_torrent_params
|
|||
bool share_mode;
|
||||
std::string trackerid;
|
||||
std::string url;
|
||||
std::string uuid;
|
||||
std::string source_feed_url;
|
||||
bool apply_ip_filter;
|
||||
bool merge_resume_trackers;
|
||||
};
|
||||
|
||||
torrent_handle add_torrent(add_torrent_params const& params);
|
||||
|
@ -823,6 +829,16 @@ is used for forward binary compatibility.</p>
|
|||
<p><tt class="docutils literal"><span class="pre">trackerid</span></tt> is the default tracker id to be used when announcing to trackers. By default
|
||||
this is empty, and no tracker ID is used, since this is an optional argument. If
|
||||
a tracker returns a tracker ID, that ID is used instead of this.</p>
|
||||
<p>if <tt class="docutils literal"><span class="pre">uuid</span></tt> is specified, it is used to find duplicates. If another torrent is already
|
||||
running with the same UUID as the one being added, it will be considered a duplicate. This
|
||||
is mainly useful for RSS feed items which has UUIDs specified.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">source_feed_url</span></tt> should point to the URL of the RSS feed this torrent comes from,
|
||||
if it comes from an RSS feed.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">apply_ip_filter</span></tt> determines if the IP filter should apply to this torrent or not. By
|
||||
default all torrents are subject to filtering by the IP filter. This is useful if certain
|
||||
torrents needs to be excempt for some reason, being an auto-update torrent for instance.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">merge_resume_trackers</span></tt> defaults to false and specifies whether tracker URLs loaded from
|
||||
resume data should be added to the trackers in the torrent or replace the trackers.</p>
|
||||
</div>
|
||||
<div class="section" id="remove-torrent">
|
||||
<h2>remove_torrent()</h2>
|
||||
|
@ -2967,8 +2983,9 @@ A high number gives more bandwidth. The priority must be within the range [0, 25
|
|||
consume, even if there's is more quota. Other peers will still be weighed in when
|
||||
bandwidth is being distributed. With other words, bandwidth is not distributed strictly
|
||||
in order of priority, but the priority is used as a weight.</p>
|
||||
<p>Torrents with higher priority are also more likely to have its peers unchoked, to
|
||||
distribute more upload capacity to them.</p>
|
||||
<p>Peers whose Torrent has a higher priority will take precedence when distributing unchoke slots.
|
||||
This is a strict prioritization where every interested peer on a high priority torrent will
|
||||
be unchoked before any other, lower priority, torrents have any peers unchoked.</p>
|
||||
</div>
|
||||
<div class="section" id="use-interface">
|
||||
<h2>use_interface()</h2>
|
||||
|
@ -3396,6 +3413,8 @@ struct torrent_status
|
|||
int queue_position;
|
||||
bool need_save_resume;
|
||||
bool ip_filter_applies;
|
||||
|
||||
sha1_hash info_hash;
|
||||
};
|
||||
</pre>
|
||||
<p><tt class="docutils literal"><span class="pre">handle</span></tt> is a handle to the torrent whose status the object represents.</p>
|
||||
|
@ -3625,6 +3644,7 @@ to its download state and statistics since the last resume data
|
|||
was saved.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">ip_filter_applies</span></tt> is true if the session global IP filter applies
|
||||
to this torrent. This defaults to true.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">info_hash</span></tt> is the info-hash of the torrent.</p>
|
||||
</div>
|
||||
<div class="section" id="peer-info">
|
||||
<h1>peer_info</h1>
|
||||
|
@ -4373,6 +4393,7 @@ struct session_settings
|
|||
bool always_send_user_agent;
|
||||
bool apply_ip_filter_to_trackers;
|
||||
int read_job_every;
|
||||
use_disk_read_ahead;
|
||||
};
|
||||
</pre>
|
||||
<p><tt class="docutils literal"><span class="pre">version</span></tt> is automatically set to the libtorrent version you're using
|
||||
|
@ -5091,6 +5112,9 @@ and serviced once all write jobs have been issued. In scenarios where the
|
|||
download rate is enough to saturate the disk, there's a risk the read jobs will
|
||||
never be serviced. With this setting, every <em>x</em> write job, issued in a row, will
|
||||
instead pick one read job off of the sorted queue, where <em>x</em> is <tt class="docutils literal"><span class="pre">read_job_every</span></tt>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">use_disk_read_ahead</span></tt> defaults to true and will attempt to optimize disk reads
|
||||
by giving the operating system heads up of disk read requests as they are queued
|
||||
in the disk job queue. This gives a significant performance boost for seeding.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="pe-settings">
|
||||
|
@ -6274,7 +6298,7 @@ struct peer_disconnected_alert: peer_alert
|
|||
<div class="section" id="invalid-request-alert">
|
||||
<h2>invalid_request_alert</h2>
|
||||
<p>This is a debug alert that is generated by an incoming invalid piece request.
|
||||
<tt class="docutils literal"><span class="pre">Ïp</span></tt> is the address of the peer and the <tt class="docutils literal"><span class="pre">request</span></tt> is the actual incoming
|
||||
<tt class="docutils literal"><span class="pre">ìp</span></tt> is the address of the peer and the <tt class="docutils literal"><span class="pre">request</span></tt> is the actual incoming
|
||||
request from the peer.</p>
|
||||
<pre class="literal-block">
|
||||
struct invalid_request_alert: peer_alert
|
||||
|
@ -6657,7 +6681,9 @@ limited, it may be higher than that.</p>
|
|||
<h2>cache_flushed_alert</h2>
|
||||
<p>This alert is posted when the disk cache has been flushed for a specific torrent
|
||||
as a result of a call to <a class="reference internal" href="#flush-cache">flush_cache()</a>. This alert belongs to the
|
||||
<tt class="docutils literal"><span class="pre">storage_notification</span></tt> category, which must be enabled to let this alert through.</p>
|
||||
<tt class="docutils literal"><span class="pre">storage_notification</span></tt> category, which must be enabled to let this alert through.
|
||||
The alert is also posted when removing a torrent from the session, once the outstanding
|
||||
cache flush is complete and the torrent does no longer have any files open.</p>
|
||||
<pre class="literal-block">
|
||||
struct flush_cached_alert: torrent_alert
|
||||
{
|
||||
|
@ -7723,13 +7749,13 @@ std::string error_code_to_string(boost::system::error_code const& ec)
|
|||
static const char const* swedish[] =
|
||||
{
|
||||
"inget fel",
|
||||
"en fil i torrenten kolliderar med en fil frÂn en annan torrent",
|
||||
"en fil i torrenten kolliderar med en fil från en annan torrent",
|
||||
"hash check misslyckades",
|
||||
"torrent filen ‰r inte en dictionary",
|
||||
"'info'-nyckeln saknas eller ‰r korrupt i torrentfilen",
|
||||
"'info'-f‰ltet ‰r inte en dictionary",
|
||||
"'piece length' f‰ltet saknas eller ‰r korrupt i torrentfilen",
|
||||
"torrentfilen saknar namnf‰ltet",
|
||||
"torrent filen är inte en dictionary",
|
||||
"'info'-nyckeln saknas eller är korrupt i torrentfilen",
|
||||
"'info'-fältet är inte en dictionary",
|
||||
"'piece length' fältet saknas eller är korrupt i torrentfilen",
|
||||
"torrentfilen saknar namnfältet",
|
||||
"ogiltigt namn i torrentfilen (kan vara en attack)",
|
||||
// ... more strings here
|
||||
};
|
||||
|
@ -7768,6 +7794,7 @@ struct storage_interface
|
|||
{
|
||||
virtual bool initialize(bool allocate_files) = 0;
|
||||
virtual bool has_any_file() = 0;
|
||||
virtual void hint_read(int slot, int offset, int len);
|
||||
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
|
||||
virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
|
||||
virtual int sparse_end(int start) const;
|
||||
|
@ -7815,6 +7842,17 @@ virtual bool has_any_file() = 0;
|
|||
It should return true if any of the files that is used in this storage exists on disk.
|
||||
If so, the storage will be checked for existing pieces before starting the download.</p>
|
||||
</div>
|
||||
<div class="section" id="hint-read">
|
||||
<h2>hint_read()</h2>
|
||||
<blockquote>
|
||||
<pre class="literal-block">
|
||||
void hint_read(int slot, int offset, int len);
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>This function is called when a read job is queued. It gives the storage wrapper an
|
||||
opportunity to hint the operating system about this coming read. For instance, the
|
||||
storage may call <tt class="docutils literal"><span class="pre">posix_fadvise(POSIX_FADV_WILLNEED)</span></tt> or <tt class="docutils literal"><span class="pre">fcntl(F_RDADVISE)</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="readv-writev">
|
||||
<h2>readv() writev()</h2>
|
||||
<blockquote>
|
||||
|
@ -7995,6 +8033,76 @@ not be opened for writing after this.</p>
|
|||
<p>On windows the default storage implementation clears the sparse file flag
|
||||
on the specified file.</p>
|
||||
</div>
|
||||
<div class="section" id="example">
|
||||
<h2>example</h2>
|
||||
<p>This is an example storage implementation that stores all pieces in a <tt class="docutils literal"><span class="pre">std::map</span></tt>,
|
||||
i.e. in RAM. It's not necessarily very useful in practice, but illustrates the
|
||||
basics of implementing a custom storage.</p>
|
||||
<pre class="literal-block">
|
||||
struct temp_storage : storage_interface
|
||||
{
|
||||
temp_storage(file_storage const& fs) : m_files(fs) {}
|
||||
virtual bool initialize(bool allocate_files) { return false; }
|
||||
virtual bool has_any_file() { return false; }
|
||||
virtual int read(char* buf, int slot, int offset, int size)
|
||||
{
|
||||
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(slot);
|
||||
if (i == m_file_data.end()) return 0;
|
||||
int available = i->second.size() - offset;
|
||||
if (available <= 0) return 0;
|
||||
if (available > size) available = size;
|
||||
memcpy(buf, &i->second[offset], available);
|
||||
return available;
|
||||
}
|
||||
virtual int write(const char* buf, int slot, int offset, int size)
|
||||
{
|
||||
std::vector<char>& data = m_file_data[slot];
|
||||
if (data.size() < offset + size) data.resize(offset + size);
|
||||
std::memcpy(&data[offset], buf, size);
|
||||
return size;
|
||||
}
|
||||
virtual bool rename_file(int file, std::string const& new_name)
|
||||
{ assert(false); return false; }
|
||||
virtual bool move_storage(std::string const& save_path) { return false; }
|
||||
virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) { return false; }
|
||||
virtual bool write_resume_data(entry& rd) const { return false; }
|
||||
virtual bool move_slot(int src_slot, int dst_slot) { assert(false); return false; }
|
||||
virtual bool swap_slots(int slot1, int slot2) { assert(false); return false; }
|
||||
virtual bool swap_slots3(int slot1, int slot2, int slot3) { assert(false); return false; }
|
||||
virtual size_type physical_offset(int slot, int offset)
|
||||
{ return slot * m_files.piece_length() + offset; };
|
||||
virtual sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size)
|
||||
{
|
||||
int left = piece_size - ph.offset;
|
||||
assert(left >= 0);
|
||||
if (left > 0)
|
||||
{
|
||||
std::vector<char>& data = m_file_data[slot];
|
||||
// if there are padding files, those blocks will be considered
|
||||
// completed even though they haven't been written to the storage.
|
||||
// in this case, just extend the piece buffer to its full size
|
||||
// and fill it with zeroes.
|
||||
if (data.size() < piece_size) data.resize(piece_size, 0);
|
||||
ph.h.update(&data[ph.offset], left);
|
||||
}
|
||||
return ph.h.final();
|
||||
}
|
||||
virtual bool release_files() { return false; }
|
||||
virtual bool delete_files() { return false; }
|
||||
|
||||
std::map<int, std::vector<char> > m_file_data;
|
||||
file_storage m_files;
|
||||
};
|
||||
|
||||
storage_interface* temp_storage_constructor(
|
||||
file_storage const& fs, file_storage const* mapped
|
||||
, std::string const& path, file_pool& fp
|
||||
, std::vector<boost::uint8_t> const& prio)
|
||||
{
|
||||
return new temp_storage(fs);
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="magnet-links">
|
||||
<h1>magnet links</h1>
|
||||
|
|
|
@ -8071,6 +8071,78 @@ not be opened for writing after this.
|
|||
On windows the default storage implementation clears the sparse file flag
|
||||
on the specified file.
|
||||
|
||||
example
|
||||
-------
|
||||
|
||||
This is an example storage implementation that stores all pieces in a ``std::map``,
|
||||
i.e. in RAM. It's not necessarily very useful in practice, but illustrates the
|
||||
basics of implementing a custom storage.
|
||||
|
||||
::
|
||||
|
||||
struct temp_storage : storage_interface
|
||||
{
|
||||
temp_storage(file_storage const& fs) : m_files(fs) {}
|
||||
virtual bool initialize(bool allocate_files) { return false; }
|
||||
virtual bool has_any_file() { return false; }
|
||||
virtual int read(char* buf, int slot, int offset, int size)
|
||||
{
|
||||
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(slot);
|
||||
if (i == m_file_data.end()) return 0;
|
||||
int available = i->second.size() - offset;
|
||||
if (available <= 0) return 0;
|
||||
if (available > size) available = size;
|
||||
memcpy(buf, &i->second[offset], available);
|
||||
return available;
|
||||
}
|
||||
virtual int write(const char* buf, int slot, int offset, int size)
|
||||
{
|
||||
std::vector<char>& data = m_file_data[slot];
|
||||
if (data.size() < offset + size) data.resize(offset + size);
|
||||
std::memcpy(&data[offset], buf, size);
|
||||
return size;
|
||||
}
|
||||
virtual bool rename_file(int file, std::string const& new_name)
|
||||
{ assert(false); return false; }
|
||||
virtual bool move_storage(std::string const& save_path) { return false; }
|
||||
virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) { return false; }
|
||||
virtual bool write_resume_data(entry& rd) const { return false; }
|
||||
virtual bool move_slot(int src_slot, int dst_slot) { assert(false); return false; }
|
||||
virtual bool swap_slots(int slot1, int slot2) { assert(false); return false; }
|
||||
virtual bool swap_slots3(int slot1, int slot2, int slot3) { assert(false); return false; }
|
||||
virtual size_type physical_offset(int slot, int offset)
|
||||
{ return slot * m_files.piece_length() + offset; };
|
||||
virtual sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size)
|
||||
{
|
||||
int left = piece_size - ph.offset;
|
||||
assert(left >= 0);
|
||||
if (left > 0)
|
||||
{
|
||||
std::vector<char>& data = m_file_data[slot];
|
||||
// if there are padding files, those blocks will be considered
|
||||
// completed even though they haven't been written to the storage.
|
||||
// in this case, just extend the piece buffer to its full size
|
||||
// and fill it with zeroes.
|
||||
if (data.size() < piece_size) data.resize(piece_size, 0);
|
||||
ph.h.update(&data[ph.offset], left);
|
||||
}
|
||||
return ph.h.final();
|
||||
}
|
||||
virtual bool release_files() { return false; }
|
||||
virtual bool delete_files() { return false; }
|
||||
|
||||
std::map<int, std::vector<char> > m_file_data;
|
||||
file_storage m_files;
|
||||
};
|
||||
|
||||
storage_interface* temp_storage_constructor(
|
||||
file_storage const& fs, file_storage const* mapped
|
||||
, std::string const& path, file_pool& fp
|
||||
, std::vector<boost::uint8_t> const& prio)
|
||||
{
|
||||
return new temp_storage(fs);
|
||||
}
|
||||
|
||||
magnet links
|
||||
============
|
||||
|
||||
|
|
Loading…
Reference in New Issue