.. include:: header.rst

`home`__

__ reference.html

.. contents:: Table of contents
  :depth: 2
  :backlinks: none


The disk I/O can be customized in libtorrent. In previous versions, the
customization was at the level of each torrent. Now, the customization point
is at the `session`__ level. All torrents added to a `session`__ will use the same
disk I/O subsystem, as determined by the disk_io_constructor (in
`session_params`__).

This allows the disk subsystem to also customize threading and disk job
management.

To customize the disk subsystem, implement `disk_interface`__ and provide a
factory function to the `session`__ constructor (via `session_params`__).

Example use:

__ reference-Session.html#session
__ reference-Session.html#session
__ reference-Session.html#session_params
__ reference-Custom_Storage.html#disk_interface
__ reference-Session.html#session
__ reference-Session.html#session_params

.. include:: ../examples/custom_storage.cpp
	:code: c++
	:tab-width: 2
	:start-after: -- example begin
	:end-before: // -- example end

.. raw:: html

	<a name="settings_interface"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+settings_interface&labels=documentation&body=Documentation+under+heading+%22class+settings_interface%22+could+be+improved">report issue</a>]</span>



settings_interface
------------------

Declared in "`libtorrent/settings_pack.hpp`__"


__ include/libtorrent/settings_pack.hpp

the common interface to `settings_pack`__ and the internal representation of
settings.


__ reference-Settings.html#settings_pack


.. parsed-literal::
	

	struct settings_interface
	{
	   virtual void **set_bool** (int name, bool val) = 0;
	   virtual void **set_int** (int name, int val) = 0;
	   virtual void **set_str** (int name, std\:\:string val) = 0;
	   virtual bool **has_val** (int name) const = 0;
	   virtual std::string const& **get_str** (int name) const = 0;
	   virtual int **get_int** (int name) const = 0;
	   virtual bool **get_bool** (int name) const = 0;
	};

.. raw:: html

	<a name="buffer_allocator_interface"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+buffer_allocator_interface&labels=documentation&body=Documentation+under+heading+%22class+buffer_allocator_interface%22+could+be+improved">report issue</a>]</span>



buffer_allocator_interface
--------------------------

Declared in "`libtorrent/disk_buffer_holder.hpp`__"


__ include/libtorrent/disk_buffer_holder.hpp

the interface for freeing disk buffers, used by the `disk_buffer_holder`__.
when implementing `disk_interface`__, this must also be implemented in order
to return disk buffers back to libtorrent


__ reference-Custom_Storage.html#disk_buffer_holder
__ reference-Custom_Storage.html#disk_interface


.. parsed-literal::
	

	struct buffer_allocator_interface
	{
	   virtual void **free_disk_buffer** (char\* b) = 0;
	};

.. raw:: html

	<a name="disk_buffer_holder"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+disk_buffer_holder&labels=documentation&body=Documentation+under+heading+%22class+disk_buffer_holder%22+could+be+improved">report issue</a>]</span>



disk_buffer_holder
------------------

Declared in "`libtorrent/disk_buffer_holder.hpp`__"


__ include/libtorrent/disk_buffer_holder.hpp

The disk buffer holder acts like a ``unique_ptr`` that frees a disk buffer
when it's destructed

If this buffer holder is moved-from, default constructed or reset,
``data()`` will return nullptr.




.. parsed-literal::
	

	struct disk_buffer_holder
	{
	   disk_buffer_holder& **operator=** (disk\_buffer\_holder&&) & noexcept;
	   **disk_buffer_holder** (disk\_buffer\_holder&&) noexcept;
	   disk_buffer_holder& **operator=** (disk\_buffer\_holder const&) = delete;
	   **disk_buffer_holder** (disk\_buffer\_holder const&) = delete;
	   **disk_buffer_holder** (buffer\_allocator\_interface& alloc
	      , char\* buf, int sz) noexcept;
	   **disk_buffer_holder** () noexcept = default;
	   **~disk_buffer_holder** ();
	   char\* **data** () const noexcept;
	   void **reset** ();
	   void **swap** (disk\_buffer\_holder& h) noexcept;
	   bool **is_mutable** () const noexcept;
	   explicit operator **bool** () const noexcept;
	   std::ptrdiff_t **size** () const;
	};

