1 /* 2 * Created on Sep 23, 2004 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 */ 19 20 package com.aelitis.azureus.core.networkmanager.impl; 21 22 import java.util.*; 23 24 import org.gudy.azureus2.core3.util.AEMonitor; 25 import org.gudy.azureus2.core3.util.Debug; 26 27 import com.aelitis.azureus.core.networkmanager.*; 28 29 30 /** 31 * Manages transfer entities on behalf of peer connections. 32 * Each entity handler has a global pool which manages all 33 * connections by default. Connections can also be "upgraded" 34 * to a higher connection control level, i.e. each connection 35 * has its own specialized entity for performance purposes. 36 */ 37 public class EntityHandler { 38 private final HashMap upgraded_connections = new HashMap(); 39 private final AEMonitor lock = new AEMonitor( "EntityHandler" ); 40 private final MultiPeerUploader global_uploader; 41 private final MultiPeerDownloader2 global_downloader; 42 private boolean global_registered = false; 43 private final int handler_type; 44 45 46 /** 47 * Create a new entity handler using the given rate handler. 48 * @param type read or write type handler 49 * @param rate_handler global max rate handler 50 */ EntityHandler( int type, RateHandler rate_handler )51 public EntityHandler( int type, RateHandler rate_handler ) { 52 this.handler_type = type; 53 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 54 global_uploader = new MultiPeerUploader( rate_handler ); 55 global_downloader = null; 56 } 57 else { //download type 58 global_downloader = new MultiPeerDownloader2( rate_handler ); 59 global_uploader = null; 60 } 61 } 62 63 64 65 /** 66 * Register a peer connection for management by the handler. 67 * @param connection to add to the global pool 68 */ registerPeerConnection( NetworkConnectionBase connection )69 public void registerPeerConnection( NetworkConnectionBase connection ) { 70 try { lock.enter(); 71 if( !global_registered ) { 72 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 73 NetworkManager.getSingleton().addWriteEntity( global_uploader, -1 ); //register global upload entity 74 } 75 else { 76 NetworkManager.getSingleton().addReadEntity( global_downloader, -1 ); //register global download entity 77 } 78 79 global_registered = true; 80 } 81 } 82 finally { lock.exit(); } 83 84 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 85 global_uploader.addPeerConnection( connection ); 86 } 87 else { 88 global_downloader.addPeerConnection( connection ); 89 } 90 } 91 92 93 /** 94 * Remove a peer connection from the entity handler. 95 * @param connection to cancel 96 */ cancelPeerConnection( NetworkConnectionBase connection )97 public void cancelPeerConnection( NetworkConnectionBase connection ) { 98 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 99 if( !global_uploader.removePeerConnection( connection ) ) { //if not found in the pool entity 100 SinglePeerUploader upload_entity = (SinglePeerUploader)upgraded_connections.remove( connection ); //check for it in the upgraded list 101 if( upload_entity != null ) { 102 NetworkManager.getSingleton().removeWriteEntity( upload_entity ); //cancel from write processing 103 } 104 } 105 } 106 else { 107 if( !global_downloader.removePeerConnection( connection ) ) { //if not found in the pool entity 108 SinglePeerDownloader download_entity = (SinglePeerDownloader)upgraded_connections.remove( connection ); //check for it in the upgraded list 109 if( download_entity != null ) { 110 NetworkManager.getSingleton().removeReadEntity( download_entity ); //cancel from read processing 111 } 112 } 113 } 114 115 } 116 117 118 /** 119 * Upgrade a peer connection from the general pool to its own high-speed entity. 120 * @param connection to upgrade from global management 121 * @param handler individual connection rate handler 122 */ upgradePeerConnection( NetworkConnectionBase connection, RateHandler handler, int partition_id )123 public void upgradePeerConnection( NetworkConnectionBase connection, RateHandler handler, int partition_id ) { 124 try { lock.enter(); 125 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 126 SinglePeerUploader upload_entity = new SinglePeerUploader( connection, handler ); 127 if( !global_uploader.removePeerConnection( connection ) ) { //remove it from the general upload pool 128 Debug.out( "upgradePeerConnection:: upload entity not found/removed !" ); 129 } 130 NetworkManager.getSingleton().addWriteEntity( upload_entity, partition_id ); //register it for write processing 131 upgraded_connections.put( connection, upload_entity ); //add it to the upgraded list 132 } 133 else { 134 SinglePeerDownloader download_entity = new SinglePeerDownloader( connection, handler ); 135 if( !global_downloader.removePeerConnection( connection ) ) { //remove it from the general upload pool 136 Debug.out( "upgradePeerConnection:: download entity not found/removed !" ); 137 } 138 NetworkManager.getSingleton().addReadEntity( download_entity, partition_id ); //register it for read processing 139 upgraded_connections.put( connection, download_entity ); //add it to the upgraded list 140 } 141 } 142 finally { lock.exit(); } 143 } 144 145 146 /** 147 * Downgrade (return) a peer connection back into the general pool. 148 * @param connection to downgrade back into the global entity 149 */ downgradePeerConnection( NetworkConnectionBase connection )150 public void downgradePeerConnection( NetworkConnectionBase connection ) { 151 try { lock.enter(); 152 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 153 SinglePeerUploader upload_entity = (SinglePeerUploader)upgraded_connections.remove( connection ); //remove from the upgraded list 154 if( upload_entity != null ) { 155 NetworkManager.getSingleton().removeWriteEntity( upload_entity ); //cancel from write processing 156 } 157 else { 158 Debug.out( "upload_entity == null" ); 159 } 160 global_uploader.addPeerConnection( connection ); //move back to the general pool 161 } 162 else { 163 SinglePeerDownloader download_entity = (SinglePeerDownloader)upgraded_connections.remove( connection ); //remove from the upgraded list 164 if( download_entity != null ) { 165 NetworkManager.getSingleton().removeReadEntity( download_entity ); //cancel from read processing 166 } 167 else { 168 Debug.out( "download_entity == null" ); 169 } 170 global_downloader.addPeerConnection( connection ); //move back to the general pool 171 } 172 } 173 finally { lock.exit(); } 174 } 175 176 public RateHandler getRateHandler( NetworkConnectionBase connection )177 getRateHandler( 178 NetworkConnectionBase connection ) 179 { 180 try{ 181 lock.enter(); 182 183 if( handler_type == TransferProcessor.TYPE_UPLOAD ){ 184 185 SinglePeerUploader upload_entity = (SinglePeerUploader)upgraded_connections.get( connection ); 186 187 if ( upload_entity != null ){ 188 189 return( upload_entity.getRateHandler()); 190 }else{ 191 192 return( global_uploader.getRateHandler()); 193 } 194 }else{ 195 196 SinglePeerDownloader download_entity = (SinglePeerDownloader)upgraded_connections.get( connection ); 197 198 if ( download_entity != null ){ 199 200 return( download_entity.getRateHandler()); 201 }else{ 202 203 return( global_downloader.getRateHandler()); 204 } 205 } 206 207 }finally{ 208 lock.exit(); 209 } 210 } 211 212 /** 213 * Is the general pool entity in need of a transfer op. 214 * NOTE: Because the general pool is backed by a MultiPeer entity, 215 * it requires at least MSS available bytes before it will/can perform 216 * a successful transfer. This method allows higher-level bandwidth allocation to 217 * determine if it should reserve the necessary MSS bytes for the general pool's needs. 218 * @return true of it has data to transfer, false if not 219 */ 220 /* 221 public boolean isGeneralPoolReserveNeeded() { 222 if( handler_type == TransferProcessor.TYPE_UPLOAD ) { 223 return global_uploader.hasWriteDataAvailable(); 224 } 225 return global_downloader.hasReadDataAvailable(); 226 } 227 */ 228 229 } 230