some more optimizations on loading torrents

This commit is contained in:
Arvid Norberg 2015-02-18 03:32:49 +00:00
parent c4a294e88a
commit 89055c4c7a
5 changed files with 96 additions and 30 deletions

View File

@ -119,7 +119,7 @@ namespace libtorrent
// internal flags for stat_file
enum { dont_follow_links = 1 };
TORRENT_EXTRA_EXPORT void stat_file(std::string f, file_status* s
TORRENT_EXTRA_EXPORT void stat_file(std::string const& f, file_status* s
, error_code& ec, int flags = 0);
TORRENT_EXTRA_EXPORT void rename(std::string const& f
, std::string const& newf, error_code& ec);
@ -157,6 +157,10 @@ namespace libtorrent
TORRENT_EXTRA_EXPORT std::string filename(std::string const& f);
TORRENT_EXTRA_EXPORT std::string combine_path(std::string const& lhs
, std::string const& rhs);
TORRENT_EXTRA_EXPORT void append_path(std::string& branch
, std::string const& leaf);
TORRENT_EXTRA_EXPORT void append_path(std::string& branch
, char const* str, int len);
// internal used by create_torrent.hpp
TORRENT_EXTRA_EXPORT std::string complete(std::string const& f);
TORRENT_EXTRA_EXPORT bool is_complete(std::string const& f);

View File

@ -3003,6 +3003,10 @@ namespace libtorrent
}
else
{
// do this to trigger parsing of the info-dict here. It's better
// than to have it be done in the network thread. It has enough to
// do as it is.
std::string cert = t->ssl_cert();
j->buffer = (char*)t;
}

View File

@ -325,23 +325,30 @@ namespace libtorrent
}
#endif
void stat_file(std::string inf, file_status* s
void stat_file(std::string const& inf, file_status* s
, error_code& ec, int flags)
{
ec.clear();
#ifdef TORRENT_WINDOWS
// apparently windows doesn't expect paths
// to directories to ever end with a \ or /
if (!inf.empty() && (inf[inf.size() - 1] == '\\'
|| inf[inf.size() - 1] == '/'))
inf.resize(inf.size() - 1);
#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS
#define GetFileAttributesEx_ GetFileAttributesExW
std::wstring f = convert_to_wstring(inf);
// apparently windows doesn't expect paths
// to directories to ever end with a \ or /
if (!f.empty() && (f[f.size() - 1] == L'\\'
|| f[f.size() - 1] == L'/'))
f.resize(f.size() - 1);
#else
#define GetFileAttributesEx_ GetFileAttributesExA
std::string f = convert_to_native(inf);
// apparently windows doesn't expect paths
// to directories to ever end with a \ or /
if (!f.empty() && (f[f.size() - 1] == '\\'
|| f[f.size() - 1] == '/'))
f.resize(f.size() - 1);
#endif
WIN32_FILE_ATTRIBUTE_DATA data;
if (!GetFileAttributesEx(f.c_str(), GetFileExInfoStandard, &data))
@ -364,7 +371,7 @@ namespace libtorrent
// posix version
std::string f = convert_to_native(inf);
std::string const& f = convert_to_native(inf);
struct stat ret;
int retval;
@ -403,8 +410,8 @@ namespace libtorrent
std::wstring f2 = convert_to_wstring(newf);
if (_wrename(f1.c_str(), f2.c_str()) < 0)
#else
std::string f1 = convert_to_native(inf);
std::string f2 = convert_to_native(newf);
std::string const& f1 = convert_to_native(inf);
std::string const& f2 = convert_to_native(newf);
if (::rename(f1.c_str(), f2.c_str()) < 0)
#endif
{
@ -438,7 +445,7 @@ namespace libtorrent
std::wstring n = convert_to_wstring(f);
#else
#define CreateDirectory_ CreateDirectoryA
std::string n = convert_to_native(f);
std::string const& n = convert_to_native(f);
#endif
#ifdef TORRENT_WINDOWS
@ -493,8 +500,8 @@ namespace libtorrent
std::wstring f2 = convert_to_wstring(newf);
#else
#define CopyFile_ CopyFileA
std::string f1 = convert_to_native(inf);
std::string f2 = convert_to_native(newf);
std::string const& f1 = convert_to_native(inf);
std::string const& f2 = convert_to_native(newf);
#endif
#ifdef TORRENT_WINDOWS
@ -750,6 +757,35 @@ namespace libtorrent
return std::string(sep + 1);
}
void append_path(std::string& branch, std::string const& leaf)
{
append_path(branch, leaf.c_str(), leaf.size());
}
void append_path(std::string& branch
, char const* str, int len)
{
TORRENT_ASSERT(!is_complete(std::string(str, len)));
if (branch.empty() || branch == ".")
{
branch.assign(str, len);
return;
}
if (len == 0) return;
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
#define TORRENT_SEPARATOR_CHAR '\\'
bool need_sep = branch[branch.size()-1] != '\\'
&& branch[branch.size()-1] != '/';
#else
#define TORRENT_SEPARATOR_CHAR '/'
bool need_sep = branch[branch.size()-1] != '/';
#endif
if (need_sep) branch += TORRENT_SEPARATOR_CHAR;
branch.append(str, len);
}
std::string combine_path(std::string const& lhs, std::string const& rhs)
{
TORRENT_ASSERT(!is_complete(rhs));
@ -917,7 +953,7 @@ namespace libtorrent
return;
}
#else // TORRENT_WINDOWS
std::string f = convert_to_native(inf);
std::string const& f = convert_to_native(inf);
if (::remove(f.c_str()) < 0)
{
ec.assign(errno, generic_category());

View File

@ -670,21 +670,42 @@ namespace libtorrent
TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size()));
internal_file_entry const& fe = m_files[index];
std::string ret;
// -2 means this is an absolute path filename
if (fe.path_index == -2) return fe.filename();
if (fe.path_index == -2)
{
ret.assign(fe.filename_ptr(), fe.filename_len());
}
else if (fe.path_index == -1)
{
// -1 means no path
if (fe.path_index == -1) return combine_path(save_path, fe.filename());
ret.reserve(save_path.size() + fe.filename_len() + 1);
ret.assign(save_path);
append_path(ret, fe.filename_ptr(), fe.filename_len());
}
else if (fe.no_root_dir)
{
std::string const& p = m_paths[fe.path_index];
if (fe.no_root_dir)
return combine_path(save_path
, combine_path(m_paths[fe.path_index]
, fe.filename()));
ret.reserve(save_path.size() + p.size() + fe.filename_len() + 2);
ret.assign(save_path);
append_path(ret, p);
append_path(ret, fe.filename_ptr(), fe.filename_len());
}
else
{
std::string const& p = m_paths[fe.path_index];
return combine_path(save_path
, combine_path(m_name
, combine_path(m_paths[fe.path_index]
, fe.filename())));
ret.reserve(save_path.size() + m_name.size() + p.size() + fe.filename_len() + 3);
ret.assign(save_path);
append_path(ret, m_name);
append_path(ret, p);
append_path(ret, fe.filename_ptr(), fe.filename_len());
}
// a single return statement, just to make NRVO more likely to kick in
return ret;
}
std::string file_storage::file_name(int index) const

