Skip to content

Commit

Permalink
Implemented a "exit please" command
Browse files Browse the repository at this point in the history
`render_list -S/--stop` will ask renderd to stop all processing and exit.
  • Loading branch information
rolandbosa authored and hummeltech committed Jun 29, 2024
1 parent 6379979 commit 16a95e0
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 81 deletions.
31 changes: 31 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/build/src/renderd",
"args": [
"-f",
"-c",
"/etc/renderd.conf"
],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
3 changes: 2 additions & 1 deletion includes/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ enum protoCmd { cmdIgnore,
cmdNotDone,
cmdRenderPrio,
cmdRenderBulk,
cmdRenderLow
cmdRenderLow,
cmdStop
};

struct protocol {
Expand Down
1 change: 1 addition & 0 deletions includes/render_submit_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
extern "C" {
#endif

int make_connection(const char *spath);
void enqueue(const char *xmlname, int x, int y, int z);
void spawn_workers(int num, const char *socketpath, int maxLoad);
void wait_for_empty_queue(void);
Expand Down
1 change: 1 addition & 0 deletions includes/renderd.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef struct {
} xmlconfigitem;

extern struct request_queue *render_request_queue;
extern int renderd_exit_requested;

void statsRenderFinish(int z, long time);
void request_exit(void);
Expand Down
2 changes: 2 additions & 0 deletions includes/request_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ struct request_queue {
pthread_mutex_t qLock;
pthread_cond_t qCond;
stats_struct stats;
int isClosing;
};

struct request_queue *request_queue_init();
void request_queue_close(struct request_queue *queue);
void request_queue_destroy(struct request_queue **queue);

struct item *request_queue_fetch_request(struct request_queue *queue);
enum protoCmd request_queue_add_request(struct request_queue *queue, struct item *request);
Expand Down
22 changes: 14 additions & 8 deletions measure_rss_anon.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ function runtest() {
done
printf '{"t": %d, "tag": "%s", "rss": %d }];\n' $SECONDS $1 $RSS >>$JSON

echo "Measurement completed. Results are here: $JSON"
kill $(pidof renderd)
echo "Measurement completed. Results are here: $JSON. PID of renderd is: `pidof renderd`"
./$BUILD/src/render_list -c /etc/renderd.conf -S
#kill $(pidof renderd)
}

runtest glib
sleep 10
runtest jemalloc
sleep 10
runtest tcmalloc
function compare_malloc() {
runtest glib
sleep 10
runtest jemalloc
sleep 10
runtest tcmalloc
echo "Comparison completed."
}

echo "All done."
# compare_malloc

runtest jemalloc
140 changes: 80 additions & 60 deletions src/gen_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,99 +420,119 @@ void *render_thread(void *arg)
}
}

