changed global router routing strategy. Should be more effective now.

This commit is contained in:
csoler 2016-01-30 20:27:56 -05:00
parent 59d4c2c829
commit f0a49a427e
10 changed files with 308 additions and 135 deletions

View File

@ -142,25 +142,44 @@ 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 > rssize || offset > rssize - item->data_size) // better than if(item->data_size + offset > rssize) if(item->data_size > 0) // This happens when the item data has been deleted from the cache
{ {
std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl; if(item->data_size > rssize || offset > rssize - item->data_size) // better than if(item->data_size + offset > rssize)
delete item; {
return NULL ; std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl;
} delete item;
return NULL ;
}
if( NULL == (item->data_bytes = (uint8_t*)rs_malloc(item->data_size))) if( NULL == (item->data_bytes = (uint8_t*)rs_malloc(item->data_size)))
{ {
delete item; delete item;
return NULL ; return NULL ;
} }
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 ;

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
locked_collectAvailableTunnels(it->second.tunnel_hash,peers);
// For now, disable friends. We'll first check that the good old tunnel system works as before.
// if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)
// locked_collectAvailableTunnels(it->second.tunnel_hash,it->second.data_item->duplication_factor,peers_and_duplication_factors);
//
// 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 ;
float duplication_factor_delta =0.0;
uint32_t duplication_factor_buff =duplication_factor ;
for(std::vector<std::pair<float,RsPeerId> >::const_reverse_iterator it = mypairs.rbegin();it!=mypairs.rend() && n<max_count;++it) for(int i=mypairs.size()-1;i>=0 && n<max_count;--i)
if( (*it).first >= probability_threshold )
{ {
friend_peers.push_back( (*it).second ), ++n ; float ideal_dupl = duplication_factor*mypairs[i].first - duplication_factor_delta ; // correct what was taken in advance
#ifdef GROUTER_DEBUG
std::cerr << " keeping " << (*it).second << std::endl; uint32_t real_dupl = std::min( duplication_factor - max_count+1,std::max(1u,uint32_t(rint(ideal_dupl)))) ;
#endif duplication_factor_delta = real_dupl - ideal_dupl ;
if(!is_origin) // only collect one peer if we're not at origin. std::cerr << " Peer " << mypairs[i].second << " prob=" << mypairs[i].first << ", ideal_dupl=" << ideal_dupl << ", real=" << real_dupl << ". Delta = " << duplication_factor_delta << std::endl;
break ;
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() ;
} }

View File

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

View File

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

View File

@ -43,15 +43,16 @@
#include "util/QtVersion.h" #include "util/QtVersion.h"
#include "util/misc.h" #include "util/misc.h"
#define COL_ID 0 #define COL_ID 0
#define COL_NICKNAME 1 #define COL_NICKNAME 1
#define COL_DESTINATION 2 #define COL_DESTINATION 2
#define COL_DATASTATUS 3 #define COL_DATASTATUS 3
#define COL_TUNNELSTATUS 4 #define COL_TUNNELSTATUS 4
#define COL_DATASIZE 5 #define COL_DATASIZE 5
#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());

View File

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