.. raw:: html

	<a name="disk_buffer_holder()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bdisk_buffer_holder%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bdisk_buffer_holder%28%29%5D%22+could+be+improved">report issue</a>]</span>



disk_buffer_holder()
....................

.. parsed-literal::
	
	**disk_buffer_holder** (buffer\_allocator\_interface& alloc
	      , char\* buf, int sz) noexcept;
	

construct a buffer holder that will free the held buffer
using a disk buffer pool directly (there's only one
disk_buffer_pool per `session`__)


__ reference-Session.html#session

.. raw:: html

	<a name="disk_buffer_holder()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bdisk_buffer_holder%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bdisk_buffer_holder%28%29%5D%22+could+be+improved">report issue</a>]</span>



disk_buffer_holder()
....................

.. parsed-literal::
	
	**disk_buffer_holder** () noexcept = default;
	

default construct a holder that does not own any buffer



.. raw:: html

	<a name="~disk_buffer_holder()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5B~disk_buffer_holder%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5B~disk_buffer_holder%28%29%5D%22+could+be+improved">report issue</a>]</span>



~disk_buffer_holder()
.....................

.. parsed-literal::
	
	**~disk_buffer_holder** ();
	

frees disk buffer held by this object



.. raw:: html

	<a name="data()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bdata%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bdata%28%29%5D%22+could+be+improved">report issue</a>]</span>



data()
......

.. parsed-literal::
	
	char\* **data** () const noexcept;
	

return a pointer to the held buffer, if any. Otherwise returns nullptr.



.. raw:: html

	<a name="reset()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Breset%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Breset%28%29%5D%22+could+be+improved">report issue</a>]</span>



reset()
.......

.. parsed-literal::
	
	void **reset** ();
	

free the held disk buffer, if any, and clear the holder. This sets the
holder object to a default-constructed state



.. raw:: html

	<a name="swap()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bswap%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bswap%28%29%5D%22+could+be+improved">report issue</a>]</span>



swap()
......

.. parsed-literal::
	
	void **swap** (disk\_buffer\_holder& h) noexcept;
	

swap pointers of two disk buffer holders.



.. raw:: html

	<a name="is_mutable()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bis_mutable%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bis_mutable%28%29%5D%22+could+be+improved">report issue</a>]</span>



is_mutable()
............

.. parsed-literal::
	
	bool **is_mutable** () const noexcept;
	

if this returns true, the buffer may not be modified in place



.. raw:: html

	<a name="bool()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_buffer_holder%3A%3A%5Bbool%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_buffer_holder%3A%3A%5Bbool%28%29%5D%22+could+be+improved">report issue</a>]</span>



bool()
......

.. parsed-literal::
	
	explicit operator **bool** () const noexcept;
	

implicitly convertible to true if the object is currently holding a
buffer



.. raw:: html

	<a name="disk_observer"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+disk_observer&labels=documentation&body=Documentation+under+heading+%22class+disk_observer%22+could+be+improved">report issue</a>]</span>



disk_observer
-------------

Declared in "`libtorrent/disk_observer.hpp`__"


__ include/libtorrent/disk_observer.hpp





.. parsed-literal::
	

	struct disk_observer
	{
	   virtual void **on_disk** () = 0;
	};

.. raw:: html

	<a name="on_disk()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_observer%3A%3A%5Bon_disk%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_observer%3A%3A%5Bon_disk%28%29%5D%22+could+be+improved">report issue</a>]</span>



on_disk()
.........

.. parsed-literal::
	
	virtual void **on_disk** () = 0;
	

called when the disk cache size has dropped
below the low watermark again and we can
resume downloading from peers



.. raw:: html

	<a name="open_file_state"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+open_file_state&labels=documentation&body=Documentation+under+heading+%22class+open_file_state%22+could+be+improved">report issue</a>]</span>



open_file_state
---------------

Declared in "`libtorrent/disk_interface.hpp`__"


