cz.cuni.amis.pogamut.udk.utils
Class UCCWrapper

Package class diagram package UCCWrapper
java.lang.Object
  extended by cz.cuni.amis.pogamut.udk.utils.UCCWrapper

public class UCCWrapper
extends Object

Wrapper of running instance of UDK server. Implements pooling of instances. The location of UDK executabe will be determined by an environment variable pogamut.udk.home (e.g. c:\Games\UDK). The property cam be set via java ... -Dpogamut.udk.home=c:\Games\UDK. Another posibility is to set it by code System.setProperty("pogamut.udk.home", "c:\\udks\\UDK-2011-05");.

As of now, UCCWrapper uses console command exit to kill the server when calling stop() or upon JVM shutdown. However, this fails if there are non-Pogamut players connected (e.g. when spectating) and the server stays alive. If the exit command is not effective, UCCWrapper tries to kill the server in a platform dependent way using UDK process PID. However, some tricks are needed to obtain the pid. The biggest problem is that UDK.com which needs to be run in order to get console output from the server spawns another process called UDK.exe and killing the original process does not kill UDK.exe. Moreover, if used on UNIX (see below) the UDK.exe is not a child process of UDK.com for some reason... So there are some not exactly neat tricks. However, on Windows, the UCCWrapper might be considered reliable (even thread-safe) providing no other code in current JVM spawns (directly or undirectly) processes called UDK.exe. On UNIX, there are some additional issues (see below).

UNIX usage

It is possible to use UCCWrapper under UNIX systems. First you need to setup UDK as described at our WIKI: pogamut.cuni.cz/pogamut-devel/doku.php?id=guidelines:udk_on_linux. Then UCCWrapper must have access to Wine in order to this, UCCWrapper uses property called WINE (might be an environment variable or it might be a Java property - see above). Property value defaults to "wine" which should be just fine if you have wine regularly installed. Make sure that WINEPREFIX environment variable is set in the shell that runs your program, otherwise Wine will not have access to correct wineprefix.

As noted above, there are some not very neat tricks in getting the process PID of UDK. On UNIX, UCCWrapper relies on the fact that no other program than the current JVM spawns new processes called UDK.exe. If this is not true, UCCWrapper will usually detect this situation and not read PID at all. But on very rare occasions (another process starts UDK.exe at the same time and starting of UDK.exe in this JVM fails or is delayed) UCCWrapper may take pid of a different UDK.exe process. Since pid is only used to kill the server if the EXIT command fails, it is even more unlikely that this problem will actually exhibit in killing wrong process.

Author:
Ik

