*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-03-03 13:47:12 +00:00
parent 02871e5977
commit 258d691dae
7 changed files with 78 additions and 332 deletions

View File

@ -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">

View File

@ -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.

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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)