forked from premiere/premiere-libtorrent
fix issue where paths were not correctly coalesced when adding files to file_storage (used more memory than necessary)
This commit is contained in:
parent
dbea43ab35
commit
4e497e1383
|
@ -583,6 +583,8 @@ namespace libtorrent
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
int get_or_add_path(char const* branch_path, int branch_len);
|
||||||
|
|
||||||
void add_pad_file(int size
|
void add_pad_file(int size
|
||||||
, std::vector<internal_file_entry>::iterator& i
|
, std::vector<internal_file_entry>::iterator& i
|
||||||
, boost::int64_t& offset
|
, boost::int64_t& offset
|
||||||
|
|
|
@ -47,10 +47,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
|
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
|
||||||
#define TORRENT_SEPARATOR '\\'
|
#define TORRENT_SEPARATOR '\\'
|
||||||
#define TORRENT_SEPARATOR_STR "\\"
|
|
||||||
#else
|
#else
|
||||||
#define TORRENT_SEPARATOR '/'
|
#define TORRENT_SEPARATOR '/'
|
||||||
#define TORRENT_SEPARATOR_STR "/"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
|
@ -138,13 +136,14 @@ namespace libtorrent
|
||||||
return fe1.size < fe2.size;
|
return fe1.size < fe2.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compare_file_offset(internal_file_entry const& lhs
|
bool compare_file_offset(internal_file_entry const& lhs
|
||||||
, internal_file_entry const& rhs)
|
, internal_file_entry const& rhs)
|
||||||
{
|
{
|
||||||
return lhs.offset < rhs.offset;
|
return lhs.offset < rhs.offset;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// path is not supposed to include the name of the torrent itself.
|
// path is not supposed to include the name of the torrent itself.
|
||||||
void file_storage::update_path_index(internal_file_entry& e
|
void file_storage::update_path_index(internal_file_entry& e
|
||||||
, std::string const& path, bool set_name)
|
, std::string const& path, bool set_name)
|
||||||
|
@ -193,6 +192,16 @@ namespace libtorrent
|
||||||
e.no_root_dir = true;
|
e.no_root_dir = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.path_index = get_or_add_path(branch_path, branch_len);
|
||||||
|
if (set_name) e.set_name(leaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_storage::get_or_add_path(char const* branch_path, int branch_len)
|
||||||
|
{
|
||||||
|
// trim trailing slashes
|
||||||
|
if (branch_len > 0 && branch_path[branch_len-1] == TORRENT_SEPARATOR)
|
||||||
|
--branch_len;
|
||||||
|
|
||||||
// do we already have this path in the path list?
|
// do we already have this path in the path list?
|
||||||
std::vector<std::string>::reverse_iterator p
|
std::vector<std::string>::reverse_iterator p
|
||||||
= std::find_if(m_paths.rbegin(), m_paths.rend()
|
= std::find_if(m_paths.rbegin(), m_paths.rend()
|
||||||
|
@ -201,23 +210,16 @@ namespace libtorrent
|
||||||
if (p == m_paths.rend())
|
if (p == m_paths.rend())
|
||||||
{
|
{
|
||||||
// no, we don't. add it
|
// no, we don't. add it
|
||||||
e.path_index = m_paths.size();
|
int const ret = int(m_paths.size());
|
||||||
TORRENT_ASSERT(branch_path[0] != '/');
|
TORRENT_ASSERT(branch_len == 0 || branch_path[0] != TORRENT_SEPARATOR);
|
||||||
|
m_paths.push_back(std::string(branch_path, branch_len));
|
||||||
// trim trailing slashes
|
return ret;
|
||||||
if (branch_len > 0 && branch_path[branch_len-1] == TORRENT_SEPARATOR)
|
|
||||||
--branch_len;
|
|
||||||
|
|
||||||
// poor man's emplace back
|
|
||||||
m_paths.resize(m_paths.size() + 1);
|
|
||||||
m_paths.back().assign(branch_path, branch_len);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// yes we do. use it
|
// yes we do. use it
|
||||||
e.path_index = p.base() - m_paths.begin() - 1;
|
return int(p.base() - m_paths.begin() - 1);
|
||||||
}
|
}
|
||||||
if (set_name) e.set_name(leaf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
|
@ -396,6 +398,8 @@ namespace libtorrent
|
||||||
|
|
||||||
int file_storage::file_index_at_offset(boost::int64_t offset) const
|
int file_storage::file_index_at_offset(boost::int64_t offset) const
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT_PRECOND(offset >= 0);
|
||||||
|
TORRENT_ASSERT_PRECOND(offset < m_total_size);
|
||||||
// find the file iterator and file offset
|
// find the file iterator and file offset
|
||||||
internal_file_entry target;
|
internal_file_entry target;
|
||||||
target.offset = offset;
|
target.offset = offset;
|
||||||
|
@ -425,6 +429,8 @@ namespace libtorrent
|
||||||
, boost::int64_t const offset
|
, boost::int64_t const offset
|
||||||
, int size) const
|
, int size) const
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT_PRECOND(piece >= 0);
|
||||||
|
TORRENT_ASSERT_PRECOND(piece < num_pieces());
|
||||||
TORRENT_ASSERT_PRECOND(num_files() > 0);
|
TORRENT_ASSERT_PRECOND(num_files() > 0);
|
||||||
std::vector<file_slice> ret;
|
std::vector<file_slice> ret;
|
||||||
|
|
||||||
|
@ -1067,11 +1073,10 @@ namespace libtorrent
|
||||||
i = m_files.begin() + cur_index;
|
i = m_files.begin() + cur_index;
|
||||||
e.size = size;
|
e.size = size;
|
||||||
e.offset = offset;
|
e.offset = offset;
|
||||||
char name[30];
|
e.path_index = get_or_add_path(".pad", 4);
|
||||||
snprintf(name, sizeof(name), ".pad" TORRENT_SEPARATOR_STR "%d"
|
char name[15];
|
||||||
, pad_file_counter);
|
snprintf(name, sizeof(name), "%d", pad_file_counter);
|
||||||
std::string path = combine_path(m_name, name);
|
e.set_name(name);
|
||||||
e.set_name(path.c_str());
|
|
||||||
e.pad_file = true;
|
e.pad_file = true;
|
||||||
offset += size;
|
offset += size;
|
||||||
++pad_file_counter;
|
++pad_file_counter;
|
||||||
|
|
|
@ -75,6 +75,36 @@ void setup_test_storage(file_storage& st)
|
||||||
TEST_EQUAL(st.num_pieces(), (100000 + 0x3fff) / 0x4000);
|
TEST_EQUAL(st.num_pieces(), (100000 + 0x3fff) / 0x4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(coalesce_path)
|
||||||
|
{
|
||||||
|
file_storage st;
|
||||||
|
st.add_file(combine_path("test", "a"), 10000);
|
||||||
|
TEST_EQUAL(st.paths().size(), 1);
|
||||||
|
TEST_EQUAL(st.paths()[0], "");
|
||||||
|
st.add_file(combine_path("test", "b"), 20000);
|
||||||
|
TEST_EQUAL(st.paths().size(), 1);
|
||||||
|
TEST_EQUAL(st.paths()[0], "");
|
||||||
|
st.add_file(combine_path("test", combine_path("c", "a")), 30000);
|
||||||
|
TEST_EQUAL(st.paths().size(), 2);
|
||||||
|
TEST_EQUAL(st.paths()[0], "");
|
||||||
|
TEST_EQUAL(st.paths()[1], "c");
|
||||||
|
|
||||||
|
// make sure that two files with the same path shares the path entry
|
||||||
|
st.add_file(combine_path("test", combine_path("c", "b")), 40000);
|
||||||
|
TEST_EQUAL(st.paths().size(), 2);
|
||||||
|
TEST_EQUAL(st.paths()[0], "");
|
||||||
|
TEST_EQUAL(st.paths()[1], "c");
|
||||||
|
|
||||||
|
// cause pad files to be created, to make sure the pad files also share the
|
||||||
|
// same path entries
|
||||||
|
st.optimize(0, 1024, true);
|
||||||
|
|
||||||
|
TEST_EQUAL(st.paths().size(), 3);
|
||||||
|
TEST_EQUAL(st.paths()[0], "");
|
||||||
|
TEST_EQUAL(st.paths()[1], "c");
|
||||||
|
TEST_EQUAL(st.paths()[2], ".pad");
|
||||||
|
}
|
||||||
|
|
||||||
TORRENT_TEST(rename_file)
|
TORRENT_TEST(rename_file)
|
||||||
{
|
{
|
||||||
// test rename_file
|
// test rename_file
|
||||||
|
|
Loading…
Reference in New Issue