__ include/libtorrent/disk_interface.hpp

this contains information about a file that's currently open by the
libtorrent disk I/O subsystem. It's associated with a single torrent.




.. parsed-literal::
	

	struct open_file_state
	{
	   file_index_t file_index;
	   file_open_mode_t open_mode;
	   time_point last_use;
	};

.. raw:: html

	<a name="file_index"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:open_file_state%3A%3A%5Bfile_index%5D&labels=documentation&body=Documentation+under+heading+%22open_file_state%3A%3A%5Bfile_index%5D%22+could+be+improved">report issue</a>]</span>


file_index
	the index of the file this `entry`__ refers to into the ``file_storage``
	file list of this torrent. This starts indexing at 0.
	

__ reference-Bencoding.html#entry

.. raw:: html

	<a name="open_mode"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:open_file_state%3A%3A%5Bopen_mode%5D&labels=documentation&body=Documentation+under+heading+%22open_file_state%3A%3A%5Bopen_mode%5D%22+could+be+improved">report issue</a>]</span>


open_mode
	``open_mode`` is a bitmask of the file flags this file is currently
	opened with. For possible flags, see `file_open_mode_t`__.
	
	Note that the read/write mode is not a bitmask. The two least significant bits are used
	to represent the read/write mode. Those bits can be masked out using the ``rw_mask`` constant.
	

__ reference-Custom_Storage.html#file_open_mode_t

.. raw:: html

	<a name="last_use"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:open_file_state%3A%3A%5Blast_use%5D&labels=documentation&body=Documentation+under+heading+%22open_file_state%3A%3A%5Blast_use%5D%22+could+be+improved">report issue</a>]</span>


last_use
	a (high precision) timestamp of when the file was last used.
	


.. raw:: html

	<a name="disk_interface"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+disk_interface&labels=documentation&body=Documentation+under+heading+%22class+disk_interface%22+could+be+improved">report issue</a>]</span>



disk_interface
--------------

Declared in "`libtorrent/disk_interface.hpp`__"


__ include/libtorrent/disk_interface.hpp

The `disk_interface`__ is the customization point for disk I/O in libtorrent.
implement this interface and provide a factory function to the `session`__ constructor
use custom disk I/O. All functions on the disk subsystem (implementing
`disk_interface`__) are called from within libtorrent's network thread. For
disk I/O to be performed in a separate thread, the disk subsystem has to
manage that itself.

Although the functions are called ``async_*``, they do not technically
*have* to be asynchronous, but they support being asynchronous, by
expecting the result passed back into a callback. The callbacks must be
posted back onto the network thread via the io_context object passed into
the constructor. The callbacks will be run in the network thread.


__ reference-Custom_Storage.html#disk_interface
__ reference-Session.html#session
__ reference-Custom_Storage.html#disk_interface


