forked from premiere/premiere-libtorrent
fixed bug in storage when forcing recheck while renaming a file or moving it
This commit is contained in:
parent
04d1684482
commit
a051228069
|
@ -5112,12 +5112,30 @@ storage_interface
|
||||||
=================
|
=================
|
||||||
|
|
||||||
The storage interface is a pure virtual class that can be implemented to
|
The storage interface is a pure virtual class that can be implemented to
|
||||||
change the behavior of the actual file storage. The interface looks like
|
customize how and where data for a torrent is stored. The default storage
|
||||||
this::
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
The interface looks like this::
|
||||||
|
|
||||||
struct storage_interface
|
struct storage_interface
|
||||||
{
|
{
|
||||||
virtual bool initialize(bool allocate_files) = 0;
|
virtual bool initialize(bool allocate_files) = 0;
|
||||||
|
virtual bool has_any_file() = 0;
|
||||||
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
|
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 writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0;
|
||||||
virtual int sparse_end(int start) const;
|
virtual int sparse_end(int start) const;
|
||||||
|
@ -5156,6 +5174,16 @@ it will also ``ftruncate`` all files to their target size.
|
||||||
|
|
||||||
Returning ``true`` indicates an error occurred.
|
Returning ``true`` indicates an error occurred.
|
||||||
|
|
||||||
|
has_any_file()
|
||||||
|
--------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
virtual bool has_any_file() = 0;
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
readv() writev()
|
readv() writev()
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -119,6 +119,8 @@ namespace libtorrent
|
||||||
// false return value indicates an error
|
// false return value indicates an error
|
||||||
virtual bool initialize(bool allocate_files) = 0;
|
virtual bool initialize(bool allocate_files) = 0;
|
||||||
|
|
||||||
|
virtual bool has_any_file() = 0;
|
||||||
|
|
||||||
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
|
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
|
||||||
virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
|
virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
|
||||||
|
|
||||||
|
|
|
@ -407,6 +407,7 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_any_file();
|
||||||
bool rename_file(int index, std::string const& new_filename);
|
bool rename_file(int index, std::string const& new_filename);
|
||||||
bool release_files();
|
bool release_files();
|
||||||
bool delete_files();
|
bool delete_files();
|
||||||
|
@ -581,6 +582,43 @@ namespace libtorrent
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool storage::has_any_file()
|
||||||
|
{
|
||||||
|
file_storage::iterator i = files().begin();
|
||||||
|
file_storage::iterator end = files().end();
|
||||||
|
|
||||||
|
for (; i != end; ++i)
|
||||||
|
{
|
||||||
|
bool file_exists = false;
|
||||||
|
fs::path f = m_save_path / i->path;
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#if TORRENT_USE_WPATH
|
||||||
|
fs::wpath wf = convert_to_wstring(f.string());
|
||||||
|
file_exists = exists(wf);
|
||||||
|
#elif TORRENT_USE_LOCALE_FILENAMES
|
||||||
|
file_exists = exists(convert_to_native(f.string()));
|
||||||
|
#else
|
||||||
|
file_exists = exists(f);
|
||||||
|
#endif
|
||||||
|
std::cerr << "has_any_file(): " << f << " " << (file_exists?"exists": "don't exist")
|
||||||
|
<< std::endl;
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
}
|
||||||
|
catch (boost::system::system_error& e)
|
||||||
|
{
|
||||||
|
set_error(f, e.code());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (file_exists && i->size > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool storage::rename_file(int index, std::string const& new_filename)
|
bool storage::rename_file(int index, std::string const& new_filename)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= m_files.num_files()) return true;
|
if (index < 0 || index >= m_files.num_files()) return true;
|
||||||
|
@ -1857,37 +1895,12 @@ ret:
|
||||||
|
|
||||||
int piece_manager::check_no_fastresume(std::string& error)
|
int piece_manager::check_no_fastresume(std::string& error)
|
||||||
{
|
{
|
||||||
file_storage::iterator i = m_files.begin();
|
bool has_files = m_storage->has_any_file();
|
||||||
file_storage::iterator end = m_files.end();
|
|
||||||
|
|
||||||
for (; i != end; ++i)
|
if (m_storage->error())
|
||||||
{
|
|
||||||
bool file_exists = false;
|
|
||||||
fs::path f = m_save_path / i->path;
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
#if TORRENT_USE_WPATH
|
|
||||||
fs::wpath wf = convert_to_wstring(f.string());
|
|
||||||
file_exists = exists(wf);
|
|
||||||
#elif TORRENT_USE_LOCALE_FILENAMES
|
|
||||||
file_exists = exists(convert_to_native(f.string()));
|
|
||||||
#else
|
|
||||||
file_exists = exists(f);
|
|
||||||
#endif
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
error = f.string();
|
|
||||||
error += ": ";
|
|
||||||
error += e.what();
|
|
||||||
TORRENT_ASSERT(!error.empty());
|
|
||||||
return fatal_disk_error;
|
return fatal_disk_error;
|
||||||
}
|
|
||||||
#endif
|
if (has_files)
|
||||||
if (file_exists && i->size > 0)
|
|
||||||
{
|
{
|
||||||
m_state = state_full_check;
|
m_state = state_full_check;
|
||||||
m_piece_to_slot.clear();
|
m_piece_to_slot.clear();
|
||||||
|
@ -1902,7 +1915,6 @@ ret:
|
||||||
TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces());
|
TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces());
|
||||||
return need_full_check;
|
return need_full_check;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (m_storage_mode == storage_mode_compact)
|
if (m_storage_mode == storage_mode_compact)
|
||||||
{
|
{
|
||||||
|
|
|
@ -804,10 +804,6 @@ namespace libtorrent
|
||||||
disconnect_all();
|
disconnect_all();
|
||||||
|
|
||||||
m_owning_storage->async_release_files();
|
m_owning_storage->async_release_files();
|
||||||
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
|
|
||||||
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
|
|
||||||
, m_storage_mode);
|
|
||||||
m_storage = m_owning_storage.get();
|
|
||||||
if (!m_picker) m_picker.reset(new piece_picker());
|
if (!m_picker) m_picker.reset(new piece_picker());
|
||||||
m_picker->init(m_torrent_file->piece_length() / m_block_size
|
m_picker->init(m_torrent_file->piece_length() / m_block_size
|
||||||
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
||||||
|
@ -845,10 +841,18 @@ namespace libtorrent
|
||||||
pause();
|
pause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
// if there are no files, just start
|
||||||
|
files_checked();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
set_state(torrent_status::queued_for_checking);
|
set_state(torrent_status::queued_for_checking);
|
||||||
if (should_check_files())
|
if (should_check_files())
|
||||||
queue_torrent_check();
|
queue_torrent_check();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void torrent::start_checking()
|
void torrent::start_checking()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue