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