More case insensitive tests and read write lock for connections

This commit is contained in:
md_5 2013-05-25 16:50:04 +10:00
parent a51ffb1f4c
commit ac4bab2425
3 changed files with 66 additions and 12 deletions

View File

@ -31,6 +31,8 @@ import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import lombok.Getter; import lombok.Getter;
@ -98,7 +100,8 @@ public class BungeeCord extends ProxyServer
/** /**
* Fully qualified connections. * Fully qualified connections.
*/ */
public TMap<String, UserConnection> connections = new CaseInsensitiveMap<>(); private final TMap<String, UserConnection> connections = new CaseInsensitiveMap<>();
private final ReadWriteLock connectionLock = new ReentrantReadWriteLock();
/** /**
* Tab list handler * Tab list handler
*/ */
@ -278,11 +281,18 @@ public class BungeeCord extends ProxyServer
stopListeners(); stopListeners();
getLogger().info( "Closing pending connections" ); getLogger().info( "Closing pending connections" );
connectionLock.readLock().lock();
try
{
getLogger().info( "Disconnecting " + connections.size() + " connections" ); getLogger().info( "Disconnecting " + connections.size() + " connections" );
for ( UserConnection user : connections.values() ) for ( UserConnection user : connections.values() )
{ {
user.disconnect( getTranslation( "restart" ) ); user.disconnect( getTranslation( "restart" ) );
} }
} finally
{
connectionLock.readLock().unlock();
}
getLogger().info( "Closing IO threads" ); getLogger().info( "Closing IO threads" );
eventLoops.shutdownGracefully(); eventLoops.shutdownGracefully();
@ -309,11 +319,18 @@ public class BungeeCord extends ProxyServer
* @param packet the packet to send * @param packet the packet to send
*/ */
public void broadcast(DefinedPacket packet) public void broadcast(DefinedPacket packet)
{
connectionLock.readLock().lock();
try
{ {
for ( UserConnection con : connections.values() ) for ( UserConnection con : connections.values() )
{ {
con.sendPacket( packet ); con.sendPacket( packet );
} }
} finally
{
connectionLock.readLock().unlock();
}
} }
@Override @Override
@ -356,8 +373,15 @@ public class BungeeCord extends ProxyServer
@Override @Override
public ProxiedPlayer getPlayer(String name) public ProxiedPlayer getPlayer(String name)
{
connectionLock.readLock().lock();
try
{ {
return connections.get( name ); return connections.get( name );
} finally
{
connectionLock.readLock().unlock();
}
} }
@Override @Override
@ -435,4 +459,28 @@ public class BungeeCord extends ProxyServer
{ {
return ConsoleCommandSender.getInstance(); return ConsoleCommandSender.getInstance();
} }
public void addConnection(UserConnection con)
{
connectionLock.writeLock().lock();
try
{
connections.put( con.getName(), con );
} finally
{
connectionLock.writeLock().unlock();
}
}
public void removeConnection(UserConnection con)
{
connectionLock.writeLock().lock();
try
{
connections.remove( con.getName() );
} finally
{
connectionLock.writeLock().unlock();
}
}
} }

View File

@ -27,7 +27,7 @@ public class UpstreamBridge extends PacketHandler
this.bungee = bungee; this.bungee = bungee;
this.con = con; this.con = con;
BungeeCord.getInstance().connections.put( con.getName(), con ); BungeeCord.getInstance().addConnection( con );
bungee.getTabListHandler().onConnect( con ); bungee.getTabListHandler().onConnect( con );
con.sendPacket( BungeeCord.getInstance().registerChannels() ); con.sendPacket( BungeeCord.getInstance().registerChannels() );
@ -51,7 +51,7 @@ public class UpstreamBridge extends PacketHandler
PlayerDisconnectEvent event = new PlayerDisconnectEvent( con ); PlayerDisconnectEvent event = new PlayerDisconnectEvent( con );
bungee.getPluginManager().callEvent( event ); bungee.getPluginManager().callEvent( event );
bungee.getTabListHandler().onDisconnect( con ); bungee.getTabListHandler().onDisconnect( con );
BungeeCord.getInstance().connections.remove( con.getName() ); //TODO: Better way, why do we need to raw access? BungeeCord.getInstance().removeConnection( con );
if ( con.getServer() != null ) if ( con.getServer() != null )
{ {

View File

@ -13,8 +13,12 @@ public class CaseInsensitiveTest
CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>(); CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>();
map.put( "FOO", obj ); map.put( "FOO", obj );
Assert.assertTrue( map.contains( "foo" ) ); // Assert that it is case insensitive Assert.assertTrue( map.contains( "foo" ) ); // Assert that contains is case insensitive
Assert.assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Asert that case is preserved Assert.assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Assert that case is preserved
// Assert that remove is case insensitive
map.remove( "FoO" );
Assert.assertFalse( map.contains( "foo" ) );
} }
@Test @Test
@ -23,6 +27,8 @@ public class CaseInsensitiveTest
CaseInsensitiveSet set = new CaseInsensitiveSet(); CaseInsensitiveSet set = new CaseInsensitiveSet();
set.add( "FOO" ); set.add( "FOO" );
Assert.assertTrue( set.contains( "foo" ) ); Assert.assertTrue( set.contains( "foo" ) ); // Assert that contains is case insensitive
set.remove( "FoO" );
Assert.assertFalse( set.contains( "foo" ) ); // Assert that remove is case insensitive
} }
} }