.. parsed-literal::
	

	struct disk_interface
	{
	   virtual storage_holder **new_torrent** (storage\_params const& p
	      , std\:\:shared\_ptr<void> const& torrent) = 0;
	   virtual void **remove_torrent** (storage\_index\_t) = 0;
	   virtual bool **async_write** (storage\_index\_t storage, peer\_request const& r
	      , char const\* buf, std\:\:shared\_ptr<disk\_observer> o
	      , std\:\:function<void(storage\_error const&)> handler
	      , disk\_job\_flags\_t flags = {}) = 0;
	   virtual void **async_read** (storage\_index\_t storage, peer\_request const& r
	      , std\:\:function<void(disk\_buffer\_holder, storage\_error const&)> handler
	      , disk\_job\_flags\_t flags = {}) = 0;
	   virtual void **async_hash** (storage\_index\_t storage, piece\_index\_t piece, span<sha256\_hash> v2
	      , disk\_job\_flags\_t flags
	      , std\:\:function<void(piece\_index\_t, sha1\_hash const&, storage\_error const&)> handler) = 0;
	   virtual void **async_hash2** (storage\_index\_t storage, piece\_index\_t piece, int offset, disk\_job\_flags\_t flags
	      , std\:\:function<void(piece\_index\_t, sha256\_hash const&, storage\_error const&)> handler) = 0;
	   virtual void **async_move_storage** (storage\_index\_t storage, std\:\:string p, move\_flags\_t flags
	      , std\:\:function<void(status\_t, std\:\:string const&, storage\_error const&)> handler) = 0;
	   virtual void **async_release_files** (storage\_index\_t storage
	      , std\:\:function<void()> handler = std\:\:function<void()>()) = 0;
	   virtual void **async_check_files** (storage\_index\_t storage
	      , add\_torrent\_params const\* resume\_data
	      , aux\:\:vector<std\:\:string, file\_index\_t> links
	      , std\:\:function<void(status\_t, storage\_error const&)> handler) = 0;
	   virtual void **async_stop_torrent** (storage\_index\_t storage
	      , std\:\:function<void()> handler = std\:\:function<void()>()) = 0;
	   virtual void **async_rename_file** (storage\_index\_t storage
	      , file\_index\_t index, std\:\:string name
	      , std\:\:function<void(std\:\:string const&, file\_index\_t, storage\_error const&)> handler) = 0;
	   virtual void **async_delete_files** (storage\_index\_t storage, remove\_flags\_t options
	      , std\:\:function<void(storage\_error const&)> handler) = 0;
	   virtual void **async_set_file_priority** (storage\_index\_t storage
	      , aux\:\:vector<download\_priority\_t, file\_index\_t> prio
	      , std\:\:function<void(storage\_error const&
	      , aux\:\:vector<download\_priority\_t, file\_index\_t>)> handler) = 0;
	   virtual void **async_clear_piece** (storage\_index\_t storage, piece\_index\_t index
	      , std\:\:function<void(piece\_index\_t)> handler) = 0;
	   virtual void **update_stats_counters** (counters& c) const = 0;
	   virtual std::vector<open_file_state> **get_status** (storage\_index\_t) const = 0;
	   virtual void **abort** (bool wait) = 0;
	   virtual void **submit_jobs** () = 0;
	   virtual void **settings_updated** () = 0;
	
	   static constexpr disk_job_flags_t **force_copy**  = 0_bit;
	   static constexpr disk_job_flags_t **sequential_access**  = 3_bit;
	   static constexpr disk_job_flags_t **volatile_read**  = 4_bit;
	   static constexpr disk_job_flags_t **v1_hash**  = 5_bit;
	   static constexpr disk_job_flags_t **flush_piece**  = 7_bit;
	};

.. raw:: html

	<a name="new_torrent()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bnew_torrent%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bnew_torrent%28%29%5D%22+could+be+improved">report issue</a>]</span>



new_torrent()
.............

.. parsed-literal::
	
	virtual storage_holder **new_torrent** (storage\_params const& p
	      , std\:\:shared\_ptr<void> const& torrent) = 0;
	

this is called when a new torrent is added. The shared_ptr can be
used to hold the internal torrent object alive as long as there are
outstanding disk operations on the storage.
The returned `storage_holder`__ is an owning reference to the underlying
storage that was just created. It is fundamentally a storage_index_t


__ reference-Custom_Storage.html#storage_holder

.. raw:: html

	<a name="remove_torrent()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bremove_torrent%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bremove_torrent%28%29%5D%22+could+be+improved">report issue</a>]</span>



remove_torrent()
................

.. parsed-literal::
	
	virtual void **remove_torrent** (storage\_index\_t) = 0;
	

remove the storage with the specified index. This is not expected to
delete any files from disk, just to clean up any resources associated
with the specified storage.



.. raw:: html

	<a name="async_write()"></a>
	<a name="async_read()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_write%28%29+async_read%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_write%28%29+async_read%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_write() async_read()
..........................

.. parsed-literal::
	
	virtual bool **async_write** (storage\_index\_t storage, peer\_request const& r
	      , char const\* buf, std\:\:shared\_ptr<disk\_observer> o
	      , std\:\:function<void(storage\_error const&)> handler
	      , disk\_job\_flags\_t flags = {}) = 0;
	virtual void **async_read** (storage\_index\_t storage, peer\_request const& r
	      , std\:\:function<void(disk\_buffer\_holder, storage\_error const&)> handler
	      , disk\_job\_flags\_t flags = {}) = 0;
	

perform a read or write operation from/to the specified storage
index and the specified request. When the operation completes, call
handler possibly with a `disk_buffer_holder`__, holding the buffer with
the result. Flags may be set to affect the read operation. See
disk_job_flags_t.

The `disk_observer`__ is a callback to indicate that
the store buffer/disk write queue is below the watermark to let peers
start writing buffers to disk again. When ``async_write()`` returns
``true``, indicating the write queue is full, the peer will stop
further writes and wait for the passed-in ``disk_observer`` to be
notified before resuming.

Note that for ``async_read``, the `peer_request`__ (``r``) is not
necessarily aligned to blocks (but it is most of the time). However,
all writes (passed to ``async_write``) are guaranteed to be block
aligned.


__ reference-Custom_Storage.html#disk_buffer_holder
__ reference-Custom_Storage.html#disk_observer
__ reference-Core.html#peer_request

.. raw:: html

	<a name="async_hash()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_hash%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_hash%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_hash()
............

.. parsed-literal::
	
	virtual void **async_hash** (storage\_index\_t storage, piece\_index\_t piece, span<sha256\_hash> v2
	      , disk\_job\_flags\_t flags
	      , std\:\:function<void(piece\_index\_t, sha1\_hash const&, storage\_error const&)> handler) = 0;
	

Compute hash(es) for the specified piece. Unless the v1_hash flag is
set (in ``flags``), the SHA-1 hash of the whole piece does not need
to be computed.

The `v2` span is optional and can be empty, which means v2 hashes
should not be computed. If v2 is non-empty it must be at least large
enough to hold all v2 blocks in the piece, and this function will
fill in the span with the SHA-256 block hashes of the piece.



.. raw:: html

	<a name="async_hash2()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_hash2%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_hash2%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_hash2()
.............

.. parsed-literal::
	
	virtual void **async_hash2** (storage\_index\_t storage, piece\_index\_t piece, int offset, disk\_job\_flags\_t flags
	      , std\:\:function<void(piece\_index\_t, sha256\_hash const&, storage\_error const&)> handler) = 0;
	

computes the v2 hash (SHA-256) of a single block. The block at
``offset`` in piece ``piece``.



.. raw:: html

	<a name="async_move_storage()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_move_storage%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_move_storage%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_move_storage()
....................

.. parsed-literal::
	
	virtual void **async_move_storage** (storage\_index\_t storage, std\:\:string p, move\_flags\_t flags
	      , std\:\:function<void(status\_t, std\:\:string const&, storage\_error const&)> handler) = 0;
	

called to request the files for the specified storage/torrent be
moved to a new location. It is the disk I/O object's responsibility
to synchronize this with any currently outstanding disk operations to
the storage. Whether files are replaced at the destination path or
not is controlled by ``flags`` (see `move_flags_t`__).


__ reference-Storage.html#move_flags_t

.. raw:: html

	<a name="async_release_files()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_release_files%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_release_files%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_release_files()
.....................

.. parsed-literal::
	
	virtual void **async_release_files** (storage\_index\_t storage
	      , std\:\:function<void()> handler = std\:\:function<void()>()) = 0;
	

This is called on disk I/O objects to request they close all open
files for the specified storage/torrent. If file handles are not
pooled/cached, it can be a no-op. For truly asynchronous disk I/O,
this should provide at least one point in time when all files are
closed. It is possible that later asynchronous operations will
re-open some of the files, by the time this completion handler is
called, that's fine.



.. raw:: html

	<a name="async_check_files()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_check_files%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_check_files%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_check_files()
...................

.. parsed-literal::
	
	virtual void **async_check_files** (storage\_index\_t storage
	      , add\_torrent\_params const\* resume\_data
	      , aux\:\:vector<std\:\:string, file\_index\_t> links
	      , std\:\:function<void(status\_t, storage\_error const&)> handler) = 0;
	

this is called when torrents are added to validate their resume data
against the files on disk. This function is expected to do a few things:

