fix build with internal_file_entry being deprecated without deprecated functions

This commit is contained in:
Arvid Norberg 2013-08-12 07:30:57 +00:00
parent 2fec803ae4
commit 3bd53f88ef
14 changed files with 288 additions and 230 deletions

View File

@ -57,7 +57,7 @@ namespace libtorrent
~file_pool();
boost::intrusive_ptr<file> open_file(void* st, std::string const& p
, file_storage::iterator fe, file_storage const& fs, int m, error_code& ec);
, int file_index, file_storage const& fs, int m, error_code& ec);
void release(void* st);
void release(void* st, int file_index);
void resize(int size);

View File

@ -101,10 +101,15 @@ namespace libtorrent
std::string symlink_path;
};
// only export this type if deprecated functions are enabled
#ifdef TORRENT_NO_DEPRECATED
#define TORRENT_DEPRECATED_EXPORT
#else
#define TORRENT_DEPRECATED_EXPORT TORRENT_EXPORT
#endif
// internal
struct TORRENT_EXPORT internal_file_entry
struct TORRENT_DEPRECATED_EXPORT internal_file_entry
{
// TODO: does this really need to be exported?
friend class file_storage;
#ifdef TORRENT_DEBUG
// for torrent_info::invariant_check
@ -249,6 +254,12 @@ namespace libtorrent
void rename_file(int index, std::string const& new_filename);
// this is a low-level function that sets the name of a file
// by making it reference a buffer that is not owned by the file_storage.
// it's an optimization used when loading .torrent files, to not
// duplicate names in memory.
void rename_file_borrow(int index, char const* new_filename, int len);
#if TORRENT_USE_WSTRING
// all wstring APIs are deprecated since 0.16.11
// instead, use the wchar -> utf8 conversion functions
@ -267,7 +278,7 @@ namespace libtorrent
std::vector<file_slice> map_block(int piece, size_type offset
, int size) const;
peer_request map_file(int file, size_type offset, int size) const;
#ifndef TORRENT_NO_DEPRECATE
// all functions depending on internal_file_entry
// were deprecated in 1.0. Use the variants that take an
@ -292,13 +303,14 @@ namespace libtorrent
TORRENT_ASSERT(index < int(m_files.size()));
return m_files[index];
}
TORRENT_DEPRECATED_PREFIX
file_entry at(iterator i) const TORRENT_DEPRECATED;
#endif // TORRENT_NO_DEPRECATE
int num_files() const
{ return int(m_files.size()); }
file_entry at(int index) const;
file_entry at(iterator i) const;
size_type total_size() const { return m_total_size; }
void set_num_pieces(int n) { m_num_pieces = n; }
@ -364,6 +376,18 @@ namespace libtorrent
bool pad_file_at(int index) const;
size_type file_offset(int index) const;
enum file_flags_t
{
flag_pad_file = 1,
flag_hidden = 2,
flag_executable = 4,
flag_symlink = 8,
};
// returns a bitmask of flags from file_flags_t that apply
// to file at ``index``.
int file_flags(int index) const;
// The file base of a file is the offset within the file on the filsystem
// where it starts to write. For the most part, this is always 0. It's
// possible to map several files (in the torrent) into a single file on
@ -373,6 +397,15 @@ namespace libtorrent
size_type file_base(int index) const;
void set_file_base(int index, size_type off);
// returns the index of the file at the given offset in the torrent
int file_index_at_offset(size_type offset) const;
// low-level function. returns a pointer to the internal storage for
// the filename. This string may not be null terinated!
// the ``file_name_len()`` function returns the length of the filename.
char const* file_name_ptr(int index) const;
int file_name_len(int index) const;
#ifndef TORRENT_NO_DEPRECATE
// these were deprecated in 1.0. Use the versions that take an index instead
TORRENT_DEPRECATED_PREFIX

View File

