use of com.biglybt.core.peer.PEPeer in project BiglyBT by BiglySoftware.
the class DownloadingUnchoker method getImmediateUnchokes.
@Override
public ArrayList<PEPeer> getImmediateUnchokes(int max_to_unchoke, ArrayList<PEPeer> all_peers) {
ArrayList<PEPeer> to_unchoke = new ArrayList<>();
// count all the currently unchoked peers
int num_unchoked = 0;
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (!peer.isChokedByMe())
num_unchoked++;
}
// if not enough unchokes
int needed = max_to_unchoke - num_unchoked;
if (needed > 0) {
for (int i = 0; i < needed; i++) {
PEPeer peer = UnchokerUtil.getNextOptimisticPeer(all_peers, true, true);
// no more new unchokes avail
if (peer == null)
break;
to_unchoke.add(peer);
peer.setOptimisticUnchoke(true);
}
}
return to_unchoke;
}
use of com.biglybt.core.peer.PEPeer in project BiglyBT by BiglySoftware.
the class SeedingUnchoker method getImmediateUnchokes.
@Override
public ArrayList<PEPeer> getImmediateUnchokes(int max_to_unchoke, ArrayList<PEPeer> all_peers) {
int peer_count = all_peers.size();
if (max_to_unchoke > peer_count) {
max_to_unchoke = peer_count;
}
// count all the currently unchoked peers
int num_unchoked = 0;
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (!peer.isChokedByMe())
num_unchoked++;
}
// if not enough unchokes
int needed = max_to_unchoke - num_unchoked;
if (needed > 0) {
ArrayList<PEPeer> to_unchoke = UnchokerUtil.getNextOptimisticPeers(all_peers, false, false, needed);
if (to_unchoke == null) {
return (new ArrayList<>(0));
}
for (int i = 0; i < to_unchoke.size(); i++) {
to_unchoke.get(i).setOptimisticUnchoke(true);
}
return (to_unchoke);
} else {
return (new ArrayList<>(0));
}
}
use of com.biglybt.core.peer.PEPeer in project BiglyBT by BiglySoftware.
the class SeedingUnchoker method calculateUnchokes.
@Override
public void calculateUnchokes(int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections, boolean do_high_latency_peers) {
// one optimistic unchoke for every 5 upload slots
int max_optimistic = ((max_to_unchoke - 1) / 5) + 1;
// get all the currently unchoked peers
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (!peer.isChokedByMe()) {
if (UnchokerUtil.isUnchokable(peer, false)) {
unchokes.add(peer);
} else {
// should be immediately choked
chokes.add(peer);
}
}
}
// if too many unchokes
while (unchokes.size() > max_to_unchoke) {
chokes.add(unchokes.remove(unchokes.size() - 1));
}
// we only recalculate the uploads when we're forced to refresh the optimistic unchokes
if (force_refresh) {
// we need to make room for new opt unchokes by finding the "worst" peers
ArrayList<PEPeer> peers_ordered_by_rate = new ArrayList<>();
ArrayList<PEPeer> peers_ordered_by_uploaded = new ArrayList<>();
// 0-initialized
long[] rates = new long[unchokes.size()];
// 0-initialized
long[] uploaded = new long[rates.length];
// calculate factor rankings
for (int i = 0; i < unchokes.size(); i++) {
PEPeer peer = unchokes.get(i);
long rate = peer.getStats().getDataSendRate();
if (rate > 256) {
// filter out really slow peers
// calculate reverse order by our upload rate to them
UnchokerUtil.updateLargestValueFirstSort(rate, rates, peer, peers_ordered_by_rate, 0);
// calculate order by the total number of bytes we've uploaded to them
UnchokerUtil.updateLargestValueFirstSort(peer.getStats().getTotalDataBytesSent(), uploaded, peer, peers_ordered_by_uploaded, 0);
}
}
// we want higher rates at the end
Collections.reverse(peers_ordered_by_rate);
ArrayList<PEPeer> peers_ordered_by_rank = new ArrayList<>();
long[] ranks = new long[peers_ordered_by_rate.size()];
Arrays.fill(ranks, Long.MIN_VALUE);
// combine factor rankings to get best
for (int i = 0; i < unchokes.size(); i++) {
PEPeer peer = unchokes.get(i);
// "better" peers have high indexes (toward the end of each list)
long rate_factor = peers_ordered_by_rate.indexOf(peer);
long uploaded_factor = peers_ordered_by_uploaded.indexOf(peer);
// wasn't downloading fast enough, skip add so it will be choked automatically
if (rate_factor == -1)
continue;
long rank_factor = rate_factor + uploaded_factor;
UnchokerUtil.updateLargestValueFirstSort(rank_factor, ranks, peer, peers_ordered_by_rank, 0);
}
// make space for new optimistic unchokes
while (peers_ordered_by_rank.size() > max_to_unchoke - max_optimistic) {
peers_ordered_by_rank.remove(peers_ordered_by_rank.size() - 1);
}
// update choke list with drops and unchoke list with optimistic unchokes
ArrayList<PEPeer> to_unchoke = new ArrayList<>();
for (Iterator<PEPeer> it = unchokes.iterator(); it.hasNext(); ) {
PEPeer peer = it.next();
peer.setOptimisticUnchoke(false);
if (!peers_ordered_by_rank.contains(peer)) {
// should be choked
// we assume that any/all chokes are to be replace by optimistics
PEPeer optimistic_peer = UnchokerUtil.getNextOptimisticPeer(all_peers, false, false);
if (optimistic_peer != null) {
// only choke if we've got a peer to replace it with
chokes.add(peer);
it.remove();
to_unchoke.add(optimistic_peer);
optimistic_peer.setOptimisticUnchoke(true);
}
}
}
for (int i = 0; i < to_unchoke.size(); i++) {
unchokes.add(to_unchoke.get(i));
}
}
if (check_priority_connections) {
// add priority peers preferentially, leaving room for 1 non-priority peer for every 5 upload slots
setPriorityUnchokes(max_to_unchoke - max_optimistic, all_peers);
}
if (do_high_latency_peers) {
UnchokerUtil.doHighLatencyPeers(chokes, unchokes, false);
}
}
use of com.biglybt.core.peer.PEPeer in project BiglyBT by BiglySoftware.
the class SeedingUnchoker method setPriorityUnchokes.
private void setPriorityUnchokes(int max_priority, ArrayList<PEPeer> all_peers) {
// don't bother trying to replace peers in an empty list
if (unchokes.isEmpty())
return;
ArrayList<PEPeer> priority_peers = new ArrayList<>();
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (peer.isPriorityConnection() && UnchokerUtil.isUnchokable(peer, true)) {
priority_peers.add(peer);
}
}
// we want to give all connected priority peers an equal chance if there are more than max_priority allowed
Collections.shuffle(priority_peers);
int num_unchoked = 0;
int num_non_priority_to_retain = priority_unchoke_retention_count;
int max = max_priority > unchokes.size() ? unchokes.size() : max_priority;
while (num_unchoked < max && !priority_peers.isEmpty()) {
// go through unchoke list and replace non-buddy peers with buddy ones
// pop peer from front of unchoke list
PEPeer peer = unchokes.remove(0);
if (priority_peers.remove(peer)) {
// peer is already in the priority list
// so insert priority peer back into list at the end
unchokes.add(peer);
} else {
if (num_non_priority_to_retain-- > 0) {
// retain if permitted
unchokes.add(peer);
}
// get next buddy
PEPeer buddy = priority_peers.remove(priority_peers.size() - 1);
// just in case
chokes.remove(buddy);
// add priority to back of list
unchokes.add(buddy);
}
num_unchoked++;
}
}
use of com.biglybt.core.peer.PEPeer in project BiglyBT by BiglySoftware.
the class UnchokerUtil method getNextOptimisticPeers.
public static ArrayList<PEPeer> getNextOptimisticPeers(ArrayList<PEPeer> all_peers, boolean factor_reciprocated, boolean allow_snubbed, int num_needed) {
// find all potential optimistic peers
ArrayList<PEPeer> optimistics = new ArrayList<>();
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (isUnchokable(peer, false) && peer.isChokedByMe()) {
optimistics.add(peer);
}
}
if (optimistics.isEmpty() && allow_snubbed) {
// try again, allowing snubbed peers as last resort
for (int i = 0; i < all_peers.size(); i++) {
PEPeer peer = all_peers.get(i);
if (isUnchokable(peer, true) && peer.isChokedByMe()) {
optimistics.add(peer);
}
}
}
// no unchokable peers avail
if (optimistics.isEmpty())
return null;
// factor in peer reciprocation ratio when picking optimistic peers
ArrayList<PEPeer> result = new ArrayList<>(optimistics.size());
if (factor_reciprocated) {
ArrayList<PEPeerTransport> ratioed_peers = new ArrayList<>(optimistics.size());
long[] ratios = new long[optimistics.size()];
Arrays.fill(ratios, Long.MIN_VALUE);
// order by upload ratio
for (int i = 0; i < optimistics.size(); i++) {
PEPeer peer = optimistics.get(i);
// score of >0 means we've uploaded more, <0 means we've downloaded more
long score = peer.getStats().getTotalDataBytesSent() - peer.getStats().getTotalDataBytesReceived();
// higher value = worse score
UnchokerUtil.updateLargestValueFirstSort(score, ratios, peer, ratioed_peers, 0);
}
for (int i = 0; i < num_needed && ratioed_peers.size() > 0; i++) {
// map to sorted list using a logistic curve
double factor = 1F / (0.8 + 0.2 * Math.pow(RandomUtils.nextFloat(), -1));
int pos = (int) (factor * ratioed_peers.size());
result.add(ratioed_peers.remove(pos));
}
} else {
for (int i = 0; i < num_needed && optimistics.size() > 0; i++) {
int rand_pos = new Random().nextInt(optimistics.size());
result.add(optimistics.remove(rand_pos));
}
}
return (result);
// TODO:
// in downloading mode, we would be better off optimistically unchoking just peers we are interested in ourselves,
// as they could potentially reciprocate. however, new peers have no pieces to share, and are not interesting to
// us, and would never be unchoked, and thus would never get any data.
// we could use a deterministic method for new peers to get their very first piece from us
}
Aggregations