diff --git a/Makefile.am b/Makefile.am index 0719baf6..3038fb2a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,15 +5,15 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = $(PTHREAD_CFLAGS) $(GLIB_CFLAGS) STORE_SOURCES = \ + src/g_logger.c \ src/store.c \ src/store_file.c \ src/store_file_utils.c \ src/store_memcached.c \ + src/store_null.c \ src/store_rados.c \ - src/store_ro_http_proxy.c \ src/store_ro_composite.c \ - src/store_null.c \ - src/g_logger.c + src/store_ro_http_proxy.c STORE_LDFLAGS = $(LIBMEMCACHED_LDFLAGS) $(LIBRADOS_LDFLAGS) $(LIBCURL) $(GLIB_LIBS) STORE_CPPFLAGS = @@ -22,8 +22,8 @@ bin_PROGRAMS = \ renderd \ render_expired \ render_list \ - render_speedtest \ - render_old + render_old \ + render_speedtest noinst_PROGRAMS = gen_tile_test man_MANS = \ @@ -38,32 +38,33 @@ renderddir = $(sysconfdir) renderd_SOURCES = \ src/renderd.c \ + src/cache_expire.c \ src/daemon_compat.c \ src/gen_tile.cpp \ - src/sys_utils.c \ - src/request_queue.c \ - src/cache_expire.c \ src/metatile.cpp \ src/parameterize_style.cpp \ src/protocol_helper.c \ + src/renderd_config.c \ + src/request_queue.c \ + src/sys_utils.c \ $(STORE_SOURCES) renderd_CXXFLAGS = $(MAPNIK_CFLAGS) -renderd_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) renderd_DATA = etc/renderd/renderd.conf +renderd_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) render_speedtest_SOURCES = \ src/render_speedtest.cpp \ + src/g_logger.c \ src/protocol_helper.c \ src/render_submit_queue.c \ - src/sys_utils.c \ - src/g_logger.c + src/sys_utils.c render_speedtest_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) render_list_SOURCES = \ src/render_list.c \ - src/sys_utils.c \ src/protocol_helper.c \ src/render_submit_queue.c \ + src/sys_utils.c \ $(STORE_SOURCES) render_list_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) @@ -76,31 +77,22 @@ render_expired_SOURCES = \ render_expired_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) render_old_SOURCES = \ - src/store_file_utils.c \ src/render_old.c \ - src/sys_utils.c \ + src/g_logger.c \ src/protocol_helper.c \ src/render_submit_queue.c \ - src/g_logger.c + src/store_file_utils.c \ + src/sys_utils.c render_old_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) #convert_meta_SOURCES = src/dir_utils.c src/store.c src/convert_meta.c gen_tile_test_SOURCES = \ tests/gen_tile_test.cpp \ - src/metatile.cpp \ - src/request_queue.c \ - src/protocol_helper.c \ - src/renderd.c \ - src/daemon_compat.c \ - src/gen_tile.cpp \ - src/sys_utils.c \ - src/cache_expire.c \ - src/parameterize_style.cpp \ - $(STORE_SOURCES) -gen_tile_test_CFLAGS = -DMAIN_ALREADY_DEFINED $(PTHREAD_CFLAGS) $(GLIB_CFLAGS) -gen_tile_test_CXXFLAGS = $(MAPNIK_CFLAGS) -gen_tile_test_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) + $(renderd_SOURCES) +gen_tile_test_CFLAGS = -DMAIN_ALREADY_DEFINED +gen_tile_test_CXXFLAGS = $(renderd_CXXFLAGS) +gen_tile_test_LDADD = $(renderd_LDADD) CLEANFILES=*.slo mod_tile.la stderr.out src/*.slo src/*.lo src/.libs/* src/*.la @@ -114,16 +106,16 @@ all-local: $(subst -pthread,-Wc$(COMMA)-pthread,$(GLIB_CFLAGS)) \ -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) \ @srcdir@/src/mod_tile.c \ - @srcdir@/src/sys_utils.c \ + @srcdir@/src/g_logger.c \ @srcdir@/src/store.c \ @srcdir@/src/store_file.c \ @srcdir@/src/store_file_utils.c \ @srcdir@/src/store_memcached.c \ + @srcdir@/src/store_null.c \ @srcdir@/src/store_rados.c \ - @srcdir@/src/store_ro_http_proxy.c \ @srcdir@/src/store_ro_composite.c \ - @srcdir@/src/store_null.c \ - @srcdir@/src/g_logger.c + @srcdir@/src/store_ro_http_proxy.c \ + @srcdir@/src/sys_utils.c install-mod_tile: mkdir -p $(DESTDIR)`$(APXS) -q LIBEXECDIR` @@ -132,13 +124,13 @@ install-mod_tile: $(subst -pthread,-Wc$(COMMA)-pthread,$(GLIB_CFLAGS)) \ -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) \ @srcdir@/src/mod_tile.c \ - @srcdir@/src/sys_utils.c \ + @srcdir@/src/g_logger.c \ @srcdir@/src/store.c \ @srcdir@/src/store_file.c \ @srcdir@/src/store_file_utils.c \ @srcdir@/src/store_memcached.c \ + @srcdir@/src/store_null.c \ @srcdir@/src/store_rados.c \ - @srcdir@/src/store_ro_http_proxy.c \ @srcdir@/src/store_ro_composite.c \ - @srcdir@/src/store_null.c \ - @srcdir@/src/g_logger.c + @srcdir@/src/store_ro_http_proxy.c \ + @srcdir@/src/sys_utils.c diff --git a/includes/renderd.h b/includes/renderd.h index 9642bf44..2e903d07 100644 --- a/includes/renderd.h +++ b/includes/renderd.h @@ -26,45 +26,49 @@ extern "C" { int daemon(int nochdir, int noclose); #endif -#include /* for PATH_MAX */ #include "gen_tile.h" #include "protocol.h" +#include #define INILINE_MAX 256 #define MAX_SLAVES 5 typedef struct { - const char *iphostname; - const char *mapnik_font_dir; - const char *mapnik_plugins_dir; - const char *pid_filename; - const char *socketname; - const char *stats_filename; - const char *tile_dir; + char *iphostname; + char *mapnik_font_dir; + char *mapnik_plugins_dir; + char *pid_filename; + char *socketname; + char *stats_filename; + char *tile_dir; int ipport; int mapnik_font_dir_recurse; int num_threads; } renderd_config; typedef struct { - char xmlname[XMLCONFIG_MAX]; - char xmlfile[PATH_MAX]; - char xmluri[PATH_MAX]; - char host[PATH_MAX]; - char htcpip[PATH_MAX]; - char tile_dir[PATH_MAX]; - char output_format[INILINE_MAX]; - char parameterization[PATH_MAX]; - int tile_px_size; + char *attribution; + char *cors; + char *description; + char *host; + char *htcpip; + char *output_format; + char *parameterization; + char *server_alias; + char *tile_dir; + char *xmlfile; + char *xmlname; + char *xmluri; double scale_factor; - int min_zoom; + int aspect_x; + int aspect_y; int max_zoom; + int min_zoom; int num_threads; + int tile_px_size; } xmlconfigitem; - - -extern struct request_queue * render_request_queue; +extern struct request_queue *render_request_queue; void statsRenderFinish(int z, long time); void request_exit(void); diff --git a/includes/renderd_config.h b/includes/renderd_config.h new file mode 100644 index 00000000..fc33587f --- /dev/null +++ b/includes/renderd_config.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007 - 2024 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#ifndef RENDERD_CONFIG_H +#define RENDERD_CONFIG_H + +#include "render_config.h" +#include "renderd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int num_slave_threads; +extern renderd_config config; +extern renderd_config config_slaves[MAX_SLAVES]; +extern xmlconfigitem maps[XMLCONFIGS_MAX]; + +int min_max_int_opt(const char *opt_arg, const char *opt_type_name, int minimum, int maximum); +void process_config_file(const char *config_file_name, int active_slave, int log_level); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/includes/sys_utils.h b/includes/sys_utils.h index 85747668..3fefc57b 100644 --- a/includes/sys_utils.h +++ b/includes/sys_utils.h @@ -18,6 +18,14 @@ #ifndef SYS_UTILS_H #define SYS_UTILS_H +#ifdef __cplusplus +extern "C" { +#endif + double get_load_avg(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0cc6982e..6e507333 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,14 +33,14 @@ set(COMMON_LIBRARIES ) set(STORE_SRCS - store_file_utils.c + store.c store_file.c + store_file_utils.c store_memcached.c store_null.c store_rados.c store_ro_composite.c store_ro_http_proxy.c - store.c ) set(STORE_LIBRARIES ${CAIRO_LIBRARIES} @@ -168,6 +168,7 @@ set(renderd_SRCS parameterize_style.cpp protocol_helper.c renderd.c + renderd_config.c request_queue.c ) set(renderd_LIBS @@ -180,13 +181,13 @@ set(renderd_LIBS add_executable(renderd ${renderd_SRCS}) target_link_libraries(renderd ${renderd_LIBS}) +if(ENABLE_TESTS) #----------------------------------------------------------------------------- # # Test targets # #----------------------------------------------------------------------------- -if(ENABLE_TESTS) #----------------------------------------------------------------------------- # # gen_tile_test @@ -201,10 +202,9 @@ set(gen_tile_test_LIBS ${renderd_LIBS} ) add_executable(gen_tile_test ${gen_tile_test_SRCS}) -target_compile_options(gen_tile_test PRIVATE -DMAIN_ALREADY_DEFINED) +target_compile_definitions(gen_tile_test PRIVATE MAIN_ALREADY_DEFINED) target_include_directories(gen_tile_test PRIVATE ${PROJECT_SOURCE_DIR}/tests) target_link_libraries(gen_tile_test ${gen_tile_test_LIBS}) -set_target_properties(gen_tile_test PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/tests -) +set_target_properties(gen_tile_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/tests) + endif() diff --git a/src/gen_tile.cpp b/src/gen_tile.cpp index 280d9223..5b3dff12 100644 --- a/src/gen_tile.cpp +++ b/src/gen_tile.cpp @@ -374,7 +374,7 @@ void *render_thread(void * arg) g_logger(G_LOG_LEVEL_DEBUG, "Starting render thread: %lu", (unsigned long) pthread_self()); for (iMaxConfigs = 0; iMaxConfigs < XMLCONFIGS_MAX; ++iMaxConfigs) { - if (parentxmlconfig[iMaxConfigs].xmlname[0] == 0 || parentxmlconfig[iMaxConfigs].xmlfile[0] == 0) { + if (parentxmlconfig[iMaxConfigs].xmlname == NULL || parentxmlconfig[iMaxConfigs].xmlfile == NULL) { break; } @@ -405,7 +405,7 @@ void *render_thread(void * arg) * up the mapnik datasources to support larger postgres connection pools */ if (parentxmlconfig[iMaxConfigs].num_threads > 10) { - g_logger(G_LOG_LEVEL_INFO, "Updating max_connection parameter for mapnik layers to reflect thread count"); + g_logger(G_LOG_LEVEL_DEBUG, "Updating max_connection parameter for mapnik layers to reflect thread count"); parameterize_map_max_connections(maps[iMaxConfigs].map, parentxmlconfig[iMaxConfigs].num_threads); } @@ -428,7 +428,7 @@ void *render_thread(void * arg) maps[iMaxConfigs].htcphost); if (maps[iMaxConfigs].htcpsock > 0) { - g_logger(G_LOG_LEVEL_INFO, "Successfully opened socket for HTCP cache expiry"); + g_logger(G_LOG_LEVEL_DEBUG, "Successfully opened socket for HTCP cache expiry"); } else { g_logger(G_LOG_LEVEL_ERROR, "Failed to open socket for HTCP cache expiry"); } diff --git a/src/parameterize_style.cpp b/src/parameterize_style.cpp index 68924dad..58e5b430 100644 --- a/src/parameterize_style.cpp +++ b/src/parameterize_style.cpp @@ -89,10 +89,10 @@ parameterize_function_ptr init_parameterization_function(char * function_name) g_logger(G_LOG_LEVEL_DEBUG, "Parameterize_style not specified (or empty string specified)"); return NULL; } else if (strcmp(function_name, "language") == 0) { - g_logger(G_LOG_LEVEL_INFO, "Loading parameterization function for %s", function_name); + g_logger(G_LOG_LEVEL_DEBUG, "Loading parameterization function for '%s'", function_name); return parameterize_map_language; } else { - g_logger(G_LOG_LEVEL_WARNING, "unknown parameterization function for %s", function_name); + g_logger(G_LOG_LEVEL_WARNING, "unknown parameterization function for '%s'", function_name); } return NULL; diff --git a/src/render_submit_queue.c b/src/render_submit_queue.c index db3d9929..05ca3955 100644 --- a/src/render_submit_queue.c +++ b/src/render_submit_queue.c @@ -31,11 +31,12 @@ #include #include -#include "render_submit_queue.h" -#include "sys_utils.h" +#include "g_logger.h" #include "protocol.h" #include "protocol_helper.h" #include "render_config.h" +#include "render_submit_queue.h" +#include "sys_utils.h" static pthread_mutex_t qLock; static pthread_mutex_t qStatsLock; @@ -76,8 +77,9 @@ static void check_load(void) double avg = get_load_avg(); while (avg >= maxLoad) { - /* printf("Load average %d, sleeping\n", avg); */ - sleep(5); + int seconds = 5; + g_logger(G_LOG_LEVEL_DEBUG, "Load average %d, sleeping %is", avg, seconds); + sleep(seconds); avg = get_load_avg(); } } @@ -93,25 +95,28 @@ static int process(struct protocol * cmd, int fd) gettimeofday(&tim, NULL); t1 = tim.tv_sec * 1000 + (tim.tv_usec / 1000); - //printf("Sending request\n"); + g_logger(G_LOG_LEVEL_DEBUG, "Sending request"); + if (send_cmd(cmd, fd) < 1) { - perror("send error"); + g_logger(G_LOG_LEVEL_ERROR, "send error: %s", strerror(errno)); }; - //printf("Waiting for response\n"); bzero(&rsp, sizeof(rsp)); + g_logger(G_LOG_LEVEL_DEBUG, "Waiting for response"); + ret = recv_cmd(&rsp, fd, 1); if (ret < 1) { return 0; } - //printf("Got response %i\n", rsp.cmd); + g_logger(G_LOG_LEVEL_DEBUG, "Got response %i", rsp.cmd); if (rsp.cmd != cmdDone) { - printf("rendering failed with command %i, pausing.\n", rsp.cmd); - sleep(10); + int seconds = 1; + g_logger(G_LOG_LEVEL_DEBUG, "Rendering not done with command %i, sleeping %is", rsp.cmd, seconds); + sleep(seconds); } else { gettimeofday(&tim, NULL); t2 = tim.tv_sec * 1000 + (tim.tv_usec / 1000); @@ -132,7 +137,7 @@ static int process(struct protocol * cmd, int fd) } if (!ret) { - perror("Socket send error"); + g_logger(G_LOG_LEVEL_ERROR, "Socket send error: %s", strerror(errno)); } return ret; @@ -153,7 +158,7 @@ static struct protocol * fetch(void) // Fetch item from queue if (!qHead) { - fprintf(stderr, "Queue failure, null qHead with %d items in list\n", qLen); + g_logger(G_LOG_LEVEL_CRITICAL, "Queue failure, null qHead with %d items in list", qLen); exit(1); } @@ -196,7 +201,7 @@ void enqueue(const char *xmlname, int x, int y, int z) e->next = NULL; if (!e->mapname) { - fprintf(stderr, "Malloc failure\n"); + g_logger(G_LOG_LEVEL_CRITICAL, "Malloc failure"); exit(1); } @@ -206,7 +211,7 @@ void enqueue(const char *xmlname, int x, int y, int z) int ret = pthread_cond_wait(&qCondNotFull, &qLock); if (ret != 0) { - fprintf(stderr, "pthread_cond_wait(qCondNotFull): %s\n", strerror(ret)); + g_logger(G_LOG_LEVEL_WARNING, "pthread_cond_wait(qCondNotFull): %s", strerror(ret)); } } @@ -235,7 +240,7 @@ int make_connection(const char *spath) fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - fprintf(stderr, "failed to create unix socket\n"); + g_logger(G_LOG_LEVEL_CRITICAL, "failed to create unix socket"); exit(2); } @@ -275,12 +280,12 @@ int make_connection(const char *spath) snprintf(port_s, sizeof(port_s), "%u", port); - printf("Connecting to %s, port %u/tcp\n", hostname, port); + g_logger(G_LOG_LEVEL_DEBUG, "Connecting to %s, port %u/tcp", hostname, port); struct protoent *protocol = getprotobyname("tcp"); if (!protocol) { - fprintf(stderr, "cannot find TCP protocol number\n"); + g_logger(G_LOG_LEVEL_CRITICAL, "cannot find TCP protocol number"); exit(2); } @@ -307,7 +312,7 @@ int make_connection(const char *spath) int ai = getaddrinfo(hostname, port_s, &hints, &result); if (ai != 0) { - fprintf(stderr, "cannot resolve hostname %s\n", hostname); + g_logger(G_LOG_LEVEL_CRITICAL, "cannot resolve hostname %s", hostname); exit(2); } @@ -325,14 +330,14 @@ int make_connection(const char *spath) int name_info = getnameinfo(rp->ai_addr, rp->ai_addrlen, resolved_addr, sizeof(resolved_addr), resolved_port, sizeof(resolved_port), NI_NUMERICHOST | NI_NUMERICSERV); if (name_info != 0) { - fprintf(stderr, "cannot retrieve name info: %d\n", name_info); + g_logger(G_LOG_LEVEL_CRITICAL, "cannot retrieve name info: %d", name_info); exit(2); } - fprintf(stderr, "Trying %s:%s\n", resolved_addr, resolved_port); + g_logger(G_LOG_LEVEL_DEBUG, "Trying %s:%s", resolved_addr, resolved_port); if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) { - printf("Connected to %s:%s\n", resolved_addr, resolved_port); + g_logger(G_LOG_LEVEL_DEBUG, "Connected to %s:%s", resolved_addr, resolved_port); break; } @@ -341,7 +346,7 @@ int make_connection(const char *spath) freeaddrinfo(result); if (rp == NULL) { - fprintf(stderr, "cannot connect to any address for %s\n", hostname); + g_logger(G_LOG_LEVEL_CRITICAL, "cannot connect to any address for %s", hostname); exit(2); } @@ -356,7 +361,7 @@ void *thread_main(void *arg) int fd = make_connection(spath); if (fd < 0) { - fprintf(stderr, "connect failed for: %s\n", spath); + g_logger(G_LOG_LEVEL_ERROR, "connect failed for: %s", spath); return NULL; } @@ -369,14 +374,15 @@ void *thread_main(void *arg) } while (process(cmd, fd) < 1) { - fprintf(stderr, "connection to renderd lost\n"); + g_logger(G_LOG_LEVEL_ERROR, "connection to renderd lost"); close(fd); fd = -1; while (fd < 0) { - fprintf(stderr, "sleeping for 30 seconds\n"); + int seconds = 30; + g_logger(G_LOG_LEVEL_WARNING, "sleeping for %i seconds", seconds); sleep(30); - fprintf(stderr, "attempting to reconnect\n"); + g_logger(G_LOG_LEVEL_WARNING, "attempting to reconnect"); fd = make_connection(spath); } } @@ -403,17 +409,17 @@ void spawn_workers(int num, const char *spath, int max_load) qMaxLen = no_workers; - printf("Starting %d rendering threads\n", no_workers); + g_logger(G_LOG_LEVEL_MESSAGE, "Starting %d rendering threads", no_workers); workers = calloc(sizeof(pthread_t), no_workers); if (!workers) { - perror("Error allocating worker memory"); + g_logger(G_LOG_LEVEL_CRITICAL, "Error allocating worker memory: %s", strerror(errno)); exit(1); } for (i = 0; i < no_workers; i++) { if (pthread_create(&workers[i], NULL, thread_main, (void *)spath)) { - perror("Thread creation failed"); + g_logger(G_LOG_LEVEL_CRITICAL, "Thread creation failed: %s", strerror(errno)); exit(1); } } @@ -452,15 +458,13 @@ void wait_for_empty_queue() void finish_workers(void) { - int i; - - printf("Waiting for rendering threads to finish\n"); + g_logger(G_LOG_LEVEL_MESSAGE, "Waiting for rendering threads to finish"); pthread_mutex_lock(&qLock); work_complete = 1; pthread_mutex_unlock(&qLock); pthread_cond_broadcast(&qCondNotEmpty); - for (i = 0; i < no_workers; i++) { + for (int i = 0; i < no_workers; i++) { pthread_join(workers[i], NULL); } diff --git a/src/renderd.c b/src/renderd.c index 9b25d08c..dc1594ff 100644 --- a/src/renderd.c +++ b/src/renderd.c @@ -15,39 +15,34 @@ * along with this program; If not, see http://www.gnu.org/licenses/. */ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include -#include -#include +#include #include -#include #include #include +#include +#include +#include #include #include -#include +#include +#include +#include +#include +#include #include "config.h" -#include "render_config.h" -#include "renderd.h" +#include "g_logger.h" #include "gen_tile.h" #include "protocol.h" #include "protocol_helper.h" +#include "render_config.h" +#include "renderd.h" +#include "renderd_config.h" #include "request_queue.h" -#include "g_logger.h" - -#ifdef HAVE_INIPARSER_INIPARSER_H -#include -#else -#include -#endif #define PFD_LISTEN 0 #define PFD_EXIT_PIPE 1 @@ -62,10 +57,6 @@ static pthread_t stats_thread; static int exit_pipe_fd; -static renderd_config config; - -int num_slave_threads; - struct request_queue * render_request_queue; static const char *cmdStr(enum protoCmd c) @@ -96,7 +87,7 @@ static const char *cmdStr(enum protoCmd c) return "NotDone"; default: - return "unknown"; + return "Unknown"; } } @@ -148,7 +139,7 @@ enum protoCmd rx_request(struct protocol *req, int fd) cmdStr(req->cmd), fd, req->xmlname, req->z, req->x, req->y, req->mimetype, req->options); if ((req->cmd != cmdRender) && (req->cmd != cmdRenderPrio) && (req->cmd != cmdRenderLow) && (req->cmd != cmdDirty) && (req->cmd != cmdRenderBulk)) { - g_logger(G_LOG_LEVEL_WARNING, "Ignoring unknown command %s fd(%d) xml(%s), z(%d), x(%d), y(%d)", + g_logger(G_LOG_LEVEL_WARNING, "Ignoring invalid command %s fd(%d) xml(%s), z(%d), x(%d), y(%d)", cmdStr(req->cmd), fd, req->xmlname, req->z, req->x, req->y); return cmdNotDone; } @@ -766,11 +757,7 @@ int main(int argc, char **argv) break; case 's': - if (sscanf(optarg, "%i", &active_slave) != 1) { - fprintf(stderr, "--slave needs to be numeric (%s)\n", optarg); - active_slave = 0; - } - + active_slave = min_max_int_opt(optarg, "slave", 0, -1); break; case 'h': @@ -809,294 +796,7 @@ int main(int argc, char **argv) exit(1); } - xmlconfigitem maps[XMLCONFIGS_MAX]; - bzero(maps, sizeof(xmlconfigitem) * XMLCONFIGS_MAX); - - renderd_config config_slaves[MAX_SLAVES]; - bzero(config_slaves, sizeof(renderd_config) * MAX_SLAVES); - bzero(&config, sizeof(renderd_config)); - - g_logger(G_LOG_LEVEL_INFO, "Parsing config file: %s", config_file_name); - dictionary *ini = iniparser_load(config_file_name); - - if (!ini) { - g_logger(G_LOG_LEVEL_CRITICAL, "Failed to load config file: %s", config_file_name); - exit(1); - } - - num_slave_threads = 0; - - int iconf = -1; - char buffer[PATH_MAX]; - - g_logger(G_LOG_LEVEL_DEBUG, "Parsing renderd config section(s)"); - - for (int section = 0; section < iniparser_getnsec(ini); section++) { - const char *name = iniparser_getsecname(ini, section); - - if (strncmp(name, "renderd", 7) == 0) { - /* this is a renderd config section */ - int render_sec = 0; - - if (sscanf(name, "renderd%i", &render_sec) != 1) { - render_sec = 0; - } - - g_logger(G_LOG_LEVEL_DEBUG, "Parsing renderd config section %i: %s", render_sec, name); - - if (render_sec >= MAX_SLAVES) { - g_logger(G_LOG_LEVEL_CRITICAL, "Can't handle more than %i renderd config sections", - MAX_SLAVES); - exit(7); - } - - snprintf(buffer, sizeof(buffer), "%s:socketname", name); - config_slaves[render_sec].socketname = iniparser_getstring(ini, - buffer, (char *) RENDERD_SOCKET); - snprintf(buffer, sizeof(buffer), "%s:iphostname", name); - config_slaves[render_sec].iphostname = iniparser_getstring(ini, - buffer, ""); - snprintf(buffer, sizeof(buffer), "%s:ipport", name); - config_slaves[render_sec].ipport = iniparser_getint(ini, buffer, 0); - snprintf(buffer, sizeof(buffer), "%s:num_threads", name); - config_slaves[render_sec].num_threads = iniparser_getint(ini, - buffer, NUM_THREADS); - snprintf(buffer, sizeof(buffer), "%s:tile_dir", name); - config_slaves[render_sec].tile_dir = iniparser_getstring(ini, - buffer, (char *) RENDERD_TILE_DIR); - snprintf(buffer, sizeof(buffer), "%s:stats_file", name); - config_slaves[render_sec].stats_filename = iniparser_getstring(ini, - buffer, NULL); - snprintf(buffer, sizeof(buffer), "%s:pid_file", name); - config_slaves[render_sec].pid_filename = iniparser_getstring(ini, - buffer, (char *) RENDERD_PIDFILE); - - if (config_slaves[render_sec].num_threads == -1) { - config_slaves[render_sec].num_threads = sysconf(_SC_NPROCESSORS_ONLN); - } - - if (render_sec == active_slave) { - config.socketname = config_slaves[render_sec].socketname; - config.iphostname = config_slaves[render_sec].iphostname; - config.ipport = config_slaves[render_sec].ipport; - config.num_threads = config_slaves[render_sec].num_threads; - config.tile_dir = config_slaves[render_sec].tile_dir; - config.stats_filename - = config_slaves[render_sec].stats_filename; - config.pid_filename - = config_slaves[render_sec].pid_filename; - config.mapnik_plugins_dir = iniparser_getstring(ini, - "mapnik:plugins_dir", (char *) MAPNIK_PLUGINS_DIR); - config.mapnik_font_dir = iniparser_getstring(ini, - "mapnik:font_dir", (char *) MAPNIK_FONTS_DIR); - config.mapnik_font_dir_recurse = iniparser_getboolean(ini, - "mapnik:font_dir_recurse", MAPNIK_FONTS_DIR_RECURSE); - } else { - num_slave_threads += config_slaves[render_sec].num_threads; - } - } - } - - g_logger(G_LOG_LEVEL_DEBUG, "Parsing map config section(s)"); - - for (int section = 0; section < iniparser_getnsec(ini); section++) { - const char *name = iniparser_getsecname(ini, section); - - if (strncmp(name, "renderd", 7) && strcmp(name, "mapnik")) { - /* this is a map config section */ - if (config.num_threads == 0 || config.tile_dir == NULL) { - g_logger(G_LOG_LEVEL_CRITICAL, "No valid (active) renderd config section available"); - exit(7); - } - - iconf++; - - g_logger(G_LOG_LEVEL_DEBUG, "Parsing map config section %i: %s", iconf, name); - - if (iconf >= XMLCONFIGS_MAX) { - g_logger(G_LOG_LEVEL_CRITICAL, "Config: more than %d configurations found", XMLCONFIGS_MAX); - exit(7); - } - - if (strlen(name) >= (XMLCONFIG_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "XML name too long: %s", name); - exit(7); - } - - strcpy(maps[iconf].xmlname, name); - - snprintf(buffer, sizeof(buffer), "%s:uri", name); - const char *ini_uri = iniparser_getstring(ini, buffer, (char *)""); - - if (strlen(ini_uri) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "URI too long: %s", ini_uri); - exit(7); - } - - strcpy(maps[iconf].xmluri, ini_uri); - - snprintf(buffer, sizeof(buffer), "%s:xml", name); - const char *ini_xmlpath = iniparser_getstring(ini, buffer, (char *)""); - - if (strlen(ini_xmlpath) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "XML path too long: %s", ini_xmlpath); - exit(7); - } - - strcpy(maps[iconf].xmlfile, ini_xmlpath); - - snprintf(buffer, sizeof(buffer), "%s:host", name); - const char *ini_hostname = iniparser_getstring(ini, buffer, (char *) ""); - - if (strlen(ini_hostname) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "Host name too long: %s", ini_hostname); - exit(7); - } - - strcpy(maps[iconf].host, ini_hostname); - - snprintf(buffer, sizeof(buffer), "%s:htcphost", name); - const char *ini_htcpip = iniparser_getstring(ini, buffer, (char *) ""); - - if (strlen(ini_htcpip) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "HTCP host name too long: %s", ini_htcpip); - exit(7); - } - - strcpy(maps[iconf].htcpip, ini_htcpip); - - snprintf(buffer, sizeof(buffer), "%s:tilesize", name); - const char *ini_tilesize = iniparser_getstring(ini, buffer, (char *) "256"); - maps[iconf].tile_px_size = atoi(ini_tilesize); - - if (maps[iconf].tile_px_size < 1) { - g_logger(G_LOG_LEVEL_CRITICAL, "Tile size is invalid: %s", ini_tilesize); - exit(7); - } - - snprintf(buffer, sizeof(buffer), "%s:scale", name); - const char *ini_scale = iniparser_getstring(ini, buffer, (char *) "1.0"); - maps[iconf].scale_factor = atof(ini_scale); - - if (maps[iconf].scale_factor < 0.1 || maps[iconf].scale_factor > 8.0) { - g_logger(G_LOG_LEVEL_CRITICAL, "Scale factor is invalid: %s", ini_scale); - exit(7); - } - - snprintf(buffer, sizeof(buffer), "%s:tiledir", name); - const char *ini_tiledir = iniparser_getstring(ini, buffer, (char *) config.tile_dir); - - if (strlen(ini_tiledir) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "Tiledir too long: %s", ini_tiledir); - exit(7); - } - - strcpy(maps[iconf].tile_dir, ini_tiledir); - - snprintf(buffer, sizeof(buffer), "%s:maxzoom", name); - const char *ini_maxzoom = iniparser_getstring(ini, buffer, "18"); - maps[iconf].max_zoom = atoi(ini_maxzoom); - - if (maps[iconf].max_zoom > MAX_ZOOM) { - g_logger(G_LOG_LEVEL_CRITICAL, "Specified max zoom (%i) is too large. Renderd currently only supports up to zoom level %i", maps[iconf].max_zoom, MAX_ZOOM); - exit(7); - } - - snprintf(buffer, sizeof(buffer), "%s:minzoom", name); - const char *ini_minzoom = iniparser_getstring(ini, buffer, "0"); - maps[iconf].min_zoom = atoi(ini_minzoom); - - if (maps[iconf].min_zoom < 0) { - g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is too small. Minimum zoom level has to be greater or equal to 0", maps[iconf].min_zoom); - exit(7); - } - - if (maps[iconf].min_zoom > maps[iconf].max_zoom) { - g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", maps[iconf].min_zoom, maps[iconf].max_zoom); - exit(7); - } - - snprintf(buffer, sizeof(buffer), "%s:parameterize_style", name); - const char *ini_parameterize = iniparser_getstring(ini, buffer, ""); - - if (strlen(ini_parameterize) >= (PATH_MAX - 1)) { - g_logger(G_LOG_LEVEL_CRITICAL, "Parameterize_style too long: %s", ini_parameterize); - exit(7); - } - - strcpy(maps[iconf].parameterization, ini_parameterize); - - snprintf(buffer, sizeof(buffer), "%s:type", name); - const char *ini_type = iniparser_getstring(ini, buffer, "png image/png png256"); - - char ini_fileExtension[INILINE_MAX] = "png"; - char ini_mimeType[INILINE_MAX] = "image/png"; - char ini_outputFormat[INILINE_MAX] = "png256"; - - sscanf(ini_type, "%[^ ] %[^ ] %[^;#]", ini_fileExtension, ini_mimeType, ini_outputFormat); - - strcpy(maps[iconf].output_format, ini_outputFormat); - - /* Pass this information into the rendering threads, - * as it is needed to configure mapniks number of connections - */ - maps[iconf].num_threads = config.num_threads; - } - } - - if (config.ipport > 0) { - g_logger(G_LOG_LEVEL_INFO, "config renderd: ip socket=%s:%i", config.iphostname, config.ipport); - } else { - g_logger(G_LOG_LEVEL_INFO, "config renderd: unix socketname=%s", config.socketname); - } - - g_logger(G_LOG_LEVEL_INFO, "config renderd: num_threads=%d", config.num_threads); - - if (active_slave == 0) { - g_logger(G_LOG_LEVEL_INFO, "config renderd: num_slave_threads=%d", num_slave_threads); - } - - g_logger(G_LOG_LEVEL_INFO, "config renderd: tile_dir=%s", config.tile_dir); - g_logger(G_LOG_LEVEL_INFO, "config renderd: stats_file=%s", config.stats_filename); - g_logger(G_LOG_LEVEL_INFO, "config renderd: pid_file=%s", config.pid_filename); - g_logger(G_LOG_LEVEL_INFO, "config mapnik: plugins_dir=%s", config.mapnik_plugins_dir); - g_logger(G_LOG_LEVEL_INFO, "config mapnik: font_dir=%s", config.mapnik_font_dir); - g_logger(G_LOG_LEVEL_INFO, "config mapnik: font_dir_recurse=%d", config.mapnik_font_dir_recurse); - - for (i = 0; i < MAX_SLAVES; i++) { - if (config_slaves[i].num_threads == 0) { - continue; - } - - if (i == active_slave) { - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): Active", i); - } - - if (config_slaves[i].ipport > 0) { - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): ip socket=%s:%i", i, - config_slaves[i].iphostname, config_slaves[i].ipport); - } else { - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): unix socketname=%s", i, - config_slaves[i].socketname); - } - - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): num_threads=%d", i, - config_slaves[i].num_threads); - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): tile_dir=%s", i, - config_slaves[i].tile_dir); - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): stats_file=%s", i, - config_slaves[i].stats_filename); - g_logger(G_LOG_LEVEL_INFO, "config renderd(%i): pid_file=%s", i, - config_slaves[i].pid_filename); - } - - for (iconf = 0; iconf < XMLCONFIGS_MAX; ++iconf) { - if (maps[iconf].xmlname[0] != 0) { - g_logger(G_LOG_LEVEL_INFO, "config map %d: name(%s) file(%s) uri(%s) output_format(%s) htcp(%s) host(%s)", - iconf, maps[iconf].xmlname, maps[iconf].xmlfile, maps[iconf].xmluri, - maps[iconf].output_format, maps[iconf].htcpip, maps[iconf].host); - } - } + process_config_file(config_file_name, active_slave, G_LOG_LEVEL_INFO); fd = server_socket_init(&config); @@ -1145,7 +845,7 @@ int main(int argc, char **argv) } } - if (config.stats_filename != NULL) { + if (strnlen(config.stats_filename, PATH_MAX - 1)) { if (pthread_create(&stats_thread, NULL, stats_writeout_thread, NULL)) { g_logger(G_LOG_LEVEL_WARNING, "Could not create stats writeout thread"); } diff --git a/src/renderd_config.c b/src/renderd_config.c new file mode 100644 index 00000000..4cbb8a57 --- /dev/null +++ b/src/renderd_config.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2007 - 2024 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include "config.h" +#include "g_logger.h" +#include "render_config.h" +#include "renderd.h" + +#ifdef HAVE_INIPARSER_INIPARSER_H +#include +#else +#include +#endif + +int num_slave_threads; + +renderd_config config; +renderd_config config_slaves[MAX_SLAVES]; +xmlconfigitem maps[XMLCONFIGS_MAX]; + +static void copy_string_with_snprintf(const char *src, char **dest, size_t maxlen) +{ + int len, size; + + size = sizeof(char) * strnlen(src, maxlen) + sizeof(char); + *dest = malloc(size); + + if (*dest == NULL) { + g_logger(G_LOG_LEVEL_CRITICAL, "malloc error"); + exit(7); + } + + len = snprintf(*dest, size, "%s", src); + + if (len < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "snprintf encoding error"); + exit(7); + } else if (len >= maxlen) { + g_logger(G_LOG_LEVEL_CRITICAL, "snprintf buffer too small"); + exit(7); + } +} + +static char *name_with_section(const char *section, const char *name) +{ + int len, maxlen = INILINE_MAX - 1; + char *key; + + key = malloc(sizeof(char) * maxlen); + + if (key == NULL) { + g_logger(G_LOG_LEVEL_CRITICAL, "malloc error"); + exit(7); + } + + len = snprintf(key, maxlen, "%s:%s", section, name); + + if (len < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "snprintf encoding error"); + exit(7); + } else if (len >= maxlen) { + g_logger(G_LOG_LEVEL_CRITICAL, "snprintf buffer too small"); + exit(7); + } + + return key; +} + +static void process_config_bool(const dictionary *ini, const char *section, const char *name, int *dest, int notfound) +{ + char *key = name_with_section(section, name); + int src = iniparser_getboolean(ini, key, notfound); + + g_logger(G_LOG_LEVEL_DEBUG, "\tRead %s: '%s'", key, src ? "true" : "false"); + + *dest = src; + + free(key); +} + +static void process_config_double(const dictionary *ini, const char *section, const char *name, double *dest, double notfound) +{ + char *key = name_with_section(section, name); + double src = iniparser_getdouble(ini, key, notfound); + + g_logger(G_LOG_LEVEL_DEBUG, "\tRead %s: '%lf'", key, src); + + *dest = src; + + free(key); +} + +static void process_config_int(const dictionary *ini, const char *section, const char *name, int *dest, int notfound) +{ + char *key = name_with_section(section, name); + int src = iniparser_getint(ini, key, notfound); + + g_logger(G_LOG_LEVEL_DEBUG, "\tRead %s: '%i'", key, src); + + *dest = src; + + free(key); +} + +static void process_config_string(const dictionary *ini, const char *section, const char *name, char **dest, char *notfound, int maxlen) +{ + int len; + char *key = name_with_section(section, name); + const char *src = iniparser_getstring(ini, key, notfound); + + g_logger(G_LOG_LEVEL_DEBUG, "\tRead %s: '%s'", key, src); + + copy_string_with_snprintf(src, dest, maxlen); + + free(key); +} + +int min_max_int_opt(const char *opt_arg, const char *opt_type_name, int minimum, int maximum) +{ + int opt; + float opt_float; + + if (sscanf(opt_arg, "%i", &opt) != 1) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid %s, must be an integer (%s was provided)", opt_type_name, opt_arg); + exit(1); + } + + if (minimum != -1 && opt < minimum) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid %s, must be >= %i (%s was provided)", opt_type_name, minimum, opt_arg); + exit(1); + } + + if (maximum != -1 && opt > maximum) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid %s, must be <= %i (%s was provided)", opt_type_name, maximum, opt_arg); + exit(1); + } + + if (sscanf(opt_arg, "%f", &opt_float) == 1) { + if ((float)opt != opt_float) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid %s, must be an integer (%s was provided)", opt_type_name, opt_arg); + exit(1); + } + } + + return opt; +} + +void process_config_file(const char *config_file_name, int active_slave, int log_level) +{ + int i, map_section_num = -1; + bzero(&config, sizeof(renderd_config)); + bzero(config_slaves, sizeof(renderd_config) * MAX_SLAVES); + bzero(maps, sizeof(xmlconfigitem) * XMLCONFIGS_MAX); + + g_logger(log_level, "Parsing renderd config file '%s':", config_file_name); + dictionary *ini = iniparser_load(config_file_name); + + if (!ini) { + g_logger(G_LOG_LEVEL_CRITICAL, "Failed to load config file: %s", config_file_name); + exit(1); + } + + num_slave_threads = 0; + + g_logger(G_LOG_LEVEL_DEBUG, "Parsing renderd config section(s)"); + + for (int section_num = 0; section_num < iniparser_getnsec(ini); section_num++) { + const char *section = iniparser_getsecname(ini, section_num); + + if (strncmp(section, "renderd", 7) == 0) { + /* this is a renderd config section */ + int renderd_section_num = 0; + + if (sscanf(section, "renderd%i", &renderd_section_num) != 1) { + renderd_section_num = 0; + } + + g_logger(G_LOG_LEVEL_DEBUG, "Parsing renderd config section %i: %s", renderd_section_num, section); + + if (renderd_section_num >= MAX_SLAVES) { + g_logger(G_LOG_LEVEL_CRITICAL, "Can't handle more than %i renderd config sections", MAX_SLAVES); + exit(7); + } + + process_config_int(ini, section, "ipport", &config_slaves[renderd_section_num].ipport, 0); + process_config_int(ini, section, "num_threads", &config_slaves[renderd_section_num].num_threads, NUM_THREADS); + process_config_string(ini, section, "iphostname", &config_slaves[renderd_section_num].iphostname, "", INILINE_MAX - 1); + process_config_string(ini, section, "pid_file", &config_slaves[renderd_section_num].pid_filename, RENDERD_PIDFILE, PATH_MAX - 1); + process_config_string(ini, section, "socketname", &config_slaves[renderd_section_num].socketname, RENDERD_SOCKET, PATH_MAX - 1); + process_config_string(ini, section, "stats_file", &config_slaves[renderd_section_num].stats_filename, "", PATH_MAX - 1); + process_config_string(ini, section, "tile_dir", &config_slaves[renderd_section_num].tile_dir, RENDERD_TILE_DIR, PATH_MAX - 1); + + if (config_slaves[renderd_section_num].num_threads == -1) { + config_slaves[renderd_section_num].num_threads = sysconf(_SC_NPROCESSORS_ONLN); + } + + if (renderd_section_num == active_slave) { + config = config_slaves[renderd_section_num]; + } else { + num_slave_threads += config_slaves[renderd_section_num].num_threads; + } + } + } + + g_logger(G_LOG_LEVEL_DEBUG, "Parsing mapnik config section"); + + for (int section_num = 0; section_num < iniparser_getnsec(ini); section_num++) { + const char *section = iniparser_getsecname(ini, section_num); + + if (strcmp(section, "mapnik") == 0) { + /* this is a mapnik config section */ + if (config.num_threads == 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "No valid (active) renderd config section available"); + exit(7); + } + + process_config_bool(ini, section, "font_dir_recurse", &config.mapnik_font_dir_recurse, MAPNIK_FONTS_DIR_RECURSE); + process_config_string(ini, section, "font_dir", &config.mapnik_font_dir, MAPNIK_FONTS_DIR, PATH_MAX - 1); + process_config_string(ini, section, "plugins_dir", &config.mapnik_plugins_dir, MAPNIK_PLUGINS_DIR, PATH_MAX - 1); + } + } + + g_logger(G_LOG_LEVEL_DEBUG, "Parsing map config section(s)"); + + for (int section_num = 0; section_num < iniparser_getnsec(ini); section_num++) { + const char *section = iniparser_getsecname(ini, section_num); + + if (strncmp(section, "renderd", 7) && strcmp(section, "mapnik")) { + /* this is a map config section */ + if (config.num_threads == 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "No valid (active) renderd config section available"); + exit(7); + } + + map_section_num++; + + g_logger(G_LOG_LEVEL_DEBUG, "Parsing map config section %i: %s", map_section_num, section); + + if (map_section_num >= XMLCONFIGS_MAX) { + g_logger(G_LOG_LEVEL_CRITICAL, "Can't handle more than %i map config sections", XMLCONFIGS_MAX); + exit(7); + } + + copy_string_with_snprintf(section, &maps[map_section_num].xmlname, XMLCONFIG_MAX - 1); + + process_config_int(ini, section, "aspectx", &maps[map_section_num].aspect_x, 1); + process_config_int(ini, section, "aspecty", &maps[map_section_num].aspect_y, 1); + process_config_int(ini, section, "tilesize", &maps[map_section_num].tile_px_size, 256); + process_config_string(ini, section, "attribution", &maps[map_section_num].attribution, "", PATH_MAX - 1); + process_config_string(ini, section, "cors", &maps[map_section_num].cors, "", PATH_MAX - 1); + process_config_string(ini, section, "description", &maps[map_section_num].description, "", PATH_MAX - 1); + process_config_string(ini, section, "host", &maps[map_section_num].host, "", PATH_MAX - 1); + process_config_string(ini, section, "htcphost", &maps[map_section_num].htcpip, "", PATH_MAX - 1); + process_config_string(ini, section, "parameterize_style", &maps[map_section_num].parameterization, "", PATH_MAX - 1); + process_config_string(ini, section, "server_alias", &maps[map_section_num].server_alias, "", PATH_MAX - 1); + process_config_string(ini, section, "tiledir", &maps[map_section_num].tile_dir, config.tile_dir, PATH_MAX - 1); + process_config_string(ini, section, "uri", &maps[map_section_num].xmluri, "", PATH_MAX - 1); + process_config_string(ini, section, "xml", &maps[map_section_num].xmlfile, "", PATH_MAX - 1); + + process_config_double(ini, section, "scale", &maps[map_section_num].scale_factor, 1.0); + + if (maps[map_section_num].scale_factor < 0.1) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified scale factor (%lf) is too small, must be greater than or equal to %lf.", maps[map_section_num].scale_factor, 0.1); + exit(7); + } else if (maps[map_section_num].scale_factor > 8.0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified scale factor (%lf) is too large, must be less than or equal to %lf.", maps[map_section_num].scale_factor, 8.0); + exit(7); + } + + process_config_int(ini, section, "maxzoom", &maps[map_section_num].max_zoom, 18); + + if (maps[map_section_num].max_zoom < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified max zoom (%i) is too small, must be greater than or equal to %i.", maps[map_section_num].max_zoom, 0); + exit(7); + } else if (maps[map_section_num].max_zoom > MAX_ZOOM) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified max zoom (%i) is too large, must be less than or equal to %i.", maps[map_section_num].max_zoom, MAX_ZOOM); + exit(7); + } + + process_config_int(ini, section, "minzoom", &maps[map_section_num].min_zoom, 0); + + if (maps[map_section_num].min_zoom < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is too small, must be greater than or equal to %i.", maps[map_section_num].min_zoom, 0); + exit(7); + } else if (maps[map_section_num].min_zoom > maps[map_section_num].max_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", maps[map_section_num].min_zoom, maps[map_section_num].max_zoom); + exit(7); + } + + char ini_fileExtension[] = "png"; + char ini_mimeType[] = "image/png"; + char ini_outputFormat[] = "png256"; + char *ini_type; + + process_config_string(ini, section, "type", &ini_type, "png image/png png256", INILINE_MAX - 1); + + sscanf(ini_type, "%[^ ] %[^ ] %[^;#]", ini_fileExtension, ini_mimeType, ini_outputFormat); + copy_string_with_snprintf(ini_outputFormat, &maps[map_section_num].output_format, INILINE_MAX - 1); + free(ini_type); + + /* Pass this information into the rendering threads, + * as it is needed to configure mapniks number of connections + */ + maps[map_section_num].num_threads = config.num_threads; + } + } + + iniparser_freedict(ini); + + if (config.ipport > 0) { + g_logger(log_level, "\trenderd: ip socket = '%s':%i", config.iphostname, config.ipport); + } else { + g_logger(log_level, "\trenderd: unix socketname = '%s'", config.socketname); + } + + g_logger(log_level, "\trenderd: num_threads = '%i'", config.num_threads); + + if (active_slave == 0 && num_slave_threads > 0) { + g_logger(log_level, "\trenderd: num_slave_threads = '%i'", num_slave_threads); + } + + g_logger(log_level, "\trenderd: pid_file = '%s'", config.pid_filename); + + if (strnlen(config.stats_filename, PATH_MAX - 1)) { + g_logger(log_level, "\trenderd: stats_file = '%s'", config.stats_filename); + } + + g_logger(log_level, "\trenderd: tile_dir = '%s'", config.tile_dir); + g_logger(log_level, "\tmapnik: font_dir = '%s'", config.mapnik_font_dir); + g_logger(log_level, "\tmapnik: font_dir_recurse = '%s'", config.mapnik_font_dir_recurse ? "true" : "false"); + g_logger(log_level, "\tmapnik: plugins_dir = '%s'", config.mapnik_plugins_dir); + + for (i = 0; i < XMLCONFIGS_MAX; i++) { + if (maps[i].xmlname != NULL) { + g_logger(log_level, "\tmap %i: name(%s) file(%s) uri(%s) output_format(%s) htcp(%s) host(%s)", i, maps[i].xmlname, maps[i].xmlfile, maps[i].xmluri, maps[i].output_format, maps[i].htcpip, maps[i].host); + } + } + + for (i = 0; i < MAX_SLAVES; i++) { + if (config_slaves[i].num_threads == 0) { + continue; + } + + if (i == active_slave) { + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): Active", i); + } + + if (config_slaves[i].ipport > 0) { + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): ip socket = '%s:%i'", i, config_slaves[i].iphostname, config_slaves[i].ipport); + } else { + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): unix socketname = '%s'", i, config_slaves[i].socketname); + } + + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): num_threads = '%i'", i, config_slaves[i].num_threads); + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): pid_file = '%s'", i, config_slaves[i].pid_filename); + + if (strnlen(config_slaves[i].stats_filename, PATH_MAX - 1)) { + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): stats_file = '%s'", i, config_slaves[i].stats_filename); + } + + g_logger(G_LOG_LEVEL_DEBUG, "\trenderd(%i): tile_dir = '%s'", i, config_slaves[i].tile_dir); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 84f25a72..61ebf151 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -644,12 +644,12 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) add_test( NAME renderd_num_threads_${STORAGE_BACKEND} COMMAND ${BASH} -c " - if ! ${GREP_EXECUTABLE} -q \"config renderd: num_threads=${PROCESSOR_COUNT}\" \"${RENDERD0_LOG}\"; then - ${GREP_EXECUTABLE} \"config renderd: num_threads=\" \"${RENDERD0_LOG}\" + if ! ${GREP_EXECUTABLE} -q \"renderd: num_threads = '${PROCESSOR_COUNT}'\" \"${RENDERD0_LOG}\"; then + ${GREP_EXECUTABLE} \"renderd: num_threads = \" \"${RENDERD0_LOG}\" exit 1; fi - if ! ${GREP_EXECUTABLE} -q \"config renderd: num_slave_threads=${CTEST_NUM_SLAVE_THREADS}\" \"${RENDERD0_LOG}\"; then - ${GREP_EXECUTABLE} \"config renderd: num_slave_threads=\" \"${RENDERD0_LOG}\" + if ! ${GREP_EXECUTABLE} -q \"renderd: num_slave_threads = '${CTEST_NUM_SLAVE_THREADS}'\" \"${RENDERD0_LOG}\"; then + ${GREP_EXECUTABLE} \"renderd: num_slave_threads = \" \"${RENDERD0_LOG}\" exit 1; fi " @@ -692,7 +692,7 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) if(STORAGE_BACKEND STREQUAL file) set(TILE_FILE_NAME "tile.parameterization.${STORAGE_BACKEND}") - set(TILE_URL_PATH "/tiles/${DEFAULT_MAP_NAME}/en,de,_/${TILE_ZXY}.png") + set(TILE_URL_PATH "/tiles/parameterization/en,de,_/${TILE_ZXY}.png") set(HTTPD0_URL "http://${HTTPD0_HOST}:${HTTPD0_PORT}${TILE_URL_PATH}") add_good_tile_download_test( parameterization_${STORAGE_BACKEND}_0 @@ -765,7 +765,7 @@ foreach(DIRECTIVE_INDEX RANGE ${DIRECTIVES_LENGTH}) # Get DIRECTIVE_ERROR from DIRECTIVE_ERRORS list list(GET DIRECTIVE_ERRORS ${DIRECTIVE_INDEX} DIRECTIVE_ERROR) - # Generate httpd.conf filelogs + # Generate httpd.conf file configure_file( httpd.conf.in ${HTTPD_CONF} @@ -774,7 +774,6 @@ foreach(DIRECTIVE_INDEX RANGE ${DIRECTIVES_LENGTH}) add_test( NAME bad_httpd_config_${DIRECTIVE_INDEX} COMMAND ${BASH} -c " - echo \"${DIRECTIVE}\" >> ${HTTPD_CONF} HTTPD_OUTPUT=$(${HTTPD_EXECUTABLE} -e debug -f ${HTTPD_CONF} -t 2>&1) if [ \"\${?}\" -eq \"0\" ]; then echo \"Unexpected success.\" diff --git a/tests/gen_tile_test.cpp b/tests/gen_tile_test.cpp index 04a3719f..7f8653f4 100644 --- a/tests/gen_tile_test.cpp +++ b/tests/gen_tile_test.cpp @@ -18,37 +18,42 @@ // https://github.com/catchorg/Catch2/blob/v2.13.9/docs/own-main.md#let-catch2-take-full-control-of-args-and-config #define CATCH_CONFIG_RUNNER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "catch/catch.hpp" #include "config.h" #include "g_logger.h" #include "gen_tile.h" #include "metatile.h" +#include "protocol.h" #include "protocol_helper.h" #include "render_config.h" #include "renderd.h" #include "request_queue.h" #include "store.h" #include "string.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #ifdef __MACH__ #include #include #endif #ifdef __FreeBSD__ -#include #include #endif @@ -966,7 +971,7 @@ TEST_CASE("renderd", "tile generation") REQUIRE((std::string)req->xmlname == expected_xmlname); REQUIRE(ret == cmdNotDone); - found = err_log_lines.find("Ignoring unknown command unknown fd(" + std::to_string(pipefd[1])); + found = err_log_lines.find("Ignoring invalid command Unknown fd(" + std::to_string(pipefd[1])); REQUIRE(found > -1); // Valid command @@ -977,7 +982,7 @@ TEST_CASE("renderd", "tile generation") std::tie(err_log_lines, out_log_lines) = end_capture(); REQUIRE(ret == cmdNotDone); - found = err_log_lines.find("Ignoring unknown command NotDone fd(" + std::to_string(pipefd[1])); + found = err_log_lines.find("Ignoring invalid command NotDone fd(" + std::to_string(pipefd[1])); REQUIRE(found > -1); free(req); @@ -1039,6 +1044,46 @@ TEST_CASE("renderd", "tile generation") ret = WEXITSTATUS(ret); REQUIRE(ret == 1); } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = "./renderd " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--slave is not a number", "should return 1") { + std::string option = "--slave abcdefg"; + std::string command = "./renderd " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--slave is a float", "should return 1") { + std::string option = "--slave 1.23456789"; + std::string command = "./renderd " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--slave subceeds minimum of 0", "should return 1") { + std::string option = "--slave -1"; + std::string command = "./renderd " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } } TEST_CASE("storage-backend", "Tile storage backend router") diff --git a/tests/httpd.conf.in b/tests/httpd.conf.in index 5fe49179..f65dffc0 100644 --- a/tests/httpd.conf.in +++ b/tests/httpd.conf.in @@ -16,7 +16,7 @@ Redirect /renderd-example-map/leaflet/leaflet.min.js https://unpkg.com/leaflet/d AddTileConfig /add_tile_config_sock/ add_tile_config_sock extension=jpg maxzoom=15 mimetype=image/jpeg minzoom=10 tile_dir=@TILE_DIR@ - AddTileConfig /download_add_tile_config/ @DEFAULT_MAP_NAME@ extension=png maxzoom=20 mimetype=image/png minzoom=0 tile_dir=@TILE_DIR@ + AddTileConfig /download_add_tile_config/ @DEFAULT_MAP_NAME@_htcp extension=png maxzoom=20 mimetype=image/png minzoom=0 tile_dir=@TILE_DIR@ AddTileMimeConfig /add_tile_mime_config_js_sock/ add_tile_mime_config_js_sock js AddTileMimeConfig /add_tile_mime_config_png_sock/ add_tile_mime_config_png_sock png LoadTileConfigFile @RENDERD_CONF@ @@ -44,7 +44,7 @@ Redirect /renderd-example-map/leaflet/leaflet.min.js https://unpkg.com/leaflet/d AddTileConfig /add_tile_config_tcp/ add_tile_config_tcp extension=jpg maxzoom=15 mimetype=image/jpeg minzoom=10 tile_dir=@TILE_DIR@ - AddTileConfig /download_add_tile_config/ @DEFAULT_MAP_NAME@ extension=png maxzoom=20 mimetype=image/png minzoom=0 tile_dir=@TILE_DIR@ + AddTileConfig /download_add_tile_config/ @DEFAULT_MAP_NAME@_htcp extension=png maxzoom=20 mimetype=image/png minzoom=0 tile_dir=@TILE_DIR@ AddTileMimeConfig /add_tile_mime_config_js_tcp/ add_tile_mime_config_js_tcp js AddTileMimeConfig /add_tile_mime_config_png_tcp/ add_tile_mime_config_png_tcp png LoadTileConfigFile @RENDERD_CONF@ @@ -113,3 +113,5 @@ User @WWW_USER_NAME@ LoadModule unixd_module @HTTPD_LIBEXECDIR@/mod_unixd.so + +@DIRECTIVE@ diff --git a/tests/renderd.conf.in b/tests/renderd.conf.in index 45687d47..5531b676 100644 --- a/tests/renderd.conf.in +++ b/tests/renderd.conf.in @@ -8,11 +8,31 @@ plugins_dir=@MAPNIK_PLUGINS_DIR@ [@DEFAULT_MAP_NAME@] ATTRIBUTION=Attribution for @DEFAULT_MAP_NAME@ DESCRIPTION=Description for @DEFAULT_MAP_NAME@ +MAXZOOM=5 +MINZOOM=0 +TILEDIR=@TILE_DIR@ +URI=/tiles/@DEFAULT_MAP_NAME@/ +XML=@PROJECT_SOURCE_DIR@/utils/example-map/mapnik.xml + +[@DEFAULT_MAP_NAME@_htcp] +ASPECTX=1 +ASPECTY=1 +CORS=* HOST=@HTTPD0_HOST@ HTCPHOST=@HTTPD1_HOST@ +MAXZOOM=20 +MINZOOM=0 +SCALE=1.0 +SERVER_ALIAS=http://localhost/ +TILEDIR=@TILE_DIR@ +TILESIZE=256 +URI=/tiles/htcp/ +XML=@PROJECT_SOURCE_DIR@/utils/example-map/mapnik.xml + +[@DEFAULT_MAP_NAME@_parameterization] PARAMETERIZE_STYLE=language TILEDIR=@TILE_DIR@ -URI=/tiles/@DEFAULT_MAP_NAME@/ +URI=/tiles/parameterization/ XML=@PROJECT_SOURCE_DIR@/utils/example-map/mapnik.xml [jpg] @@ -47,7 +67,7 @@ pid_file=@RENDERD1_PID@ stats_file=@TEST_RUN_DIR@/renderd1_@STORAGE_BACKEND@.stats tile_dir=@TILE_DIR@ -[renderd0] +[renderd] num_threads=-1 pid_file=@RENDERD0_PID@ socketname=@RENDERD0_SOCKET@