📄 trnonblockingserver.java
字号:
/*
* Created on 02-Jan-2005
* Created by Paul Gardner
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking;
import java.util.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.tracker.server.TRTrackerServerException;
import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector;
import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelector;
import com.aelitis.azureus.core.networkmanager.VirtualServerChannelSelectorFactory;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
/**
* @author parg
*
*/
public class
TRNonBlockingServer
extends TRTrackerServerTCP
implements VirtualServerChannelSelector.SelectListener
{
private static final LogIDs LOGID = LogIDs.TRACKER;
private static final int TIMEOUT_CHECK_INTERVAL = 10*1000; //10sec
private static final int CLOSE_DELAY = 5*1000;
private TRNonBlockingServerProcessorFactory processor_factory;
private final VirtualChannelSelector read_selector;
private final VirtualChannelSelector write_selector;
private List connections_to_close = new ArrayList();
private List processors = new ArrayList();
/*
private long last_stats_time;
private long last_timeouts;
private long last_connections;
*/
private long total_timeouts;
private long total_connections;
public static final int MAX_CONCURRENT_CONNECTIONS = COConfigurationManager.getIntParameter( "Tracker TCP NonBlocking Conc Max" );
private final AEMonitor this_mon = new AEMonitor( "TRNonBlockingServer" );
public
TRNonBlockingServer(
String _name,
int _port,
InetAddress _bind_ip,
boolean _apply_ip_filter,
TRNonBlockingServerProcessorFactory _processor_factory )
throws TRTrackerServerException
{
this( _name, _port, _bind_ip, _apply_ip_filter, true, _processor_factory );
}
public
TRNonBlockingServer(
String _name,
int _port,
InetAddress _bind_ip,
boolean _apply_ip_filter,
boolean _start_up_ready,
TRNonBlockingServerProcessorFactory _processor_factory )
throws TRTrackerServerException
{
super( _name, _port, false, _apply_ip_filter, _start_up_ready );
processor_factory = _processor_factory;
read_selector = new VirtualChannelSelector( _name + ":" + _port, VirtualChannelSelector.OP_READ, false );
write_selector = new VirtualChannelSelector( _name + ":" + _port, VirtualChannelSelector.OP_WRITE, true );
boolean ok = false;
if ( _port == 0 ){
throw( new TRTrackerServerException( "port of 0 not currently supported"));
}
try{
InetSocketAddress address;
if ( _bind_ip == null ){
_bind_ip = NetworkAdmin.getSingleton().getDefaultBindAddress();
if ( _bind_ip == null ){
address = new InetSocketAddress( _port );
}else{
address = new InetSocketAddress( _bind_ip, _port );
}
}else{
address = new InetSocketAddress( _bind_ip, _port );
}
VirtualServerChannelSelector accept_server = VirtualServerChannelSelectorFactory.createBlocking( address, 0, this );
accept_server.start();
AEThread read_thread =
new AEThread( "TRTrackerServer:readSelector")
{
public void
runSupport()
{
selectLoop( read_selector );
}
};
read_thread.setDaemon(true);
read_thread.start();
AEThread write_thread =
new AEThread( "TRTrackerServer:writeSelector")
{
public void
runSupport()
{
selectLoop( write_selector );
}
};
write_thread.setDaemon(true);
write_thread.start();
AEThread close_thread =
new AEThread( "TRTrackerServer:closeScheduler")
{
public void
runSupport()
{
closeLoop();
}
};
close_thread.setDaemon(true);
close_thread.start();
Logger.log(new LogEvent(LOGID,
"TRTrackerServer: Non-blocking listener established on port "
+ getPort()));
ok = true;
}catch( Throwable e){
Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { ""
+ getPort() });
throw( new TRTrackerServerException( "TRTrackerServer: accept fails", e ));
}finally{
if ( !ok ){
destroy();
}
}
}
protected void
selectLoop(
VirtualChannelSelector selector )
{
long last_time = 0;
while( true ){
try{
selector.select( 100 );
// only use one selector to trigger the timeouts!
if ( selector == read_selector ){
long now = SystemTime.getCurrentTime();
if ( now < last_time ){
last_time = now;
}else if ( now - last_time >= TIMEOUT_CHECK_INTERVAL ){
last_time = now;
checkTimeouts(now);
}
}
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
public void
newConnectionAccepted(
ServerSocketChannel server,
SocketChannel channel )
{
final TRNonBlockingServerProcessor processor = processor_factory.create( this, channel );
int num_processors;
try{
this_mon.enter();
total_connections++;
processors.add( processor );
num_processors = processors.size();
}finally{
this_mon.exit();
}
if ( MAX_CONCURRENT_CONNECTIONS != 0 &&
num_processors > MAX_CONCURRENT_CONNECTIONS ){
removeAndCloseConnection( processor );
}else if ( isIPFilterEnabled() &&
ip_filter.isInRange( channel.socket().getInetAddress().getHostAddress(), "Tracker" )){
removeAndCloseConnection( processor );
}else{
VirtualChannelSelector.VirtualSelectorListener read_listener =
new VirtualChannelSelector.VirtualSelectorListener()
{
private boolean selector_registered;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -