From 258d691dae7e4fab3241b49211a4ea9657125b9b Mon Sep 17 00:00:00 2001
From: Arvid Norberg
Date: Wed, 3 Mar 2004 13:47:12 +0000
Subject: [PATCH] *** empty log message ***
---
docs/manual.html | 6 +-
docs/manual.rst | 6 +-
examples/client_test.cpp | 8 +-
include/libtorrent/torrent_info.hpp | 19 +-
src/session.cpp | 22 +-
src/storage.cpp | 311 ----------------------------
src/torrent_info.cpp | 38 ++++
7 files changed, 78 insertions(+), 332 deletions(-)
diff --git a/docs/manual.html b/docs/manual.html
index 2feec6f04..8bdf133c5 100755
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -868,7 +868,11 @@ This reference is valid as long as the
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.
diff --git a/docs/manual.rst b/docs/manual.rst
index 445c7995c..0e96eec24 100755
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -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.
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 898560c8c..b7b4b20c1 100755
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -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)
diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp
index c638ad315..ff418db5c 100755
--- a/include/libtorrent/torrent_info.hpp
+++ b/include/libtorrent/torrent_info.hpp
@@ -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& files
+ , int piece_size);
typedef std::vector::const_iterator file_iterator;
typedef std::vector::const_reverse_iterator reverse_file_iterator;
diff --git a/src/session.cpp b/src/session.cpp
index d4f153805..3f12578c7 100755
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -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 >::iterator i
= m_torrents.find(info_hash);
+#ifndef NDEBUG
+ for (std::map >::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;
}
diff --git a/src/storage.cpp b/src/storage.cpp
index 077308701..1c8082f85 100755
--- a/src/storage.cpp
+++ b/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& 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 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::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& piece_data
, int current_slot
diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp
index fce98d44c..ac8feebdb 100755
--- a/src/torrent_info.cpp
+++ b/src/torrent_info.cpp
@@ -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& 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::iterator i = m_files.begin(); i != m_files.end(); ++i)
+ m_total_size += i->size;
+
+ int num_pieces = static_cast((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)