*** empty log message ***
This commit is contained in:
parent
02871e5977
commit
258d691dae
|
@ -868,7 +868,11 @@ This reference is valid as long as the <a class="reference" href="#torrent-handl
|
|||
<div class="section" id="is-valid">
|
||||
<h2><a name="is-valid">is_valid()</a></h2>
|
||||
<p>Returns true if this handle refers to a valid torrent and false if it hasn't been initialized
|
||||
or if the torrent it refers to has been aborted.</p>
|
||||
or if the torrent it refers to has been aborted. Note that a handle may become invalid after
|
||||
it has been added to the session. Usually this is because the storage for the torrent is
|
||||
somehow invalid or if the filenames are not allowed (and hence cannot be opened/created) on
|
||||
your filesystem. If such an error occurs, a <a class="reference" href="#file-error-alert">file_error_alert</a> is generated and all handles
|
||||
that refers to that torrent will become invalid.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="address">
|
||||
|
|
|
@ -891,7 +891,11 @@ is_valid()
|
|||
----------
|
||||
|
||||
Returns true if this handle refers to a valid torrent and false if it hasn't been initialized
|
||||
or if the torrent it refers to has been aborted.
|
||||
or if the torrent it refers to has been aborted. Note that a handle may become invalid after
|
||||
it has been added to the session. Usually this is because the storage for the torrent is
|
||||
somehow invalid or if the filenames are not allowed (and hence cannot be opened/created) on
|
||||
your filesystem. If such an error occurs, a file_error_alert_ is generated and all handles
|
||||
that refers to that torrent will become invalid.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
// boost::filesystem::path::default_name_check(boost::filesystem::native);
|
||||
boost::filesystem::path::default_name_check(boost::filesystem::native);
|
||||
|
||||
http_settings settings;
|
||||
// settings.proxy_ip = "192.168.0.1";
|
||||
|
@ -340,6 +340,12 @@ int main(int argc, char* argv[])
|
|||
i != handles.end();
|
||||
++i)
|
||||
{
|
||||
if (!i->is_valid())
|
||||
{
|
||||
handles.erase(i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
torrent_status s = i->status();
|
||||
|
||||
switch(s.state)
|
||||
|
|
|
@ -91,20 +91,11 @@ namespace libtorrent
|
|||
{
|
||||
public:
|
||||
|
||||
torrent_info(const entry& torrent_file)
|
||||
: m_creation_date(boost::gregorian::date(1970
|
||||
, boost::gregorian::Jan
|
||||
, 1))
|
||||
{
|
||||
try
|
||||
{
|
||||
read_torrent_info(torrent_file);
|
||||
}
|
||||
catch(type_error&)
|
||||
{
|
||||
throw invalid_torrent_file();
|
||||
}
|
||||
}
|
||||
torrent_info(const entry& torrent_file);
|
||||
|
||||
torrent_info(
|
||||
const std::vector<file_entry>& files
|
||||
, int piece_size);
|
||||
|
||||
typedef std::vector<file_entry>::const_iterator file_iterator;
|
||||
typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator;
|
||||
|
|
|
@ -215,17 +215,22 @@ namespace libtorrent { namespace detail
|
|||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
// TODO: generate an alert here!
|
||||
// This will happen if the storage fails to initialize
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "error while checking files: " << e.what() << "\n";
|
||||
#endif
|
||||
boost::mutex::scoped_lock l(m_ses.m_mutex);
|
||||
if (m_ses.m_alerts.should_post(alert::fatal))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
file_error_alert(
|
||||
t->torrent_ptr->get_handle()
|
||||
, e.what()));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "error while checking files\n";
|
||||
#endif
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// remove ourself from the 'checking'-list
|
||||
|
@ -730,6 +735,15 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
||||
= m_torrents.find(info_hash);
|
||||
#ifndef NDEBUG
|
||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator j
|
||||
= m_torrents.begin();
|
||||
j != m_torrents.end();
|
||||
++j)
|
||||
{
|
||||
torrent* p = boost::get_pointer(j->second);
|
||||
}
|
||||
#endif
|
||||
if (i != m_torrents.end()) return boost::get_pointer(i->second);
|
||||
return 0;
|
||||
}
|
||||
|
|
311
src/storage.cpp
311
src/storage.cpp
|
@ -750,318 +750,7 @@ namespace libtorrent
|
|||
{
|
||||
m_pimpl->write(buf, piece_index, offset, size);
|
||||
}
|
||||
/*
|
||||
void piece_manager::impl::check_pieces(
|
||||
boost::mutex& mutex
|
||||
, detail::piece_checker_data& data
|
||||
, std::vector<bool>& pieces)
|
||||
{
|
||||
// synchronization ------------------------------------------------------
|
||||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#ifndef NDEBUG
|
||||
check_invariant();
|
||||
#endif
|
||||
|
||||
m_allocating = false;
|
||||
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
|
||||
m_slot_to_piece.resize(m_info.num_pieces(), unallocated);
|
||||
m_free_slots.clear();
|
||||
m_unallocated_slots.clear();
|
||||
|
||||
const std::size_t piece_size = m_info.piece_length();
|
||||
const std::size_t last_piece_size = m_info.piece_size(
|
||||
m_info.num_pieces() - 1);
|
||||
|
||||
|
||||
|
||||
// if we have fast-resume info
|
||||
// use it instead of doing the actual checking
|
||||
if (!data.piece_map.empty()
|
||||
&& data.piece_map.size() <= m_slot_to_piece.size())
|
||||
{
|
||||
for (int i = 0; i < (int)data.piece_map.size(); ++i)
|
||||
{
|
||||
m_slot_to_piece[i] = data.piece_map[i];
|
||||
if (data.piece_map[i] >= 0)
|
||||
{
|
||||
m_piece_to_slot[data.piece_map[i]] = i;
|
||||
int found_piece = data.piece_map[i];
|
||||
|
||||
// if the piece is not in the unfinished list
|
||||
// we have all of it
|
||||
if (std::find_if(
|
||||
data.unfinished_pieces.begin()
|
||||
, data.unfinished_pieces.end()
|
||||
, piece_picker::has_index(found_piece))
|
||||
== data.unfinished_pieces.end())
|
||||
{
|
||||
pieces[found_piece] = true;
|
||||
}
|
||||
}
|
||||
else if (data.piece_map[i] == unassigned)
|
||||
{
|
||||
m_free_slots.push_back(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(data.piece_map[i] == unallocated);
|
||||
m_unallocated_slots.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = data.piece_map.size(); i < (int)pieces.size(); ++i)
|
||||
{
|
||||
m_unallocated_slots.push_back(i);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
check_invariant();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// do the real check (we didn't have valid resume data)
|
||||
|
||||
bool changed_file = true;
|
||||
file in;
|
||||
|
||||
std::vector<char> piece_data(m_info.piece_length());
|
||||
std::size_t piece_offset = 0;
|
||||
|
||||
int current_slot = 0;
|
||||
std::size_t bytes_to_read = m_info.piece_size(0);
|
||||
size_type bytes_current_read = 0;
|
||||
size_type seek_into_next = 0;
|
||||
size_type filesize = 0;
|
||||
size_type start_of_read = 0;
|
||||
size_type start_of_file = 0;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
data.progress = 0.f;
|
||||
}
|
||||
|
||||
for (torrent_info::file_iterator file_iter = m_info.begin_files(),
|
||||
end_iter = m_info.end_files();
|
||||
file_iter != end_iter;)
|
||||
{
|
||||
assert(current_slot >= 0 && current_slot < m_info.num_pieces());
|
||||
|
||||
// Update progress meter and check if we've been requested to abort
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
|
||||
data.progress = (float)current_slot / m_info.num_pieces();
|
||||
if (data.abort)
|
||||
return;
|
||||
}
|
||||
|
||||
fs::path path(m_save_path / file_iter->path);
|
||||
|
||||
// if the path doesn't exist, create the
|
||||
// entire directory tree
|
||||
if (!fs::exists(path))
|
||||
fs::create_directories(path);
|
||||
|
||||
path /= file_iter->filename;
|
||||
|
||||
if (changed_file)
|
||||
{
|
||||
try
|
||||
{
|
||||
changed_file = false;
|
||||
bytes_current_read = seek_into_next;
|
||||
in.open(path, file::in);
|
||||
|
||||
in.seek(0, file::end);
|
||||
filesize = in.tell();
|
||||
in.seek(seek_into_next);
|
||||
}
|
||||
catch (file_error&)
|
||||
{
|
||||
filesize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// we are at the start of a new piece
|
||||
// so we store the start of the piece
|
||||
if (bytes_to_read == m_info.piece_size(current_slot))
|
||||
start_of_read = current_slot * (size_type)piece_size;
|
||||
|
||||
std::size_t bytes_read = 0;
|
||||
|
||||
if (filesize > 0)
|
||||
{
|
||||
bytes_read = in.read(&piece_data[piece_offset], bytes_to_read);
|
||||
assert(bytes_read>0);
|
||||
}
|
||||
|
||||
bytes_current_read += bytes_read;
|
||||
bytes_to_read -= bytes_read;
|
||||
|
||||
assert(bytes_to_read >= 0);
|
||||
|
||||
// bytes left to read, go on with next file
|
||||
if (bytes_to_read > 0)
|
||||
{
|
||||
if (bytes_current_read != file_iter->size)
|
||||
{
|
||||
size_type pos;
|
||||
size_type file_end = start_of_file + file_iter->size;
|
||||
|
||||
for (pos = start_of_read; pos < file_end;
|
||||
pos += piece_size)
|
||||
{
|
||||
m_unallocated_slots.push_back(current_slot);
|
||||
++current_slot;
|
||||
}
|
||||
|
||||
seek_into_next = pos - file_end;
|
||||
if (current_slot >= m_info.num_pieces())
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes_to_read = m_info.piece_size(current_slot);
|
||||
piece_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
seek_into_next = 0;
|
||||
piece_offset += bytes_read;
|
||||
}
|
||||
|
||||
changed_file = true;
|
||||
start_of_file += file_iter->size;
|
||||
++file_iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(current_slot < m_info.num_pieces());
|
||||
assert(m_slot_to_piece[current_slot] == unallocated);
|
||||
assert(m_piece_to_slot[current_slot] == has_no_slot ||
|
||||
(m_piece_to_slot[current_slot] >= 0 &&
|
||||
m_piece_to_slot[current_slot] < current_slot &&
|
||||
m_slot_to_piece[m_piece_to_slot[current_slot]] == current_slot));
|
||||
|
||||
// we need to take special actions if this is
|
||||
// the last piece, since that piece might actually
|
||||
// be smaller than piece_size.
|
||||
|
||||
lazy_hash large_digest(&piece_data[0], piece_size);
|
||||
lazy_hash small_digest(&piece_data[0], last_piece_size);
|
||||
|
||||
const lazy_hash* digest[2] = {
|
||||
&large_digest, &small_digest
|
||||
};
|
||||
|
||||
int found_piece = -1;
|
||||
|
||||
for (int i = current_slot; i < m_info.num_pieces(); ++i)
|
||||
{
|
||||
if (pieces[i] && i != current_slot) continue;
|
||||
|
||||
const sha1_hash& hash = digest[
|
||||
(i == m_info.num_pieces() - 1) ? 1 : 0]->get();
|
||||
|
||||
if (hash == m_info.hash_for_piece(i))
|
||||
{
|
||||
found_piece = i;
|
||||
if (i == current_slot) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_piece != -1)
|
||||
{
|
||||
// if we have found this piece hash once already
|
||||
// move it to the free pieces and don't decrease
|
||||
// bytes_left
|
||||
if (pieces[found_piece])
|
||||
{
|
||||
assert(m_piece_to_slot[found_piece] == current_slot);
|
||||
m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned;
|
||||
m_free_slots.push_back(m_piece_to_slot[found_piece]);
|
||||
m_piece_to_slot[found_piece] = has_no_slot;
|
||||
}
|
||||
|
||||
assert(m_piece_to_slot[found_piece] == has_no_slot);
|
||||
m_piece_to_slot[found_piece] = current_slot;
|
||||
m_slot_to_piece[current_slot] = found_piece;
|
||||
pieces[found_piece] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(found_piece == -1);
|
||||
m_slot_to_piece[current_slot] = unassigned;
|
||||
|
||||
m_free_slots.push_back(current_slot);
|
||||
}
|
||||
|
||||
assert(m_slot_to_piece[current_slot] != unallocated);
|
||||
|
||||
// done with piece, move on to next
|
||||
piece_offset = 0;
|
||||
++current_slot;
|
||||
if (current_slot == m_info.num_pieces())
|
||||
{
|
||||
assert(file_iter == end_iter-1);
|
||||
break;
|
||||
}
|
||||
bytes_to_read = m_info.piece_size(current_slot);
|
||||
}
|
||||
|
||||
// dirty "fix" for a bug when file is corrupt
|
||||
for (int i = 0; i < (int)m_info.num_pieces(); ++i)
|
||||
{
|
||||
if(m_piece_to_slot[i] != has_no_slot
|
||||
&& m_piece_to_slot[i] != i
|
||||
&& m_slot_to_piece[i] != unallocated)
|
||||
{
|
||||
assert(m_piece_to_slot[i] >= 0);
|
||||
assert(m_piece_to_slot[i] < (int)m_slot_to_piece.size());
|
||||
assert(m_slot_to_piece[m_piece_to_slot[i]] == i);
|
||||
if(m_slot_to_piece[i]!=unassigned)
|
||||
{
|
||||
assert(m_slot_to_piece[i] >= 0);
|
||||
assert(m_slot_to_piece[i] < (int)m_piece_to_slot.size());
|
||||
assert(m_piece_to_slot[m_slot_to_piece[i]] == i);
|
||||
|
||||
m_piece_to_slot[m_slot_to_piece[i]] = has_no_slot;
|
||||
m_slot_to_piece[i] = unassigned;
|
||||
m_free_slots.push_back(i);
|
||||
}
|
||||
m_slot_to_piece[m_piece_to_slot[i]] = unassigned;
|
||||
m_free_slots.push_back(m_piece_to_slot[i]);
|
||||
m_piece_to_slot[i] = has_no_slot;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::stringstream s;
|
||||
|
||||
s << " m_free_slots: " << m_free_slots.size() << "\n"
|
||||
" m_unallocated_slots: " << m_unallocated_slots.size() << "\n"
|
||||
" num pieces: " << m_info.num_pieces() << "\n"
|
||||
" have_pieces:\n";
|
||||
for (std::vector<bool>::iterator i = pieces.begin();
|
||||
i != pieces.end();
|
||||
++i)
|
||||
{
|
||||
if (((i - pieces.begin()) % 60) == 0) s << "\n";
|
||||
if (*i) s << "1"; else s << "0";
|
||||
}
|
||||
s << "\n";
|
||||
s << std::count(pieces.begin(), pieces.end(), true) << "\n";
|
||||
data.torrent_ptr->debug_log(s.str());
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
check_invariant();
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
int piece_manager::impl::identify_data(
|
||||
const std::vector<char>& piece_data
|
||||
, int current_slot
|
||||
|
|
|
@ -91,6 +91,44 @@ namespace
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
// standard constructor that parses a torrent file
|
||||
torrent_info::torrent_info(const entry& torrent_file)
|
||||
: m_creation_date(boost::gregorian::date(1970
|
||||
, boost::gregorian::Jan
|
||||
, 1))
|
||||
{
|
||||
try
|
||||
{
|
||||
read_torrent_info(torrent_file);
|
||||
}
|
||||
catch(type_error&)
|
||||
{
|
||||
throw invalid_torrent_file();
|
||||
}
|
||||
}
|
||||
|
||||
// constructor used for creating new torrents
|
||||
// will not contain any hashes, comments, creation date
|
||||
// just the necessary to use it with piece manager
|
||||
torrent_info::torrent_info(
|
||||
const std::vector<file_entry>& files
|
||||
, int piece_size)
|
||||
: m_piece_length(piece_size)
|
||||
, m_files(files)
|
||||
, m_creation_date(boost::gregorian::date(1970
|
||||
, boost::gregorian::Jan
|
||||
, 1))
|
||||
{
|
||||
// calculate total size of all pieces
|
||||
m_total_size = 0;
|
||||
for (std::vector<file_entry>::iterator i = m_files.begin(); i != m_files.end(); ++i)
|
||||
m_total_size += i->size;
|
||||
|
||||
int num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// extracts information from a libtorrent file and fills in the structures in
|
||||
// the torrent object
|
||||
void torrent_info::read_torrent_info(const entry& torrent_file)
|
||||
|
|
Loading…
Reference in New Issue