package edu.uw.cse.netlab.reputation;
import java.io.IOException;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.peer.PEPeerStats;
import org.gudy.azureus2.core3.peer.impl.transport.PEPeerTransportProtocol;
import org.gudy.azureus2.core3.util.ByteFormatter;
import com.aelitis.azureus.core.impl.AzureusCoreImpl;
import edu.uw.cse.netlab.reputation.storage.Receipt;
import edu.uw.cse.netlab.reputation.storage.ReputationDAO;
import edu.uw.cse.netlab.utils.BloomFilter;
public class Computation
{
private static Logger logger = Logger.getLogger(Computation.class.getName());
public static double intermediary_weight( long inID ) throws IOException
{
ReputationDAO rep = ReputationDAO.get();
/* Equation 1:
*
* The data I've received from intermediary both directly and indirectly
* --------------------------------------------------------------------------
* The data I've sent to intermediary and due to intermediary recommendations
*/
double top = (rep.get_received_direct(inID) + rep.get_local_recv_due_to_remote_reco(inID));
//------------------------------------------------------------------------------
double bottom = (rep.get_sent_direct(inID) + rep.get_local_sent_due_to_remote_reco(inID));
/*
* Sanity checking
*/
if( bottom == 0 )
return 5.0; // TODO: This is arbitrary, make sure this makes sense in practice.
if( top == 0 )
System.err.println( "Negotiating with a shared intermediary that has no standing. (Top K shouldn't have included this intermediary): " + inID );
return Math.min(top/bottom, 100.0); // TODO: Also arbitrary, make sure this is sensible.
}
public static double peer_value_at_intermediary( Receipt inReceipt ) throws IOException
{
/* Equation 2:
*
* Total data that peer has sent to any of intermediary's recommendations + data sent directly to intermediary
* --------------------------------------------------------------------------------------------------------------
* Total data sent to inPeer because of standing with intermediary + data sent directly from intermediary to peer
*/
double top = inReceipt.get_peer_sent_to_recos() + inReceipt.get_received_direct();
// -----------------------------------------------------------------------------
double bottom = inReceipt.get_peer_received_due_to_reco() + inReceipt.get_sent_direct();
if( bottom == 0 )
return 5.0; // TODO: arbitrary constant.
return Math.min(top/bottom, 100.0); // TODO: arbitrary constant.
}
public static double indirect_reputation( Receipt [] inSharedIntermediaries ) throws IOException
{
if( inSharedIntermediaries.length == 0 )
return 0.0;
double rep_sum = 0.0;
for( Receipt r : inSharedIntermediaries )
{
if( r == null )
throw new IOException("********** r is null");
rep_sum += intermediary_weight(r.getSigningID()) * peer_value_at_intermediary(r);
}
return rep_sum/(double)inSharedIntermediaries.length;
}
public static double direct_reputation( PublicKey inRemotePeerKey ) throws IOException
{
ReputationDAO rep = ReputationDAO.get();
long remote_id = rep.get_internal_id(inRemotePeerKey);
double top = rep.get_received_direct(remote_id);
double bottom = rep.get_sent_direct(remote_id);
if( top == -1 ||
bottom == -1 )
{
return -1;
}
if( top == 0 )
return 0;
if( bottom == 0 )
return 5.0; // TODO: arbitrary constant
return Math.min(top/bottom, 100.0); // TODO: arbitrary constant
}
public static Map<PublicKey, Float> desired_nodes_from_topK( BloomFilter inFilter ) throws IOException
{
ReputationDAO rep = ReputationDAO.get();
List<PublicKey> desired = new ArrayList<PublicKey>();
for( PublicKey k : rep.get_desired_peers() )
{
if( inFilter.test(k.getEncoded()) )
{
logger.finest("\tadding: " + ByteFormatter.encodeString(k.getEncoded()));
desired.add(k);
}
}
logger.finer("shared total (desired_nodes_from_topK): " + desired.size());
// Default policy is choose random 10.
Collections.shuffle(desired);
PublicKey [] keys = desired.subList(0, Math.min(desired.size(), 10)).toArray(new PublicKey[0]);
double equal_split = 1.0 / (double)keys.length;
Map<PublicKey, Float> map = new HashMap<PublicKey, Float>();
for( PublicKey k : keys )
map.put(k, (float)equal_split); // TODO: make this not equally load balanced, maybe...
return map;
}
public static final double DIRECT_WEIGHT = 0.5;
/**
* This function computes the fractional weight with which to record the indirect observations of a peer
*
* @param peer The peer whose weight we are computing
* @return weight
*/
public static double indirect_advertisements_weight( PEPeerTransportProtocol peer )
{
/**
* Compare the recent volume of data received from this peer to the recent volume received from others
*/
long max_rate = 0, max_volume = 0;
for( DownloadManager dm : (List<DownloadManager>)AzureusCoreImpl.getSingleton().getGlobalManager().getDownloadManagers() )
{
if( dm.getPeerManager() == null )
{
logger.warning("null peer manager for swarm: " + dm.getDisplayName());
continue;
}
if( dm.getPeerManager().getPeers() == null )
{
logger.warning("null peer list for swarm: " + dm.getDisplayName());
continue;
}
for( PEPeerTransportProtocol p : (List<PEPeerTransportProtocol>)dm.getPeerManager().getPeers() )
{
PEPeerStats s = p.getStats();
if( s.getTotalDataBytesReceived() > max_volume )
max_volume = s.getTotalDataBytesReceived();
if( s.getDataReceiveRate() > max_rate )
max_rate = s.getDataReceiveRate();
}
}
logger.finer("indirect_advertisements_weight(), max_volume: " + max_volume + " max_rate: " + max_rate);
double direct = max_volume > 0 ? ((double)peer.getStats().getTotalDataBytesReceived()/(double)max_volume) : 0;
double indirect = max_rate > 0 ? ((double)peer.getStats().getDataReceiveRate()/(double)max_rate) : 0;
logger.finer("indirect_obs_weight: direct: " + direct + " indirect: " + indirect);
return DIRECT_WEIGHT * direct +
(1-DIRECT_WEIGHT) * indirect;
}
}