if ``links`` is non-empty, it contains a string for each file in the
torrent. The string being a path to an existing identical file. The
default behavior is to create hard links of those files into the
storage of the new torrent (specified by ``storage``). An empty
string indicates that there is no known identical file. This is part
of the "mutable torrent" feature, where files can be reused from
other torrents.

The ``resume_data`` points the resume data passed in by the client.

If the ``resume_data->flags`` field has the seed_mode flag set, all
files/pieces are expected to be on disk already. This should be
verified. Not just the existence of the file, but also that it has
the correct size.

Any file with a piece set in the ``resume_data->have_pieces`` bitmask
should exist on disk, this should be verified. Pad files and files
with zero priority may be skipped.



.. raw:: html

	<a name="async_stop_torrent()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_stop_torrent%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_stop_torrent%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_stop_torrent()
....................

.. parsed-literal::
	
	virtual void **async_stop_torrent** (storage\_index\_t storage
	      , std\:\:function<void()> handler = std\:\:function<void()>()) = 0;
	

This is called when a torrent is stopped. It gives the disk I/O
object an opportunity to flush any data to disk that's currently kept
cached. This function should at least do the same thing as
`async_release_files()`__.


__ reference-Custom_Storage.html#async_release_files()

.. raw:: html

	<a name="async_rename_file()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_rename_file%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_rename_file%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_rename_file()
...................

.. parsed-literal::
	
	virtual void **async_rename_file** (storage\_index\_t storage
	      , file\_index\_t index, std\:\:string name
	      , std\:\:function<void(std\:\:string const&, file\_index\_t, storage\_error const&)> handler) = 0;
	

This function is called when the name of a file in the specified
storage has been requested to be renamed. The disk I/O object is
responsible for renaming the file without racing with other
potentially outstanding operations against the file (such as read,
write, move, etc.).



.. raw:: html

	<a name="async_delete_files()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_delete_files%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_delete_files%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_delete_files()
....................

.. parsed-literal::
	
	virtual void **async_delete_files** (storage\_index\_t storage, remove\_flags\_t options
	      , std\:\:function<void(storage\_error const&)> handler) = 0;
	

This function is called when some file(s) on disk have been requested
to be removed by the client. ``storage`` indicates which torrent is
referred to. See `session_handle`__ for ``remove_flags_t`` flags
indicating which files are to be removed.
e.g. `session_handle::delete_files`__ - delete all files
`session_handle::delete_partfile`__ - only delete part file.


__ reference-Session.html#session_handle
__ reference-Session.html#delete_files
__ reference-Session.html#delete_partfile

.. raw:: html

	<a name="async_set_file_priority()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_set_file_priority%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_set_file_priority%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_set_file_priority()
.........................

.. parsed-literal::
	
	virtual void **async_set_file_priority** (storage\_index\_t storage
	      , aux\:\:vector<download\_priority\_t, file\_index\_t> prio
	      , std\:\:function<void(storage\_error const&
	      , aux\:\:vector<download\_priority\_t, file\_index\_t>)> handler) = 0;
	

This is called to set the priority of some or all files. Changing the
priority from or to 0 may involve moving data to and from the
partfile. The disk I/O object is responsible for correctly
synchronizing this work to not race with any potentially outstanding
asynchronous operations affecting these files.

``prio`` is a vector of the file priority for all files. If it's
shorter than the total number of files in the torrent, they are
assumed to be set to the default priority.



.. raw:: html

	<a name="async_clear_piece()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Basync_clear_piece%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Basync_clear_piece%28%29%5D%22+could+be+improved">report issue</a>]</span>



async_clear_piece()
...................

.. parsed-literal::
	
	virtual void **async_clear_piece** (storage\_index\_t storage, piece\_index\_t index
	      , std\:\:function<void(piece\_index\_t)> handler) = 0;
	

This is called when a piece fails the hash check, to ensure there are
no outstanding disk operations to the piece before blocks are
re-requested from peers to overwrite the existing blocks. The disk I/O
object does not need to perform any action other than synchronize
with all outstanding disk operations to the specified piece before
posting the result back.