@ -431,7 +431,7 @@ namespace libtorrent
file_storage const& m_files;
// helper function to open a file in the file pool with the right mode
boost::intrusive_ptr<file> open_file(file_storage::iterator fe, int mode
boost::intrusive_ptr<file> open_file(int file, int mode
, error_code& ec) const;
std::vector<boost::uint8_t> m_file_priority;

View File

@ -437,6 +437,9 @@ namespace libtorrent
const sha1_hash& info_hash() const { return m_info_hash; }
#ifndef TORRENT_NO_DEPRECATE
// deprecated in 1.0. Use the variants that take an index instead
// internal_file_entry is no longer exposed in the API
typedef file_storage::iterator file_iterator;
typedef file_storage::reverse_iterator reverse_file_iterator;
@ -447,19 +450,25 @@ namespace libtorrent
//
// You can resolve it into the public representation of a file (``file_entry``)
// using the ``file_storage::at`` function, which takes an index and an iterator.
file_iterator begin_files() const { return m_files.begin(); }
file_iterator end_files() const { return m_files.end(); }
reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
reverse_file_iterator rend_files() const { return m_files.rend(); }
TORRENT_DEPRECATED_PREFIX
file_iterator begin_files() const TORRENT_DEPRECATED { return m_files.begin(); }
TORRENT_DEPRECATED_PREFIX
file_iterator end_files() const TORRENT_DEPRECATED { return m_files.end(); }
reverse_file_iterator rbegin_files() const TORRENT_DEPRECATED { return m_files.rbegin(); }
TORRENT_DEPRECATED_PREFIX
reverse_file_iterator rend_files() const TORRENT_DEPRECATED { return m_files.rend(); }
TORRENT_DEPRECATED_PREFIX
file_iterator file_at_offset(size_type offset) const TORRENT_DEPRECATED
{ return m_files.file_at_offset(offset); }
#endif // TORRENT_NO_DEPRECATE
// If you need index-access to files you can use the ``num_files()`` and ``file_at()``
// to access files using indices.
int num_files() const { return m_files.num_files(); }
file_entry file_at(int index) const { return m_files.at(index); }
file_iterator file_at_offset(size_type offset) const
{ return m_files.file_at_offset(offset); }
// This function will map a piece index, a byte offset within that piece and
// a size (in bytes) into the corresponding files with offsets where that data
// for that piece is supposed to be stored. See file_slice.

View File

@ -273,7 +273,7 @@ namespace libtorrent
// return instead of crash in release mode
if (fs.num_files() == 0) return;
if (!m_multifile && has_parent_path(m_files.file_path(*m_files.begin()))) m_multifile = true;
if (!m_multifile && has_parent_path(m_files.file_path(0))) m_multifile = true;
// a piece_size of 0 means automatic
if (piece_size == 0 && !m_merkle_torrent)
@ -493,49 +493,45 @@ namespace libtorrent
{
entry& files = info["files"];
for (file_storage::iterator i = m_files.begin();
i != m_files.end(); ++i)
for (int i = 0; i < m_files.num_files(); ++i)
{
files.list().push_back(entry());
entry& file_e = files.list().back();
if (m_include_mtime && m_files.mtime(*i)) file_e["mtime"] = m_files.mtime(*i);
file_e["length"] = i->size;
if (m_include_mtime && m_files.mtime(i)) file_e["mtime"] = m_files.mtime(i);
file_e["length"] = m_files.file_size(i);
entry& path_e = file_e["path"];
TORRENT_ASSERT(has_parent_path(m_files.file_path(*i)));
TORRENT_ASSERT(has_parent_path(m_files.file_path(i)));
std::string split = split_path(m_files.file_path(*i));
std::string split = split_path(m_files.file_path(i));
TORRENT_ASSERT(split.c_str() == m_files.name());
for (char const* e = next_path_element(split.c_str());
e != 0; e = next_path_element(e))
path_e.list().push_back(entry(e));
if (i->pad_file
|| i->hidden_attribute
|| i->executable_attribute
|| i->symlink_attribute)
int flags = m_files.file_flags(i);
if (flags != 0)
{
std::string& attr = file_e["attr"].string();
if (i->pad_file) attr += 'p';
if (i->hidden_attribute) attr += 'h';
if (i->executable_attribute) attr += 'x';
if (m_include_symlinks && i->symlink_attribute) attr += 'l';
if (flags & file_storage::flag_pad_file) attr += 'p';
if (flags & file_storage::flag_hidden) attr += 'h';
if (flags & file_storage::flag_executable) attr += 'x';
if (m_include_symlinks && (flags & file_storage::flag_symlink)) attr += 'l';
}
if (m_include_symlinks
&& i->symlink_attribute
&& i->symlink_index != -1)
&& (flags & file_storage::flag_symlink))
{
entry& sympath_e = file_e["symlink path"];
std::string split = split_path(m_files.symlink(*i));
std::string split = split_path(m_files.symlink(i));
for (char const* e = split.c_str(); e != 0; e = next_path_element(e))
sympath_e.list().push_back(entry(e));
}
int file_index = i - m_files.begin();
if (!m_filehashes.empty() && m_filehashes[file_index] != sha1_hash())
if (!m_filehashes.empty() && m_filehashes[i] != sha1_hash())
{
file_e["sha1"] = m_filehashes[file_index].to_string();
file_e["sha1"] = m_filehashes[i].to_string();
}
}
}

View File

@ -169,14 +169,14 @@ namespace libtorrent
#endif // TORRENT_WINDOWS
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p
, file_storage::iterator fe, file_storage const& fs, int m, error_code& ec)
, int file_index, file_storage const& fs, int m, error_code& ec)
{
TORRENT_ASSERT(st != 0);
TORRENT_ASSERT(is_complete(p));
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|| (m & file::rw_mask) == file::read_write);
mutex::scoped_lock l(m_mutex);
file_set::iterator i = m_files.find(std::make_pair(st, fs.file_index(*fe)));
file_set::iterator i = m_files.find(std::make_pair(st, file_index));
if (i != m_files.end())
{
lru_file_entry& e = i->second;
@ -214,7 +214,7 @@ namespace libtorrent
#else
e.file_ptr->close();
#endif
std::string full_path = fs.file_path(*fe, p);
std::string full_path = fs.file_path(file_index, p);
if (!e.file_ptr->open(full_path, m, ec))
{
m_files.erase(i);
@ -244,7 +244,7 @@ namespace libtorrent
ec = error_code(ENOMEM, get_posix_category());
return e.file_ptr;
}
std::string full_path = fs.file_path(*fe, p);
std::string full_path = fs.file_path(file_index, p);
if (!e.file_ptr->open(full_path, m, ec))
return boost::intrusive_ptr<file>();
#ifdef TORRENT_WINDOWS
@ -253,7 +253,7 @@ namespace libtorrent
#endif
e.mode = m;
e.key = st;
m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(*fe)), e));
m_files.insert(std::make_pair(std::make_pair(st, file_index), e));
TORRENT_ASSERT(e.file_ptr->is_open());
return e.file_ptr;
}

View File

