2013-11-02 10:35:33 -04:00
/*
* libretroshare / src / services : groutermatrix . cc
*
* Services for RetroShare .
*
* Copyright 2013 by Cyril Soler
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " csoler@users.sourceforge.net " .
*
*/
2013-11-08 17:22:40 -05:00
# include "groutertypes.h"
2013-11-02 10:35:33 -04:00
# include "groutermatrix.h"
2013-12-27 15:06:47 -05:00
# include "grouteritems.h"
2013-11-02 10:35:33 -04:00
2013-11-05 16:15:26 -05:00
GRouterMatrix : : GRouterMatrix ( )
2013-11-02 10:35:33 -04:00
{
2013-11-05 16:15:26 -05:00
_proba_need_updating = true ;
2013-11-02 10:35:33 -04:00
}
2013-11-05 16:15:26 -05:00
bool GRouterMatrix : : addRoutingClue ( const GRouterKeyId & key_id , const GRouterServiceId & sid , float distance ,
2014-03-17 16:56:06 -04:00
const std : : string & desc_string , const RsPeerId & source_friend )
2013-11-05 16:15:26 -05:00
{
// 1 - get the friend index.
//
uint32_t fid = getFriendId ( source_friend ) ;
// 2 - get the Key map, and add the routing clue.
//
time_t now = time ( NULL ) ;
RoutingMatrixHitEntry rc ;
rc . weight = 1.0f / ( 1.0f + distance ) ;
rc . time_stamp = now ;
rc . friend_id = fid ;
2013-11-08 17:22:40 -05:00
std : : list < RoutingMatrixHitEntry > & lst ( _routing_clues [ key_id ] ) ;
// Prevent flooding. Happens in two scenarii:
// 1 - a user restarts RS very often => keys get republished for some reason
// 2 - a user intentionnaly floods a key
//
if ( ! lst . empty ( ) & & lst . front ( ) . time_stamp + RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS > now )
{
std : : cerr < < " GRouterMatrix::addRoutingClue(): too clues for key " < < key_id . toStdString ( ) < < " in a small interval of " < < now - lst . front ( ) . time_stamp < < " seconds. Flooding? " < < std : : endl ;
return false ;
}
lst . push_front ( rc ) ; // create it if necessary
// Remove older elements
//
uint32_t sz = lst . size ( ) ; // O(n)!
for ( uint32_t i = RS_GROUTER_MATRIX_MAX_HIT_ENTRIES ; i < sz ; + + i )
{
lst . pop_back ( ) ;
std : : cerr < < " Poped one entry " < < std : : endl ;
}
2013-11-05 16:15:26 -05:00
_proba_need_updating = true ; // always, since we added new clues.
return true ;
}
2014-03-17 16:56:06 -04:00
uint32_t GRouterMatrix : : getFriendId_const ( const RsPeerId & source_friend ) const
2013-11-08 17:22:40 -05:00
{
2014-03-17 16:56:06 -04:00
std : : map < RsPeerId , uint32_t > : : const_iterator it = _friend_indices . find ( source_friend ) ;
2013-11-05 16:15:26 -05:00
2013-11-08 17:22:40 -05:00
if ( it = = _friend_indices . end ( ) )
return _reverse_friend_indices . size ( ) ;
else
return it - > second ;
}
2014-03-17 16:56:06 -04:00
uint32_t GRouterMatrix : : getFriendId ( const RsPeerId & source_friend )
2013-11-05 16:15:26 -05:00
{
2014-03-17 16:56:06 -04:00
std : : map < RsPeerId , uint32_t > : : const_iterator it = _friend_indices . find ( source_friend ) ;
2013-11-05 16:15:26 -05:00
if ( it = = _friend_indices . end ( ) )
{
// add a new friend
uint32_t new_id = _reverse_friend_indices . size ( ) ;
_reverse_friend_indices . push_back ( source_friend ) ;
_friend_indices [ source_friend ] = new_id ;
return new_id ;
}
else
return it - > second ;
}
void GRouterMatrix : : debugDump ( ) const
{
std : : cerr < < " Proba needs up: " < < _proba_need_updating < < std : : endl ;
2013-11-08 17:22:40 -05:00
std : : cerr < < " Known keys: " < < _time_combined_hits . size ( ) < < std : : endl ;
2013-11-05 16:15:26 -05:00
std : : cerr < < " Routing events: " < < std : : endl ;
time_t now = time ( NULL ) ;
for ( std : : map < GRouterKeyId , std : : list < RoutingMatrixHitEntry > > : : const_iterator it ( _routing_clues . begin ( ) ) ; it ! = _routing_clues . end ( ) ; + + it )
{
std : : cerr < < " " < < it - > first . toStdString ( ) < < " : " ;
for ( std : : list < RoutingMatrixHitEntry > : : const_iterator it2 ( it - > second . begin ( ) ) ; it2 ! = it - > second . end ( ) ; + + it2 )
std : : cerr < < now - ( * it2 ) . time_stamp < < " ( " < < ( * it2 ) . friend_id < < " , " < < ( * it2 ) . weight < < " ) " ;
std : : cerr < < std : : endl ;
}
2013-11-08 17:22:40 -05:00
std : : cerr < < " Routing values: " < < std : : endl ;
2013-11-05 16:15:26 -05:00
for ( std : : map < GRouterKeyId , std : : vector < float > > : : const_iterator it ( _time_combined_hits . begin ( ) ) ; it ! = _time_combined_hits . end ( ) ; + + it )
{
2013-12-28 16:47:15 -05:00
std : : cerr < < " " < < it - > first . toStdString ( ) < < " : " ;
2013-11-05 16:15:26 -05:00
for ( uint32_t i = 0 ; i < it - > second . size ( ) ; + + i )
std : : cerr < < it - > second [ i ] < < " " ;
std : : cerr < < std : : endl ;
}
}
2014-03-17 16:56:06 -04:00
bool GRouterMatrix : : computeRoutingProbabilities ( const GRouterKeyId & key_id , const std : : list < RsPeerId > & friends , std : : map < RsPeerId , float > & probas ) const
2013-11-05 16:15:26 -05:00
{
// Routing probabilities are computed according to routing clues
//
// For a given key, each friend has a known set of routing clues (time_t, weight)
// We combine these to compute a static weight for each friend/key pair.
// This is performed in updateRoutingProbabilities()
//
// Then for a given list of online friends, the weights are computed into probabilities,
// that always sum up to 1.
//
2013-11-08 17:22:40 -05:00
if ( _proba_need_updating )
std : : cerr < < " GRouterMatrix::computeRoutingProbabilities(): matrix is not up to date. Not a real problem, but still... " < < std : : endl ;
probas . clear ( ) ;
float total = 0.0f ;
std : : map < GRouterKeyId , std : : vector < float > > : : const_iterator it2 = _time_combined_hits . find ( key_id ) ;
if ( it2 = = _time_combined_hits . end ( ) )
{
std : : cerr < < " GRouterMatrix::computeRoutingProbabilities(): key id " < < key_id . toStdString ( ) < < " does not exist! " < < std : : endl ;
return false ;
}
const std : : vector < float > & w ( it2 - > second ) ;
2014-03-17 16:56:06 -04:00
for ( std : : list < RsPeerId > : : const_iterator it ( friends . begin ( ) ) ; it ! = friends . end ( ) ; + + it )
2013-11-08 17:22:40 -05:00
{
uint32_t findex = getFriendId_const ( * it ) ;
if ( findex > = w . size ( ) )
probas [ * it ] = 0.0f ;
else
{
probas [ * it ] = w [ findex ] ;
total + = w [ findex ] ;
}
}
if ( total > 0.0f )
2014-03-17 16:56:06 -04:00
for ( std : : map < RsPeerId , float > : : iterator it ( probas . begin ( ) ) ; it ! = probas . end ( ) ; + + it )
2013-11-08 17:22:40 -05:00
it - > second / = total ;
2013-11-05 16:15:26 -05:00
return true ;
}
bool GRouterMatrix : : updateRoutingProbabilities ( )
{
2013-12-27 15:06:47 -05:00
std : : cerr < < " Updating routing probabilities... " < < std : : endl ;
2013-11-05 16:15:26 -05:00
if ( ! _proba_need_updating )
2013-12-27 15:06:47 -05:00
{
std : : cerr < < " not needed. " < < std : : endl ;
2013-11-05 16:15:26 -05:00
return false ;
2013-12-27 15:06:47 -05:00
}
2013-11-05 16:15:26 -05:00
time_t now = time ( NULL ) ;
for ( std : : map < GRouterKeyId , std : : list < RoutingMatrixHitEntry > > : : const_iterator it ( _routing_clues . begin ( ) ) ; it ! = _routing_clues . end ( ) ; + + it )
{
std : : cerr < < " " < < it - > first . toStdString ( ) < < " : " ;
std : : vector < float > & v ( _time_combined_hits [ it - > first ] ) ;
v . clear ( ) ;
v . resize ( _friend_indices . size ( ) , 0.0f ) ;
for ( std : : list < RoutingMatrixHitEntry > : : const_iterator it2 ( it - > second . begin ( ) ) ; it2 ! = it - > second . end ( ) ; + + it2 )
{
float time_difference_in_days = 1 + ( now - ( * it2 ) . time_stamp ) / 86400.0f ;
v [ ( * it2 ) . friend_id ] + = ( * it2 ) . weight / ( time_difference_in_days * time_difference_in_days ) ;
}
}
2013-12-27 15:06:47 -05:00
std : : cerr < < " done. " < < std : : endl ;
2013-11-05 16:15:26 -05:00
_proba_need_updating = false ;
return true ;
}
2013-12-27 15:06:47 -05:00
bool GRouterMatrix : : saveList ( std : : list < RsItem * > & items )
{
std : : cerr < < " GRoutingMatrix::saveList() " < < std : : endl ;
RsGRouterMatrixFriendListItem * item = new RsGRouterMatrixFriendListItem ;
item - > reverse_friend_indices = _reverse_friend_indices ;
items . push_back ( item ) ;
2013-11-05 16:15:26 -05:00
2013-12-27 15:06:47 -05:00
for ( std : : map < GRouterKeyId , std : : list < RoutingMatrixHitEntry > > : : const_iterator it ( _routing_clues . begin ( ) ) ; it ! = _routing_clues . end ( ) ; + + it )
{
RsGRouterMatrixCluesItem * item = new RsGRouterMatrixCluesItem ;
item - > destination_key = it - > first ;
item - > clues = it - > second ;
items . push_back ( item ) ;
}
2013-11-05 16:15:26 -05:00
2013-12-27 15:06:47 -05:00
return true ;
}
bool GRouterMatrix : : loadList ( std : : list < RsItem * > & items )
{
RsGRouterMatrixFriendListItem * itm1 = NULL ;
RsGRouterMatrixCluesItem * itm2 = NULL ;
2013-11-05 16:15:26 -05:00
2013-12-27 15:06:47 -05:00
std : : cerr < < " GRoutingMatrix::loadList() " < < std : : endl ;
for ( std : : list < RsItem * > : : const_iterator it ( items . begin ( ) ) ; it ! = items . end ( ) ; + + it )
{
if ( NULL ! = ( itm2 = dynamic_cast < RsGRouterMatrixCluesItem * > ( * it ) ) )
{
std : : cerr < < " initing routing clues. " < < std : : endl ;
_routing_clues [ itm2 - > destination_key ] = itm2 - > clues ;
_proba_need_updating = true ; // notifies to re-compute all the info.
}
if ( NULL ! = ( itm1 = dynamic_cast < RsGRouterMatrixFriendListItem * > ( * it ) ) )
{
_reverse_friend_indices = itm1 - > reverse_friend_indices ;
_friend_indices . clear ( ) ;
for ( uint32_t i = 0 ; i < _reverse_friend_indices . size ( ) ; + + i )
_friend_indices [ _reverse_friend_indices [ i ] ] = i ;
_proba_need_updating = true ; // notifies to re-compute all the info.
}
}
return true ;
}
2013-11-02 10:35:33 -04:00