premiere-libtorrent/docs/reference-Custom_Storage.html

577 lines
29 KiB
HTML

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Custom Storage</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="custom-storage">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Custom Storage</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#file-pool" id="id12">file_pool</a></li>
<li><a class="reference internal" href="#storage-interface" id="id13">storage_interface</a></li>
<li><a class="reference internal" href="#default-storage" id="id14">default_storage</a></li>
</ul>
</div>
<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&amp; 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&lt;int, std::vector&lt;char&gt; &gt;::const_iterator i = m_file_data.find(slot);
if (i == m_file_data.end()) return 0;
int available = i-&gt;second.size() - offset;
if (available &lt;= 0) return 0;
if (available &gt; size) available = size;
memcpy(buf, &amp;i-&gt;second[offset], available);
return available;
}
virtual int write(const char* buf, int slot, int offset, int size)
{
std::vector&lt;char&gt;&amp; data = m_file_data[slot];
if (data.size() &lt; offset + size) data.resize(offset + size);
std::memcpy(&amp;data[offset], buf, size);
return size;
}
virtual bool rename_file(int file, std::string const&amp; new_name)
{ assert(false); return false; }
virtual bool move_storage(std::string const&amp; save_path) { return false; }
virtual bool verify_resume_data(lazy_entry const&amp; rd, error_code&amp; error) { return false; }
virtual bool write_resume_data(entry&amp; 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&amp; ph, int piece_size)
{
int left = piece_size - ph.offset;
assert(left &gt;= 0);
if (left &gt; 0)
{
std::vector&lt;char&gt;&amp; 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() &lt; piece_size) data.resize(piece_size, 0);
ph.h.update(&amp;data[ph.offset], left);
}
return ph.h.final();
}
virtual bool release_files() { return false; }
virtual bool delete_files() { return false; }
std::map&lt;int, std::vector&lt;char&gt; &gt; m_file_data;
file_storage m_files;
};
storage_interface* temp_storage_constructor(
file_storage const&amp; fs, file_storage const* mapped
, std::string const&amp; path, file_pool&amp; fp
, std::vector&lt;boost::uint8_t&gt; const&amp; prio)
{
return new temp_storage(fs);
}
</pre>
<a name="file_pool"></a><div class="section" id="file-pool">
<h1>file_pool</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_pool.hpp">libtorrent/file_pool.hpp</a>&quot;</p>
<p>this is an internal cache of open file handles. It's primarily used by
<a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a> implementations. It provides semi weak guarantees of
not opening more file handles than specified. Given multiple threads,
each with the ability to lock a file handle (via smart pointer), there
may be windows where more file handles are open.</p>
<pre class="literal-block">
struct file_pool : boost::noncopyable
{
<strong>~file_pool</strong> ();
<strong>file_pool</strong> (int size = 40);
boost::intrusive_ptr&lt;file&gt; <strong>open_file</strong> (void* st, std::string const&amp; p
, int file_index, file_storage const&amp; fs, int m, error_code&amp; ec);
void <strong>release</strong> (void* st);
void <strong>release</strong> (void* st, int file_index);
void <strong>resize</strong> (int size);
int <strong>size_limit</strong> () const;
};
</pre>
<a name="~file_pool()"></a>
<a name="file_pool()"></a><div class="section" id="file-pool-file-pool">
<h2>~file_pool() file_pool()</h2>
<pre class="literal-block">
<strong>~file_pool</strong> ();
<strong>file_pool</strong> (int size = 40);
</pre>
<p><tt class="docutils literal">size</tt> specifies the number of allowed files handles
to hold open at any given time.</p>
<a name="open_file()"></a></div>
<div class="section" id="open-file">
<h2>open_file()</h2>
<pre class="literal-block">
boost::intrusive_ptr&lt;file&gt; <strong>open_file</strong> (void* st, std::string const&amp; p
, int file_index, file_storage const&amp; fs, int m, error_code&amp; ec);
</pre>
<p>return an open file handle to file at <tt class="docutils literal">file_index</tt> in the
<a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> <tt class="docutils literal">fs</tt> opened at save path <tt class="docutils literal">p</tt>. <tt class="docutils literal">m</tt> is the
file open mode (see <a class="reference external" href="file::open_mode_t">file::open_mode_t</a>).</p>
<a name="release()"></a></div>
<div class="section" id="release">
<h2>release()</h2>
<pre class="literal-block">
void <strong>release</strong> (void* st);
void <strong>release</strong> (void* st, int file_index);
</pre>
<p>release all files belonging to the specified <a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a> (<tt class="docutils literal">st</tt>)
the overload that takes <tt class="docutils literal">file_index</tt> releases only the file with
that index in storage <tt class="docutils literal">st</tt>.</p>
<a name="resize()"></a></div>
<div class="section" id="resize">
<h2>resize()</h2>
<pre class="literal-block">
void <strong>resize</strong> (int size);
</pre>
<p>update the allowed number of open file handles to <tt class="docutils literal">size</tt>.</p>
<a name="size_limit()"></a></div>
<div class="section" id="size-limit">
<h2>size_limit()</h2>
<pre class="literal-block">
int <strong>size_limit</strong> () const;
</pre>
<p>returns the current limit of number of allowed open file handles held
by the <a class="reference external" href="reference-Custom_Storage.html#file_pool">file_pool</a>.</p>
<a name="storage_interface"></a></div>
</div>
<div class="section" id="storage-interface">
<h1>storage_interface</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<p>The storage interface is a pure virtual class that can be implemented to
customize how and where data for a torrent is stored. The default storage
implementation uses regular files in the filesystem, mapping the files in the
torrent in the way one would assume a torrent is saved to disk. Implementing
your own storage interface makes it possible to store all data in RAM, or in
some optimized order on disk (the order the pieces are received for instance),
or saving multifile torrents in a single file in order to be able to take
advantage of optimized disk-I/O.</p>
<p>It is also possible to write a thin class that uses the default storage but
modifies some particular behavior, for instance encrypting the data before
it's written to disk, and decrypting it when it's read again.</p>
<p>The storage interface is based on slots, each slot is 'piece_size' number
of bytes. All access is done by writing and reading whole or partial
slots. One slot is one piece in the torrent, but the data in the slot
does not necessarily correspond to the piece with the same index (in
compact allocation mode it won't).</p>
<p>libtorrent comes with two built-in storage implementations; <tt class="docutils literal">default_storage</tt>
and <tt class="docutils literal">disabled_storage</tt>. Their constructor functions are called <a class="reference external" href="reference-Storage.html#default_storage_constructor()">default_storage_constructor()</a>
and <tt class="docutils literal">disabled_storage_constructor</tt> respectively. The disabled storage does
just what it sounds like. It throws away data that's written, and it
reads garbage. It's useful mostly for benchmarking and profiling purpose.</p>
<pre class="literal-block">
struct storage_interface
{
virtual bool <strong>initialize</strong> (bool allocate_files) = 0;
virtual bool <strong>has_any_file</strong> () = 0;
virtual int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual void <strong>hint_read</strong> (int, int, int);
virtual int <strong>read</strong> (char* buf, int slot, int offset, int size) = 0;
virtual int <strong>write</strong> (const char* buf, int slot, int offset, int size) = 0;
virtual size_type <strong>physical_offset</strong> (int slot, int offset) = 0;
virtual int <strong>sparse_end</strong> (int start) const;
virtual int <strong>move_storage</strong> (std::string const&amp; save_path, int flags) = 0;
virtual bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error) = 0;
virtual bool <strong>write_resume_data</strong> (entry&amp; rd) const = 0;
virtual bool <strong>move_slot</strong> (int src_slot, int dst_slot) = 0;
virtual bool <strong>swap_slots</strong> (int slot1, int slot2) = 0;
virtual bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3) = 0;
virtual bool <strong>release_files</strong> () = 0;
virtual bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename) = 0;
virtual bool <strong>delete_files</strong> () = 0;
disk_buffer_pool* <strong>disk_pool</strong> ();
session_settings const&amp; <strong>settings</strong> () const;
void <strong>set_error</strong> (std::string const&amp; file, error_code const&amp; ec) const;
error_code const&amp; <strong>error</strong> () const;
std::string const&amp; <strong>error_file</strong> () const;
virtual void <strong>clear_error</strong> ();
};
</pre>
<a name="initialize()"></a><div class="section" id="initialize">
<h2>initialize()</h2>
<pre class="literal-block">
virtual bool <strong>initialize</strong> (bool allocate_files) = 0;
</pre>
<p>This function is called when the storage is to be initialized. The default storage
will create directories and empty files at this point. If <tt class="docutils literal">allocate_files</tt> is true,
it will also <tt class="docutils literal">ftruncate</tt> all files to their target size.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="has_any_file()"></a></div>
<div class="section" id="has-any-file">
<h2>has_any_file()</h2>
<pre class="literal-block">
virtual bool <strong>has_any_file</strong> () = 0;
</pre>
<p>This function is called when first checking (or re-checking) the storage for a torrent.
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>
<a name="writev()"></a>
<a name="readv()"></a></div>
<div class="section" id="writev-readv">
<h2>writev() readv()</h2>
<pre class="literal-block">
virtual int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
</pre>
<p>These functions should read or write the data in or to the given <tt class="docutils literal">slot</tt> at the given <tt class="docutils literal">offset</tt>.
It should read or write <tt class="docutils literal">num_bufs</tt> buffers sequentially, where the size of each buffer
is specified in the buffer array <tt class="docutils literal">bufs</tt>. The <a class="reference external" href="file::iovec_t">file::iovec_t</a> type has the following members:</p>
<pre class="literal-block">
struct iovec_t
{
void* iov_base;
size_t iov_len;
};
</pre>
<p>The return value is the number of bytes actually read or written, or -1 on failure. If
it returns -1, the error code is expected to be set to</p>
<p>Every buffer in <tt class="docutils literal">bufs</tt> can be assumed to be page aligned and be of a page aligned size,
except for the last buffer of the torrent. The allocated buffer can be assumed to fit a
fully page aligned number of bytes though. This is useful when reading and writing the
last piece of a file in unbuffered mode.</p>
<p>The <tt class="docutils literal">offset</tt> is aligned to 16 kiB boundries <em>most of the time</em>, but there are rare
exceptions when it's not. Specifically if the read cache is disabled/or full and a
client requests unaligned data, or the file itself is not aligned in the torrent.
Most clients request aligned data.</p>
<a name="hint_read()"></a></div>
<div class="section" id="hint-read">
<h2>hint_read()</h2>
<pre class="literal-block">
virtual void <strong>hint_read</strong> (int, int, int);
</pre>
<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">posix_fadvise(POSIX_FADV_WILLNEED)</tt> or <tt class="docutils literal">fcntl(F_RDADVISE)</tt>.</p>
<a name="read()"></a></div>
<div class="section" id="read">
<h2>read()</h2>
<pre class="literal-block">
virtual int <strong>read</strong> (char* buf, int slot, int offset, int size) = 0;
</pre>
<p>negative return value indicates an error</p>
<a name="write()"></a></div>
<div class="section" id="write">
<h2>write()</h2>
<pre class="literal-block">
virtual int <strong>write</strong> (const char* buf, int slot, int offset, int size) = 0;
</pre>
<p>negative return value indicates an error</p>
<a name="physical_offset()"></a></div>
<div class="section" id="physical-offset">
<h2>physical_offset()</h2>
<pre class="literal-block">
virtual size_type <strong>physical_offset</strong> (int slot, int offset) = 0;
</pre>
<p>returns the offset on the physical storage medium for the
byte at offset <tt class="docutils literal">offset</tt> in slot <tt class="docutils literal">slot</tt>.</p>
<a name="sparse_end()"></a></div>
<div class="section" id="sparse-end">
<h2>sparse_end()</h2>
<pre class="literal-block">
virtual int <strong>sparse_end</strong> (int start) const;
</pre>
<p>This function is optional. It is supposed to return the first piece, starting at
<tt class="docutils literal">start</tt> that is fully contained within a data-region on disk (i.e. non-sparse
region). The purpose of this is to skip parts of files that can be known to contain
zeros when checking files.</p>
<a name="move_storage()"></a></div>
<div class="section" id="move-storage">
<h2>move_storage()</h2>
<pre class="literal-block">
virtual int <strong>move_storage</strong> (std::string const&amp; save_path, int flags) = 0;
</pre>
<p>This function should move all the files belonging to the storage to the new save_path.
The default storage moves the single file or the directory of the torrent.</p>
<p>Before moving the files, any open file handles may have to be closed, like
<tt class="docutils literal">release_files()</tt>.</p>
<p>returns one of:
| no_error = 0
| need_full_check = -1
| fatal_disk_error = -2
| file_exist = -4</p>
<a name="verify_resume_data()"></a></div>
<div class="section" id="verify-resume-data">
<h2>verify_resume_data()</h2>
<pre class="literal-block">
virtual bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error) = 0;
</pre>
<p>This function should verify the resume data <tt class="docutils literal">rd</tt> with the files
on disk. If the resume data seems to be up-to-date, return true. If
not, set <tt class="docutils literal">error</tt> to a description of what mismatched and return false.</p>
<p>The default storage may compare file sizes and time stamps of the files.</p>
<p>Returning <tt class="docutils literal">false</tt> indicates an error occurred.</p>
<a name="write_resume_data()"></a></div>
<div class="section" id="write-resume-data">
<h2>write_resume_data()</h2>
<pre class="literal-block">
virtual bool <strong>write_resume_data</strong> (entry&amp; rd) const = 0;
</pre>
<p>This function should fill in resume data, the current state of the
storage, in <tt class="docutils literal">rd</tt>. The default storage adds file timestamps and
sizes.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="move_slot()"></a></div>
<div class="section" id="move-slot">
<h2>move_slot()</h2>
<pre class="literal-block">
virtual bool <strong>move_slot</strong> (int src_slot, int dst_slot) = 0;
</pre>
<p>This function should copy or move the data in slot <tt class="docutils literal">src_slot</tt> to
the slot <tt class="docutils literal">dst_slot</tt>. This is only used in compact mode.</p>
<p>If the storage caches slots, this could be implemented more
efficient than reading and writing the data.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="swap_slots()"></a></div>
<div class="section" id="swap-slots">
<h2>swap_slots()</h2>
<pre class="literal-block">
virtual bool <strong>swap_slots</strong> (int slot1, int slot2) = 0;
</pre>
<p>This function should swap the data in <tt class="docutils literal">slot1</tt> and <tt class="docutils literal">slot2</tt>. The default
storage uses a scratch buffer to read the data into, then moving the other
slot and finally writing back the temporary slot's data</p>
<p>This is only used in compact mode.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="swap_slots3()"></a></div>
<div class="section" id="swap-slots3">
<h2>swap_slots3()</h2>
<pre class="literal-block">
virtual bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3) = 0;
</pre>
<p>This function should do a 3-way swap, or shift of the slots. <tt class="docutils literal">slot1</tt>
should move to <tt class="docutils literal">slot2</tt>, which should be moved to <tt class="docutils literal">slot3</tt> which in turn
should be moved to <tt class="docutils literal">slot1</tt>.</p>
<p>This is only used in compact mode.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="release_files()"></a></div>
<div class="section" id="release-files">
<h2>release_files()</h2>
<pre class="literal-block">
virtual bool <strong>release_files</strong> () = 0;
</pre>
<p>This function should release all the file handles that it keeps open to files
belonging to this storage. The default implementation just calls
<tt class="docutils literal"><span class="pre">file_pool::release_files(this)</span></tt>.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="rename_file()"></a></div>
<div class="section" id="rename-file">
<h2>rename_file()</h2>
<pre class="literal-block">
virtual bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename) = 0;
</pre>
<p>Rename file with index <tt class="docutils literal">file</tt> to the thame <tt class="docutils literal">new_name</tt>. If there is an error,
<tt class="docutils literal">true</tt> should be returned.</p>
<a name="delete_files()"></a></div>
<div class="section" id="delete-files">
<h2>delete_files()</h2>
<pre class="literal-block">
virtual bool <strong>delete_files</strong> () = 0;
</pre>
<p>This function should delete all files and directories belonging to this storage.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<p>The <tt class="docutils literal">disk_buffer_pool</tt> is used to allocate and free disk buffers. It has the
following members:</p>
<pre class="literal-block">
struct disk_buffer_pool : boost::noncopyable
{
char* allocate_buffer(char const* category);
void free_buffer(char* buf);
char* allocate_buffers(int blocks, char const* category);
void free_buffers(char* buf, int blocks);
int block_size() const { return m_block_size; }
void release_memory();
};
</pre>
<a name="disk_pool()"></a></div>
<div class="section" id="disk-pool">
<h2>disk_pool()</h2>
<pre class="literal-block">
disk_buffer_pool* <strong>disk_pool</strong> ();
</pre>
<p>access global disk_buffer_pool, for allocating and freeing disk buffers</p>
<a name="settings()"></a></div>
<div class="section" id="settings">
<h2>settings()</h2>
<pre class="literal-block">
session_settings const&amp; <strong>settings</strong> () const;
</pre>
<p>access global <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a></p>
<a name="set_error()"></a></div>
<div class="section" id="set-error">
<h2>set_error()</h2>
<pre class="literal-block">
void <strong>set_error</strong> (std::string const&amp; file, error_code const&amp; ec) const;
</pre>
<p>called by the storage implementation to set it into an
error state. Typically whenever a critical file operation
fails.</p>
<a name="error_file()"></a>
<a name="error()"></a></div>
<div class="section" id="error-file-error">
<h2>error_file() error()</h2>
<pre class="literal-block">
error_code const&amp; <strong>error</strong> () const;
std::string const&amp; <strong>error_file</strong> () const;
</pre>
<p>returns the currently set error code and file path associated with it,
if set.</p>
<a name="clear_error()"></a></div>
<div class="section" id="clear-error">
<h2>clear_error()</h2>
<pre class="literal-block">
virtual void <strong>clear_error</strong> ();
</pre>
<p>reset the error state to allow continuing reading and writing
to the storage</p>
<a name="default_storage"></a></div>
</div>
<div class="section" id="default-storage">
<h1>default_storage</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<p>The default implementation of <a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a>. Behaves as a normal bittorrent client.
It is possible to derive from this class in order to override some of its behavior, when
implementing a custom storage.</p>
<pre class="literal-block">
class default_storage : public storage_interface, boost::noncopyable
{
<strong>default_storage</strong> (file_storage const&amp; fs, file_storage const* mapped, std::string const&amp; path
, file_pool&amp; fp, std::vector&lt;boost::uint8_t&gt; const&amp; file_prio);
bool <strong>move_slot</strong> (int src_slot, int dst_slot);
bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename);
int <strong>read</strong> (char* buf, int slot, int offset, int size);
bool <strong>has_any_file</strong> ();
int <strong>move_storage</strong> (std::string const&amp; save_path, int flags);
bool <strong>write_resume_data</strong> (entry&amp; rd) const;
int <strong>write</strong> (char const* buf, int slot, int offset, int size);
int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* buf, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
size_type <strong>physical_offset</strong> (int slot, int offset);
bool <strong>release_files</strong> ();
bool <strong>delete_files</strong> ();
bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error);
int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3);
bool <strong>initialize</strong> (bool allocate_files);
void <strong>hint_read</strong> (int slot, int offset, int len);
bool <strong>swap_slots</strong> (int slot1, int slot2);
int <strong>sparse_end</strong> (int start) const;
file_storage const&amp; <strong>files</strong> () const;
};
</pre>
<a name="move_flags_t"></a><div class="section" id="enum-move-flags-t">
<h2>enum move_flags_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="25%" />
<col width="8%" />
<col width="67%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>always_replace_files</td>
<td>0</td>
<td>replace any files in the destination when copying
or moving the storage</td>
</tr>
<tr><td>fail_if_exist</td>
<td>1</td>
<td>if any files that we want to copy exist in the destination
exist, fail the whole operation and don't perform
any copy or move. There is an inherent race condition
in this mode. The files are checked for existence before
the operation starts. In between the check and performing
the copy, the destination files may be created, in which
case they are replaced.</td>
</tr>
<tr><td>dont_replace</td>
<td>2</td>
<td>if any file exist in the target, take those files instead
of the ones we may have in the source.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="footer">
<span>Copyright &copy; 2005-2013 Rasterbar Software.</span>
</div>
</div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1599045-1";
urchinTracker();
</script>
</div>
</body>
</html>