alaCarte Maps
Renderer for OpenStreetMap tiles
alacarte_server.cpp
Go to the documentation of this file.
1 
23 #include <iostream>
24 #include <thread>
25 
26 #include "config.hpp"
27 #include "settings.hpp"
28 
29 #include "utils/application.hpp"
30 
32 #include "general/geodata.hpp"
33 
34 #include "server/cache.hpp"
35 #include "server/http_server.hpp"
39 
40 #include <boost/log/expressions.hpp>
41 #include <boost/log/utility/setup/file.hpp>
42 
43 
44 using boost::program_options::options_description;
45 using boost::make_shared;
46 
47 
53  : public Application
54 {
55 public:
61  {
62 #define OPT(_name, _shortcut) (string(_name).append(",").append(_shortcut)).c_str()
63  using namespace boost::program_options;
64 
65 
66  cmd_desc.add_options()
67  (OPT(opt::help, "h"), "produce help message")
68  (OPT(opt::config, "c"), value<string>()->default_value(DEFAULT_CONFIG_NAME)/*->value_name("path")*/,
69  "Specifies a config file which will be loaded at program start. Absolute and relative paths are possible. Additionally we search in " SYSCONFDIR ".")
70  ;
71 
72  // in cmd and config
73  config_desc.add_options()
74  (OPT(opt::logfile, "l"), value<string>()->default_value("log.txt")/*->value_name("path")*/, "specifies the logfile")
75  (OPT(opt::server::path_to_geodata, "g"), value<string>()->required()/*->value_name("path")*/, "path, where preprocessed data will be saved")
76  (OPT(opt::server::style_source, "s"), value<string>()->required()->default_value(".")/*->value_name("path")*/, "path, to be observed for stylesheets")
77  (OPT(opt::server::access_log, "a"), value<string>()->default_value("access_log.txt")/*->value_name("path")*/, "file where server access will be logged")
78  (OPT(opt::server::path_to_default_style, "d"), value<string>()->default_value("default"), "default stylesheet")
79  (OPT(opt::server::path_to_default_tile, "t"), value<string>()->default_value("default.png")/*->value_name("image")*/, "default tile")
80  (OPT(opt::server::num_threads, "n"), value<int>()->default_value(std::thread::hardware_concurrency())/*->value_name("num")*/,"number of threads used to process a request")
81  (OPT(opt::server::parse_timeout, "o"), value<int>()->default_value(750)/*->value_name("ms")*/, "maximal time in ms to parse a stylesheet")
82  //(OPT(opt::server::request_timeout, "r"), value<int>()/*->value_name("ms")*/, "maximal time in ms to process a request")
83  (OPT(opt::server::prerender_level, "z"), value<int>()->default_value(12)/*->value_name("ms")*/, "highest zoomlevel to enqueue for prerendering")
84  (opt::server::server_address, value<string>()->default_value("0.0.0.0")/*->value_name("addr")*/, "Address of the server")
85  (OPT(opt::server::server_port, "p"), value<string>()->required()->default_value("8080")/*->value_name("port")*/, "port to bind the server")
86  (OPT(opt::server::max_queue_size, "q"), value<int>()->default_value(1024)/*->value_name("size")*/, "size for server queue")
87  (opt::server::cache_size, value<int>()->default_value(1024)/*->value_name("size")*/, "maximal amount of tiles in cache")
88  (opt::server::cache_keep_tile, value<int>()->default_value(12)/*->value_name("size")*/, "from 0 this zoomlevel, tiles are written to harddrive")
89  (opt::server::cache_path, value<string>()->default_value("cache")/*->value_name("path")*/, "path to store evicted prerendered tiles")
90  (opt::server::log_mute_component, value<std::vector<string> >()->multitoken(), "List of all components which should be muted.")
91  (opt::server::performance_log, value<string>(), "path, where the performance log will be saved. If not set the performance log will not be created.")
92  ;
93 
94 
95  cmd_desc.add(config_desc);
97  }
98 
99 protected:
100  virtual bool startupDiagnostic(const shared_ptr<Configuration>& config)
101  {
102  if (!diagnosticCheckFile(config, opt::server::path_to_geodata)) return false;
103 
104  int max_queue_size = config->get<int>(opt::server::max_queue_size);
105  if (max_queue_size < 1) {
106  LOG_SEV(server_log, error) << "It's not possible to use a max_queue_size(" << opt::server::max_queue_size << ") less than 1";
107  return false;
108  }
109 
110  int hardware_concurrency = std::thread::hardware_concurrency();
111  int threads = config->get<int>(opt::server::num_threads);
112  if (hardware_concurrency == 0)
113  {
114  LOG_SEV(server_log, info) << "Couldn't detect amount of cores in this machine.";
115  }
116  else if (threads > hardware_concurrency)
117  {
118  LOG_SEV(server_log, info) << "It's not recommended to use more than " << hardware_concurrency << " (amount of cores) threads.";
119  }
120 
121  if (threads < 1)
122  {
123  LOG_SEV(server_log, error) << "It's not possible to use less then 1 thread for rendering. Please set " << opt::server::num_threads << " appropriate.";
124  return false;
125  }
126 
127  int parse_timeout = config->get<int>(opt::server::parse_timeout);
128  if (parse_timeout < 50) {
129  LOG_SEV(server_log, error) << "It's not possible to use less than 50ms for " << opt::server::parse_timeout;
130  return false;
131  }
132  /*
133  if (config->has(opt::server::request_timeout)) {
134  int request_timeout = config->get<int>(opt::server::request_timeout);
135  }
136 
137  if (true) {
138  LOG_SEV(server_log, info) << opt::server::request_timeout << " not implemented yet";
139  }
140  */
141  if (config->has(opt::server::style_source)) {
142  boost::filesystem::path folder = config->get<string>(opt::server::style_source);
143  if (!boost::filesystem::is_directory(folder)) {
144  LOG_SEV(server_log, error) << opt::server::style_source << " = \"" << folder.string() << "\" is not a directory.";
145  return false;
146  }
147 
148  } else {
149  LOG_SEV(server_log, error) << opt::server::style_source << " is not set.";
150  return false;
151  }
152 
153  if (config->has(opt::server::cache_path)) {
154  boost::filesystem::path folder = config->get<string>(opt::server::cache_path);
155  if (!boost::filesystem::is_directory(folder)) {
156  try {
157  boost::filesystem::create_directory(folder);
158  } catch (boost::filesystem::filesystem_error) {
159  LOG_SEV(server_log, error) << opt::server::cache_path << " = \"" << folder.string() << "\" could not be created.";
160  return false;
161  }
162  }
163  }
164 
166  }
167 
168  virtual void customInitLog(const shared_ptr<Configuration>& config)
169  {
170  fileLogger->set_filter(logging::expressions::attr<std::string>("Channel") != "Access");
171  consoleLogger->set_filter(logging::expressions::attr<std::string>("Channel") != "Access");
172 
173  logging::add_file_log(
174  keywords::file_name = config->get<string>(opt::server::access_log),
175  keywords::rotation_size = 10 * 1024 * 1024,
176  keywords::time_based_rotation = logging::sinks::file::rotation_at_time_point(0, 0, 0),
177  keywords::format = "%Message%",
178  keywords::filter = (logging::expressions::attr<std::string>("Channel") == "Access")
179  );
180  }
181 
182 
188  virtual void onRun( const shared_ptr<Configuration>& config )
189  {
190  Statistic::Init(config);
191 
192  shared_ptr<Geodata> geodata = make_shared<Geodata>();
193  try {
194  geodata->load(config->get<string>(opt::server::path_to_geodata));
195  } catch(...)
196  {
197  BOOST_LOG_TRIVIAL(error) << "Failed to load geodata!";
198  BOOST_LOG_TRIVIAL(error) << "Try to import your osm data again!";
199  return;
200  }
201  shared_ptr<Cache> cache = make_shared<Cache>(config);
202 
203  shared_ptr<StylesheetManager> ssm = make_shared<StylesheetManager>(config);
204 
205  shared_ptr<Renderer> renderer = make_shared<Renderer>(geodata);
206 
207  shared_ptr<RequestManager> req_manager = make_shared<RequestManager>(config, geodata, renderer, cache, ssm);
208 
209  shared_ptr<HttpServer> server = make_shared<HttpServer>(config, req_manager);
210 
211  ssm->startStylesheetObserving(req_manager);
212 
213  server->listen();
214 
215  // Stop all threads so they loose all their handles!
216  req_manager->stop();
217 
218  ssm->stopStylesheetObserving();
219  }
220 
221 };
222 
223 
224 
225 
227 int main(int argc, char** argv)
228 {
229  AlacarteServerApp app;
230 
231  int result = app.start(argc, argv);
232 
234 
235  return result;
236 }
boost::program_options::positional_options_description pos_desc
Definition: application.hpp:53
static const char * server_address
Address of the server (type: string)
virtual void onRun(const shared_ptr< Configuration > &config)
Contains the main functionality for the server.
AlacarteServerApp()
Inits the Configuration descriptions.
static const char * path_to_default_style
Path to the default stylesheet (type: string)
static void Shutdown()
Frees all internal memory used by the cache mechanism.
shared_ptr< logging::sinks::synchronous_sink< logging::sinks::basic_text_ostream_backend< char > > > consoleLogger
Definition: application.hpp:58
static const char * path_to_geodata
Filepath where the geodata is located (type: string)
shared_ptr< logging::sinks::synchronous_sink< logging::sinks::text_file_backend > > fileLogger
Definition: application.hpp:57
static const char * cache_size
Option to get the cache size (type: int)
#define OPT(_name, _shortcut)
static const char * cache_keep_tile
Option to get the zoomlevel until tiles are kept on harddrive (type: int)
Represents the Server-Application.
#define LOG_SEV(log, lvl)
Definition: settings.hpp:78
static const char * performance_log
Filepath to the performance log (type: string)
static const char * style_source
Path to be observed for stylesheets (type: string)
static const char * access_log
Filepath to the access log (type: string)
bool diagnosticCheckFile(const shared_ptr< Configuration > &config, const string &key)
boost::program_options::options_description config_desc
Definition: application.hpp:52
virtual bool startupDiagnostic(const shared_ptr< Configuration > &config)
static const char * max_queue_size
Maximum size for the queue (type: int)
static const char * path_to_default_tile
Path to the default tile (type: string)
#define DEFAULT_CONFIG_NAME
Definition: settings.hpp:127
boost::program_options::options_description cmd_desc
Definition: application.hpp:51
static const char * config
Option to get the configuration filename (type: string)
static const char * parse_timeout
Option to get the timeout for stylesheet-parsing (type: int)
static const char * log_mute_component
Option to get the muted Components.
static void Init(const shared_ptr< Configuration > &conf)
Definition: statistic.hpp:89
virtual void customInitLog(const shared_ptr< Configuration > &config)
static const char * cache_path
Option to get the cache path (type: string)
static const char * num_threads
Option to get number of worker threads (type: int)
static const char * help
Use Configuration::has to check weather the user wanted help.
static const char * prerender_level
Option to get the timeout for request-processing (type: int)
int start(int argc, char **argv)
Starts the aplication with or without Exceptionhandling.
static const char * server_port
Port the server should listen at (type: int)
static const char * logfile
Option to get the filename of the log (type: string)