*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-01-13 03:08:59 +00:00
parent b6c826c6af
commit abbedbf104
13 changed files with 234 additions and 124 deletions

View File

@ -1305,10 +1305,8 @@ tells which piece is on which slot. If piece index is -2 it
means it is free, that there's no piece there. If it is -1,
means the slot isn't allocated on disk yet. The pieces have
to meet the following requirement:</p>
<ul class="last simple">
<li>if there's a slot at the position of the piece index,
the piece must be located in that slot.</li>
</ul>
<p class="last">If there's a slot at the position of the piece index,
the piece must be located in that slot.</p>
</td>
</tr>
<tr><td><tt class="literal"><span class="pre">peers</span></tt></td>

View File

@ -1104,6 +1104,29 @@ as severity level ``debug``.
};
invalid_request_alert
---------------------
Thie is a debug alert that is generated by an incoming invalid piece request.
::
struct invalid_request_alert: alert
{
invalid_request_alert(
const peer_request& r
, const torrent_handle& h
, const peer_id& send
, const std::string& msg);
virtual std::auto_ptr<alert> clone() const;
torrent_handle handle;
peer_id sender;
peer_request request;
};
chat_message_alert
------------------
@ -1372,8 +1395,8 @@ The file format is a bencoded dictionary containing the following fields:
| | means the slot isn't allocated on disk yet. The pieces have |
| | to meet the following requirement: |
| | |
| | * if there's a slot at the position of the piece index, |
| | the piece must be located in that slot. |
| | If there's a slot at the position of the piece index, |
| | the piece must be located in that slot. |
+----------------------+--------------------------------------------------------------+
| ``peers`` | list of dictionaries. Each dictionary has the following |
| | layout: |
@ -1398,6 +1421,7 @@ The file format is a bencoded dictionary containing the following fields:
| | | | blocks that have been downloaded in this | |
| | | | piece. | |
| | +-------------+--------------------------------------------+ |
| | |
+----------------------+--------------------------------------------------------------+

View File

@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/format.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/fstream.hpp>
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
@ -186,9 +187,9 @@ std::string add_suffix(float val)
int i;
for (i = 0; i < num_prefix; ++i)
{
if (fabs(val) < 1024.f)
if (fabs(val) < 1000.f)
return to_string(val, i==0?7:6) + prefix[i];
val /= 1024.f;
val /= 1000.f;
}
return to_string(val, 6) + prefix[i];
}
@ -233,11 +234,13 @@ int main(int argc, char* argv[])
torrent_info t(e);
t.print(std::cout);
boost::filesystem::path save_path("");
entry resume_data;
try
{
// TODO: use a torrent-specific name here
std::ifstream resume_file("test.fastresume", std::ios_base::binary);
std::stringstream s;
s << t.name() << ".fastresume";
boost::filesystem::ifstream resume_file(save_path / s.str(), std::ios_base::binary);
resume_file.unsetf(std::ios_base::skipws);
resume_data = bdecode(std::istream_iterator<char>(resume_file)
, std::istream_iterator<char>());
@ -245,7 +248,7 @@ int main(int argc, char* argv[])
catch (invalid_encoding&)
{}
handles.push_back(ses.add_torrent(t, "", resume_data));
handles.push_back(ses.add_torrent(t, save_path, resume_data));
handles.back().set_max_uploads(7);
handles.back().set_ratio(1);
}
@ -265,11 +268,18 @@ int main(int argc, char* argv[])
{
if (c == 'q')
{
entry data = handles.front().write_resume_data();
// TODO: use a torrent-specific name here
std::ofstream out("test.fastresume", std::ios_base::binary);
out.unsetf(std::ios_base::skipws);
bencode(std::ostream_iterator<char>(out), data);
for (std::vector<torrent_handle>::iterator i = handles.begin();
i != handles.end();
++i)
{
torrent_handle h = *i;
entry data = h.write_resume_data();
std::stringstream s;
s << h.get_torrent_info().name() << ".fastresume";
boost::filesystem::ofstream out(h.save_path() / s.str(), std::ios_base::binary);
out.unsetf(std::ios_base::skipws);
bencode(std::ostream_iterator<char>(out), data);
}
break;
}
}

View File