.. raw:: html

	<a name="update_stats_counters()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bupdate_stats_counters%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bupdate_stats_counters%28%29%5D%22+could+be+improved">report issue</a>]</span>



update_stats_counters()
.......................

.. parsed-literal::
	
	virtual void **update_stats_counters** (counters& c) const = 0;
	

`update_stats_counters()`__ is called to give the disk storage an
opportunity to update gauges in the ``c`` stats `counters`__, that aren't
updated continuously as operations are performed. This is called
before a snapshot of the `counters`__ are passed to the client.


__ reference-Custom_Storage.html#update_stats_counters()
__ reference-Stats.html#counters
__ reference-Stats.html#counters

.. raw:: html

	<a name="get_status()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bget_status%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bget_status%28%29%5D%22+could+be+improved">report issue</a>]</span>



get_status()
............

.. parsed-literal::
	
	virtual std::vector<open_file_state> **get_status** (storage\_index\_t) const = 0;
	

Return a list of all the files that are currently open for the
specified storage/torrent. This is is just used for the client to
query the currently open files, and which modes those files are open
in.



.. raw:: html

	<a name="abort()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Babort%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Babort%28%29%5D%22+could+be+improved">report issue</a>]</span>



abort()
.......

.. parsed-literal::
	
	virtual void **abort** (bool wait) = 0;
	

this is called when the `session`__ is starting to shut down. The disk
I/O object is expected to flush any outstanding write jobs, cancel
hash jobs and initiate tearing down of any internal threads. If
``wait`` is true, this should be asynchronous. i.e. this call should
not return until all threads have stopped and all jobs have either
been aborted or completed and the disk I/O object is ready to be
destructed.


__ reference-Session.html#session

.. raw:: html

	<a name="submit_jobs()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bsubmit_jobs%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bsubmit_jobs%28%29%5D%22+could+be+improved">report issue</a>]</span>



submit_jobs()
.............

.. parsed-literal::
	
	virtual void **submit_jobs** () = 0;
	

This will be called after a batch of disk jobs has been issues (via
the ``async_*`` ). It gives the disk I/O object an opportunity to
notify any potential condition variables to wake up the disk
thread(s). The ``async_*`` calls can of course also notify condition
variables, but doing it in this call allows for batching jobs, by
issuing the notification once for a collection of jobs.



.. raw:: html

	<a name="settings_updated()"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bsettings_updated%28%29%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bsettings_updated%28%29%5D%22+could+be+improved">report issue</a>]</span>



settings_updated()
..................

.. parsed-literal::
	
	virtual void **settings_updated** () = 0;
	

This is called to notify the disk I/O object that the settings have
been updated. In the disk io constructor, a `settings_interface`__
reference is passed in. Whenever these settings are updated, this
function is called to allow the disk I/O object to react to any
changed settings relevant to its operations.


__ reference-Custom_Storage.html#settings_interface

.. raw:: html

	<a name="force_copy"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bforce_copy%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bforce_copy%5D%22+could+be+improved">report issue</a>]</span>