@ -200,6 +200,12 @@ namespace libtorrent
update_path_index(m_files[index]);
}
void file_storage::rename_file_borrow(int index, char const* new_filename, int len)
{
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
m_files[index].set_name(new_filename, len);
}
namespace
{
bool compare_file_offset(internal_file_entry const& lhs, internal_file_entry const& rhs)
@ -208,6 +214,7 @@ namespace libtorrent
}
}
#ifndef TORRENT_NO_DEPRECATE
file_storage::iterator file_storage::file_at_offset(size_type offset) const
{
// find the file iterator and file offset
@ -222,6 +229,32 @@ namespace libtorrent
--file_iter;
return file_iter;
}
#endif
int file_storage::file_index_at_offset(size_type offset) const
{
// find the file iterator and file offset
internal_file_entry target;
target.offset = offset;
TORRENT_ASSERT(!compare_file_offset(target, m_files.front()));
std::vector<internal_file_entry>::const_iterator file_iter = std::upper_bound(
m_files.begin(), m_files.end(), target, compare_file_offset);
TORRENT_ASSERT(file_iter != m_files.begin());
--file_iter;
return file_iter - m_files.begin();
}
char const* file_storage::file_name_ptr(int index) const
{
return m_files[index].name;
}
int file_storage::file_name_len(int index) const
{
return m_files[index].name_len;
}
std::vector<file_slice> file_storage::map_block(int piece, size_type offset
, int size) const
@ -238,20 +271,20 @@ namespace libtorrent
TORRENT_ASSERT(!compare_file_offset(target, m_files.front()));
std::vector<internal_file_entry>::const_iterator file_iter = std::upper_bound(
begin(), end(), target, compare_file_offset);
m_files.begin(), m_files.end(), target, compare_file_offset);
TORRENT_ASSERT(file_iter != begin());
TORRENT_ASSERT(file_iter != m_files.begin());
--file_iter;
size_type file_offset = target.offset - file_iter->offset;
for (; size > 0; file_offset -= file_iter->size, ++file_iter)
{
TORRENT_ASSERT(file_iter != end());
TORRENT_ASSERT(file_iter != m_files.end());
if (file_offset < file_iter->size)
{
file_slice f;
f.file_index = file_iter - begin();
f.offset = file_offset + file_base(*file_iter);
f.file_index = file_iter - m_files.begin();
f.offset = file_offset + file_base(f.file_index);
f.size = (std::min)(file_iter->size - file_offset, (size_type)size);
TORRENT_ASSERT(f.size <= size);
size -= int(f.size);
@ -264,25 +297,22 @@ namespace libtorrent
return ret;
}
file_entry file_storage::at(file_storage::iterator i) const
{ return at(i - begin()); }
file_entry file_storage::at(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
file_entry ret;
internal_file_entry const& ife = m_files[index];
ret.path = file_path(ife);
ret.path = file_path(index);
ret.offset = ife.offset;
ret.size = ife.size;
ret.file_base = file_base(ife);
ret.mtime = mtime(ife);
ret.file_base = file_base(index);
ret.mtime = mtime(index);
ret.pad_file = ife.pad_file;
ret.hidden_attribute = ife.hidden_attribute;
ret.executable_attribute = ife.executable_attribute;
ret.symlink_attribute = ife.symlink_attribute;
if (ife.symlink_index >= 0) ret.symlink_path = symlink(ife);
ret.filehash = hash(ife);
if (ife.symlink_index >= 0) ret.symlink_path = symlink(index);
ret.filehash = hash(index);
return ret;
}
@ -382,6 +412,7 @@ namespace libtorrent
m_name = split_path(ent.path).c_str();
}
internal_file_entry ife(ent);
int file_index = m_files.size();
m_files.push_back(ife);
internal_file_entry& e = m_files.back();
if (e.size < 0) e.size = 0;
@ -402,7 +433,7 @@ namespace libtorrent
if (m_mtime.size() < m_files.size()) m_mtime.resize(m_files.size());
m_mtime[m_files.size() - 1] = ent.mtime;
}
if (ent.file_base) set_file_base(e, ent.file_base);
if (ent.file_base) set_file_base(file_index, ent.file_base);
update_path_index(e);
}
@ -478,6 +509,15 @@ namespace libtorrent
return m_files[index].offset;
}
int file_storage::file_flags(int index) const
{
internal_file_entry const& fe = m_files[index];
return (fe.pad_file ? flag_pad_file : 0)
| (fe.hidden_attribute ? flag_hidden : 0)
| (fe.executable_attribute ? flag_executable : 0)
| (fe.symlink_attribute ? flag_symlink : 0);
}
#ifndef TORRENT_NO_DEPRECATE
sha1_hash file_storage::hash(internal_file_entry const& fe) const
{
@ -552,7 +592,10 @@ namespace libtorrent
{
return fe.offset;
}
#endif
file_entry file_storage::at(file_storage::iterator i) const
{ return at(i - begin()); }
#endif // TORRENT_NO_DEPRECATE
bool compare_file_entry_size(internal_file_entry const& fe1, internal_file_entry const& fe2)
{ return fe1.size < fe2.size; }
@ -612,8 +655,8 @@ namespace libtorrent
if (best_match != i)
{
int index = file_index(*best_match);
int cur_index = file_index(*i);
int index = best_match - m_files.begin();
int cur_index = i - m_files.begin();
reorder_file(index, cur_index);
i = m_files.begin() + cur_index;
}
@ -645,8 +688,8 @@ namespace libtorrent
// look for files <= pad_size, which never is greater than
// alignment
TORRENT_ASSERT(best_match != i);
int index = file_index(*best_match);
int cur_index = file_index(*i);
int index = best_match - m_files.begin();
int cur_index = i - m_files.begin();
reorder_file(index, cur_index);
i = m_files.begin() + cur_index;
i->offset = off;
@ -663,7 +706,7 @@ namespace libtorrent
// then swap it in place. This minimizes the amount
// of copying of internal_file_entry, which is somewhat
// expensive (until we have move semantics)
int cur_index = file_index(*i);
int cur_index = i - m_files.begin();
int index = m_files.size();
m_files.push_back(internal_file_entry());
internal_file_entry& e = m_files.back();

View File

@ -100,17 +100,16 @@ namespace libtorrent
{
std::string save_path = complete(p);
std::vector<std::pair<size_type, std::time_t> > sizes;
for (file_storage::iterator i = storage.begin()
, end(storage.end()); i != end; ++i)
for (int i = 0; i < storage.num_files(); ++i)
{
size_type size = 0;
std::time_t time = 0;
if (!i->pad_file)
if (!storage.pad_file_at(i))
{
file_status s;
error_code ec;
stat_file(storage.file_path(*i, save_path), &s, ec);
stat_file(storage.file_path(i, save_path), &s, ec);
if (!ec)
{
@ -151,16 +150,15 @@ namespace libtorrent
std::vector<std::pair<size_type, std::time_t> >::const_iterator size_iter
= sizes.begin();
for (file_storage::iterator i = fs.begin()
, end(fs.end());i != end; ++i, ++size_iter)
for (int i = 0; i < fs.num_files(); ++i, ++size_iter)
{
size_type size = 0;
std::time_t time = 0;
if (i->pad_file) continue;
if (fs.pad_file_at(i)) continue;
file_status s;
error_code ec;
stat_file(fs.file_path(*i, p), &s, ec);
stat_file(fs.file_path(i, p), &s, ec);
if (!ec)
{
@ -393,7 +391,7 @@ namespace libtorrent
{
if (mapped) m_mapped_files.reset(new file_storage(*mapped));
TORRENT_ASSERT(m_files.begin() != m_files.end());
TORRENT_ASSERT(m_files.num_files() > 0);
m_save_path = complete(path);
}
@ -405,19 +403,16 @@ namespace libtorrent
error_code ec;
// first, create all missing directories
std::string last_path;
for (file_storage::iterator file_iter = files().begin(),
end_iter = files().end(); file_iter != end_iter; ++file_iter)
for (int file_index = 0; file_index < files().num_files(); ++file_index)
{
int file_index = files().file_index(*file_iter);
// ignore files that have priority 0
if (int(m_file_priority.size()) > file_index
&& m_file_priority[file_index] == 0) continue;
// ignore pad files
if (file_iter->pad_file) continue;
if (files().pad_file_at(file_index)) continue;
std::string file_path = files().file_path(*file_iter, m_save_path);
std::string file_path = files().file_path(file_index, m_save_path);
file_status s;
stat_file(file_path, &s, ec);
@ -433,7 +428,7 @@ namespace libtorrent
// if the file already exists, but is larger than what
// it's supposed to be, also truncate it
// if the file is empty, just create it either way.
if ((ec && allocate_files) || (!ec && s.file_size > file_iter->size) || file_iter->size == 0)
if ((ec && allocate_files) || (!ec && s.file_size > files().file_size(file_index)) || files().file_size(file_index) == 0)
{
std::string dir = parent_path(file_path);
@ -450,11 +445,11 @@ namespace libtorrent
}
ec.clear();
boost::intrusive_ptr<file> f = open_file(file_iter, file::read_write | file::random_access, ec);
boost::intrusive_ptr<file> f = open_file(file_index, file::read_write | file::random_access, ec);
if (ec) set_error(file_path, ec);
else if (f)
{
f->set_size(file_iter->size, ec);
f->set_size(files().file_size(file_index), ec);
if (ec) set_error(file_path, ec);
}
if (ec) break;
@ -475,16 +470,13 @@ namespace libtorrent
bool default_storage::has_any_file()
{
file_storage::iterator i = files().begin();
file_storage::iterator end = files().end();
for (; i != end; ++i)
for (int i = 0; i < files().num_files(); ++i)
{
error_code ec;
file_status s;
stat_file(files().file_path(*i, m_save_path), &s, ec);
stat_file(files().file_path(i, m_save_path), &s, ec);
if (ec) continue;
if (s.mode & file_status::regular_file && i->size > 0)
if (s.mode & file_status::regular_file && files().file_size(i) > 0)
return true;
}
return false;
@ -554,10 +546,9 @@ namespace libtorrent
// delete the files from disk
std::set<std::string> directories;
typedef std::set<std::string>::iterator iter_t;
for (file_storage::iterator i = files().begin()
, end(files().end()); i != end; ++i)
for (int i = 0; i < files().num_files(); ++i)
{
std::string fp = files().file_path(*i);
std::string fp = files().file_path(i);
bool complete = is_complete(fp);
std::string p = complete ? fp : combine_path(m_save_path, fp);
if (!complete)
@ -613,20 +604,20 @@ namespace libtorrent
TORRENT_ASSERT(slot < m_files.num_pieces());
size_type file_offset = (size_type)slot * m_files.piece_length();
file_storage::iterator file_iter;
int file_index = 0;
for (file_iter = files().begin();;)
for (;;)
{
if (file_offset < file_iter->size)
if (file_offset < m_files.file_size(file_index))
break;
file_offset -= file_iter->size;
++file_iter;
TORRENT_ASSERT(file_iter != files().end());
file_offset -= m_files.file_size(file_index);
++file_index;
TORRENT_ASSERT(file_index != files().num_files());
}
error_code ec;
boost::intrusive_ptr<file> file_handle = open_file(file_iter, file::read_only, ec);
boost::intrusive_ptr<file> file_handle = open_file(file_index, file::read_only, ec);
if (!file_handle || ec) return slot;
size_type data_start = file_handle->sparse_end(file_offset);
@ -737,10 +728,9 @@ namespace libtorrent
fs = file_sizes.begin();
// the resume data says we have the entire torrent
// make sure the file sizes are the right ones
for (file_storage::iterator i = files().begin()
, end(files().end()); i != end; ++i, ++fs)
for (int i = 0; i < files().num_files(); ++i)
{
if (!i->pad_file && i->size != fs->first)
if (!files().pad_file_at(i) && files().file_size(i) != fs->first)
{
error = errors::mismatching_file_size;
return false;
@ -771,13 +761,12 @@ namespace libtorrent
if (ec != boost::system::errc::no_such_file_or_directory)
{
// the directory exists, check all the files
for (file_storage::iterator i = f.begin()
, end(f.end()); i != end; ++i)
for (int i = 0; i < f.num_files(); ++i)
{
// files moved out to absolute paths are ignored
if (is_complete(f.file_path(*i))) continue;
if (is_complete(f.file_path(i))) continue;
std::string new_path = f.file_path(*i, save_path);
std::string new_path = f.file_path(i, save_path);
stat_file(new_path, &s, ec);
if (ec != boost::system::errc::no_such_file_or_directory)
return piece_manager::file_exist;
@ -789,13 +778,12 @@ namespace libtorrent
// try to move entire directories by default (instead of
// files independently).
std::set<std::string> to_move;
for (file_storage::iterator i = f.begin()
, end(f.end()); i != end; ++i)
for (int i = 0; i < f.num_files(); ++i)
{
// files moved out to absolute paths are not moved
if (is_complete(f.file_path(*i))) continue;
if (is_complete(f.file_path(i))) continue;
std::string split = split_path(f.file_path(*i));
std::string split = split_path(f.file_path(i));
to_move.insert(to_move.begin(), split);
}
@ -1007,24 +995,25 @@ ret:
// find the file and file
size_type tor_off = size_type(slot)
* files().piece_length() + offset;
file_storage::iterator file_iter = files().file_at_offset(tor_off);
while (file_iter->pad_file)
int file_index = files().file_index_at_offset(tor_off);
while (files().pad_file_at(file_index))
{
++file_iter;
if (file_iter == files().end())
++file_index;
if (file_index == files().num_files())
return size_type(slot) * files().piece_length() + offset;
// update offset as well, since we're moving it up ahead
tor_off = file_iter->offset;
}
TORRENT_ASSERT(!file_iter->pad_file);
tor_off = files().file_offset(file_index);
size_type file_offset = tor_off - file_iter->offset;
}
TORRENT_ASSERT(!files().pad_file_at(file_index));
size_type file_offset = tor_off - files().file_offset(file_index);
TORRENT_ASSERT(file_offset >= 0);
// open the file read only to avoid re-opening
// it in case it's already opened in read-only mode
error_code ec;
boost::intrusive_ptr<file> f = open_file(file_iter, file::read_only | file::random_access, ec);
boost::intrusive_ptr<file> f = open_file(file_index, file::read_only | file::random_access, ec);
size_type ret = 0;
if (f && !ec) ret = f->phys_offset(file_offset);
@ -1043,11 +1032,10 @@ ret:
size_type start = slot * (size_type)m_files.piece_length() + offset;
TORRENT_ASSERT(start + size <= m_files.total_size());
file_storage::iterator file_iter = files().file_at_offset(start);
TORRENT_ASSERT(file_iter != files().end());
TORRENT_ASSERT(start >= files().file_offset(*file_iter));
TORRENT_ASSERT(start < files().file_offset(*file_iter) + files().file_size(*file_iter));
size_type file_offset = start - files().file_offset(*file_iter);
int file_index = files().file_index_at_offset(start);
TORRENT_ASSERT(start >= files().file_offset(file_index));
TORRENT_ASSERT(start < files().file_offset(file_index) + files().file_size(file_index));
size_type file_offset = start - files().file_offset(file_index);
boost::intrusive_ptr<file> file_handle;
int bytes_left = size;
@ -1059,20 +1047,20 @@ ret:
TORRENT_ASSERT(bytes_left >= 0);
int file_bytes_left;
for (;bytes_left > 0; ++file_iter, bytes_left -= file_bytes_left)
for (;bytes_left > 0; ++file_index, bytes_left -= file_bytes_left)
{
TORRENT_ASSERT(file_iter != files().end());
TORRENT_ASSERT(file_index < files().num_files());
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > file_iter->size)
file_bytes_left = (std::max)(static_cast<int>(file_iter->size - file_offset), 0);
if (file_offset + file_bytes_left > files().file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files().file_size(file_index) - file_offset), 0);
if (file_bytes_left == 0) continue;
if (file_iter->pad_file) continue;
if (files().file_size(file_index)) continue;
error_code ec;
file_handle = open_file(file_iter, file::read_only | file::random_access, ec);
file_handle = open_file(file_index, file::read_only | file::random_access, ec);
// failing to hint that we want to read is not a big deal
// just swollow the error and keep going
@ -1141,11 +1129,10 @@ ret:
TORRENT_ASSERT(start + size <= m_files.total_size());
// find the file iterator and file offset
file_storage::iterator file_iter = files().file_at_offset(start);
TORRENT_ASSERT(file_iter != files().end());
TORRENT_ASSERT(start >= files().file_offset(*file_iter));
TORRENT_ASSERT(start < files().file_offset(*file_iter) + files().file_size(*file_iter));
size_type file_offset = start - files().file_offset(*file_iter);
int file_index = files().file_index_at_offset(start);
TORRENT_ASSERT(start >= files().file_offset(file_index));
TORRENT_ASSERT(start < files().file_offset(file_index) + files().file_size(file_index));
size_type file_offset = start - files().file_offset(file_index);
int buf_pos = 0;
error_code ec;
@ -1168,15 +1155,15 @@ ret:
copy_bufs(bufs, size, current_buf);
TORRENT_ASSERT(count_bufs(current_buf, size) == num_bufs);
int file_bytes_left;
for (;bytes_left > 0; ++file_iter, bytes_left -= file_bytes_left
for (;bytes_left > 0; ++file_index, bytes_left -= file_bytes_left
, buf_pos += file_bytes_left)
{
TORRENT_ASSERT(file_iter != files().end());
TORRENT_ASSERT(file_index < files().num_files());
TORRENT_ASSERT(buf_pos >= 0);
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > file_iter->size)
file_bytes_left = (std::max)(static_cast<int>(file_iter->size - file_offset), 0);
if (file_offset + file_bytes_left > files().file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files().file_size(file_index) - file_offset), 0);
if (file_bytes_left == 0) continue;
@ -1184,12 +1171,11 @@ ret:
TORRENT_ASSERT(int(slices.size()) > counter);
size_type slice_size = slices[counter].size;
TORRENT_ASSERT(slice_size == file_bytes_left);
TORRENT_ASSERT((files().begin() + slices[counter].file_index)
== file_iter);
TORRENT_ASSERT(slices[counter].file_index == file_index);
++counter;
#endif
if (file_iter->pad_file)
if (files().pad_file_at(file_index))
{
if ((op.mode & file::rw_mask) == file::read_only)
{
@ -1205,22 +1191,22 @@ ret:
}
error_code ec;
file_handle = open_file(file_iter, op.mode, ec);
file_handle = open_file(file_index, op.mode, ec);
if (((op.mode & file::rw_mask) == file::read_write) && ec == boost::system::errc::no_such_file_or_directory)
{
// this means the directory the file is in doesn't exist.
// so create it
ec.clear();
std::string path = files().file_path(*file_iter, m_save_path);
std::string path = files().file_path(file_index, m_save_path);
create_directories(parent_path(path), ec);
// if the directory creation failed, don't try to open the file again
// but actually just fail
if (!ec) file_handle = open_file(file_iter, op.mode, ec);
if (!ec) file_handle = open_file(file_index, op.mode, ec);
}
if (!file_handle || ec)
{
std::string path = files().file_path(*file_iter, m_save_path);
std::string path = files().file_path(file_index, m_save_path);
TORRENT_ASSERT(ec);
set_error(path, ec);
return -1;
@ -1234,7 +1220,7 @@ ret:
// read is unaligned, we need to fall back on a slow
// special read that reads aligned buffers and copies
// it into the one supplied
size_type adjusted_offset = files().file_base(*file_iter) + file_offset;
size_type adjusted_offset = files().file_base(file_index) + file_offset;
if ((file_handle->open_mode() & file::no_buffer)
&& ((adjusted_offset & (file_handle->pos_alignment()-1)) != 0
|| (uintptr_t(tmp_bufs->iov_base) & (file_handle->buf_alignment()-1)) != 0))
@ -1242,7 +1228,7 @@ ret:
bytes_transferred = (int)(this->*op.unaligned_op)(file_handle, adjusted_offset
, tmp_bufs, num_tmp_bufs, ec);
if ((op.mode & file::rw_mask) == file::read_write
&& adjusted_offset + bytes_transferred >= file_iter->size
&& adjusted_offset + bytes_transferred >= files().file_size(file_index)
&& (file_handle->pos_alignment() > 0 || file_handle->size_alignment() > 0))
{
// we were writing, and we just wrote the last block of the file
@ -1252,7 +1238,7 @@ ret:
// TODO: 0 what if file_base is used to merge several virtual files
// into a single physical file? We should probably disable this
// if file_base is used. This is not a widely used feature though
file_handle->set_size(file_iter->size, ec);
file_handle->set_size(files().file_size(file_index), ec);
}
}
else
@ -1265,7 +1251,7 @@ ret:
if (ec)
{
set_error(files().file_path(*file_iter, m_save_path), ec);
set_error(files().file_path(file_index, m_save_path), ec);
return -1;
}
@ -1398,20 +1384,20 @@ ret:
return readv(&b, slot, offset, 1);
}
boost::intrusive_ptr<file> default_storage::open_file(file_storage::iterator fe, int mode
boost::intrusive_ptr<file> default_storage::open_file(int file_index, int mode
, error_code& ec) const
{
int cache_setting = m_settings ? settings().disk_io_write_mode : 0;
if (cache_setting == session_settings::disable_os_cache
|| (cache_setting == session_settings::disable_os_cache_for_aligned_files
&& ((fe->offset + files().file_base(*fe)) & (m_page_size-1)) == 0))
&& ((files().file_offset(file_index) + files().file_base(file_index)) & (m_page_size-1)) == 0))
mode |= file::no_buffer;
bool lock_files = m_settings ? settings().lock_files : false;
if (lock_files) mode |= file::lock_file;
if (!m_allocate_files) mode |= file::sparse;
if (m_settings && settings().no_atime_storage) mode |= file::no_atime;
return m_pool.open_file(const_cast<default_storage*>(this), m_save_path, fe, files(), mode, ec);
return m_pool.open_file(const_cast<default_storage*>(this), m_save_path, file_index, files(), mode, ec);
}
storage_interface* default_storage_constructor(file_storage const& fs
@ -2482,10 +2468,9 @@ ret:
{
size_type file_offset = 0;
size_type current_offset = size_type(m_current_slot) * m_files.piece_length();
for (file_storage::iterator i = m_files.begin()
, end(m_files.end()); i != end; ++i)
for (int i = 0; i < m_files.num_files(); ++i)
{
file_offset += i->size;
file_offset += m_files.file_size(i);
if (file_offset > current_offset) break;
}

View File

@ -1717,14 +1717,13 @@ namespace libtorrent
#endif
TORRENT_ASSERT(block_size() > 0);
int file = 0;
for (file_storage::iterator i = m_torrent_file->files().begin()
, end(m_torrent_file->files().end()); i != end; ++i, ++file)
file_storage const& fs = m_torrent_file->files();
for (int i = 0; i < fs.num_files(); ++i)
{
if (!i->pad_file || i->size == 0) continue;
m_padding += i->size;
if (!fs.pad_file_at(i) || fs.file_size(i) == 0) continue;
m_padding += fs.file_size(i);
peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size);
peer_request pr = m_torrent_file->map_file(i, 0, fs.file_size(i));
int off = pr.start & (block_size()-1);
if (off != 0) { pr.length -= block_size() - off; pr.start += block_size() - off; }
TORRENT_ASSERT((pr.start & (block_size()-1)) == 0);
@ -1740,8 +1739,8 @@ namespace libtorrent
// ugly edge case where padfiles are not used they way they're
// supposed to be. i.e. added back-to back or at the end
if (int(pb.block_index) == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; }
if (pr.length > 0 && ((boost::next(i) != end && boost::next(i)->pad_file)
|| boost::next(i) == end))
if (pr.length > 0 && ((i+1 != fs.num_files() && fs.pad_file_at(i+1))
|| i + 1 == fs.num_files()))
{
m_picker->mark_as_finished(pb, 0);
}
@ -2991,12 +2990,10 @@ namespace libtorrent
if (m_padding > 0 && accurate)
{
file_storage const& files = m_torrent_file->files();
int fileno = 0;
for (file_storage::iterator i = files.begin()
, end(files.end()); i != end; ++i, ++fileno)
for (int i = 0; i < files.num_files(); ++i)
{
if (!i->pad_file) continue;
peer_request p = files.map_file(fileno, 0, i->size);
if (!files.pad_file_at(i)) continue;
peer_request p = files.map_file(i, 0, files.file_size(i));
for (int j = p.piece; p.length > 0; ++j)
{
int deduction = (std::min)(p.length, piece_size - p.start);
@ -3233,15 +3230,15 @@ namespace libtorrent
const int piece_size = m_torrent_file->piece_length();
size_type off = size_type(index) * piece_size;
file_storage::iterator f = m_torrent_file->files().file_at_offset(off);
int file_index = m_torrent_file->files().file_index_at_offset(off);
int size = m_torrent_file->piece_size(index);
int file_index = f - m_torrent_file->files().begin();
for (; size > 0; ++f, ++file_index)
file_storage const& fs = m_torrent_file->files();
for (; size > 0; ++file_index)
{
size_type file_offset = off - f->offset;
TORRENT_ASSERT(f != m_torrent_file->files().end());
TORRENT_ASSERT(file_offset <= f->size);
int add = (std::min)(f->size - file_offset, (size_type)size);
size_type file_offset = off - fs.file_offset(file_index);
TORRENT_ASSERT(file_index != fs.num_files());
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
int add = (std::min)(fs.file_size(file_index) - file_offset, (size_type)size);
m_file_progress[file_index] += add;
TORRENT_ASSERT(m_file_progress[file_index]
@ -4130,16 +4127,15 @@ namespace libtorrent
// initialize the piece priorities to 0, then only allow
// setting higher priorities
std::vector<int> pieces(m_torrent_file->num_pieces(), 0);
int index = 0;
for (file_storage::iterator i = m_torrent_file->files().begin()
, end(m_torrent_file->files().end()); i != end; ++i, ++index)
file_storage const& fs = m_torrent_file->files();
for (int i = 0; i < fs.num_files(); ++i)
{
if (index >= m_torrent_file->num_files()) break;
if (i >= m_torrent_file->num_files()) break;
size_type start = position;
size_type size = m_torrent_file->files().file_size(*i);
size_type size = m_torrent_file->files().file_size(i);
if (size == 0) continue;
position += size;
if (m_file_priority[index] == 0) continue;
if (m_file_priority[i] == 0) continue;
// mark all pieces of the file with this file's priority
// but only if the priority is higher than the pieces
@ -4151,7 +4147,7 @@ namespace libtorrent
// come here several times with the same start_piece, end_piece
std::for_each(pieces.begin() + start_piece
, pieces.begin() + last_piece + 1
, boost::bind(&set_if_greater, _1, m_file_priority[index]));
, boost::bind(&set_if_greater, _1, m_file_priority[i]));
}
prioritize_pieces(pieces);
}
@ -5484,10 +5480,10 @@ namespace libtorrent
&& m_torrent_file->files().num_files() == m_torrent_file->orig_files().num_files())
{
entry::list_type& fl = ret["mapped_files"].list();
for (torrent_info::file_iterator i = m_torrent_file->begin_files()
, end(m_torrent_file->end_files()); i != end; ++i)
file_storage const& fs = m_torrent_file->files();
for (int i = 0; i < fs.num_files(); ++i)
{
fl.push_back(m_torrent_file->files().file_path(*i));
fl.push_back(fs.file_path(i));
}
}
@ -8536,26 +8532,25 @@ namespace libtorrent
const std::vector<piece_picker::downloading_piece>& q
= m_picker->get_download_queue();
file_storage const& fs = m_torrent_file->files();
for (std::vector<piece_picker::downloading_piece>::const_iterator
i = q.begin(), end(q.end()); i != end; ++i)
{
size_type offset = size_type(i->index) * m_torrent_file->piece_length();
torrent_info::file_iterator file = m_torrent_file->file_at_offset(offset);
int file_index = file - m_torrent_file->begin_files();
int file = fs.file_index_at_offset(offset);
int num_blocks = m_picker->blocks_in_piece(i->index);
piece_picker::block_info const* info = i->info;
for (int k = 0; k < num_blocks; ++k)
{
TORRENT_ASSERT(file != m_torrent_file->end_files());
TORRENT_ASSERT(file < fs.num_files());
TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length()
+ k * block_size());
TORRENT_ASSERT(offset < m_torrent_file->total_size());
while (offset >= file->offset + file->size)
while (offset >= fs.file_offset(file) + fs.file_size(file))
{
++file;
++file_index;
}
TORRENT_ASSERT(file != m_torrent_file->end_files());
TORRENT_ASSERT(file < fs.num_files());
size_type block = block_size();
@ -8585,24 +8580,23 @@ namespace libtorrent
}
}
if (offset + block > file->offset + file->size)
if (offset + block > fs.file_offset(file) + fs.file_size(file))
{
int left_over = int(block_size() - block);
// split the block on multiple files
while (block > 0)
{
TORRENT_ASSERT(offset <= file->offset + file->size);
size_type slice = (std::min)(file->offset + file->size - offset
TORRENT_ASSERT(offset <= fs.file_offset(file) + fs.file_size(file));
size_type slice = (std::min)(fs.file_offset(file) + fs.file_size(file) - offset
, block);
fp[file_index] += slice;
fp[file] += slice;
offset += slice;
block -= slice;
TORRENT_ASSERT(offset <= file->offset + file->size);
if (offset == file->offset + file->size)
TORRENT_ASSERT(offset <= fs.file_offset(file) + fs.file_size(file));
if (offset == fs.file_offset(file) + fs.file_size(file))
{
++file;
++file_index;
if (file == m_torrent_file->end_files())
if (file == fs.num_files())
{
offset += block;
break;
@ -8615,10 +8609,10 @@ namespace libtorrent
}
else
{
fp[file_index] += block;
fp[file] += block;
offset += block_size();
}
TORRENT_ASSERT(file_index <= m_torrent_file->num_files());
TORRENT_ASSERT(file <= m_torrent_file->num_files());
}
}
}

View File

@ -412,15 +412,15 @@ namespace libtorrent
// This is a memory optimization! Instead of having
// each entry keep a string for its filename, make it
// simply point into the info-section buffer
internal_file_entry const& fe = *target.rbegin();
int last_index = target.num_files() - 1;
// TODO: 1 once the filename renaming is removed from here
// this check can be removed as well
if (fee && fe.filename() == fee->string_value())
if (fee && target.file_name(last_index) == fee->string_value())
{
// this string pointer does not necessarily point into
// the m_info_section buffer.
char const* str_ptr = fee->string_ptr() + info_ptr_diff;
const_cast<internal_file_entry&>(fe).set_name(str_ptr, fee->string_length());
target.rename_file_borrow(last_index, str_ptr, fee->string_length());
}
}
return true;
@ -1396,20 +1396,19 @@ namespace libtorrent
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
void torrent_info::check_invariant() const
{
for (file_storage::iterator i = m_files.begin()
, end(m_files.end()); i != end; ++i)
for (int i = 0; i < m_files.num_files(); ++i)
{
TORRENT_ASSERT(i->name != 0);
if (i->name_len > 0)
TORRENT_ASSERT(m_files.file_name_ptr(i) != 0);
if (m_files.file_name_len(i) > 0)
{
// name needs to point into the allocated info section buffer
TORRENT_ASSERT(i->name >= m_info_section.get());
TORRENT_ASSERT(i->name < m_info_section.get() + m_info_section_size);
TORRENT_ASSERT(m_files.file_name_ptr(i) >= m_info_section.get());
TORRENT_ASSERT(m_files.file_name_ptr(i) < m_info_section.get() + m_info_section_size);
}
else
{
// name must be a valid string
TORRENT_ASSERT(strlen(i->name) < 2048);
TORRENT_ASSERT(strlen(m_files.file_name_ptr(i)) < 2048);
}
}

View File

@ -225,7 +225,7 @@ namespace libtorrent
i != files.end(); ++i)
{
file_slice const& f = *i;
if (info.orig_files().internal_at(f.file_index).pad_file)
if (info.orig_files().pad_file_at(f.file_index))
{
m_file_requests.push_back(f.file_index);
continue;
@ -235,7 +235,7 @@ namespace libtorrent
if (using_proxy)
{
request += m_url;
std::string path = info.orig_files().file_path(info.orig_files().internal_at(f.file_index));
std::string path = info.orig_files().file_path(f.file_index);
#ifdef TORRENT_WINDOWS
convert_path_to_posix(path);
#endif
@ -244,7 +244,7 @@ namespace libtorrent
else
{
std::string path = m_path;
path += info.orig_files().file_path(info.orig_files().internal_at(f.file_index));
path += info.orig_files().file_path(f.file_index);
#ifdef TORRENT_WINDOWS
convert_path_to_posix(path);
#endif
@ -522,7 +522,7 @@ namespace libtorrent
int file_index = m_file_requests.front();
torrent_info const& info = t->torrent_file();
std::string path = info.orig_files().file_path(info.orig_files().at(file_index));
std::string path = info.orig_files().file_path(file_index);
#ifdef TORRENT_WINDOWS
convert_path_to_posix(path);
#endif
@ -866,7 +866,7 @@ namespace libtorrent
torrent_info const& info = t->torrent_file();
while (!m_file_requests.empty()
&& info.orig_files().internal_at(m_file_requests.front()).pad_file)
&& info.orig_files().pad_file_at(m_file_requests.front()))
{
// the next file is a pad file. We didn't actually send
// a request for this since it most likely doesn't exist on
@ -874,7 +874,7 @@ namespace libtorrent
// bunch of zeroes here and pop it again
int file_index = m_file_requests.front();
m_file_requests.pop_front();
size_type file_size = info.orig_files().file_size(info.orig_files().internal_at(file_index));
size_type file_size = info.orig_files().file_size(file_index);
TORRENT_ASSERT(m_block_pos < front_request.length);
int pad_size = (std::min)(file_size, size_type(front_request.length - m_block_pos));

View File

@ -872,7 +872,7 @@ void run_test(std::string const& test_path, bool unbuffered)
file_storage fs;
fs.add_file(combine_path("temp_storage", "test1.tmp"), 3 * piece_size);
libtorrent::create_torrent t(fs, piece_size, -1, 0);
TEST_CHECK(fs.file_path(*fs.begin()) == combine_path("temp_storage", "test1.tmp"));
TEST_CHECK(fs.file_path(0) == combine_path("temp_storage", "test1.tmp"));
t.set_hash(0, hasher(piece0, piece_size).final());
t.set_hash(1, hasher(piece1, piece_size).final());
t.set_hash(2, hasher(piece2, piece_size).final());

View File

@ -179,24 +179,24 @@ int test_main()
#endif
}
int index = 0;
for (torrent_info::file_iterator i = ti->begin_files();
i != ti->end_files(); ++i, ++index)
file_storage const& fs = ti->files();
for (int i = 0; i < fs.num_files(); ++i)
{
int first = ti->map_file(index, 0, 0).piece;
int last = ti->map_file(index, (std::max)(size_type(i->size)-1, size_type(0)), 0).piece;
int first = ti->map_file(i, 0, 0).piece;
int last = ti->map_file(i, (std::max)(fs.file_size(i)-1, size_type(0)), 0).piece;
int flags = fs.file_flags(i);
fprintf(stderr, " %11"PRId64" %c%c%c%c [ %4d, %4d ] %7u %s %s %s%s\n"
, i->size
, (i->pad_file?'p':'-')
, (i->executable_attribute?'x':'-')
, (i->hidden_attribute?'h':'-')
, (i->symlink_attribute?'l':'-')
, fs.file_size(i)
, (flags & file_storage::flag_pad_file)?'p':'-'
, (flags & file_storage::flag_executable)?'x':'-'
, (flags & file_storage::flag_hidden)?'h':'-'
, (flags & file_storage::flag_symlink)?'l':'-'
, first, last
, boost::uint32_t(ti->files().mtime(*i))
, ti->files().hash(*i) != sha1_hash(0) ? to_hex(ti->files().hash(*i).to_string()).c_str() : ""
, ti->files().file_path(*i).c_str()
, i->symlink_attribute ? "-> ": ""
, i->symlink_attribute && i->symlink_index != -1 ? ti->files().symlink(*i).c_str() : "");
, boost::uint32_t(fs.mtime(i))
, fs.hash(i) != sha1_hash(0) ? to_hex(fs.hash(i).to_string()).c_str() : ""
, fs.file_path(i).c_str()
, flags & file_storage::flag_symlink ? "-> ": ""
, flags & file_storage::flag_symlink ? fs.symlink(i).c_str() : "");
}
// test swap

View File

@ -174,8 +174,7 @@ void test_transfer(boost::intrusive_ptr<torrent_info> torrent_file
if (proxy) stop_proxy(8002);
TEST_CHECK(exists(combine_path("tmp2_web_seed", torrent_file->files().file_path(
torrent_file->file_at(0)))) || test_ban);
TEST_CHECK(exists(combine_path("tmp2_web_seed", torrent_file->files().file_path(0))) || test_ban);
remove_all("tmp2_web_seed", ec);
}