@ -168,7 +168,6 @@ namespace libtorrent
peer_id sender;
};
// TODO: document
struct invalid_request_alert: alert
{
invalid_request_alert(

View File

@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <bitset>
#include <cassert>
#include <boost/optional.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
@ -166,10 +168,13 @@ namespace libtorrent
// the hash-check yet
int unverified_blocks() const;
void get_downloaders(std::vector<address>& d, int index);
void get_downloaders(std::vector<address>& d, int index) const;
const std::vector<downloading_piece>& get_download_queue() const
{ return m_downloads; }
boost::optional<address> get_downloader(piece_block block) const;
#ifndef NDEBUG
// used in debug mode
void integrity_check(const torrent* t = 0) const;

View File

@ -55,7 +55,7 @@ namespace libtorrent
{
file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
virtual const char* what() const throw() { return m_msg.c_str(); }
virtual ~file_allocation_failed() {}
virtual ~file_allocation_failed() throw() {}
std::string m_msg;
};

View File

@ -173,6 +173,13 @@ namespace libtorrent
// decreased in the piece_picker
void remove_peer(peer_connection* p);
peer_connection* connection_for(const address& a)
{
peer_iterator i = m_connections.find(a);
if (i == m_connections.end()) return 0;
return i->second;
}
// the number of peers that belong to this torrent
int num_peers() const { return m_connections.size(); }
@ -180,11 +187,11 @@ namespace libtorrent
// to a peer with the given peer_id
bool has_peer(const peer_id& id) const;
typedef std::vector<peer_connection*>::iterator peer_iterator;
typedef std::vector<peer_connection*>::const_iterator peer_const_iterator;
typedef std::map<address, peer_connection*>::iterator peer_iterator;
typedef std::map<address, peer_connection*>::const_iterator const_peer_iterator;
peer_const_iterator begin() const { return m_connections.begin(); }
peer_const_iterator end() const { return m_connections.end(); }
const_peer_iterator begin() const { return m_connections.begin(); }
const_peer_iterator end() const { return m_connections.end(); }
peer_iterator begin() { return m_connections.begin(); }
peer_iterator end() { return m_connections.end(); }
@ -311,7 +318,10 @@ namespace libtorrent
// from the tracker
int m_duration;
std::vector<peer_connection*> m_connections;
// TODO: this should be a map, mapping address
// to peer_connection*
std::map<address, peer_connection*> m_connections;
// std::vector<peer_connection*> m_connections;
// this is the upload and download statistics for the whole torrent.
// it's updated from all its peers once every second.

View File

@ -33,7 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <iomanip>
#include <vector>
#include <limits>
#include "libtorrent/peer_connection.hpp"
@ -620,8 +619,8 @@ namespace libtorrent
&& i->block_index == p.start / m_torrent->block_size())
break;
(*m_logger) << " <== SKIPPED_PIECE [ piece: " << i->piece_index << " | "
"b: " << i->block_index << " ]\n";
(*m_logger) << " *** SKIPPED_PIECE [ piece: " << i->piece_index << " | "
"b: " << i->block_index << " ] ***\n";
if (m_torrent->alerts().should_post(alert::debug))
{
std::stringstream s;
@ -640,6 +639,9 @@ namespace libtorrent
piece_picker& picker = m_torrent->picker();
piece_block block_finished(p.piece, p.start / m_torrent->block_size());
// if the block we got is already finished, then ignore it
if (picker.is_finished(block_finished)) return;
std::deque<piece_block>::iterator b
= std::find(
m_download_queue.begin()
@ -654,13 +656,32 @@ namespace libtorrent
}
else
{
// TODO: cancel the block from the
// cancel the block from the
// peer that has taken over it.
boost::optional<address> peer = m_torrent->picker().get_downloader(block_finished);
if (peer)
{
peer_connection* pc = m_torrent->connection_for(*peer);
if (pc && pc != this)
{
pc->send_cancel(block_finished);
}
}
else
{
if (m_torrent->alerts().should_post(alert::debug))
{
m_torrent->alerts().post_alert(
peer_error_alert(
m_peer_id
, "got a block that was not requested"));
}
#ifndef NDEBUG
(*m_logger) << " *** The block we just got was not requested ***\n";
#endif
}
}
// if the block we got is already finished, then ignore it
if (picker.is_finished(block_finished)) return;
m_torrent->filesystem().write(&m_recv_buffer[9], p.piece, p.start, p.length);
picker.mark_as_finished(block_finished, m_socket->sender());
@ -1026,7 +1047,6 @@ namespace libtorrent
send_buffer_updated();
}
// TODO: rename to send_choke?
void peer_connection::send_choke()
{
if (m_choked) return;

View File

@ -152,11 +152,11 @@ namespace libtorrent
if (t != 0)
{
int actual_peer_count = 0;
for (std::vector<peer_connection*>::const_iterator peer = t->begin();
for (torrent::const_peer_iterator peer = t->begin();
peer != t->end();
++peer)
{
if ((*peer)->has_piece(index)) actual_peer_count++;
if (peer->second->has_piece(index)) actual_peer_count++;
}
assert(i->peer_count == actual_peer_count);
@ -518,7 +518,11 @@ namespace libtorrent
if (m_piece_map[block.piece_index].downloading == 0) return false;
std::vector<downloading_piece>::const_iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
= std::find_if(
m_downloads.begin()
, m_downloads.end()
, has_index(block.piece_index));
assert(i != m_downloads.end());
return i->requested_blocks[block.block_index];
}
@ -632,9 +636,9 @@ namespace libtorrent
#endif
}
*/
void piece_picker::get_downloaders(std::vector<address>& d, int index)
void piece_picker::get_downloaders(std::vector<address>& d, int index) const
{
std::vector<downloading_piece>::iterator i
std::vector<downloading_piece>::const_iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
assert(i != m_downloads.end());
@ -645,6 +649,26 @@ namespace libtorrent
}
}
boost::optional<address> piece_picker::get_downloader(piece_block block) const
{
std::vector<downloading_piece>::const_iterator i = std::find_if(
m_downloads.begin()
, m_downloads.end()
, has_index(block.piece_index));
if (i == m_downloads.end())
return boost::optional<address>();
assert(block.block_index < max_blocks_per_piece);
assert(block.block_index >= 0);
if (i->requested_blocks[block.block_index] == false
|| i->finished_blocks[block.block_index] == true)
return boost::optional<address>();
return boost::optional<address>(i->info[block.block_index].peer);
}
void piece_picker::abort_download(piece_block block)
{
#ifndef NDEBUG

View File

@ -168,15 +168,15 @@ namespace
i != t.end();
++i)
{
const std::deque<piece_block>& queue = (*i)->download_queue();
if ((*i)->statistics().down_peak() > down_speed
const std::deque<piece_block>& queue = i->second->download_queue();
if (i->second->statistics().down_peak() > down_speed
&& has_intersection(busy_pieces.begin(),
busy_pieces.end(),
queue.begin(),
queue.end()))
{
peer = *i;
down_speed = (*i)->statistics().down_peak();
peer = i->second;
down_speed = peer->statistics().down_peak();
}
}
@ -209,12 +209,12 @@ namespace
// want to trade it's surplus uploads for downloads itself
// (and we should consider it free). If the share diff is
// negative, there's no free download to get from this peer.
int diff = (*i)->share_diff();
if ((*i)->is_peer_interested() || diff <= 0)
int diff = i->second->share_diff();
if (i->second->is_peer_interested() || diff <= 0)
continue;
assert(diff > 0);
(*i)->add_free_upload(-diff);
i->second->add_free_upload(-diff);
accumulator += diff;
assert(accumulator > 0);
}
@ -235,8 +235,8 @@ namespace
int total_diff = 0;
for (torrent::peer_iterator i = start; i != end; ++i)
{
total_diff += (*i)->share_diff();
if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue;
total_diff += i->second->share_diff();
if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue;
++num_peers;
}
@ -254,8 +254,9 @@ namespace
for (torrent::peer_iterator i = start; i != end; ++i)
{
if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue;
(*i)->add_free_upload(upload_share);
peer_connection* p = i->second;
if (!p->is_peer_interested() || p->share_diff() >= 0) continue;
p->add_free_upload(upload_share);
free_upload -= upload_share;
}
return free_upload;

View File

@ -43,7 +43,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include "libtorrent/storage.hpp"
@ -437,6 +436,8 @@ namespace libtorrent {
boost::recursive_mutex::scoped_lock lock(m_mutex);
// ----------------------------------------------------------------------
check_invariant();
p.clear();
std::vector<int>::const_reverse_iterator last;
for (last = m_slot_to_piece.rbegin();
@ -453,6 +454,9 @@ namespace libtorrent {
{
p.push_back(*i);
}
check_invariant();
}
void piece_manager::export_piece_map(
@ -462,22 +466,30 @@ namespace libtorrent {
}
// TODO: daniel, make sure this function does everything it needs to do
void piece_manager::impl::mark_failed(int index)
void piece_manager::impl::mark_failed(int piece_index)
{
// synchronization ------------------------------------------------------
boost::recursive_mutex::scoped_lock lock(m_mutex);
// ----------------------------------------------------------------------
assert(index >= 0 && index < m_piece_to_slot.size());
assert(m_piece_to_slot[index] >= 0);
#ifndef NDEBUG
check_invariant();
#endif
assert(piece_index >= 0 && piece_index < m_piece_to_slot.size());
assert(m_piece_to_slot[piece_index] >= 0);
int slot = m_slot_to_piece[m_piece_to_slot[index]];
int slot_index = m_piece_to_slot[piece_index];
assert(slot >= 0);
assert(slot_index >= 0);
m_slot_to_piece[slot_index] = -2;
m_piece_to_slot[piece_index] = -1;
m_free_slots.push_back(slot_index);
#ifndef NDEBUG
check_invariant();
#endif
m_slot_to_piece[m_piece_to_slot[index]] = -2;
m_piece_to_slot[index] = -1;
m_free_slots.push_back(slot);
}
void piece_manager::mark_failed(int index)
@ -809,6 +821,9 @@ namespace libtorrent {
{
assert(slot_index >= 0);
assert(slot_index < m_slot_to_piece.size());
check_invariant();
return slot_index;
}

View File

@ -167,16 +167,6 @@ namespace
return true;
}
bool operator()(const peer_connection* p) const
{
if (p->get_peer_id() != id) return false;
if (tor != p->associated_torrent()) return false;
// have a special case for all zeros. We can have any number
// of peers with that id, since it's used to indicate no id.
if (std::count(id.begin(), id.end(), 0) == 20) return false;
return true;
}
const peer_id& id;
const torrent* tor;
};
@ -196,6 +186,23 @@ namespace
const torrent* tor;
};
struct peer_by_id
{
peer_by_id(const peer_id& i): id(i) {}
bool operator()(const std::pair<address, peer_connection*>& p) const
{
if (p.second->get_peer_id() != id) return false;
// have a special case for all zeros. We can have any number
// of peers with that id, since it's used to indicate no id.
if (std::count(id.begin(), id.end(), 0) == 20) return false;
return true;
}
const peer_id& id;
};
}
namespace libtorrent
@ -313,7 +320,7 @@ namespace libtorrent
{
assert(std::count_if(m_connections.begin()
, m_connections.end()
, find_peer_by_id(id, this)) <= 1);
, peer_by_id(id)) <= 1);
// pretend that we are connected to
// ourself to avoid real connections
@ -323,7 +330,7 @@ namespace libtorrent
return std::find_if(
m_connections.begin()
, m_connections.end()
, find_peer_by_id(id, this))
, peer_by_id(id))
!= m_connections.end();
}
@ -360,20 +367,19 @@ namespace libtorrent
// decrease the trust point of all peers that sent
// parts of this piece.
// TODO: implement this loop more efficient
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
i != m_connections.end();
for (std::vector<address>::iterator i = downloaders.begin();
i != downloaders.end();
++i)
{
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_socket()->sender())
== downloaders.end()) continue;
peer_iterator p = m_connections.find(*i);
if (p == m_connections.end()) continue;
p->second->received_invalid_data();
(*i)->received_invalid_data();
if ((*i)->trust_points() <= -5)
if (p->second->trust_points() <= -5)
{
// we don't trust this peer anymore
// ban it.
m_policy->ban_peer(*(*i));
m_policy->ban_peer(*p->second);
}
}
@ -401,22 +407,20 @@ namespace libtorrent
// increase the trust point of all peers that sent
// parts of this piece.
// TODO: implement this loop more efficient
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
i != m_connections.end();
for (std::vector<address>::iterator i = downloaders.begin();
i != downloaders.end();
++i)
{
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_socket()->sender())
!= downloaders.end())
{
(*i)->received_valid_data();
}
peer_iterator p = m_connections.find(*i);
if (p == m_connections.end()) continue;
p->second->received_valid_data();
}
m_picker.we_have(index);
for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
i->second->announce_piece(index);
// TODO: if we became a seed, disconnect from all other seeds
}
std::string torrent::generate_tracker_request(int port)
@ -489,7 +493,7 @@ namespace libtorrent
void torrent::remove_peer(peer_connection* p)
{
std::vector<peer_connection*>::iterator i = std::find(m_connections.begin(), m_connections.end(), p);
peer_iterator i = m_connections.find(p->get_socket()->sender());
assert(i != m_connections.end());
// if the peer_connection was downloading any pieces
@ -540,18 +544,20 @@ namespace libtorrent
, this
, s
, id));
if (m_ses.m_upload_rate != -1) c->set_send_quota(0);
detail::session_impl::connection_map::iterator p =
m_ses.m_connections.insert(std::make_pair(s, c)).first;
// add the newly connected peer to this torrent's peer list
assert(std::find(
m_connections.begin()
, m_connections.end()
, boost::get_pointer(p->second))
assert(m_connections.find(p->second->get_socket()->sender())
== m_connections.end());
m_connections.push_back(boost::get_pointer(p->second));
m_connections.insert(
std::make_pair(
p->second->get_socket()->sender()
, boost::get_pointer(p->second)));
m_ses.m_selector.monitor_readability(s);
m_ses.m_selector.monitor_errors(s);
@ -561,8 +567,10 @@ namespace libtorrent
void torrent::attach_peer(peer_connection* p)
{
assert(std::find(m_connections.begin(), m_connections.end(), p) == m_connections.end());
m_connections.push_back(p);
assert(m_connections.find(p->get_socket()->sender()) == m_connections.end());
m_connections.insert(std::make_pair(p->get_socket()->sender(), p));
detail::session_impl::connection_map::iterator i
= m_ses.m_connections.find(p->get_socket());
assert(i != m_ses.m_connections.end());
@ -572,29 +580,25 @@ namespace libtorrent
void torrent::close_all_connections()
{
for (detail::session_impl::connection_map::iterator i = m_ses.m_connections.begin();
i != m_ses.m_connections.end();)
for (peer_iterator i = m_connections.begin();
i != m_connections.end();)
{
if (i->second->associated_torrent() == this)
{
#ifndef NDEBUG
std::size_t num_connections = m_connections.size();
peer_connection* pc = boost::get_pointer(i->second);
#endif
assert(std::find(m_connections.begin(), m_connections.end(), pc) != m_connections.end());
detail::session_impl::connection_map::iterator j = i;
++i;
m_ses.m_connections.erase(j);
assert(m_connections.size() + 1 == num_connections);
assert(std::find(m_connections.begin(), m_connections.end(), pc) == m_connections.end());
}
else
{
assert(std::find(m_connections.begin(), m_connections.end(), boost::get_pointer(i->second)) == m_connections.end());
++i;
}
assert(i->second->associated_torrent() == this);
detail::session_impl::connection_map::iterator j =
m_ses.m_connections.find(i->second->get_socket());
assert(j != m_ses.m_connections.end());
// in the destructor of the peer_connection
// it will remove itself from this torrent
// and from the list we're iterating over.
// so we need to increment the iterator riht
// away.
++i;
m_ses.m_connections.erase(j);
}
assert(m_connections.empty());
}
@ -659,11 +663,11 @@ namespace libtorrent
m_policy->pulse();
}
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
for (peer_iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
peer_connection* p = (*i);
peer_connection* p = i->second;
const stat& s = p->statistics();
m_stat += s;
p->second_tick();

View File

@ -243,15 +243,15 @@ namespace libtorrent
ret.dict()["peers"] = entry::list_type();
entry::list_type& peer_list = ret.dict()["peers"].list();
for (torrent::peer_const_iterator i = t->begin();
for (torrent::const_peer_iterator i = t->begin();
i != t->end();
++i)
{
// we cannot save remote connection
// since we don't know their listen port
if (!(*i)->is_local()) continue;
if (!i->second->is_local()) continue;
address ip = (*i)->get_socket()->sender();
address ip = i->second->get_socket()->sender();
entry::dictionary_type peer;
peer["ip"] = ip.as_string();
peer["port"] = ip.port();
@ -360,11 +360,11 @@ namespace libtorrent
const torrent* t = m_ses->find_torrent(m_info_hash);
if (t == 0) return;
for (std::vector<peer_connection*>::const_iterator i = t->begin();
for (torrent::const_peer_iterator i = t->begin();
i != t->end();
++i)
{
peer_connection* peer = *i;
peer_connection* peer = i->second;
// peers that hasn't finished the handshake should
// not be included in this list