Nested Class Summary
 class UCCWrapper.ScannerSink
          Scanns the output of UCC for some specific srings (Ports bounded.
protected  class UCCWrapper.StreamSink
          Reads content of the stream and discards it.
static class UCCWrapper.UCCWrapperConf
          Configuration object of the UCC wrapper instance.
 
Field Summary
protected  boolean aggressiveKilling
          Agressive killing means that the server is always killed by PID, if PID is available Otherwise it is killed by EXIT command first and if the connection dies, it is considered killed.
protected static int basePort
          First port assigned to a ucc instance.
static int CHANGE_MAP_COMMAND_MAX_REPEATS
          How many times will the wrapper try to send ChangeMap command to server, until it gives up waiting for notification.
static int CHANGE_MAP_CONFIRMATION_TIMEOUT
          How long (msec) will wrapper wait for confirmation of ChangeMap message
protected  UCCWrapper.UCCWrapperConf configuration
           
protected  int controlPort
          Port for server connection.
static long DEFAULT_START_TIMEOUT
           
static long DEFAULT_UDK_EXE_SPAWN_TIMEOUT_UNIX
          The ammount of time taken to to start UDK.exe on UNIX is quite large, since wine needs to boot in that time
static long DEFAULT_UDK_EXE_SPAWN_TIMEOUT_WINDOWS
           
protected static int fileCounter
           
protected  int gbPort
          Port for bots.
protected static Integer nextUccWrapperUID
           
protected  int observerPort
          Port for observer connection.
protected  UDKServerFactory serverFactory
           
static long stamp
           
protected  long startingTimeout
           
protected  boolean stopped
          Was this instance already released?
protected  LogCategory uccLog
          Loger containing all output from running instance of UCC.
protected  int uccPid
           
protected  int uccWrapperUID
          ID of the wrapper object.
protected  String unrealHome
           
protected  IUDKServer utServer
           
 
Constructor Summary
UCCWrapper(UCCWrapper.UCCWrapperConf configuration)
           
UCCWrapper(UCCWrapper.UCCWrapperConf configuration, boolean startImmediately)
           
UCCWrapper(UCCWrapper.UCCWrapperConf configuration, UDKServerFactory factory)
           
UCCWrapper(UCCWrapper.UCCWrapperConf configuration, UDKServerFactory serverFactory, boolean startImmediately)
           
 
Method Summary
 CountDownLatch awaitGameStart()
          Returns a countdown latch, that is raised after map change message was encountered
 void changeMap(String mapName, boolean notifyGame, long timeout)
          Tries to change map on the server and blocks until either the map has changed or timeout happens.
 SocketConnectionAddress getBotAddress()
           
 int getBotPort()
           
 UCCWrapper.UCCWrapperConf getConfiguration()
           
 int getControlPort()
           
 String getHost()
           
 Logger getLogger()
           
protected  String getMapNameWithOptions()
           
 SocketConnectionAddress getObserverAddress()
          Deprecated. there is no observer connection in UDK
 int getObserverPort()
          Deprecated. observer port is not used in UDK
 Process getProcess()
          Process of the
 SocketConnectionAddress getServerAddress()
           
 UDKServerFactory getServerFactory()
           
 long getStartingTimeout()
           
 long getUdkExeSpawnTimeoutUnix()
           
 long getUdkExeSpawnTimeoutWindows()
           
protected  String getUnrealHome()
           
 IUDKServer getUTServer()
           
protected  void initUCCWrapper()
           
 boolean isAggressiveKilling()
           
static void killAllUCCs(LogCategory uccLog)
          Kills all UDK instances with platform specific-system call.
 void restartServer()
           
 void setAggressiveKilling(boolean aggressiveKilling)
           
 void setConfiguration(UCCWrapper.UCCWrapperConf configuration)
          Only makes sense if created with startImmediately = false
 void setServerFactory(UDKServerFactory serverFactory)
          Only makes sense if created with startImmediately = false
 void setStartingTimeout(long startingTimeout)
          Only makes sense if created with startImmediately = false and the serve was not started yet
 void setUdkExeSpawnTimeoutUnix(long udkExeSpawnTimeoutUnix)
          Only makes sense if created with startImmediately = false and the serve was not started yet
 void setUdkExeSpawnTimeoutWindows(long udkExeSpawnTimeoutWindows)
          Only makes sense if created with startImmediately = false and the serve was not started yet
 void start()
          Start the server, if not already started.
 void stop()
          Stops the UCC server.
protected  void stopCheck()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DEFAULT_START_TIMEOUT

public static final long DEFAULT_START_TIMEOUT
See Also:
Constant Field Values

CHANGE_MAP_COMMAND_MAX_REPEATS

public static final int CHANGE_MAP_COMMAND_MAX_REPEATS
How many times will the wrapper try to send ChangeMap command to server, until it gives up waiting for notification.

See Also:
Constant Field Values

DEFAULT_UDK_EXE_SPAWN_TIMEOUT_WINDOWS

public static final long DEFAULT_UDK_EXE_SPAWN_TIMEOUT_WINDOWS
See Also:
Constant Field Values

DEFAULT_UDK_EXE_SPAWN_TIMEOUT_UNIX

public static final long DEFAULT_UDK_EXE_SPAWN_TIMEOUT_UNIX
The ammount of time taken to to start UDK.exe on UNIX is quite large, since wine needs to boot in that time

See Also:
Constant Field Values

CHANGE_MAP_CONFIRMATION_TIMEOUT

public static final int CHANGE_MAP_CONFIRMATION_TIMEOUT
How long (msec) will wrapper wait for confirmation of ChangeMap message

See Also:
Constant Field Values

uccLog

protected LogCategory uccLog
Loger containing all output from running instance of UCC.


fileCounter

protected static int fileCounter

gbPort

protected int gbPort
Port for bots.


controlPort

protected int controlPort
Port for server connection.


observerPort

protected int observerPort
Port for observer connection.


utServer

protected IUDKServer utServer

basePort

protected static final int basePort
First port assigned to a ucc instance.

See Also:
Constant Field Values

nextUccWrapperUID

protected static Integer nextUccWrapperUID

uccWrapperUID

protected int uccWrapperUID
ID of the wrapper object. Useful for debuging.


unrealHome

protected String unrealHome

configuration

protected UCCWrapper.UCCWrapperConf configuration

startingTimeout

protected long startingTimeout

uccPid

protected int uccPid

serverFactory

protected UDKServerFactory serverFactory

aggressiveKilling

protected boolean aggressiveKilling
Agressive killing means that the server is always killed by PID, if PID is available Otherwise it is killed by EXIT command first and if the connection dies, it is considered killed. In some cases however, the connection dies after exit command, but the server is not down. Setting this to false is conservative as it lessens the chance of killing a wrong process, setting this to true on the other hand raise chances that the server is actually stopped. Set to false by default, since the reading of PID depends on some non-obvious requirements the programmer should check (see class docs)


stamp

public static long stamp

stopped

protected boolean stopped
Was this instance already released?

Constructor Detail

UCCWrapper

public UCCWrapper(UCCWrapper.UCCWrapperConf configuration)

UCCWrapper

public UCCWrapper(UCCWrapper.UCCWrapperConf configuration,
                  UDKServerFactory factory)

UCCWrapper

public UCCWrapper(UCCWrapper.UCCWrapperConf configuration,
                  boolean startImmediately)

UCCWrapper

public UCCWrapper(UCCWrapper.UCCWrapperConf configuration,
                  UDKServerFactory serverFactory,
                  boolean startImmediately)
           throws UCCStartException
Parameters:
configuration -
startingTimeout -
serverFactory - allows to specify external server factory. As of 3.3.0, this is needed to prevent memory leaks on subsequent creation of multiple UCCWrappers
Throws:
UCCStartException
Method Detail

start

public void start()
           throws UCCStartException
Start the server, if not already started. This method blocks, until the server is ready to accept bot connections

Throws:
UCCStartException

getMapNameWithOptions

protected String getMapNameWithOptions()

killAllUCCs

public static void killAllUCCs(LogCategory uccLog)
Kills all UDK instances with platform specific-system call. Useful to enforce a full cleanup.


getLogger

public Logger getLogger()
Returns:
Log with output of UCC. If you want to listen also for messages from the startup sequence then use UCCWrapper.create(Logger parent). Set Parent logger of this log and register listeners before creating this instance of UCCWrapper.

getUTServer

public IUDKServer getUTServer()
Returns:
Server connected to this UCC instance.

restartServer

public void restartServer()

getUnrealHome

protected String getUnrealHome()

getConfiguration

public UCCWrapper.UCCWrapperConf getConfiguration()

setConfiguration

public void setConfiguration(UCCWrapper.UCCWrapperConf configuration)
Only makes sense if created with startImmediately = false

Parameters:
configuration -

getServerFactory

public UDKServerFactory getServerFactory()

setServerFactory

public void setServerFactory(UDKServerFactory serverFactory)
Only makes sense if created with startImmediately = false

Parameters:
serverFactory -

getStartingTimeout

public long getStartingTimeout()

setStartingTimeout

public void setStartingTimeout(long startingTimeout)
Only makes sense if created with startImmediately = false and the serve was not started yet

Parameters:
udkExeSpawnTimeout -

getUdkExeSpawnTimeoutUnix

public long getUdkExeSpawnTimeoutUnix()

setUdkExeSpawnTimeoutUnix

public void setUdkExeSpawnTimeoutUnix(long udkExeSpawnTimeoutUnix)
Only makes sense if created with startImmediately = false and the serve was not started yet

Parameters:
udkExeSpawnTimeout -

getUdkExeSpawnTimeoutWindows

public long getUdkExeSpawnTimeoutWindows()

setUdkExeSpawnTimeoutWindows

public void setUdkExeSpawnTimeoutWindows(long udkExeSpawnTimeoutWindows)
Only makes sense if created with startImmediately = false and the serve was not started yet

Parameters:
udkExeSpawnTimeout -

isAggressiveKilling

public boolean isAggressiveKilling()

setAggressiveKilling

public void setAggressiveKilling(boolean aggressiveKilling)

initUCCWrapper

protected void initUCCWrapper()
                       throws UCCStartException
Throws:
UCCStartException

changeMap

public void changeMap(String mapName,
                      boolean notifyGame,
                      long timeout)
Tries to change map on the server and blocks until either the map has changed or timeout happens.

Throws:
cz.cuni.amis.utils.exception.PogamutException - if the map change was not succesful

awaitGameStart

public CountDownLatch awaitGameStart()
Returns a countdown latch, that is raised after map change message was encountered

Returns:

getProcess

public Process getProcess()
Process of the

Returns:

stop

public void stop()
Stops the UCC server.


getBotPort

public int getBotPort()
Returns:
Port for GameBots connection.

getObserverPort

@Deprecated
public int getObserverPort()
Deprecated. observer port is not used in UDK

Returns:
Port of the Observer of GameBots2004.

getControlPort

public int getControlPort()
Returns:
Port for control connection.

stopCheck

protected void stopCheck()

getHost

public String getHost()

getBotAddress

public SocketConnectionAddress getBotAddress()

getServerAddress

public SocketConnectionAddress getServerAddress()

getObserverAddress

@Deprecated
public SocketConnectionAddress getObserverAddress()
Deprecated. there is no observer connection in UDK

Returns:


Copyright © 2013 AMIS research group, Faculty of Mathematics and Physics, Charles University in Prague, Czech Republic. All Rights Reserved.