source: subversion/applications/utils/mod_tile/render_list.c @ 15889

Last change on this file since 15889 was 15867, checked in by jochen, 11 years ago

off-by-one bug fixed for render_list -a

File size: 11.0 KB
Line 
1#define _GNU_SOURCE
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <sys/stat.h>
9#include <sys/time.h>
10#include <sys/un.h>
11#include <poll.h>
12#include <errno.h>
13#include <math.h>
14#include <getopt.h>
15#include <time.h>
16#include <limits.h>
17#include <string.h>
18
19#include "gen_tile.h"
20#include "protocol.h"
21#include "render_config.h"
22#include "dir_utils.h"
23
24#ifndef METATILE
25#warning("render_list not implemented for non-metatile mode. Feel free to submit fix")
26int main(int argc, char **argv)
27{
28    fprintf(stderr, "render_list not implemented for non-metatile mode. Feel free to submit fix!\n");
29    return -1;
30}
31#else
32
33static int minZoom = 0;
34static int maxZoom = 18;
35static int verbose = 0;
36
37void display_rate(struct timeval start, struct timeval end, int num) 
38{
39    int d_s, d_us;
40    float sec;
41
42    d_s  = end.tv_sec  - start.tv_sec;
43    d_us = end.tv_usec - start.tv_usec;
44
45    sec = d_s + d_us / 1000000.0;
46
47    printf("Rendered %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec);
48    fflush(NULL);
49}
50
51static time_t getPlanetTime(char *tile_dir)
52{
53    static time_t last_check;
54    static time_t planet_timestamp;
55    time_t now = time(NULL);
56    struct stat buf;
57    char filename[PATH_MAX];
58
59    snprintf(filename, PATH_MAX-1, "%s/%s", tile_dir, PLANET_TIMESTAMP);
60
61    // Only check for updates periodically
62    if (now < last_check + 300)
63        return planet_timestamp;
64
65    last_check = now;
66    if (stat(filename, &buf)) {
67        fprintf(stderr, "Planet timestamp file (%s) is missing\n", filename);
68        // Make something up
69        planet_timestamp = now - 3 * 24 * 60 * 60;
70    } else {
71        if (buf.st_mtime != planet_timestamp) {
72            fprintf(stderr, "Planet file updated at %s", ctime(&buf.st_mtime));
73            planet_timestamp = buf.st_mtime;
74        }
75    }
76    return planet_timestamp;
77}
78
79int process_loop(int fd, const char *mapname, int x, int y, int z)
80{
81    struct protocol cmd, rsp;
82    //struct pollfd fds[1];
83    int ret = 0;
84
85    bzero(&cmd, sizeof(cmd));
86
87    cmd.ver = 2;
88    cmd.cmd = cmdRender;
89    cmd.z = z;
90    cmd.x = x;
91    cmd.y = y;
92    strcpy(cmd.xmlname, mapname);
93
94    //strcpy(cmd.path, "/tmp/foo.png");
95
96        //printf("Sending request\n");
97    ret = send(fd, &cmd, sizeof(cmd), 0);
98    if (ret != sizeof(cmd)) {
99        perror("send error");
100    }
101        //printf("Waiting for response\n");
102    bzero(&rsp, sizeof(rsp));
103    ret = recv(fd, &rsp, sizeof(rsp), 0);
104    if (ret != sizeof(rsp)) {
105        perror("recv error");
106        return 0;
107    }
108        //printf("Got response\n");
109
110    if (!ret)
111        perror("Socket send error");
112    return ret;
113}
114
115
116int main(int argc, char **argv)
117{
118    char *spath = RENDER_SOCKET;
119    char *mapname = "default";
120    char *tile_dir = HASH_PATH;
121    int fd;
122    struct sockaddr_un addr;
123    int ret=0;
124    int minX=-1, maxX=-1, minY=-1, maxY=-1;
125    int x, y, z;
126    char name[PATH_MAX];
127    struct timeval start, end;
128    int num_render = 0, num_all = 0;
129    time_t planetTime;
130    int c;
131    int all=0;
132
133    while (1) {
134        int option_index = 0;
135        static struct option long_options[] = {
136            {"min-zoom", 1, 0, 'z'},
137            {"max-zoom", 1, 0, 'Z'},
138            {"min-x", 1, 0, 'x'},
139            {"max-x", 1, 0, 'X'},
140            {"min-y", 1, 0, 'y'},
141            {"max-y", 1, 0, 'Y'},
142            {"socket", 1, 0, 's'},
143            {"tile-dir", 1, 0, 't'},
144            {"map", 1, 0, 'm'},
145            {"verbose", 0, 0, 'v'},
146            {"all", 0, 0, 'a'},
147            {"help", 0, 0, 'h'},
148            {0, 0, 0, 0}
149        };
150
151        c = getopt_long(argc, argv, "hvaz:Z:x:X:y:Y:s:m:t:", long_options, &option_index);
152        if (c == -1)
153            break;
154
155        switch (c) {
156            case 'a':   /* -a, --all */
157                all=1;
158                break;
159            case 's':   /* -s, --socket */
160                spath = strdup(optarg);
161                break;
162            case 't':   /* -t, --tile-dir */
163                tile_dir=strdup(optarg);
164                break;
165            case 'm':   /* -m, --map */
166                mapname=strdup(optarg);
167                break;
168            case 'x':   /* -x, --min-x */
169                minX=atoi(optarg);
170                break;
171            case 'X':   /* -X, --max-x */
172                maxX=atoi(optarg);
173                break;
174            case 'y':   /* -y, --min-y */
175                minY=atoi(optarg);
176                break;
177            case 'Y':   /* -Y, --max-y */
178                maxY=atoi(optarg);
179                break;
180            case 'z':   /* -z, --min-zoom */
181                minZoom=atoi(optarg);
182                if (minZoom < 0 || minZoom > 18) {
183                    fprintf(stderr, "Invalid minimum zoom selected, must be between 0 and 18\n");
184                    return 1;
185                }
186                break;
187            case 'Z':   /* -Z, --max-zoom */
188                maxZoom=atoi(optarg);
189                if (maxZoom < 0 || maxZoom > 18) {
190                    fprintf(stderr, "Invalid maximum zoom selected, must be between 0 and 18\n");
191                    return 1;
192                }
193                break;
194            case 'v':   /* -v, --verbose */
195                verbose=1;
196                break;
197            case 'h':   /* -h, --help */
198                fprintf(stderr, "Usage: render_list [OPTION] ...\n");
199                fprintf(stderr, "  -a, --all            render all tiles in given zoom level range instead of reading from STDIN\n");
200                fprintf(stderr, "  -m, --map=MAP        render tiles in this map (defaults to 'default')\n");
201                fprintf(stderr, "  -s, --socket=SOCKET  unix domain socket name for contacting renderd\n");
202                fprintf(stderr, "  -t, --tile-dir       tile cache directory (defaults to '" HASH_PATH "')\n");
203                fprintf(stderr, "  -z, --min-zoom=ZOOM  filter input to only render tiles greater or equal to this zoom level (default is 0)\n");
204                fprintf(stderr, "  -Z, --max-zoom=ZOOM  filter input to only render tiles less than or equal to this zoom level (default is 18)\n");
205                fprintf(stderr, "If you are using --all, you can restrict the tile range by adding these options:\n");
206                fprintf(stderr, "  -x, --min-x=X        minimum X tile coordinate\n");
207                fprintf(stderr, "  -X, --max-x=X        maximum X tile coordinate\n");
208                fprintf(stderr, "  -y, --min-y=Y        minimum Y tile coordinate\n");
209                fprintf(stderr, "  -Y, --max-y=Y        maximum Y tile coordinate\n");
210                fprintf(stderr, "Without --all, send a list of tiles to be rendered from STDIN in the format:\n");
211                fprintf(stderr, "  X Y Z\n");
212                fprintf(stderr, "e.g.\n");
213                fprintf(stderr, "  0 0 1\n");
214                fprintf(stderr, "  0 1 1\n");
215                fprintf(stderr, "  1 0 1\n");
216                fprintf(stderr, "  1 1 1\n");
217                fprintf(stderr, "The above would cause all 4 tiles at zoom 1 to be rendered\n");
218                return -1;
219            default:
220                fprintf(stderr, "unhandled char '%c'\n", c);
221                break;
222        }
223    }
224
225    if (maxZoom < minZoom) {
226        fprintf(stderr, "Invalid zoom range, max zoom must be greater or equal to minimum zoom\n");
227        return 1;
228    }
229
230    if (all) {
231        if ((minX != -1 || minY != -1 || maxX != -1 || maxY != -1) && minZoom != maxZoom) {
232            fprintf(stderr, "min-zoom must be equal to max-zoom when using min-x, max-x, min-y, or max-y options\n");
233            return 1;
234        }
235
236        if (minX == -1) { minX = 0; }
237        if (minY == -1) { minY = 0; }
238
239        int lz = (1 << minZoom) - 1;
240
241        if (minZoom == maxZoom) {
242            if (maxX == -1) { maxX = lz; }
243            if (maxY == -1) { maxY = lz; }
244            if (minX > lz || minY > lz || maxX > lz || maxY > lz) {
245                fprintf(stderr, "Invalid range, x and y values must be <= %d (2^zoom-1)\n", lz);
246                return 1;
247            }
248        }
249
250        if (minX < 0 || minY < 0 || maxX < -1 || maxY < -1) {
251            fprintf(stderr, "Invalid range, x and y values must be >= 0\n");
252            return 1;
253        }
254
255    }
256
257    fprintf(stderr, "Rendering client\n");
258
259    planetTime = getPlanetTime(tile_dir);
260
261    fd = socket(PF_UNIX, SOCK_STREAM, 0);
262    if (fd < 0) {
263        fprintf(stderr, "failed to create unix socket\n");
264        exit(2);
265    }
266
267    bzero(&addr, sizeof(addr));
268    addr.sun_family = AF_UNIX;
269    strncpy(addr.sun_path, spath, sizeof(addr.sun_path));
270
271    if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
272        fprintf(stderr, "socket connect failed for: %s\n", spath);
273        close(fd);
274        exit(3);
275    }
276
277    gettimeofday(&start, NULL);
278
279    if (all) {
280        int x, y, z;
281        printf("Rendering all tiles from zoom %d to zoom %d\n", minZoom, maxZoom);
282        for (z=minZoom; z <= maxZoom; z++) {
283            int current_maxX = (maxX == -1) ? (1 << z)-1 : maxX;
284            int current_maxY = (maxY == -1) ? (1 << z)-1 : maxY;
285            printf("Rendering all tiles for zoom %d from (%d, %d) to (%d, %d)\n", z, minX, minY, current_maxX, current_maxY);
286            for (x=minX; x <= current_maxX; x+=METATILE) {
287                for (y=minY; y <= current_maxY; y+=METATILE) {
288                    process_loop(fd, mapname, x, y, z);
289                }
290            }
291        }
292    } else {
293        while(!feof(stdin)) {
294            struct stat s;
295            int n = fscanf(stdin, "%d %d %d", &x, &y, &z);
296
297            if (n != 3) {
298                // Discard input line
299                char tmp[1024];
300                char *r = fgets(tmp, sizeof(tmp), stdin);
301                if (!r)
302                    continue;
303                // fprintf(stderr, "bad line %d: %s", num_all, tmp);
304                continue;
305            }
306
307            if (z < minZoom || z > maxZoom)
308                continue;
309
310            printf("got: x(%d) y(%d) z(%d)\n", x, y, z);
311
312            num_all++;
313            xyz_to_path(name, sizeof(name), tile_dir, XMLCONFIG_DEFAULT, x, y, z);
314
315            if ((stat(name, &s) < 0) || (planetTime > s.st_mtime)) {
316                // missing or old, render it
317                ret = process_loop(fd, mapname, x, y, z);
318                num_render++;
319                if (!(num_render % 10)) {
320                    gettimeofday(&end, NULL);
321                    printf("\n");
322                    printf("Meta tiles rendered: ");
323                    display_rate(start, end, num_render);
324                    printf("Total tiles rendered: ");
325                    display_rate(start, end, num_render * METATILE * METATILE);
326                    printf("Total tiles handled from input: ");
327                    display_rate(start, end, num_all);
328                }
329            }
330        }
331    }
332    gettimeofday(&end, NULL);
333    printf("\nTotal for all tiles rendered\n");
334    printf("Meta tiles rendered: ");
335    display_rate(start, end, num_render);
336    printf("Total tiles rendered: ");
337    display_rate(start, end, num_render * METATILE * METATILE);
338    printf("Total tiles handled: ");
339    display_rate(start, end, num_all);
340
341    close(fd);
342    return ret;
343}
344#endif
Note: See TracBrowser for help on using the repository browser.