force_copy
	force making a copy of the cached block, rather than getting a
	reference to a block already in the cache. This is used the block is
	expected to be overwritten very soon, by async_write()`, and we need
	access to the previous content.
	


.. raw:: html

	<a name="sequential_access"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bsequential_access%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bsequential_access%5D%22+could+be+improved">report issue</a>]</span>


sequential_access
	hint that there may be more disk operations with sequential access to
	the file
	


.. raw:: html

	<a name="volatile_read"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bvolatile_read%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bvolatile_read%5D%22+could+be+improved">report issue</a>]</span>


volatile_read
	don't keep the read block in cache. This is a hint that this block is
	unlikely to be read again anytime soon, and caching it would be
	wasteful.
	


.. raw:: html

	<a name="v1_hash"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bv1_hash%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bv1_hash%5D%22+could+be+improved">report issue</a>]</span>


v1_hash
	compute a v1 piece hash. This is only used by the `async_hash()`__ call.
	If this flag is not set in the `async_hash()`__ call, the SHA-1 piece
	hash does not need to be computed.
	

__ reference-Custom_Storage.html#async_hash()
__ reference-Custom_Storage.html#async_hash()

.. raw:: html

	<a name="flush_piece"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:disk_interface%3A%3A%5Bflush_piece%5D&labels=documentation&body=Documentation+under+heading+%22disk_interface%3A%3A%5Bflush_piece%5D%22+could+be+improved">report issue</a>]</span>


flush_piece
	this flag instructs a hash job that we just completed this piece, and
	it should be flushed to disk
	


.. raw:: html

	<a name="storage_holder"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:class+storage_holder&labels=documentation&body=Documentation+under+heading+%22class+storage_holder%22+could+be+improved">report issue</a>]</span>



storage_holder
--------------

Declared in "`libtorrent/disk_interface.hpp`__"


__ include/libtorrent/disk_interface.hpp

a unique, owning, reference to the storage of a torrent in a disk io
subsystem (class that implements `disk_interface`__). This is held by the
internal libtorrent torrent object to tie the storage object allocated
for a torrent to the lifetime of the internal torrent object. When a
torrent is removed from the `session`__, this holder is destructed and will
inform the disk object.


__ reference-Custom_Storage.html#disk_interface
__ reference-Session.html#session


.. parsed-literal::
	

	struct storage_holder
	{
	   **~storage_holder** ();
	   **storage_holder** (storage\_index\_t idx, disk\_interface& disk\_io);
	   **storage_holder** () = default;
	   explicit operator **bool** () const;
	   operator **storage_index_t** () const;
	   void **reset** ();
	   **storage_holder** (storage\_holder const&) = delete;
	   storage_holder& **operator=** (storage\_holder const&) = delete;
	   **storage_holder** (storage\_holder&& rhs) noexcept;
	   storage_holder& **operator=** (storage\_holder&& rhs) noexcept;
	};

.. raw:: html

	<a name="file_open_mode_t"></a>

.. raw:: html

	<span class="report-issue">[<a href="http://github.com/arvidn/libtorrent/issues/new?title=docs:file_open_mode_t&labels=documentation&body=Documentation+under+heading+%22file_open_mode_t%22+could+be+improved">report issue</a>]</span>



file_open_mode_t
----------------

Declared in "`libtorrent/disk_interface.hpp`__"


__ include/libtorrent/disk_interface.hpp

.. raw:: html

	<a name="file_open_mode_t::read_only"></a>

read_only
	open the file for reading only
	


.. raw:: html

	<a name="file_open_mode_t::write_only"></a>

write_only
	open the file for writing only
	


.. raw:: html

	<a name="file_open_mode_t::read_write"></a>

read_write
	open the file for reading and writing
	


.. raw:: html

	<a name="file_open_mode_t::rw_mask"></a>

rw_mask
	the mask for the bits determining read or write mode
	


.. raw:: html

	<a name="file_open_mode_t::sparse"></a>

sparse
	open the file in sparse mode (if supported by the
	filesystem).
	


.. raw:: html

	<a name="file_open_mode_t::no_atime"></a>

no_atime
	don't update the access timestamps on the file (if
	supported by the operating system and filesystem).
	this generally improves disk performance.
	


.. raw:: html

	<a name="file_open_mode_t::random_access"></a>

random_access
	open the file for random access. This disables read-ahead
	logic
	


.. raw:: html

	<a name="file_open_mode_t::mmapped"></a>

mmapped
	the file is memory mapped
	





.. _`BEP 3`: https://www.bittorrent.org/beps/bep_0003.html
.. _`BEP 17`: https://www.bittorrent.org/beps/bep_0017.html
.. _extensions: manual-ref.html#extensions
.. _`BEP 52`: https://www.bittorrent.org/beps/bep_0052.html
.. _`BEP 19`: https://www.bittorrent.org/beps/bep_0019.html
.. _`BEP 38`: https://www.bittorrent.org/beps/bep_0038.html
.. _`rate based choking`: manual-ref.html#rate-based-choking
.. _`BEP 42`: https://www.bittorrent.org/beps/bep_0042.html
