mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
changed global router routing strategy. Should be more effective now.
This commit is contained in:
parent
59d4c2c829
commit
f0a49a427e
@ -142,6 +142,8 @@ RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataI
|
|||||||
ok &= getRawUInt32(data, pktsize, &offset, &item->service_id);
|
ok &= getRawUInt32(data, pktsize, &offset, &item->service_id);
|
||||||
ok &= getRawUInt32(data, pktsize, &offset, &item->data_size);
|
ok &= getRawUInt32(data, pktsize, &offset, &item->data_size);
|
||||||
|
|
||||||
|
if(item->data_size > 0) // This happens when the item data has been deleted from the cache
|
||||||
|
{
|
||||||
if(item->data_size > rssize || offset > rssize - item->data_size) // better than if(item->data_size + offset > rssize)
|
if(item->data_size > rssize || offset > rssize - item->data_size) // better than if(item->data_size + offset > rssize)
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl;
|
std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl;
|
||||||
@ -157,10 +159,27 @@ RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataI
|
|||||||
|
|
||||||
memcpy(item->data_bytes,&((uint8_t*)data)[offset],item->data_size) ;
|
memcpy(item->data_bytes,&((uint8_t*)data)[offset],item->data_size) ;
|
||||||
offset += item->data_size ;
|
offset += item->data_size ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
item->data_bytes = NULL ;
|
||||||
|
|
||||||
ok &= item->signature.GetTlv(data, pktsize, &offset) ;
|
ok &= item->signature.GetTlv(data, pktsize, &offset) ;
|
||||||
|
|
||||||
ok &= getRawUInt32(data, pktsize, &offset, &item->randomized_distance);
|
ok &= getRawUInt32(data, pktsize, &offset, &item->duplication_factor);
|
||||||
|
|
||||||
|
// make sure the duplication factor is not altered by friends. In the worst case, the item will duplicate a bit more.
|
||||||
|
|
||||||
|
if(item->duplication_factor < 1)
|
||||||
|
{
|
||||||
|
item->duplication_factor = 1 ;
|
||||||
|
std::cerr << "(II) correcting GRouter item duplication factor from 0 to 1, to ensure backward compat." << std::endl;
|
||||||
|
}
|
||||||
|
if(item->duplication_factor > GROUTER_MAX_DUPLICATION_FACTOR)
|
||||||
|
{
|
||||||
|
std::cerr << "(WW) correcting GRouter item duplication factor of " << item->duplication_factor << ". This is very unexpected." << std::endl;
|
||||||
|
item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ;
|
||||||
|
}
|
||||||
|
|
||||||
ok &= getRawUInt32(data, pktsize, &offset, &item->flags);
|
ok &= getRawUInt32(data, pktsize, &offset, &item->flags);
|
||||||
|
|
||||||
if (offset != rssize || !ok)
|
if (offset != rssize || !ok)
|
||||||
@ -382,7 +401,7 @@ uint32_t RsGRouterGenericDataItem::serial_size() const
|
|||||||
s += 4 ; // service id
|
s += 4 ; // service id
|
||||||
s += data_size ; // data
|
s += data_size ; // data
|
||||||
s += signature.TlvSize() ; // signature
|
s += signature.TlvSize() ; // signature
|
||||||
s += 4 ; // randomized distance
|
s += 4 ; // duplication_factor
|
||||||
s += 4 ; // flags
|
s += 4 ; // flags
|
||||||
|
|
||||||
return s ;
|
return s ;
|
||||||
@ -483,7 +502,7 @@ bool RsGRouterGenericDataItem::serialise(void *data,uint32_t& size) const
|
|||||||
|
|
||||||
ok &= signature.SetTlv(data, tlvsize, &offset) ;
|
ok &= signature.SetTlv(data, tlvsize, &offset) ;
|
||||||
|
|
||||||
ok &= setRawUInt32(data, tlvsize, &offset, randomized_distance) ;
|
ok &= setRawUInt32(data, tlvsize, &offset, duplication_factor) ;
|
||||||
ok &= setRawUInt32(data, tlvsize, &offset, flags) ;
|
ok &= setRawUInt32(data, tlvsize, &offset, flags) ;
|
||||||
|
|
||||||
if (offset != tlvsize)
|
if (offset != tlvsize)
|
||||||
@ -796,7 +815,7 @@ std::ostream& RsGRouterGenericDataItem::print(std::ostream& o, uint16_t)
|
|||||||
o << " Data size: " << data_size << std::endl ;
|
o << " Data size: " << data_size << std::endl ;
|
||||||
o << " Data hash: " << RsDirUtil::sha1sum(data_bytes,data_size) << std::endl ;
|
o << " Data hash: " << RsDirUtil::sha1sum(data_bytes,data_size) << std::endl ;
|
||||||
o << " signature key: " << signature.keyId << std::endl;
|
o << " signature key: " << signature.keyId << std::endl;
|
||||||
o << " randomized dist:" << randomized_distance << std::endl;
|
o << " duplication fac:" << duplication_factor << std::endl;
|
||||||
o << " flags: " << flags << std::endl;
|
o << " flags: " << flags << std::endl;
|
||||||
|
|
||||||
return o ;
|
return o ;
|
||||||
|
@ -133,7 +133,7 @@ class RsGRouterGenericDataItem: public RsGRouterAbstractMsgItem, public RsGRoute
|
|||||||
uint32_t data_size ;
|
uint32_t data_size ;
|
||||||
uint8_t *data_bytes;
|
uint8_t *data_bytes;
|
||||||
|
|
||||||
uint32_t randomized_distance ; // number of hops (tunnel wise. Does not preclude of the real distance)
|
uint32_t duplication_factor ; // number of duplicates allowed. Should be capped at each de-serialise operation!
|
||||||
|
|
||||||
// utility methods for signing data
|
// utility methods for signing data
|
||||||
virtual uint32_t signed_data_size() const ;
|
virtual uint32_t signed_data_size() const ;
|
||||||
|
@ -203,7 +203,7 @@ void GRouterMatrix::debugDump() const
|
|||||||
std::cerr << " " << it->first << ": from " << it->second.friend_id << " " << now - it->second.time_stamp << " secs ago." << std::endl;
|
std::cerr << " " << it->first << ": from " << it->second.friend_id << " " << now - it->second.time_stamp << " secs ago." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, const std::vector<RsPeerId>& friends, std::vector<float>& probas) const
|
bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, const std::vector<RsPeerId>& friends, std::vector<float>& probas, float& maximum) const
|
||||||
{
|
{
|
||||||
// Routing probabilities are computed according to routing clues
|
// Routing probabilities are computed according to routing clues
|
||||||
//
|
//
|
||||||
@ -239,6 +239,7 @@ bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, cons
|
|||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
const std::vector<float>& w(it2->second) ;
|
const std::vector<float>& w(it2->second) ;
|
||||||
|
maximum = 0.0f ;
|
||||||
|
|
||||||
for(uint32_t i=0;i<friends.size();++i)
|
for(uint32_t i=0;i<friends.size();++i)
|
||||||
{
|
{
|
||||||
@ -250,6 +251,9 @@ bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, cons
|
|||||||
{
|
{
|
||||||
probas[i] = w[findex] ;
|
probas[i] = w[findex] ;
|
||||||
total += w[findex] ;
|
total += w[findex] ;
|
||||||
|
|
||||||
|
if(maximum < w[findex])
|
||||||
|
maximum = w[findex] ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ class GRouterMatrix
|
|||||||
// the computation accounts for the time at which the info was received and the
|
// the computation accounts for the time at which the info was received and the
|
||||||
// weight of each routing hit record.
|
// weight of each routing hit record.
|
||||||
//
|
//
|
||||||
bool computeRoutingProbabilities(const GRouterKeyId& id, const std::vector<RsPeerId>& friends, std::vector<float>& probas) const ;
|
bool computeRoutingProbabilities(const GRouterKeyId& id, const std::vector<RsPeerId>& friends, std::vector<float>& probas, float &maximum) const ;
|
||||||
|
|
||||||
// Update routing probabilities for each key, accounting for all received events, but without
|
// Update routing probabilities for each key, accounting for all received events, but without
|
||||||
// activity information
|
// activity information
|
||||||
|
@ -44,6 +44,8 @@ static const uint32_t RS_GROUTER_MAX_KEEP_TRACKING_CLUES = 86400*10 ; // m
|
|||||||
|
|
||||||
static const float RS_GROUTER_BASE_WEIGHT_ROUTED_MSG = 1.0f ; // base contribution of routed message clue to routing matrix
|
static const float RS_GROUTER_BASE_WEIGHT_ROUTED_MSG = 1.0f ; // base contribution of routed message clue to routing matrix
|
||||||
static const float RS_GROUTER_BASE_WEIGHT_GXS_PACKET = 0.1f ; // base contribution of GXS message to routing matrix
|
static const float RS_GROUTER_BASE_WEIGHT_GXS_PACKET = 0.1f ; // base contribution of GXS message to routing matrix
|
||||||
|
static const float RS_GROUTER_PROBABILITY_THRESHOLD_FOR_RANDOM_ROUTING = 0.01f ; // routing probability under which the routage is performed randomly
|
||||||
|
static const float RS_GROUTER_PROBABILITY_THRESHOLD_BEST_PEERS_SELECT = 0.5f ; // min ratio of forward proba with respect to best peer.
|
||||||
|
|
||||||
static const uint32_t MAX_TUNNEL_WAIT_TIME = 60 ; // wait for 60 seconds at most for a tunnel response.
|
static const uint32_t MAX_TUNNEL_WAIT_TIME = 60 ; // wait for 60 seconds at most for a tunnel response.
|
||||||
static const uint32_t MAX_TUNNEL_UNMANAGED_TIME = 600 ; // min time before retry tunnels for that msg.
|
static const uint32_t MAX_TUNNEL_UNMANAGED_TIME = 600 ; // min time before retry tunnels for that msg.
|
||||||
@ -54,6 +56,8 @@ static const uint32_t MAX_GROUTER_DATA_SIZE = 2*1024*1024 ; // 2M
|
|||||||
static const uint32_t MAX_TRANSACTION_ACK_WAITING_TIME = 60 ; // wait for at most 60 secs for a ACK. If not restart the transaction.
|
static const uint32_t MAX_TRANSACTION_ACK_WAITING_TIME = 60 ; // wait for at most 60 secs for a ACK. If not restart the transaction.
|
||||||
static const uint32_t DIRECT_FRIEND_TRY_DELAY = 20 ; // wait for 20 secs if no friends available, then try tunnels.
|
static const uint32_t DIRECT_FRIEND_TRY_DELAY = 20 ; // wait for 20 secs if no friends available, then try tunnels.
|
||||||
static const uint32_t MAX_INACTIVE_DATA_PIPE_DELAY = 300 ; // clean inactive data pipes for more than 5 mins
|
static const uint32_t MAX_INACTIVE_DATA_PIPE_DELAY = 300 ; // clean inactive data pipes for more than 5 mins
|
||||||
|
static const uint32_t GROUTER_MAX_DUPLICATION_FACTOR = 10 ; // max number of duplicates for a given message to keep in the network
|
||||||
|
static const uint32_t GROUTER_MAX_BRANCHING_FACTOR = 3 ; // max number of branches, for locally forwarding items
|
||||||
|
|
||||||
static const time_t RS_GROUTER_DEBUG_OUTPUT_PERIOD = 10 ; // Output everything
|
static const time_t RS_GROUTER_DEBUG_OUTPUT_PERIOD = 10 ; // Output everything
|
||||||
static const time_t RS_GROUTER_AUTOWASH_PERIOD = 10 ; // Autowash every minute. Not a costly operation.
|
static const time_t RS_GROUTER_AUTOWASH_PERIOD = 10 ; // Autowash every minute. Not a costly operation.
|
||||||
|
@ -190,6 +190,7 @@
|
|||||||
#include "services/p3idservice.h"
|
#include "services/p3idservice.h"
|
||||||
#include "turtle/p3turtle.h"
|
#include "turtle/p3turtle.h"
|
||||||
#include "gxs/rsgixs.h"
|
#include "gxs/rsgixs.h"
|
||||||
|
#include "retroshare/rspeers.h"
|
||||||
|
|
||||||
#include "p3grouter.h"
|
#include "p3grouter.h"
|
||||||
#include "grouteritems.h"
|
#include "grouteritems.h"
|
||||||
@ -197,7 +198,7 @@
|
|||||||
#include "grouterclientservice.h"
|
#include "grouterclientservice.h"
|
||||||
|
|
||||||
/**********************/
|
/**********************/
|
||||||
//#define GROUTER_DEBUG
|
#define GROUTER_DEBUG
|
||||||
/**********************/
|
/**********************/
|
||||||
|
|
||||||
const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ;
|
const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ;
|
||||||
@ -855,6 +856,34 @@ void p3GRouter::handleTunnels()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void p3GRouter::locked_sendToPeers(RsGRouterGenericDataItem *data_item,const std::map<RsPeerId,uint32_t>& peers_and_duplication_factors)
|
||||||
|
{
|
||||||
|
// slice the data appropriately and send.
|
||||||
|
|
||||||
|
uint32_t saved_duplication_factor = data_item->duplication_factor ; // this little trick avoids copying the item for each peer before slicing it up
|
||||||
|
|
||||||
|
for(std::map<RsPeerId,uint32_t>::const_iterator itpid(peers_and_duplication_factors.begin());itpid!=peers_and_duplication_factors.end();++itpid)
|
||||||
|
{
|
||||||
|
std::list<RsGRouterTransactionChunkItem*> chunks ;
|
||||||
|
data_item->duplication_factor = itpid->second;
|
||||||
|
|
||||||
|
sliceDataItem(data_item,chunks) ;
|
||||||
|
|
||||||
|
for(std::list<RsGRouterTransactionChunkItem*>::const_iterator it2(chunks.begin());it2!=chunks.end();++it2)
|
||||||
|
locked_sendTransactionData(itpid->first,*(*it2) ) ;
|
||||||
|
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " sending " << chunks.size() << " slices to peer " << itpid->first << " with duplication factor = " << itpid->second << std::endl;
|
||||||
|
#endif
|
||||||
|
// delete temporary items
|
||||||
|
|
||||||
|
for(std::list<RsGRouterTransactionChunkItem*>::const_iterator cit=chunks.begin();cit!=chunks.end();++cit)
|
||||||
|
delete *cit;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_item->duplication_factor = saved_duplication_factor ;
|
||||||
|
}
|
||||||
|
|
||||||
void p3GRouter::routePendingObjects()
|
void p3GRouter::routePendingObjects()
|
||||||
{
|
{
|
||||||
// Go throught he list of pending messages. For those with a peer ready, send the message to that peer.
|
// Go throught he list of pending messages. For those with a peer ready, send the message to that peer.
|
||||||
@ -885,56 +914,59 @@ void p3GRouter::routePendingObjects()
|
|||||||
{
|
{
|
||||||
// Look for tunnels and friends where to send the data. Send to both.
|
// Look for tunnels and friends where to send the data. Send to both.
|
||||||
|
|
||||||
std::list<RsPeerId> peers ;
|
std::map<RsPeerId,uint32_t> peers_and_duplication_factors ;
|
||||||
|
|
||||||
if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)
|
// if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)
|
||||||
locked_collectAvailableTunnels(it->second.tunnel_hash,peers);
|
// locked_collectAvailableTunnels(it->second.tunnel_hash,it->second.data_item->duplication_factor,peers_and_duplication_factors);
|
||||||
|
//
|
||||||
// For now, disable friends. We'll first check that the good old tunnel system works as before.
|
// if(!peers_and_duplication_factors.empty())
|
||||||
|
// {
|
||||||
|
//#ifdef GROUTER_DEBUG
|
||||||
|
// std::cerr << " tunnels available! sending!" << std::endl;
|
||||||
|
//#endif
|
||||||
|
// locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ;
|
||||||
|
//
|
||||||
|
// // change item state in waiting list
|
||||||
|
//
|
||||||
|
// it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ;
|
||||||
|
// it->second.data_transaction_TS = now ;
|
||||||
|
//
|
||||||
|
// pending_messages_changed = true ;
|
||||||
|
// continue ; // no need to seek for friend asynced routes since tunnels directly go to the final destination!
|
||||||
|
// }
|
||||||
|
|
||||||
if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS)
|
if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS)
|
||||||
locked_collectAvailableFriends(it->second.data_item->destination_key,peers, it->second.incoming_routes.ids, it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN);
|
locked_collectAvailableFriends(it->second.data_item->destination_key,it->second.incoming_routes.ids,it->second.data_item->duplication_factor,peers_and_duplication_factors);
|
||||||
|
|
||||||
if(peers.empty())
|
// if(!peers_and_duplication_factors.empty())
|
||||||
{
|
// {
|
||||||
#ifdef GROUTER_DEBUG
|
//#ifdef GROUTER_DEBUG
|
||||||
std::cerr << " no direct friends available" << std::endl;
|
// std::cerr << " friends available! sending!" << std::endl;
|
||||||
#endif
|
//#endif
|
||||||
|
// locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ;
|
||||||
|
//
|
||||||
|
// // change item state in waiting list
|
||||||
|
//
|
||||||
|
// it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ;
|
||||||
|
// it->second.data_transaction_TS = now ;
|
||||||
|
//
|
||||||
|
// pending_messages_changed = true ;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
//#ifdef GROUTER_DEBUG
|
||||||
|
// std::cerr << " no direct friends available" << std::endl;
|
||||||
|
//#endif
|
||||||
|
//
|
||||||
|
// if(it->second.received_time_TS + DIRECT_FRIEND_TRY_DELAY < now && !(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS))
|
||||||
|
// {
|
||||||
|
//#ifdef GROUTER_DEBUG
|
||||||
|
// std::cerr << " enabling tunnels for this message." << std::endl;
|
||||||
|
//#endif
|
||||||
|
// it->second.routing_flags |= GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if(it->second.received_time_TS + DIRECT_FRIEND_TRY_DELAY < now && !(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS))
|
|
||||||
{
|
|
||||||
#ifdef GROUTER_DEBUG
|
|
||||||
std::cerr << " enabling tunnels for this message." << std::endl;
|
|
||||||
#endif
|
|
||||||
it->second.routing_flags |= GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ;
|
|
||||||
}
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// slice the data appropriately and send.
|
|
||||||
|
|
||||||
std::list<RsGRouterTransactionChunkItem*> chunks ;
|
|
||||||
sliceDataItem(it->second.data_item,chunks) ;
|
|
||||||
|
|
||||||
#ifdef GROUTER_DEBUG
|
|
||||||
if(!peers.empty())
|
|
||||||
std::cerr << " sending to peers:" << std::endl;
|
|
||||||
#endif
|
|
||||||
for(std::list<RsPeerId>::const_iterator itpid(peers.begin());itpid!=peers.end();++itpid)
|
|
||||||
for(std::list<RsGRouterTransactionChunkItem*>::const_iterator it2(chunks.begin());it2!=chunks.end();++it2)
|
|
||||||
locked_sendTransactionData(*itpid,*(*it2) ) ;
|
|
||||||
|
|
||||||
// delete temporary items
|
|
||||||
|
|
||||||
for(std::list<RsGRouterTransactionChunkItem*>::const_iterator cit=chunks.begin();cit!=chunks.end();++cit)
|
|
||||||
delete *cit;
|
|
||||||
|
|
||||||
// change item state in waiting list
|
|
||||||
|
|
||||||
it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ;
|
|
||||||
it->second.data_transaction_TS = now ;
|
|
||||||
|
|
||||||
pending_messages_changed = true ;
|
|
||||||
}
|
}
|
||||||
else if(it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING && now > MAX_TRANSACTION_ACK_WAITING_TIME + it->second.data_transaction_TS)
|
else if(it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING && now > MAX_TRANSACTION_ACK_WAITING_TIME + it->second.data_transaction_TS)
|
||||||
{
|
{
|
||||||
@ -1014,70 +1046,161 @@ void p3GRouter::routePendingObjects()
|
|||||||
IndicateConfigChanged() ;
|
IndicateConfigChanged() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3GRouter::locked_collectAvailableFriends(const GRouterKeyId& gxs_id,std::list<RsPeerId>& friend_peers,const std::set<RsPeerId>& incoming_routes,bool is_origin)
|
void p3GRouter::locked_collectAvailableFriends(const GRouterKeyId& gxs_id,const std::set<RsPeerId>& incoming_routes,uint32_t duplication_factor, std::map<RsPeerId,uint32_t>& friend_peers_and_duplication_factors)
|
||||||
{
|
{
|
||||||
// The strategy is the following:
|
// Old strategy was the following:
|
||||||
// if origin
|
// if origin
|
||||||
// send to multiple neighbors : best and random
|
// send to multiple neighbors : best and random
|
||||||
// else
|
// else
|
||||||
// send to a single "best" neighbor (determined by threshold over routing probability),
|
// send to a single "best" neighbor (determined by threshold over routing probability),
|
||||||
|
|
||||||
std::set<RsPeerId> ids ;
|
// New strategy is:
|
||||||
mServiceControl->getPeersConnected(getServiceInfo().mServiceType,ids) ;
|
//
|
||||||
|
// Characteristics of the distribution to look at:
|
||||||
std::vector<float> probas;
|
// * who's online, who's not
|
||||||
std::vector<RsPeerId> tmp_peers;
|
// * all values quite equal
|
||||||
|
// * single value well above others
|
||||||
// remove previous peers
|
// * largest value is small
|
||||||
|
// Algorithm:
|
||||||
for(std::set<RsPeerId>::const_iterator it(ids.begin());it!=ids.end();++it)
|
//
|
||||||
if(incoming_routes.find(*it) == incoming_routes.end())
|
// 0 - encode duplicate factor in routed item and allow at most N duplicates
|
||||||
tmp_peers.push_back(*it) ;
|
// - when forwarding to N peers, split the duplication factor into N bins, each being proportional to the forwarding probability.
|
||||||
|
// Example for N=3 and D=10:
|
||||||
if(tmp_peers.empty())
|
//
|
||||||
return ;
|
// p Calculation Final bin
|
||||||
|
//
|
||||||
_routing_matrix.computeRoutingProbabilities(gxs_id, tmp_peers, probas) ;
|
// +-0.21--> 0.21*10=2.1 --> 2 0.1 below
|
||||||
|
// |
|
||||||
|
// 10 ----+-0.45--> 0.45*10=4.5 --> 4.6-> 5 0.4 above
|
||||||
|
// |
|
||||||
|
// +-0.34--> 0.34*10=3.4 --> 3.0-> 3 0
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 1 - get routing probabilities p_i for all peers as well as the maximum proba p before normalization.
|
||||||
|
//
|
||||||
|
// Set N = min(3,item->duplication_factor) // max number of friends to route to
|
||||||
|
//
|
||||||
|
// if p < threshold // That means the routage info is too old => Fallback to random routing.
|
||||||
|
// Select N random online friends and forward to them.
|
||||||
|
// else
|
||||||
|
// Let p_i be the probabilities of all peers
|
||||||
|
// Select all online peers for which p_i >= 0.5*p.
|
||||||
|
// if !empty
|
||||||
|
// Update duplication factors according to probabilities and number of peers
|
||||||
|
// Route to these peers
|
||||||
|
// else
|
||||||
|
// Keep the item
|
||||||
|
//
|
||||||
|
|
||||||
#ifdef GROUTER_DEBUG
|
#ifdef GROUTER_DEBUG
|
||||||
std::cerr << "locked_getAvailableFriends()" << std::endl;
|
std::cerr << "locked_getAvailableFriends()" << std::endl;
|
||||||
std::cerr << " getting connected friends, computing routing probabilities" << std::endl;
|
std::cerr << " looking for friends for item to ID " << gxs_id << " duplication factor = " << duplication_factor << std::endl;
|
||||||
|
std::cerr << " retrieving online friends and all friends lists." << std::endl;
|
||||||
|
#endif
|
||||||
|
std::set<RsPeerId> online_ids ;
|
||||||
|
std::list<RsPeerId> all_ids ;
|
||||||
|
|
||||||
|
rsPeers->getFriendList(all_ids) ;
|
||||||
|
mServiceControl->getPeersConnected(getServiceInfo().mServiceType,online_ids) ;
|
||||||
|
|
||||||
|
std::vector<RsPeerId> tmp_peers;
|
||||||
|
|
||||||
|
for(std::list<RsPeerId>::const_iterator it(all_ids.begin());it!=all_ids.end();++it)
|
||||||
|
tmp_peers.push_back(*it) ;
|
||||||
|
|
||||||
|
std::vector<float> probas;
|
||||||
|
float maximum = 1.0;
|
||||||
|
float max_probability = 0.0;
|
||||||
|
|
||||||
|
_routing_matrix.computeRoutingProbabilities(gxs_id, tmp_peers, probas, maximum) ;
|
||||||
|
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " initial routing probabilities (maximum=" << maximum << ")" << std::endl;
|
||||||
|
for(uint32_t i=0;i<tmp_peers.size();++i)
|
||||||
|
std::cerr << " " << tmp_peers[i] << " " << probas[i] << std::endl;
|
||||||
|
#endif
|
||||||
|
if(maximum < RS_GROUTER_PROBABILITY_THRESHOLD_FOR_RANDOM_ROUTING)
|
||||||
|
{
|
||||||
|
max_probability = 0.0f ;
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " max proba: " << maximum << " is below random threshold => using uniform random routing." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(uint32_t i=0;i<tmp_peers.size();++i)
|
||||||
|
max_probability = std::max(max_probability,probas[i]) ;
|
||||||
|
}
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " maxi probability=" << max_probability << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// remove incoming peers and peers for which the proba is less than half the maximum proba
|
||||||
|
float total_probas = 0.0f ;
|
||||||
|
uint32_t count=0;
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<tmp_peers.size();++i)
|
||||||
|
if(incoming_routes.find(tmp_peers[i]) != incoming_routes.end())
|
||||||
|
std::cerr << " removing " << tmp_peers[i] << " which is an incoming route" << std::endl;
|
||||||
|
else if(probas[i] < RS_GROUTER_PROBABILITY_THRESHOLD_BEST_PEERS_SELECT*max_probability)
|
||||||
|
std::cerr << " removing " << tmp_peers[i] << " because probability is below best peers threshold" << std::endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_peers[count] = tmp_peers[i] ;
|
||||||
|
probas[count] = (max_probability==0.0)? (0.5+0.001*RSRandom::random_f32()) : probas[i] ;
|
||||||
|
++count ;
|
||||||
|
|
||||||
|
total_probas+=probas[i] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_peers.resize(count) ;
|
||||||
|
probas.resize(count) ;
|
||||||
|
|
||||||
|
if(tmp_peers.empty())
|
||||||
|
{
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " online - available peers empty => giving up." << std::endl;
|
||||||
|
#endif
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now select the N best peers
|
||||||
|
#ifdef GROUTER_DEBUG
|
||||||
|
std::cerr << " Remaining peers and routing probabilities:" << std::endl;
|
||||||
for(uint32_t i=0;i<tmp_peers.size();++i)
|
for(uint32_t i=0;i<tmp_peers.size();++i)
|
||||||
std::cerr << " " << tmp_peers[i] << ", probability: " << probas[i] << std::endl;
|
std::cerr << " " << tmp_peers[i] << ", probability: " << probas[i] << std::endl;
|
||||||
#endif
|
#endif
|
||||||
uint32_t max_count = is_origin?3:1 ;
|
float probability_threshold = RS_GROUTER_PROBABILITY_THRESHOLD_FOR_RANDOM_ROUTING ;
|
||||||
float probability_threshold = is_origin?0.0:0.5 ;
|
|
||||||
|
|
||||||
#ifdef GROUTER_DEBUG
|
|
||||||
std::cerr << " position at origin: " << is_origin << " => mac_count=" << max_count << ", proba threshold=" << probability_threshold << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<std::pair<float,RsPeerId> > mypairs ;
|
std::vector<std::pair<float,RsPeerId> > mypairs ;
|
||||||
|
|
||||||
for(uint32_t i=0;i<tmp_peers.size();++i)
|
for(uint32_t i=0;i<tmp_peers.size();++i)
|
||||||
mypairs.push_back(std::make_pair(probas[i],tmp_peers[i])) ;
|
mypairs.push_back(std::make_pair(probas[i]/total_probas,tmp_peers[i])) ;
|
||||||
|
|
||||||
// now sort them up
|
// now sort them up
|
||||||
std::sort(mypairs.begin(),mypairs.end(),item_comparator_001()) ;
|
std::sort(mypairs.begin(),mypairs.end(),item_comparator_001()) ;
|
||||||
|
|
||||||
// take the max_count peers that are still above min_probability
|
uint32_t max_count = std::min(std::min((uint32_t)mypairs.size(),(uint32_t)GROUTER_MAX_BRANCHING_FACTOR),duplication_factor);
|
||||||
|
|
||||||
uint32_t n=0 ;
|
uint32_t n=0 ;
|
||||||
|
|
||||||
for(std::vector<std::pair<float,RsPeerId> >::const_reverse_iterator it = mypairs.rbegin();it!=mypairs.rend() && n<max_count;++it)
|
float duplication_factor_delta =0.0;
|
||||||
if( (*it).first >= probability_threshold )
|
uint32_t duplication_factor_buff =duplication_factor ;
|
||||||
{
|
|
||||||
friend_peers.push_back( (*it).second ), ++n ;
|
|
||||||
#ifdef GROUTER_DEBUG
|
|
||||||
std::cerr << " keeping " << (*it).second << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!is_origin) // only collect one peer if we're not at origin.
|
for(int i=mypairs.size()-1;i>=0 && n<max_count;--i)
|
||||||
break ;
|
{
|
||||||
|
float ideal_dupl = duplication_factor*mypairs[i].first - duplication_factor_delta ; // correct what was taken in advance
|
||||||
|
|
||||||
|
uint32_t real_dupl = std::min( duplication_factor - max_count+1,std::max(1u,uint32_t(rint(ideal_dupl)))) ;
|
||||||
|
duplication_factor_delta = real_dupl - ideal_dupl ;
|
||||||
|
|
||||||
|
std::cerr << " Peer " << mypairs[i].second << " prob=" << mypairs[i].first << ", ideal_dupl=" << ideal_dupl << ", real=" << real_dupl << ". Delta = " << duplication_factor_delta << std::endl;
|
||||||
|
|
||||||
|
friend_peers_and_duplication_factors[ mypairs[i].second ] = real_dupl ; // should be updated correctly
|
||||||
|
++n ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3GRouter::locked_collectAvailableTunnels(const TurtleFileHash& hash,std::list<RsPeerId>& tunnel_peers)
|
void p3GRouter::locked_collectAvailableTunnels(const TurtleFileHash& hash,uint32_t total_duplication,std::map<RsPeerId,uint32_t>& tunnel_peers_and_duplication_factors)
|
||||||
{
|
{
|
||||||
time_t now = time(NULL) ;
|
time_t now = time(NULL) ;
|
||||||
|
|
||||||
@ -1110,7 +1233,7 @@ void p3GRouter::locked_collectAvailableTunnels(const TurtleFileHash& hash,std::l
|
|||||||
#endif
|
#endif
|
||||||
TurtleVirtualPeerId vpid = *(vpit->second.virtual_peers.begin()) ;
|
TurtleVirtualPeerId vpid = *(vpit->second.virtual_peers.begin()) ;
|
||||||
|
|
||||||
tunnel_peers.push_back(vpid) ;
|
tunnel_peers_and_duplication_factors[vpid] = total_duplication ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3GRouter::locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& trans_item)
|
bool p3GRouter::locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& trans_item)
|
||||||
@ -1927,7 +2050,7 @@ bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& clie
|
|||||||
|
|
||||||
data_item->data_size = data_size ;
|
data_item->data_size = data_size ;
|
||||||
data_item->routing_id = propagation_id ;
|
data_item->routing_id = propagation_id ;
|
||||||
data_item->randomized_distance = 0 ;
|
data_item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ;
|
||||||
data_item->service_id = client_id ;
|
data_item->service_id = client_id ;
|
||||||
data_item->destination_key = destination ;
|
data_item->destination_key = destination ;
|
||||||
data_item->flags = 0 ; // this is unused for now.
|
data_item->flags = 0 ; // this is unused for now.
|
||||||
@ -1987,7 +2110,7 @@ bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& clie
|
|||||||
grouter_debug() << " data status = " << info.data_status << std::endl;
|
grouter_debug() << " data status = " << info.data_status << std::endl;
|
||||||
grouter_debug() << " tunnel status = " << info.tunnel_status << std::endl;
|
grouter_debug() << " tunnel status = " << info.tunnel_status << std::endl;
|
||||||
grouter_debug() << " sending attempt= " << info.sending_attempts << std::endl;
|
grouter_debug() << " sending attempt= " << info.sending_attempts << std::endl;
|
||||||
grouter_debug() << " distance = " << info.data_item->randomized_distance << std::endl;
|
grouter_debug() << " duplicate fact = " << info.data_item->duplication_factor << std::endl;
|
||||||
grouter_debug() << " recv time = " << info.received_time_TS << std::endl;
|
grouter_debug() << " recv time = " << info.received_time_TS << std::endl;
|
||||||
grouter_debug() << " client id = " << std::hex << data_item->service_id << std::dec << std::endl;
|
grouter_debug() << " client id = " << std::hex << data_item->service_id << std::dec << std::endl;
|
||||||
grouter_debug() << " tunnel hash = " << info.tunnel_hash << std::endl;
|
grouter_debug() << " tunnel hash = " << info.tunnel_hash << std::endl;
|
||||||
@ -2134,21 +2257,23 @@ bool p3GRouter::getRoutingMatrixInfo(RsGRouter::GRouterRoutingMatrixInfo& info)
|
|||||||
info.friend_ids.clear() ;
|
info.friend_ids.clear() ;
|
||||||
info.published_keys.clear() ;
|
info.published_keys.clear() ;
|
||||||
|
|
||||||
std::set<RsPeerId> ids ;
|
std::list<RsPeerId> ids ;
|
||||||
mServiceControl->getPeersConnected(getServiceInfo().mServiceType,ids) ;
|
//mServiceControl->getPeersConnected(getServiceInfo().mServiceType,ids) ;
|
||||||
|
rsPeers->getFriendList(ids) ;
|
||||||
|
|
||||||
info.published_keys = _owned_key_ids ;
|
info.published_keys = _owned_key_ids ;
|
||||||
|
|
||||||
for(std::set<RsPeerId>::const_iterator it(ids.begin());it!=ids.end();++it)
|
for(std::list<RsPeerId>::const_iterator it(ids.begin());it!=ids.end();++it)
|
||||||
info.friend_ids.push_back(*it) ;
|
info.friend_ids.push_back(*it) ;
|
||||||
|
|
||||||
std::vector<GRouterKeyId> known_keys ;
|
std::vector<GRouterKeyId> known_keys ;
|
||||||
std::vector<float> probas ;
|
std::vector<float> probas ;
|
||||||
|
float maximum= 0.0f;
|
||||||
_routing_matrix.getListOfKnownKeys(known_keys) ;
|
_routing_matrix.getListOfKnownKeys(known_keys) ;
|
||||||
|
|
||||||
for(uint32_t i=0;i<known_keys.size();++i)
|
for(uint32_t i=0;i<known_keys.size();++i)
|
||||||
{
|
{
|
||||||
_routing_matrix.computeRoutingProbabilities(known_keys[i],info.friend_ids,probas) ;
|
_routing_matrix.computeRoutingProbabilities(known_keys[i],info.friend_ids,probas,maximum) ;
|
||||||
info.per_friend_probabilities[known_keys[i]] = probas ;
|
info.per_friend_probabilities[known_keys[i]] = probas ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2167,6 +2292,7 @@ bool p3GRouter::getRoutingCacheInfo(std::vector<GRouterRoutingCacheInfo>& infos)
|
|||||||
cinfo.mid = it->first ;
|
cinfo.mid = it->first ;
|
||||||
cinfo.local_origin = it->second.incoming_routes.ids ;
|
cinfo.local_origin = it->second.incoming_routes.ids ;
|
||||||
cinfo.destination = it->second.data_item->destination_key ;
|
cinfo.destination = it->second.data_item->destination_key ;
|
||||||
|
cinfo.duplication_factor = it->second.data_item->duplication_factor ;
|
||||||
cinfo.routing_time = it->second.received_time_TS ;
|
cinfo.routing_time = it->second.received_time_TS ;
|
||||||
cinfo.last_tunnel_attempt_time = it->second.last_tunnel_request_TS ;
|
cinfo.last_tunnel_attempt_time = it->second.last_tunnel_request_TS ;
|
||||||
cinfo.last_sent_time = it->second.last_sent_TS ;
|
cinfo.last_sent_time = it->second.last_sent_TS ;
|
||||||
@ -2220,15 +2346,16 @@ void p3GRouter::debugDump()
|
|||||||
{
|
{
|
||||||
grouter_debug() << " Msg id: " << std::hex << it->first << std::dec ;
|
grouter_debug() << " Msg id: " << std::hex << it->first << std::dec ;
|
||||||
grouter_debug() << " data hash: " << it->second.item_hash ;
|
grouter_debug() << " data hash: " << it->second.item_hash ;
|
||||||
grouter_debug() << " client id: " << std::hex << it->second.client_id << std::dec;
|
grouter_debug() << " client: " << std::hex << it->second.client_id << std::dec;
|
||||||
grouter_debug() << " Flags: " << std::hex << it->second.routing_flags << std::dec;
|
grouter_debug() << " Flags: " << std::hex << it->second.routing_flags << std::dec;
|
||||||
grouter_debug() << " Destination: " << it->second.data_item->destination_key ;
|
grouter_debug() << " Dest: " << it->second.data_item->destination_key ;
|
||||||
grouter_debug() << " Received: " << now - it->second.received_time_TS << " secs ago.";
|
grouter_debug() << " Recd: " << now - it->second.received_time_TS << " secs ago.";
|
||||||
grouter_debug() << " Last sent: " << now - it->second.last_sent_TS << " secs ago.";
|
grouter_debug() << " Sent: " << now - it->second.last_sent_TS << " secs ago.";
|
||||||
grouter_debug() << " Transaction TS: " << now - it->second.data_transaction_TS << " secs ago.";
|
grouter_debug() << " Trans. TS: " << now - it->second.data_transaction_TS << " secs ago." ;
|
||||||
grouter_debug() << " Data Status: " << statusString[it->second.data_status] << std::endl;
|
grouter_debug() << " Data Status: " << statusString[it->second.data_status] ;
|
||||||
grouter_debug() << " Tunl Status: " << statusString[it->second.tunnel_status] << std::endl;
|
grouter_debug() << " Tunl Status: " << statusString[it->second.tunnel_status] ;
|
||||||
grouter_debug() << " Receipt ok: " << (it->second.receipt_item != NULL) << std::endl;
|
grouter_debug() << " Receipt ok: " << (it->second.receipt_item != NULL) ;
|
||||||
|
grouter_debug() << " Dup: " << it->second.data_item->duplication_factor << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
grouter_debug() << " Tunnels: " << std::endl;
|
grouter_debug() << " Tunnels: " << std::endl;
|
||||||
@ -2251,8 +2378,8 @@ void p3GRouter::debugDump()
|
|||||||
|
|
||||||
grouter_debug() << " Routing matrix: " << std::endl;
|
grouter_debug() << " Routing matrix: " << std::endl;
|
||||||
|
|
||||||
if(_debug_enabled)
|
// if(_debug_enabled)
|
||||||
_routing_matrix.debugDump() ;
|
// _routing_matrix.debugDump() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -272,8 +272,9 @@ private:
|
|||||||
//bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id);
|
//bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id);
|
||||||
bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item);
|
bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item);
|
||||||
|
|
||||||
void locked_collectAvailableFriends(const GRouterKeyId &gxs_id,std::list<RsPeerId>& friend_peers, const std::set<RsPeerId>& incoming_routes,bool is_origin);
|
void locked_collectAvailableFriends(const GRouterKeyId &gxs_id, const std::set<RsPeerId>& incoming_routes,uint32_t duplication_factor, std::map<RsPeerId, uint32_t> &friend_peers_and_duplication_factors);
|
||||||
void locked_collectAvailableTunnels(const TurtleFileHash& hash,std::list<RsPeerId>& tunnel_peers);
|
void locked_collectAvailableTunnels(const TurtleFileHash& hash, uint32_t total_duplication, std::map<RsPeerId, uint32_t> &tunnel_peers_and_duplication_factors);
|
||||||
|
void locked_sendToPeers(RsGRouterGenericDataItem *data_item, const std::map<RsPeerId, uint32_t> &peers_and_duplication_factors);
|
||||||
|
|
||||||
//===================================================//
|
//===================================================//
|
||||||
// p3Config methods //
|
// p3Config methods //
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
time_t last_tunnel_attempt_time;
|
time_t last_tunnel_attempt_time;
|
||||||
time_t last_sent_time;
|
time_t last_sent_time;
|
||||||
bool receipt_available ;
|
bool receipt_available ;
|
||||||
|
uint32_t duplication_factor ;
|
||||||
uint32_t data_status ;
|
uint32_t data_status ;
|
||||||
uint32_t tunnel_status ;
|
uint32_t tunnel_status ;
|
||||||
uint32_t data_size ;
|
uint32_t data_size ;
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#define COL_DATAHASH 6
|
#define COL_DATAHASH 6
|
||||||
#define COL_RECEIVED 7
|
#define COL_RECEIVED 7
|
||||||
#define COL_SEND 8
|
#define COL_SEND 8
|
||||||
|
#define COL_DUPLICATION_FACTOR 9
|
||||||
|
|
||||||
static const int PARTIAL_VIEW_SIZE = 5 ;
|
static const int PARTIAL_VIEW_SIZE = 5 ;
|
||||||
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
|
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
|
||||||
@ -187,6 +188,7 @@ void GlobalRouterStatistics::updateContent()
|
|||||||
item -> setData(COL_DATAHASH, Qt::DisplayRole, QString::fromStdString(cache_infos[i].item_hash.toStdString()));
|
item -> setData(COL_DATAHASH, Qt::DisplayRole, QString::fromStdString(cache_infos[i].item_hash.toStdString()));
|
||||||
item -> setData(COL_RECEIVED, Qt::DisplayRole, QString::number(now - cache_infos[i].routing_time));
|
item -> setData(COL_RECEIVED, Qt::DisplayRole, QString::number(now - cache_infos[i].routing_time));
|
||||||
item -> setData(COL_SEND, Qt::DisplayRole, QString::number(now - cache_infos[i].last_sent_time));
|
item -> setData(COL_SEND, Qt::DisplayRole, QString::number(now - cache_infos[i].last_sent_time));
|
||||||
|
item -> setData(COL_DUPLICATION_FACTOR, Qt::DisplayRole, QString::number(cache_infos[i].duplication_factor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +335,9 @@ void GlobalRouterStatisticsWidget::updateContent()
|
|||||||
mMinWheelZoneX = ox+2*cellx ;
|
mMinWheelZoneX = ox+2*cellx ;
|
||||||
mMinWheelZoneY = oy ;
|
mMinWheelZoneY = oy ;
|
||||||
|
|
||||||
|
RsGxsId current_id ;
|
||||||
|
float current_width=0 ;
|
||||||
|
|
||||||
for(std::map<GRouterKeyId,std::vector<float> >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it,++n)
|
for(std::map<GRouterKeyId,std::vector<float> >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it,++n)
|
||||||
if(n >= mCurrentN-PARTIAL_VIEW_SIZE/2 && n <= mCurrentN+PARTIAL_VIEW_SIZE/2)
|
if(n >= mCurrentN-PARTIAL_VIEW_SIZE/2 && n <= mCurrentN+PARTIAL_VIEW_SIZE/2)
|
||||||
{
|
{
|
||||||
@ -355,12 +360,19 @@ void GlobalRouterStatisticsWidget::updateContent()
|
|||||||
{
|
{
|
||||||
current_probs = it->second ;
|
current_probs = it->second ;
|
||||||
current_oy = oy ;
|
current_oy = oy ;
|
||||||
|
current_id = it->first ;
|
||||||
|
current_width = ox+matrix_info.friend_ids.size()*cellx+fm_monospace.width(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
oy += celly ;
|
oy += celly ;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsIdentityDetails iddetails ;
|
||||||
|
if(rsIdentity->getIdDetails(current_id,iddetails))
|
||||||
|
painter.drawText(current_width+cellx, current_oy+celly, QString::fromUtf8(iddetails.mNickname.c_str())) ;
|
||||||
|
|
||||||
mMaxWheelZoneY = oy+celly ;
|
mMaxWheelZoneY = oy+celly ;
|
||||||
|
|
||||||
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
||||||
@ -382,7 +394,7 @@ void GlobalRouterStatisticsWidget::updateContent()
|
|||||||
|
|
||||||
painter.drawLine(x1,y1,x1,y2);
|
painter.drawLine(x1,y1,x1,y2);
|
||||||
painter.drawLine(x1,y2,x1 + total_length - i*cellx,y2) ;
|
painter.drawLine(x1,y2,x1 + total_length - i*cellx,y2) ;
|
||||||
painter.drawText(cellx+ x1 + total_length - i*cellx,y2+(0.35)*celly, QString::fromUtf8(peer_ssl_details.name.c_str()) + " ("+QString::number(current_probs[i])+")");
|
painter.drawText(cellx+ x1 + total_length - i*cellx,y2+(0.35)*celly, QString::fromUtf8(peer_ssl_details.name.c_str()) + " - " + QString::fromUtf8(peer_ssl_details.location.c_str()) + " ("+QString::number(current_probs[i])+")");
|
||||||
}
|
}
|
||||||
oy += celly * (2+matrix_info.friend_ids.size());
|
oy += celly * (2+matrix_info.friend_ids.size());
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>593</width>
|
<width>593</width>
|
||||||
<height>159</height>
|
<height>156</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -101,6 +101,11 @@
|
|||||||
<string>Send</string>
|
<string>Send</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Branching factor</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
Reference in New Issue
Block a user