1 /* 2 * Created on Jul 17, 2006 3 * Created by Alon Rohter 4 * Copyright (C) Azureus Software, Inc, All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 * AELITIS, SARL au capital de 30,000 euros 19 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. 20 * 21 */ 22 package com.aelitis.azureus.core.peermanager.uploadslots; 23 24 import java.util.*; 25 26 import org.gudy.azureus2.core3.peer.PEPeer; 27 import org.gudy.azureus2.core3.util.*; 28 29 30 31 32 /** 33 * 34 */ 35 public class UploadSessionPicker { 36 37 private final LinkedList next_optimistics = new LinkedList(); 38 private final AEMonitor next_optimistics_mon = new AEMonitor( "UploadSessionPicker" ); 39 40 private final LinkedList helpers = new LinkedList(); 41 42 private final DownloadingRanker down_ranker = new DownloadingRanker(); 43 private final SeedingRanker seed_ranker = new SeedingRanker(); 44 45 UploadSessionPicker()46 protected UploadSessionPicker() { 47 /*nothing*/ 48 } 49 50 51 registerHelper( UploadHelper helper )52 protected void registerHelper( UploadHelper helper ) { 53 try { next_optimistics_mon.enter(); 54 helpers.add( helper ); 55 56 int priority = helper.getPriority(); 57 58 //the higher the priority, the more optimistic unchoke chances they get 59 for( int i=0; i < priority; i++ ) { 60 insertHelper( helper ); 61 } 62 } 63 finally { next_optimistics_mon.exit(); } 64 } 65 66 67 deregisterHelper( UploadHelper helper )68 protected void deregisterHelper( UploadHelper helper ) { 69 try { next_optimistics_mon.enter(); 70 helpers.remove( helper ); 71 72 boolean rem = next_optimistics.removeAll( Collections.singleton( helper ) ); 73 if( !rem ) Debug.out( "!rem" ); 74 } 75 finally { next_optimistics_mon.exit(); } 76 } 77 78 79 updateHelper( UploadHelper helper )80 protected void updateHelper( UploadHelper helper ) { 81 try { next_optimistics_mon.enter(); 82 int priority = helper.getPriority(); //new priority 83 84 int count = 0; 85 86 for( Iterator it = next_optimistics.iterator(); it.hasNext(); ) { 87 UploadHelper h = (UploadHelper)it.next(); 88 if( h == helper ) { 89 count++; 90 91 if( count > priority ) { //new priority is lower 92 it.remove(); //trim 93 } 94 } 95 } 96 97 if( count < priority ) { //new priority is higher 98 for( int i=count; i < priority; i++ ) { 99 insertHelper( helper ); //add 100 } 101 } 102 } 103 finally { next_optimistics_mon.exit(); } 104 } 105 106 107 insertHelper( UploadHelper helper )108 private void insertHelper( UploadHelper helper ) { 109 int pos = RandomUtils.nextInt( next_optimistics.size() + 1 ); //pick a random location 110 next_optimistics.add( pos, helper ); //store into location 111 } 112 113 114 115 getHelperCount()116 protected int getHelperCount() { 117 try { next_optimistics_mon.enter(); 118 return next_optimistics.size(); 119 } 120 finally { next_optimistics_mon.exit(); } 121 } 122 123 124 125 //this picks both downloading and seeding sessions pickNextOptimisticSession()126 protected UploadSession pickNextOptimisticSession() { 127 128 try { next_optimistics_mon.enter(); 129 130 HashSet failed_helpers = null; 131 132 int loops_allowed = next_optimistics.size(); 133 134 while( loops_allowed > 0 ) { 135 136 UploadHelper helper = (UploadHelper)next_optimistics.removeFirst(); //take from front 137 138 next_optimistics.addLast( helper ); //add back at end 139 140 if( failed_helpers == null || !failed_helpers.contains( helper ) ) { //pre-emptive check to see if we've already tried this helper 141 142 PEPeer peer; 143 144 if( helper.isSeeding() ) { 145 peer = seed_ranker.getNextOptimisticPeer( helper.getAllPeers() ); 146 } 147 else { 148 peer = down_ranker.getNextOptimisticPeer( helper.getAllPeers() ); 149 } 150 151 if( peer == null ) { //no peers from this helper to unchoke 152 153 if( failed_helpers == null ) failed_helpers = new HashSet(); //lazy alloc 154 155 failed_helpers.add( helper ); //remember this helper in case we get it again in another loop round 156 } 157 else { //found an optimistic peer! 158 159 return new UploadSession( peer, helper.isSeeding() ? UploadSession.TYPE_SEED : UploadSession.TYPE_DOWNLOAD ); 160 } 161 } 162 163 loops_allowed--; 164 } 165 166 return null; //no optimistic peer found 167 168 } 169 finally { next_optimistics_mon.exit(); } 170 } 171 172 173 174 globalGetAllDownloadPeers()175 private ArrayList<PEPeer> globalGetAllDownloadPeers() { 176 try { next_optimistics_mon.enter(); 177 ArrayList<PEPeer> all = new ArrayList<PEPeer>(); 178 179 for( Iterator<PEPeer> it = helpers.iterator(); it.hasNext(); ) { 180 UploadHelper helper = (UploadHelper)it.next(); 181 182 if( !helper.isSeeding() ) { //filter out seeding 183 all.addAll( helper.getAllPeers() ); 184 } 185 } 186 187 return all; 188 } 189 finally { next_optimistics_mon.exit(); } 190 } 191 192 193 194 //this picks downloading sessions only pickBestDownloadSessions( int max_sessions )195 protected LinkedList<UploadSession> pickBestDownloadSessions( int max_sessions ) { 196 //TODO factor download priority into best calculation? 197 198 ArrayList<PEPeer> all_peers = globalGetAllDownloadPeers(); 199 200 if( all_peers.isEmpty() ) return new LinkedList(); 201 202 ArrayList<PEPeer> best = down_ranker.rankPeers( max_sessions, all_peers ); 203 204 if( best.size() != max_sessions ) { 205 Debug.outNoStack( "best.size()[" +best.size()+ "] != max_sessions[" +max_sessions+ "]" ); 206 } 207 208 if( best.isEmpty() ) { 209 return new LinkedList<UploadSession>(); 210 } 211 212 213 LinkedList<UploadSession> best_sessions = new LinkedList<UploadSession>(); 214 215 for( Iterator<PEPeer> it = best.iterator(); it.hasNext(); ) { 216 PEPeer peer = it.next(); 217 UploadSession session = new UploadSession( peer, UploadSession.TYPE_DOWNLOAD ); 218 best_sessions.add( session ); 219 } 220 221 return best_sessions; 222 } 223 224 225 226 227 } 228