-
Notifications
You must be signed in to change notification settings - Fork 3
Backend: Implementation
The backend is organized in the following way:
-
Main
- Entry point of the program, forwards toApplication
. -
Application
- The backend itself, initializes and starts the whole application -
commands - Representing and parsing command line arguments
-
CommandParser
- Parses command line arguments intoCommandDate
objects -
CommandDate
- The model which represents command line arguments
-
-
config - Read, store and provide data of configuration files
-
ConfigLoader
- Loads configuration files into theConfigStore
-
ConfigStore
- Provider of configuration data
-
-
db - Interaction with a database that stores application relevant data
-
ExternalDatabase
- External database to use if configuration is set accordingly -
MemoryDatabase
- Internal fall-back database to use if configuration is set accordingly -
DatabaseUtil
- Contains all SQL queries whichExternalDatabase
uses -
OsmDatabaseHandler
- Fills the database with OSM data
-
-
parsing - Parsing external data-sets into the internal model
-
DataParser
- Parses all data-sets and forwards entities to registered handler -
osm
-
OsmParser
- Parses OSM files into entities -
OsmReducer
- Reduces OSM files using a filter, is used by thereduce
command line argument
-
-
-
routing - Answering routing queries, computation of shortest paths
- algorithms - Algorithms used for answering routing queries
-
model
-
graph
-
IGraph
- Model of the graph, main user isRoadGraph
-
INode
- Model of nodes, main user isRoadNode
-
IEdge
- Model of egdes, main user isRoadEdge
-
-
graph
-
parsing
-
osm
-
OsmRoadBuilder
- Creates instances ofRoadNode
andRoadEdge
out of OSM entities -
OsmRoadHandler
- Filles the graph with OSM data
-
-
osm
-
server
-
RoutingServer
- Server which offers the REST API for answering routing requests -
model
-
RoutingRequest
- POJO representing the request, directly constructed out of the JSON request -
RoutingResponse
- POJO representing the response, directly parsed into a JSON response
-
-
-
searching - Answering search queries, computation of inverted indices and search algorithms
-
model
-
NodeNameSet
- Data-structure to query name searches on
-
-
server
-
NameSearchServer
- Server which offers the REST API for answering name search requests -
model
-
NameSearchRequest
- POJO representing the request, directly constructed out of the JSON request -
NameSearchResponse
- POJO representing the response, directly parsed into a JSON response
-
-
-
model
-
util - Utility methods not necessarily related to the application itself
-
CleanUtil
- Cleans the database, caches and serialized data, used by theclean
command line argument - http - Low level HTTP communication
- collections - Various specialized collections used to optimize the application
-
For answering routing requests the application offers the following algorithms:
-
metrics
-
AsTheCrowFliesMetric
- As-the-crow-flies metric forISpatial
objects, see As the crow flies -
landmark
-
LandmarkMetric
- Approximates distance by comparing shortest paths from objects to landmarks, see Computing the shortest path: A search meets graph theory -
GreedyFarthestLandmarks
- Landmark provider which greedily selects landmarks that are farthest away from each other -
RandomLandmarks
- Landmark provider which selects landmarks randomly
-
-
-
scc
-
tarjan
-
TarjanRecursive
- Recursive implementation of Tarjan's algorithm for computing SCCs, see Tarjan's strongly connected components algorithm -
TarjanIterative
- Iterative implementation of Tarjan's algorithm for computing SCCs
-
-
tarjan
-
shortestpath
-
dijkstra
-
Dijkstra
- Implementation of Dijkstra's algorithm for computing shortest paths, see Dijkstra's algorithm -
A-Star
- Implementation of the A-Star algorithm, a variant of Dijkstra's algorithm which uses a heuristic for approximation, see A* search algorithm
-
-
dijkstra
For answering name search requests the application uses the LexiSearch API. The main involved classes are:
-
QGramProvider
- Splits a word into n-grams, see n-gram -
NodeNameSet
- Data-set to query on, optimized by using an inverted index which links n-grams to containing words, see Inverted index -
FuzzyPrefixQuery
- Searches names by using a fuzzy prefix query on the given data-set, see Approximate string matching and Edit distance
The program starts with the Main#main(args)
method which creates an instance of Application
and calls initialize()
on it.
The method Application#initialize()
configures the logger and loads configuration settings. After that initializeApi()
is called if the command is start
.
It creates a database, either ExternalDatabase
or MemoryDatabase
, depending on the configuration. Then a graph instance is created, either an empty one or it is deserialized from a cache, depending on the configuration.
Then a DataParser
is created and handler like OsmDatabaseHandler
and OsmRoadHandler
are created and registered to the parser. The parser runs and parses all data-sets. Entities are forwarded to the handler which fill the database and the graph with the corresponding data.
The graph and database are now ready to go. If desired, according to the configuration, the graph is serialized to speedup future calls.
Now the routing and name search server are initialized using initializeRouting()
and initializeNameSearch()
. This includes initialization of algorithms and data-structures. In particular, it includes pre-computation for routing queries which may take a while depending on the graph size.
After initialization has finished the main
method calls Application#start
which starts the corresponding action:
-
start
- Callsstart()
on the routing and name search server -
reduce
- CallsApplication#startReducer
-
clean
- CallsCleanUtil#clean
When the server are started they create a new thread which listens on the configured port for requests. The APIs are now ready for usage and will answer requests.
Shutting down the API is done using Application#shutdown()
. It passes the shutdown request to all modules of the application. In particular, it calls shutdown()
on both server.
The Main#main
method registers Application#shutdown()
as shutdown-hook to the JVM. Thus, destroying the JVM (for example by passing Control-C
) will correctly trigger the shutdown()
method.
The class DataParser
is responsible for determining the data-sets to parse. Handler can be registered to it and it will then forward parsed entities to them.
The DataParser
uses the class OsmParser
for parsing OSM files. It parses data directly into OSM entities and forwards them to the handler.
The OsmDatabaseHandler
collects all nodes, ways and relations and forwards them to the database by IRoutingDatabase#offerOsmEntities
. The database will then insert all relevant data it did not already contain.
The OsmRoadHandler
collects only ways. Therefore, it uses a filter to only collect relevant ways. From the remaining ways it collects all included nodes and adds them and the corresponding edges to the graph. However, at this point the handler does not know spatial data of nodes. Therefore, the handler queues in requests to the database which are then later executed in order to fill spatial data for all nodes. As the graph does not use OSM IDs for nodes, the handler pushes the mapping of the internal to OSM IDs to the database.
The routing and name search server are structured fairly simple. When calling start()
they create a new thread which listens on the configured port for requests. For client handling they use a ExecutorService
which offers a cached thread pool. Thus, every request is executed in an independent thread.
For this purpose a ClientHandler
is used. It parses the HTTP request and does the HTTP communication and general request validation. If a JSON request is valid it parses it into the corresponding request POJO (RoutingRequest
or NameSearchRequest
). Then a RequestHandler
is created and handleRequest
is called on it.
The RequestHandler
computes the response, for example by using shortest path or search algorithms. It builds the response POJO (RoutingResponse
or NameSearchResponse
) and sends it to the client.