View File

@ -348,11 +348,10 @@ namespace libtorrent
// ignore pad files
if (files().pad_file_at(file_index)) continue;
std::string file_path = files().file_path(file_index, m_save_path);
if (m_stat_cache.get_filesize(file_index) == stat_cache::not_in_cache)
{
file_status s;
std::string file_path = files().file_path(file_index, m_save_path);
stat_file(file_path, &s, ec.ec);
if (ec && ec.ec != boost::system::errc::no_such_file_or_directory)
{
@ -370,6 +369,7 @@ namespace libtorrent
if ((!ec && m_stat_cache.get_filesize(file_index) > files().file_size(file_index))
|| files().file_size(file_index) == 0)
{
std::string file_path = files().file_path(file_index, m_save_path);
std::string dir = parent_path(file_path);
if (dir != last_path)
@ -389,19 +389,21 @@ namespace libtorrent
| file::random_access, ec);
if (ec) return;
f->set_size(files().file_size(file_index), ec.ec);
boost::int64_t size = files().file_size(file_index);
f->set_size(size, ec.ec);
if (ec)
{
ec.file = file_index;
ec.operation = storage_error::fallocate;
break;
}
size_t mtime = m_stat_cache.get_filetime(file_index);
m_stat_cache.set_cache(file_index, size, mtime);
}
ec.ec.clear();
}
// close files that were opened in write mode
m_stat_cache.clear();
m_pool.release(this);
#if TORRENT_DEBUG_FILE_LEAKS
@ -463,7 +465,6 @@ namespace libtorrent
ec.operation = storage_error::stat;
return false;
}
m_stat_cache.clear();
return false;
}