first version of 'part file' support. Can currently only be set when starting torrent
This commit is contained in:
parent
b00096ad33
commit
769d8aefe2
|
@ -918,7 +918,7 @@ The ``torrent_info`` has the following synopsis::
|
|||
typedef std::vector<file_entry>::const_reverse_iterator
|
||||
reverse_file_iterator;
|
||||
|
||||
bool remap_files(std::vector<std::pair<std::string, libtorrent::size_type> > const& map);
|
||||
bool remap_files(std::vector<file_entry> const& map);
|
||||
|
||||
file_iterator begin_files(bool storage = false) const;
|
||||
file_iterator end_files(bool storage = false) const;
|
||||
|
@ -1052,18 +1052,20 @@ remap_files()
|
|||
|
||||
::
|
||||
|
||||
bool remap_files(std::vector<std::pair<std::string, libtorrent::size_type> > const& map);
|
||||
bool remap_files(std::vector<file_entry> const& map);
|
||||
|
||||
This call will create a new mapping of the data in this torrent to other files. The
|
||||
``torrent_info`` maintains 2 views of the file storage. One that is true to the torrent
|
||||
file, and one that represents what is actually saved on disk. This call will change
|
||||
what the files on disk are called.
|
||||
|
||||
The each entry in the vector ``map`` is a pair of a (relative) file path and the file's size.
|
||||
The each entry in the vector ``map`` is a ``file_entry``. The only fields in this struct
|
||||
that are used in this case are ``path``, ``size`` and ``file_base``.
|
||||
|
||||
The return value indicates if the remap was successful or not. True means success and
|
||||
false means failure. The sum of all the files passed in through ``map`` has to be exactly
|
||||
the same as the total_size of the torrent.
|
||||
the same as the total_size of the torrent. If the number of bytes that are mapped do not
|
||||
match, false will be returned (this is the only case this function may fail).
|
||||
|
||||
Changing this mapping for an existing torrent will not move or rename files. If some files
|
||||
should be renamed, this can be done before the torrent is added.
|
||||
|
@ -1097,6 +1099,7 @@ remapped, they may differ. For more info, see `remap_files()`_.
|
|||
boost::filesystem::path path;
|
||||
size_type offset;
|
||||
size_type size;
|
||||
size_type file_base;
|
||||
boost::shared_ptr<const boost::filesystem::path> orig_path;
|
||||
};
|
||||
|
||||
|
@ -1108,6 +1111,13 @@ The filenames are encoded with UTF-8.
|
|||
of the file within the torrent. i.e. the sum of all the sizes of the files
|
||||
before it in the list.
|
||||
|
||||
``file_base`` is the offset in the file where the storage should start. The normal
|
||||
case is to have this set to 0, so that the storage starts saving data at the start
|
||||
if the file. In cases where multiple files are mapped into the same file though,
|
||||
the ``file_base`` should be set to an offset so that the different regions do
|
||||
not overlap. This is used when mapping "unselected" files into a so-called part
|
||||
file.
|
||||
|
||||
``orig_path`` is set to 0 in case the path element is an exact copy of that
|
||||
found in the metadata. In case the path in the original metadata was
|
||||
incorrectly encoded, and had to be fixed in order to be acceptable utf-8,
|
||||
|
|
|
@ -69,9 +69,15 @@ namespace libtorrent
|
|||
|
||||
struct TORRENT_EXPORT file_entry
|
||||
{
|
||||
file_entry(): offset(0), size(0), file_base(0) {}
|
||||
|
||||
fs::path path;
|
||||
size_type offset; // the offset of this file inside the torrent
|
||||
size_type size; // the size of this file
|
||||
// the offset in the file where the storage starts.
|
||||
// This is always 0 unless parts of the torrent is
|
||||
// compressed into a single file, such as a so-called part file.
|
||||
size_type file_base;
|
||||
// if the path was incorrectly encoded, this is
|
||||
// the original corrupt encoded string. It is
|
||||
// preserved in order to be able to reproduce
|
||||
|
@ -117,7 +123,7 @@ namespace libtorrent
|
|||
void add_file(fs::path file, size_type size);
|
||||
void add_url_seed(std::string const& url);
|
||||
|
||||
bool remap_files(std::vector<std::pair<std::string, libtorrent::size_type> > const& map);
|
||||
bool remap_files(std::vector<file_entry> const& map);
|
||||
|
||||
std::vector<file_slice> map_block(int piece, size_type offset
|
||||
, int size, bool storage = false) const;
|
||||
|
@ -271,7 +277,7 @@ namespace libtorrent
|
|||
|
||||
// this vector is typically empty. If it is not
|
||||
// empty, it means the user has re-mapped the
|
||||
// files in this torrent to diffefrent names
|
||||
// files in this torrent to different names
|
||||
// on disk. This is only used when reading and
|
||||
// writing the disk.
|
||||
std::vector<file_entry> m_remapped_files;
|
||||
|
|
|
@ -768,10 +768,10 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type new_pos = in->seek(file_offset);
|
||||
if (new_pos != file_offset)
|
||||
size_type new_pos = in->seek(file_offset + file_iter->file_base);
|
||||
if (new_pos != file_offset + file_iter->file_base)
|
||||
{
|
||||
// the file was not big enough
|
||||
if (!fill_zero)
|
||||
|
@ -782,7 +782,7 @@ namespace libtorrent
|
|||
|
||||
#ifndef NDEBUG
|
||||
size_type in_tell = in->tell();
|
||||
TORRENT_ASSERT(in_tell == file_offset);
|
||||
TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base);
|
||||
#endif
|
||||
|
||||
int left_to_read = size;
|
||||
|
@ -846,7 +846,7 @@ namespace libtorrent
|
|||
file_offset = 0;
|
||||
in = m_files.open_file(
|
||||
this, path, file::in);
|
||||
in->seek(0);
|
||||
in->seek(file_iter->file_base);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -892,11 +892,11 @@ namespace libtorrent
|
|||
this, p, file::out | file::in);
|
||||
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type pos = out->seek(file_offset);
|
||||
size_type pos = out->seek(file_offset + file_iter->file_base);
|
||||
|
||||
if (pos != file_offset)
|
||||
if (pos != file_offset + file_iter->file_base)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "no storage for slot " << slot;
|
||||
|
@ -962,7 +962,7 @@ namespace libtorrent
|
|||
out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
|
||||
out->seek(0);
|
||||
out->seek(file_iter->file_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace
|
|||
{
|
||||
target.size = dict["length"].integer();
|
||||
target.path = root_dir;
|
||||
|
||||
target.file_base = 0;
|
||||
|
||||
// prefer the name.utf-8
|
||||
// because if it exists, it is more
|
||||
|
@ -824,20 +824,19 @@ namespace libtorrent
|
|||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
bool torrent_info::remap_files(std::vector<std::pair<std::string
|
||||
, libtorrent::size_type> > const& map)
|
||||
bool torrent_info::remap_files(std::vector<file_entry> const& map)
|
||||
{
|
||||
typedef std::vector<std::pair<std::string, size_type> > files_t;
|
||||
|
||||
size_type offset = 0;
|
||||
m_remapped_files.resize(map.size());
|
||||
|
||||
for (int i = 0; i < int(map.size()); ++i)
|
||||
{
|
||||
file_entry& fe = m_remapped_files[i];
|
||||
fe.path = map[i].first;
|
||||
fe.path = map[i].path;
|
||||
fe.offset = offset;
|
||||
fe.size = map[i].second;
|
||||
fe.size = map[i].size;
|
||||
fe.file_base = map[i].file_base;
|
||||
fe.orig_path.reset();
|
||||
offset += fe.size;
|
||||
}
|
||||
if (offset != total_size())
|
||||
|
@ -846,6 +845,26 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_entry> map2(m_remapped_files);
|
||||
std::sort(map2.begin(), map2.end()
|
||||
, bind(&file_entry::file_base, _1) < bind(&file_entry::file_base, _2));
|
||||
std::stable_sort(map2.begin(), map2.end()
|
||||
, bind(&file_entry::path, _1) < bind(&file_entry::path, _2));
|
||||
fs::path last_path;
|
||||
size_type last_end = 0;
|
||||
for (std::vector<file_entry>::iterator i = map2.begin(), end(map2.end());
|
||||
i != end; ++i)
|
||||
{
|
||||
if (last_path == i->path)
|
||||
{
|
||||
assert(last_end <= i->file_base);
|
||||
}
|
||||
last_end = i->file_base + i->size;
|
||||
last_path = i->path;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -871,7 +890,7 @@ namespace libtorrent
|
|||
{
|
||||
file_slice f;
|
||||
f.file_index = counter;
|
||||
f.offset = file_offset;
|
||||
f.offset = file_offset + file_iter->file_base;
|
||||
f.size = (std::min)(file_iter->size - file_offset, (size_type)size);
|
||||
size -= f.size;
|
||||
file_offset += f.size;
|
||||
|
|
|
@ -192,8 +192,17 @@ void run_test(path const& test_path)
|
|||
// ==============================================
|
||||
|
||||
// make sure remap_files works
|
||||
std::vector<std::pair<std::string, libtorrent::size_type> > map;
|
||||
map.push_back(std::make_pair(std::string("temp_storage/test.tmp"), 17 + 612 + 1));
|
||||
std::vector<file_entry> map;
|
||||
file_entry fe;
|
||||
fe.path = "temp_storage/test.tmp";
|
||||
fe.size = 17;
|
||||
fe.file_base = 612 + 1;
|
||||
map.push_back(fe);
|
||||
fe.path = "temp_storage/test.tmp";
|
||||
fe.size = 612 + 1;
|
||||
fe.file_base = 0;
|
||||
map.push_back(fe);
|
||||
|
||||
bool ret = info->remap_files(map);
|
||||
TEST_CHECK(ret);
|
||||
|
||||
|
@ -202,7 +211,7 @@ void run_test(path const& test_path)
|
|||
run_storage_tests(info, test_path, storage_mode_compact);
|
||||
|
||||
std::cerr << file_size(test_path / "temp_storage" / "test.tmp") << std::endl;
|
||||
TEST_CHECK(file_size(test_path / "temp_storage" / "test.tmp") == 48);
|
||||
TEST_CHECK(file_size(test_path / "temp_storage" / "test.tmp") == 17 + 612 + 1);
|
||||
|
||||
remove_all(test_path / "temp_storage");
|
||||
|
||||
|
|
Loading…
Reference in New Issue