while (1) {
struct item *item;
g_logger(G_LOG_LEVEL_DEBUG, "Render thread waiting for work...");
while ((item = request_queue_fetch_request(render_request_queue)) != NULL) {
g_logger(G_LOG_LEVEL_DEBUG, "Render thread received work: %p", item);

enum protoCmd ret;
struct item *item = request_queue_fetch_request(render_request_queue);
render_time = -1;

if (item) {
struct protocol *req = &item->req;
struct protocol *req = &item->req;
#ifdef METATILE
// At very low zoom the whole world may be smaller than METATILE
unsigned int size = MIN(METATILE, 1 << req->z);
// At very low zoom the whole world may be smaller than METATILE
unsigned int size = MIN(METATILE, 1 << req->z);

for (i = 0; i < iMaxConfigs; ++i) {
if (!strcmp(maps[i].xmlname, req->xmlname)) {
if (maps[i].ok) {
if (check_xyz(item->mx, item->my, req->z, &(maps[i]))) {
for (i = 0; i < iMaxConfigs; ++i) {
if (!strcmp(maps[i].xmlname, req->xmlname)) {
if (maps[i].ok) {
if (check_xyz(item->mx, item->my, req->z, &(maps[i]))) {

metaTile tiles(req->xmlname, req->options, item->mx, item->my, req->z);
metaTile tiles(req->xmlname, req->options, item->mx, item->my, req->z);

timeval tim;
gettimeofday(&tim, NULL);
long t1 = tim.tv_sec * 1000 + (tim.tv_usec / 1000);
timeval tim;
gettimeofday(&tim, NULL);
long t1 = tim.tv_sec * 1000 + (tim.tv_usec / 1000);

struct stat_info sinfo = maps[i].store->tile_stat(maps[i].store, req->xmlname, req->options, item->mx, item->my, req->z);
struct stat_info sinfo = maps[i].store->tile_stat(maps[i].store, req->xmlname, req->options, item->mx, item->my, req->z);

if (sinfo.size > 0)
g_logger(G_LOG_LEVEL_DEBUG, "START TILE %s %d %d-%d %d-%d, age %.2f days",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1,
(tim.tv_sec - sinfo.mtime) / 86400.0);
else
g_logger(G_LOG_LEVEL_DEBUG, "START TILE %s %d %d-%d %d-%d, new metatile",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1);
if (sinfo.size > 0)
g_logger(G_LOG_LEVEL_DEBUG, "START TILE %s %d %d-%d %d-%d, age %.2f days",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1,
(tim.tv_sec - sinfo.mtime) / 86400.0);
else
g_logger(G_LOG_LEVEL_DEBUG, "START TILE %s %d %d-%d %d-%d, new metatile",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1);

ret = render(&(maps[i]), item->mx, item->my, req->z, req->options, tiles);
ret = render(&(maps[i]), item->mx, item->my, req->z, req->options, tiles);

gettimeofday(&tim, NULL);
long t2 = tim.tv_sec * 1000 + (tim.tv_usec / 1000);
gettimeofday(&tim, NULL);
long t2 = tim.tv_sec * 1000 + (tim.tv_usec / 1000);

g_logger(G_LOG_LEVEL_DEBUG, "DONE TILE %s %d %d-%d %d-%d in %.3lf seconds",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1, (t2 - t1) / 1000.0);
g_logger(G_LOG_LEVEL_DEBUG, "DONE TILE %s %d %d-%d %d-%d in %.3lf seconds",
req->xmlname, req->z, item->mx, item->mx + size - 1, item->my, item->my + size - 1, (t2 - t1) / 1000.0);

render_time = t2 - t1;
render_time = t2 - t1;

if (ret == cmdDone) {
try {
tiles.save(maps[i].store);
if (ret == cmdDone) {
try {
tiles.save(maps[i].store);
#ifdef HTCP_EXPIRE_CACHE
tiles.expire_tiles(maps[i].htcpsock, maps[i].host, maps[i].xmluri);
tiles.expire_tiles(maps[i].htcpsock, maps[i].host, maps[i].xmluri);
#endif // HTCP_EXPIRE_CACHE

} catch (std::exception const &ex) {
g_logger(G_LOG_LEVEL_ERROR, "Received exception when writing metatile to disk: %s", ex.what());
ret = cmdNotDone;
} catch (...) {
// Treat any error as fatal and request end of processing
g_logger(G_LOG_LEVEL_CRITICAL, "Failed writing metatile to disk with unknown error, requesting exit.");
ret = cmdNotDone;
request_exit();
}
} catch (std::exception const &ex) {
g_logger(G_LOG_LEVEL_ERROR, "Received exception when writing metatile to disk: %s", ex.what());
ret = cmdNotDone;
} catch (...) {
// Treat any error as fatal and request end of processing
g_logger(G_LOG_LEVEL_CRITICAL, "Failed writing metatile to disk with unknown error, requesting exit.");
ret = cmdNotDone;
request_exit();
}
}

#else // METATILE
ret = render(maps[i].map, maps[i].tile_dir, req->xmlname, maps[i].prj, req->x, req->y, req->z, maps[i].output_format);
ret = render(maps[i].map, maps[i].tile_dir, req->xmlname, maps[i].prj, req->x, req->y, req->z, maps[i].output_format);
#ifdef HTCP_EXPIRE_CACHE
cache_expire(maps[i].htcpsock, maps[i].host, maps[i].xmluri, req->x, req->y, req->z);
cache_expire(maps[i].htcpsock, maps[i].host, maps[i].xmluri, req->x, req->y, req->z);
#endif // HTCP_EXPIRE_CACHE
#endif // METATILE
} else {
g_logger(G_LOG_LEVEL_WARNING, "Received request for map layer %s is outside of acceptable bounds z(%i), x(%i), y(%i)",
req->xmlname, req->z, req->x, req->y);
ret = cmdIgnore;
}
} else {
g_logger(G_LOG_LEVEL_ERROR, "Received request for map layer '%s' which failed to load", req->xmlname);
ret = cmdNotDone;
g_logger(G_LOG_LEVEL_WARNING, "Received request for map layer %s is outside of acceptable bounds z(%i), x(%i), y(%i)",
req->xmlname, req->z, req->x, req->y);
ret = cmdIgnore;
}
} else {
g_logger(G_LOG_LEVEL_ERROR, "Received request for map layer '%s' which failed to load", req->xmlname);
ret = cmdNotDone;
}

send_response(item, ret, render_time);

if ((ret != cmdDone) && (ret != cmdIgnore)) {
sleep(10); // Something went wrong with rendering, delay next processing to allow temporary issues to fix them selves
}
send_response(item, ret, render_time);

break;
if ((ret != cmdDone) && (ret != cmdIgnore)) {
sleep(10); // Something went wrong with rendering, delay next processing to allow temporary issues to fix them selves
}

break;
}
}

if (i == iMaxConfigs) {
g_logger(G_LOG_LEVEL_ERROR, "No map for: %s", req->xmlname);
}
}

if (i == iMaxConfigs) {
g_logger(G_LOG_LEVEL_ERROR, "No map for: %s", req->xmlname);
g_logger(G_LOG_LEVEL_DEBUG, "Render thread is cleaning up...");
for (iMaxConfigs = 0; iMaxConfigs < XMLCONFIGS_MAX; ++iMaxConfigs) {
if (maps[iMaxConfigs].ok) {
free((void *) maps[iMaxConfigs].output_format);
if (maps[iMaxConfigs].store != NULL) {
maps[iMaxConfigs].store->close_storage(maps[iMaxConfigs].store);
free(maps[iMaxConfigs].store);
maps[iMaxConfigs].store = NULL;
}
} else {
sleep(1); // TODO: Use an event to indicate there are new requests
free((void *) maps[iMaxConfigs].xmlfile);
free((void *) maps[iMaxConfigs].xmlname);
#ifdef HTCP_EXPIRE_CACHE
free((void *) maps[iMaxConfigs].host);
free((void *) maps[iMaxConfigs].htcphost);
free((void *) maps[iMaxConfigs].xmluri);
close(maps[iMaxConfigs].htcpsock);
#endif
}
}

g_logger(G_LOG_LEVEL_DEBUG, "Render thread exiting.");
return NULL;
}
43 changes: 42 additions & 1 deletion src/render_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "config.h"
#include "g_logger.h"
#include "protocol.h"
#include "protocol_helper.h"
#include "render_config.h"
#include "render_submit_queue.h"
#include "renderd_config.h"
Expand Down Expand Up @@ -126,6 +127,7 @@ int main(int argc, char **argv)
int all = 0;
int force = 0;
int verbose = 0;
int stop_renderd = 0;
struct storage_backend *store;
struct stat_info s;

Expand Down Expand Up @@ -153,13 +155,14 @@ int main(int argc, char **argv)
{"socket", required_argument, 0, 's'},
{"tile-dir", required_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
{"stop", no_argument, 0, 'S'},

{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};

int c = getopt_long(argc, argv, "ac:fm:G:l:W:X:Y:Z:g:w:x:y:z:n:s:t:vhV", long_options, &option_index);
int c = getopt_long(argc, argv, "ac:fm:G:l:W:X:Y:Z:g:w:x:y:z:n:s:t:vShV", long_options, &option_index);

if (c == -1) {
break;
Expand Down Expand Up @@ -266,6 +269,10 @@ int main(int argc, char **argv)
verbose = 1;
break;

case 'S': /* -S, --stop */
stop_renderd = 1;
break;

case 'h': /* -h, --help */
fprintf(stderr, "Usage: render_list [OPTION] ...\n");
fprintf(stderr, " -a, --all render all tiles in given zoom level range instead of reading from STDIN\n");
Expand All @@ -280,6 +287,8 @@ int main(int argc, char **argv)
fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater than or equal to this zoom level (default is '%d')\n", min_zoom_default);
fprintf(stderr, "\n");
fprintf(stderr, " -h, --help display this help and exit\n");
fprintf(stderr, " -v, --verbose turn on verbose output\n");
fprintf(stderr, " -S, --stop request renderd to stop and exit");
fprintf(stderr, " -V, --version display the version number and exit\n");
fprintf(stderr, "\n");
fprintf(stderr, "If you are using --all, you can restrict the tile range by adding these options:\n");
Expand Down Expand Up @@ -420,6 +429,38 @@ int main(int argc, char **argv)
}
}

if (stop_renderd != 0) {
g_logger(G_LOG_LEVEL_INFO, "Sending STOP comand to renderd");
int fd = make_connection(socketname);

if (fd < 0) {
g_logger(G_LOG_LEVEL_ERROR, "connect failed for: %s", socketname);
return 1;
}

struct protocol cmd;
bzero(&cmd, sizeof(cmd));
cmd.ver = 1;
cmd.cmd = cmdStop;
if (send_cmd(&cmd, fd) < 1) {
g_logger(G_LOG_LEVEL_ERROR, "send error: %s", strerror(errno));
}

struct protocol rsp;
bzero(&rsp, sizeof(rsp));

g_logger(G_LOG_LEVEL_DEBUG, "Waiting for response");

int ret = recv_cmd(&rsp, fd, 1);

if (ret < 1) {
return 0;
}

g_logger(G_LOG_LEVEL_DEBUG, "Got response %i", rsp.cmd);
return 0;
}

store = init_storage_backend(tile_dir);

if (store == NULL) {
Expand Down
Loading

0 comments on commit 16a95e0

Please sign in to comment.