From 5e68d4e2aeb9257989584daba623d494bc9cdb57 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Fri, 20 Sep 2013 18:59:31 -0300 Subject: [PATCH] new getposts rpc --- libtorrent/include/libtorrent/torrent.hpp | 5 ++ .../include/libtorrent/torrent_handle.hpp | 1 + libtorrent/src/torrent.cpp | 40 +++++++++++++ libtorrent/src/torrent_handle.cpp | 26 +++++++++ src/bitcoinrpc.cpp | 3 + src/bitcoinrpc.h | 1 + src/twister.cpp | 56 +++++++++++++++++++ twister-test.py | 2 +- 8 files changed, 133 insertions(+), 1 deletion(-) diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 54e7103b..aff7ba3f 100644 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -200,6 +200,11 @@ namespace libtorrent void read_piece(int piece); void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r, read_piece_struct* rp); + void get_pieces(std::vector *pieces, int count, int max_id, int since_id, + mutex *mut, condition_variable *cond, int *reqs); + void on_disk_read_get_piece_complete(int ret, disk_io_job const& j, + std::vector *pieces, mutex *mut, condition_variable *cond, int *reqs); + storage_mode_t storage_mode() const { return (storage_mode_t)m_storage_mode; } storage_interface* get_storage() { diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp index c4574ead..da3bb65f 100644 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ b/libtorrent/include/libtorrent/torrent_handle.hpp @@ -168,6 +168,7 @@ namespace libtorrent enum flags_t { overwrite_existing = 1 }; void add_piece(int piece, char const* data, int size, int flags = 0) const; void read_piece(int piece) const; + void get_pieces(std::vector &pieces, int count, int max_id, int since_id) const; bool have_piece(int piece) const; void get_full_peer_list(std::vector& v) const; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index ab8ce3ca..95cbd7ef 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -908,6 +908,46 @@ namespace libtorrent } } + void torrent::get_pieces(std::vector *pieces, int count, int max_id, int since_id, + mutex *mut, condition_variable *cond, int *reqs) + { + if( !m_picker ) return; + + if( max_id < 0 ) + max_id = m_picker->last_have(); + + int piece_size = m_torrent_file->piece_size(0); + + for( int i = max_id; i >= 0 && i > since_id && (*reqs) < count; i--) { + if( m_picker->have_piece(i) ) { + (*reqs)++; + + peer_request r; + r.piece = i; + r.start = 0; + r.length = piece_size; + filesystem().async_read(r, boost::bind(&torrent::on_disk_read_get_piece_complete + , shared_from_this(), _1, _2, pieces, mut, cond, reqs)); + } + } + } + + void torrent::on_disk_read_get_piece_complete(int ret, disk_io_job const& j, + std::vector *pieces, mutex *mut, condition_variable *cond, int *reqs) + { + TORRENT_ASSERT(m_ses.is_network_thread()); + + mutex::scoped_lock l(*mut); + //printf("on_disk_read_get_piece_complete ret=%d reqs=%d\n", ret, *reqs); + + if (ret > 0) { + pieces->push_back( std::string(j.buffer, ret)); + } + (*reqs)--; + + if (!(*reqs)) cond->notify_all(); + } + void torrent::send_share_mode() { #ifndef TORRENT_DISABLE_EXTENSIONS diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index 7f6087f9..0e2721f7 100644 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -238,6 +238,16 @@ namespace libtorrent t.reset(); \ do { ses.cond.wait(l); } while(!done); } +#define TORRENT_SYNC_CALL7(x, a1, a2, a3, a4, a5, a6, a7) \ + boost::shared_ptr t = m_torrent.lock(); \ + if (t) { \ + bool done = false; \ + session_impl& ses = t->session(); \ + mutex::scoped_lock l(ses.mut); \ + ses.m_io_service.dispatch(boost::bind(&fun_wrap, &done, &ses.cond, &ses.mut, boost::function(boost::bind(&torrent:: x, t, a1, a2, a3, a4, a5, a6, a7)))); \ + t.reset(); \ + do { ses.cond.wait(l); } while(!done); } + #define TORRENT_SYNC_CALL_RET(type, def, x) \ boost::shared_ptr t = m_torrent.lock(); \ if (!t) return def; \ @@ -813,6 +823,22 @@ namespace libtorrent TORRENT_ASYNC_CALL1(read_piece, piece); } + void torrent_handle::get_pieces(std::vector &pieces, int count, int max_id, int since_id) const + { + INVARIANT_CHECK; + + libtorrent::mutex mut; + libtorrent::condition_variable cond; + int reqs = 0; + + TORRENT_SYNC_CALL7(get_pieces, &pieces, count, max_id, since_id, &mut, &cond, &reqs); + + mutex::scoped_lock l2(mut); + while( reqs > 0 ) { + cond.wait(l2); + } + } + bool torrent_handle::have_piece(int piece) const { INVARIANT_CHECK; diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3a4f71a8..004ed0d7 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -240,6 +240,7 @@ static const CRPCCommand vRPCCommands[] = { "newpostmsg", &newpostmsg, false, true }, { "newdirectmsg", &newdirectmsg, false, true }, { "newrtmsg", &newrtmsg, false, true }, + { "getposts", &getposts, false, true }, }; CRPCTable::CRPCTable() @@ -1184,6 +1185,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "newrtmsg" && n > 1) ConvertTo(params[1]); if (strMethod == "newrtmsg" && n > 2) ConvertTo(params[2]); + if (strMethod == "getposts" && n > 0) ConvertTo(params[0]); + if (strMethod == "getposts" && n > 1) ConvertTo(params[1]); return params; } diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 30d79222..5d66523d 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -197,5 +197,6 @@ extern json_spirit::Value dhtget(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value newpostmsg(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value newdirectmsg(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value newrtmsg(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getposts(const json_spirit::Array& params, bool fHelp); #endif diff --git a/src/twister.cpp b/src/twister.cpp index e3ad5f7a..73f91c39 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1082,3 +1082,59 @@ Value newrtmsg(const Array& params, bool fHelp) return entryToJson(v); } +Value getposts(const Array& params, bool fHelp) +{ + if (fHelp || (params.size() != 2)) + throw runtime_error( + "getposts [{\"username\":username,\"max_id\":max_id,\"since_id\":since_id},...]\n" + "get posts from users\n" + "max_id and since_id may be omited or -1"); + + int count = params[0].get_int(); + Array users = params[1].get_array(); + + std::multimap postsByTime; + + for( unsigned int u = 0; u < users.size(); u++ ) { + Object user = users[u].get_obj(); + string strUsername; + int max_id = -1; + int since_id = -1; + + for (Object::const_iterator i = user.begin(); i != user.end(); ++i) { + if( i->name_ == "username" ) strUsername = i->value_.get_str(); + if( i->name_ == "max_id" ) max_id = i->value_.get_int(); + if( i->name_ == "since_id" ) since_id = i->value_.get_int(); + } + + if( strUsername.size() && m_userTorrent.count(strUsername) && + m_userTorrent[strUsername].is_valid() ){ + + std::vector pieces; + m_userTorrent[strUsername].get_pieces(pieces, count, max_id, since_id); + + BOOST_FOREACH(string const& piece, pieces) { + lazy_entry v; + int pos; + error_code ec; + if (lazy_bdecode(piece.data(), piece.data()+piece.size(), v, ec, &pos) == 0) { + lazy_entry const* post = v.dict_find_dict("userpost"); + int64 time = post->dict_find_int_value("time",-1); + + entry vEntry; + vEntry = v; + postsByTime.insert( pair(time, vEntry) ); + } + } + } + } + + Array ret; + std::multimap::reverse_iterator rit; + for (rit=postsByTime.rbegin(); rit!=postsByTime.rend() && (int)ret.size() < count; ++rit) { + ret.push_back( entryToJson(rit->second) ); + } + + return ret; +} + diff --git a/twister-test.py b/twister-test.py index 328cb32b..44258828 100755 --- a/twister-test.py +++ b/twister-test.py @@ -35,6 +35,6 @@ if cmd == "cmd": sys.exit(-1) parms = "" for i in xrange(3,len(sys.argv)): - parms += ' "' + sys.argv[i] + '"' + parms += " '" + sys.argv[i] + "'" os.system( twister + rpccfg + parms )