route server with threadpool
This commit is contained in:
parent
0dfb8b1d26
commit
47b8369b26
4 changed files with 47 additions and 186 deletions
|
@ -186,6 +186,11 @@ public class RoutingEngine extends Thread
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if ( nodesCache != null )
|
||||||
|
{
|
||||||
|
nodesCache.close();
|
||||||
|
nodesCache = null;
|
||||||
|
}
|
||||||
openSet.clear();
|
openSet.clear();
|
||||||
finished = true; // this signals termination to outside
|
finished = true; // this signals termination to outside
|
||||||
}
|
}
|
||||||
|
@ -195,7 +200,6 @@ public class RoutingEngine extends Thread
|
||||||
{
|
{
|
||||||
boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint;
|
boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint;
|
||||||
nodesMap = null;
|
nodesMap = null;
|
||||||
nodesCache = null;
|
|
||||||
terminate();
|
terminate();
|
||||||
return oom_carsubset_hint ? "\nPlease use 'carsubset' maps for long-distance car-routing" : "";
|
return oom_carsubset_hint ? "\nPlease use 'carsubset' maps for long-distance car-routing" : "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ public final class NodesCache
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
f.ra.close();
|
if ( f != null ) f.ra.close();
|
||||||
}
|
}
|
||||||
catch( IOException ioe )
|
catch( IOException ioe )
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,9 +9,11 @@ import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import btools.router.OsmNodeNamed;
|
import btools.router.OsmNodeNamed;
|
||||||
|
@ -20,84 +22,21 @@ import btools.router.RoutingContext;
|
||||||
import btools.router.RoutingEngine;
|
import btools.router.RoutingEngine;
|
||||||
import btools.server.request.RequestHandler;
|
import btools.server.request.RequestHandler;
|
||||||
import btools.server.request.ServerHandler;
|
import btools.server.request.ServerHandler;
|
||||||
import btools.server.request.YoursHandler;
|
|
||||||
|
|
||||||
public class RouteServer extends Thread
|
public class RouteServer extends Thread
|
||||||
{
|
{
|
||||||
public ServiceContext serviceContext;
|
public ServiceContext serviceContext;
|
||||||
public short port = 17777;
|
|
||||||
|
|
||||||
private ServerSocket serverSocket = null;
|
private Socket clientSocket = null;
|
||||||
|
private RoutingEngine cr = null;
|
||||||
|
|
||||||
public void close()
|
public void stopRouter()
|
||||||
{
|
{
|
||||||
try
|
RoutingEngine e = cr;
|
||||||
{
|
if ( e != null ) e.terminate();
|
||||||
ServerSocket ss = serverSocket;
|
|
||||||
serverSocket = null;
|
|
||||||
ss.close();
|
|
||||||
}
|
|
||||||
catch( Throwable t ) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void killOtherServer() throws Exception
|
|
||||||
{
|
|
||||||
Socket socket = new Socket( "localhost", port );
|
|
||||||
BufferedWriter bw = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
bw = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream() ) );
|
|
||||||
bw.write( "EXIT\n" );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bw.close();
|
|
||||||
socket.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run()
|
public void run()
|
||||||
{
|
|
||||||
// first go an kill any other server on that port
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
killOtherServer();
|
|
||||||
System.out.println( "killed, waiting" );
|
|
||||||
try { Thread.sleep( 3000 ); } catch( InterruptedException ie ) {}
|
|
||||||
}
|
|
||||||
catch( Throwable t ) {
|
|
||||||
System.out.println( "not killed: " + t );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
serverSocket = new ServerSocket(port);
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
System.out.println("RouteServer accepting connections..");
|
|
||||||
Socket clientSocket = serverSocket.accept();
|
|
||||||
if ( !serveRequest( clientSocket ) ) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( Throwable e )
|
|
||||||
{
|
|
||||||
System.out.println("RouteServer main loop got exception (exiting): "+e);
|
|
||||||
if ( serverSocket != null )
|
|
||||||
{
|
|
||||||
try { serverSocket.close(); } catch( Throwable t ) {}
|
|
||||||
}
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean serveRequest( Socket clientSocket )
|
|
||||||
{
|
{
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
BufferedWriter bw = null;
|
BufferedWriter bw = null;
|
||||||
|
@ -108,15 +47,14 @@ public class RouteServer extends Thread
|
||||||
|
|
||||||
// we just read the first line
|
// we just read the first line
|
||||||
String getline = br.readLine();
|
String getline = br.readLine();
|
||||||
if ( getline == null || getline.startsWith( "EXIT") )
|
if ( getline == null || getline.startsWith("GET /favicon.ico") )
|
||||||
{
|
{
|
||||||
throw new RuntimeException( "socketExitRequest" );
|
return;
|
||||||
}
|
|
||||||
if ( getline.startsWith("GET /favicon.ico") )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InetAddress ip = clientSocket.getInetAddress();
|
||||||
|
System.out.println( "ip=" + (ip==null ? "null" : ip.toString() ) + " -> " + getline );
|
||||||
|
|
||||||
String url = getline.split(" ")[1];
|
String url = getline.split(" ")[1];
|
||||||
HashMap<String,String> params = getUrlParams(url);
|
HashMap<String,String> params = getUrlParams(url);
|
||||||
|
|
||||||
|
@ -129,12 +67,12 @@ public class RouteServer extends Thread
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
handler = new YoursHandler( serviceContext, params );
|
throw new IllegalArgumentException( "unknown request syntax: " + getline );
|
||||||
}
|
}
|
||||||
RoutingContext rc = handler.readRoutingContext();
|
RoutingContext rc = handler.readRoutingContext();
|
||||||
List<OsmNodeNamed> wplist = handler.readWayPointList();
|
List<OsmNodeNamed> wplist = handler.readWayPointList();
|
||||||
|
|
||||||
RoutingEngine cr = new RoutingEngine( null, null, serviceContext.segmentDir, wplist, rc );
|
cr = new RoutingEngine( null, null, serviceContext.segmentDir, wplist, rc );
|
||||||
cr.quite = true;
|
cr.quite = true;
|
||||||
cr.doRun( maxRunningTime );
|
cr.doRun( maxRunningTime );
|
||||||
|
|
||||||
|
@ -162,74 +100,62 @@ public class RouteServer extends Thread
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
if ( "socketExitRequest".equals( e.getMessage() ) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
System.out.println("RouteServer got exception (will continue): "+e);
|
System.out.println("RouteServer got exception (will continue): "+e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
cr = null;
|
||||||
if ( br != null ) try { br.close(); } catch( Exception e ) {}
|
if ( br != null ) try { br.close(); } catch( Exception e ) {}
|
||||||
if ( bw != null ) try { bw.close(); } catch( Exception e ) {}
|
if ( bw != null ) try { bw.close(); } catch( Exception e ) {}
|
||||||
|
if ( clientSocket != null ) try { clientSocket.close(); } catch( Exception e ) {}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception
|
public static void main(String[] args) throws Exception
|
||||||
{
|
{
|
||||||
System.out.println("BRouter 0.98 / 12012014 / abrensch");
|
System.out.println("BRouter 0.98 / 12012014 / abrensch");
|
||||||
if ( args.length != 3 )
|
if ( args.length != 4 )
|
||||||
{
|
{
|
||||||
System.out.println("serve YOURS protocol for BRouter");
|
|
||||||
System.out.println("usage: java RouteServer <segmentdir> <profile-list> <port>");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("serve BRouter protocol");
|
System.out.println("serve BRouter protocol");
|
||||||
System.out.println("usage: java RouteServer <segmentdir> <profiledir> <port>");
|
System.out.println("usage: java RouteServer <segmentdir> <profiledir> <port> <maxthreads>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceContext serviceContext = new ServiceContext();
|
ServiceContext serviceContext = new ServiceContext();
|
||||||
serviceContext.segmentDir = args[0];
|
serviceContext.segmentDir = args[0];
|
||||||
File profileMapOrDir = new File( args[1] );
|
System.setProperty( "profileBaseDir", args[1] );
|
||||||
if ( profileMapOrDir.isDirectory() )
|
|
||||||
{
|
int maxthreads = Integer.parseInt( args[3] );
|
||||||
System.setProperty( "profileBaseDir", args[1] );
|
|
||||||
}
|
TreeMap<Long,RouteServer> threadMap = new TreeMap<Long,RouteServer>();
|
||||||
else
|
|
||||||
{
|
|
||||||
serviceContext.profileMap = loadProfileMap( profileMapOrDir );
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[2]));
|
ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[2]));
|
||||||
|
long last_ts = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Socket clientSocket = serverSocket.accept();
|
Socket clientSocket = serverSocket.accept();
|
||||||
RouteServer server = new RouteServer();
|
RouteServer server = new RouteServer();
|
||||||
server.serviceContext = serviceContext;
|
server.serviceContext = serviceContext;
|
||||||
server.serveRequest( clientSocket );
|
server.clientSocket = clientSocket;
|
||||||
|
|
||||||
|
// kill thread if limit reached
|
||||||
|
if ( threadMap.size() >= maxthreads )
|
||||||
|
{
|
||||||
|
Long k = threadMap.firstKey();
|
||||||
|
RouteServer victim = threadMap.get( k );
|
||||||
|
threadMap.remove( k );
|
||||||
|
victim.stopRouter();
|
||||||
|
}
|
||||||
|
|
||||||
|
long ts = System.currentTimeMillis();
|
||||||
|
while ( ts <= last_ts ) ts++;
|
||||||
|
threadMap.put( Long.valueOf( ts ), server );
|
||||||
|
last_ts = ts;
|
||||||
|
server.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String,String> loadProfileMap( File file ) throws IOException
|
|
||||||
{
|
|
||||||
Map<String,String> profileMap = new HashMap<String,String>();
|
|
||||||
|
|
||||||
BufferedReader pr = new BufferedReader( new InputStreamReader( new FileInputStream( file ) ) );
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
String key = pr.readLine();
|
|
||||||
if ( key == null ) break;
|
|
||||||
key = key.trim();
|
|
||||||
if ( key.length() == 0 ) continue;
|
|
||||||
String value = pr.readLine();
|
|
||||||
value = value.trim();
|
|
||||||
profileMap.put( key, value );
|
|
||||||
}
|
|
||||||
pr.close();
|
|
||||||
return profileMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HashMap<String,String> getUrlParams( String url )
|
private static HashMap<String,String> getUrlParams( String url )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
package btools.server.request;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import btools.router.OsmNodeNamed;
|
|
||||||
import btools.router.OsmTrack;
|
|
||||||
import btools.router.RoutingContext;
|
|
||||||
import btools.server.ServiceContext;
|
|
||||||
|
|
||||||
public class YoursHandler extends RequestHandler {
|
|
||||||
|
|
||||||
public YoursHandler( ServiceContext serviceContext, HashMap<String,String> params )
|
|
||||||
{
|
|
||||||
super(serviceContext, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RoutingContext readRoutingContext()
|
|
||||||
{
|
|
||||||
RoutingContext rc = new RoutingContext();
|
|
||||||
|
|
||||||
String profile_key = params.get( "v" ) + " " + params.get( "fast" );
|
|
||||||
if (serviceContext.profileMap == null) throw new IllegalArgumentException( "no profile map loaded" );
|
|
||||||
String profile_path = serviceContext.profileMap.get( profile_key );
|
|
||||||
if ( profile_path == null ) profile_path = serviceContext.profileMap.get( "default" );
|
|
||||||
if ( profile_path == null ) throw new IllegalArgumentException( "no profile for key: " + profile_key );
|
|
||||||
rc.localFunction = profile_path;
|
|
||||||
|
|
||||||
List<OsmNodeNamed> nogoList = serviceContext.nogoList;
|
|
||||||
if ( nogoList != null )
|
|
||||||
{
|
|
||||||
rc.prepareNogoPoints( nogoList );
|
|
||||||
rc.nogopoints = nogoList;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<OsmNodeNamed> readWayPointList()
|
|
||||||
{
|
|
||||||
List<OsmNodeNamed> wplist = new ArrayList<OsmNodeNamed>();
|
|
||||||
wplist.add( readPosition( params, "flon", "flat", "from" ) );
|
|
||||||
wplist.add( readPosition( params, "tlon", "tlat", "to" ) );
|
|
||||||
return wplist;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String formatTrack(OsmTrack track)
|
|
||||||
{
|
|
||||||
return track.formatAsKml();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static OsmNodeNamed readPosition( HashMap<String,String> params, String plon, String plat, String name )
|
|
||||||
{
|
|
||||||
String vlon = params.get( plon );
|
|
||||||
if ( vlon == null ) throw new IllegalArgumentException( "param " + plon + " bot found in input" );
|
|
||||||
String vlat = params.get( plat );
|
|
||||||
if ( vlat == null ) throw new IllegalArgumentException( "param " + plat + " bot found in input" );
|
|
||||||
|
|
||||||
OsmNodeNamed n = new OsmNodeNamed();
|
|
||||||
n.name = name;
|
|
||||||
n.ilon = (int)( ( Double.parseDouble( vlon ) + 180. ) *1000000. + 0.5);
|
|
||||||
n.ilat = (int)( ( Double.parseDouble( vlat ) + 90. ) *1000000. + 0.5);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue