Write GeoJSON to the filter and read (but don't parse) what comes back

This commit is contained in:
Eric Fischer 2016-12-01 12:04:49 -08:00
parent adfceed554
commit 94bebbd276
4 changed files with 134 additions and 1 deletions

View File

@ -50,7 +50,7 @@ tippecanoe-enumerate: enumerate.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3
tippecanoe-decode: decode.o projection.o mvt.o plugin.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tile-join: tile-join.o projection.o pool.o mbtiles.o mvt.o memfile.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread

View File

@ -3,11 +3,142 @@
#include <vector>
#include <string>
#include <map>
#include <pthread.h>
#include <unistd.h>
#include "mvt.hpp"
#include "plugin.hpp"
#include "projection.hpp"
#include "geometry.hpp"
struct writer_arg {
int *pipe_orig;
mvt_layer *layer;
unsigned z;
unsigned x;
unsigned y;
};
void *run_writer(void *a) {
writer_arg *wa = (writer_arg *) a;
// XXX worry about SIGPIPE?
FILE *fp = fdopen(wa->pipe_orig[1], "w");
if (fp == NULL) {
perror("fdopen (pipe writer)");
exit(EXIT_FAILURE);
}
layer_to_geojson(fp, *(wa->layer), wa->z, wa->x, wa->y);
if (fclose(fp) != 0) {
perror("fclose output to filter");
exit(EXIT_FAILURE);
}
return NULL;
}
mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y) {
// This will create two pipes, a new thread, and a new process.
//
// The new process will read from one pipe and write to the other, and execute the filter.
// The new thread will write the GeoJSON to the pipe that leads to the filter.
// The original thread will read the GeoJSON from the filter and convert it back into vector tiles.
int pipe_orig[2], pipe_filtered[2];
if (pipe(pipe_orig) < 0) {
perror("pipe (original features)");
exit(EXIT_FAILURE);
}
if (pipe(pipe_filtered) < 0) {
perror("pipe (filtered features)");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// child
if (dup2(pipe_orig[0], 0) < 0) {
perror("dup child stdin");
exit(EXIT_FAILURE);
}
if (dup2(pipe_filtered[1], 1) < 0) {
perror("dup child stdout");
exit(EXIT_FAILURE);
}
if (close(pipe_orig[1]) != 0) {
perror("close output to filter");
exit(EXIT_FAILURE);
}
if (close(pipe_filtered[0]) != 0) {
perror("close input from filter");
exit(EXIT_FAILURE);
}
// XXX close other fds?
// XXX add zyx args
if (execlp("sh", "sh", "-c", filter, NULL) != 0) {
perror("exec");
exit(EXIT_FAILURE);
}
} else {
// parent
if (close(pipe_orig[0]) != 0) {
perror("close filter-side reader");
exit(EXIT_FAILURE);
}
if (close(pipe_filtered[1]) != 0) {
perror("close filter-side writer");
exit(EXIT_FAILURE);
}
writer_arg wa;
wa.pipe_orig = pipe_orig;
wa.layer = &layer;
wa.z = z;
wa.x = x;
wa.y = y;
pthread_t writer;
if (pthread_create(&writer, NULL, run_writer, &wa) != 0) {
perror("pthread_create (filter writer)");
exit(EXIT_FAILURE);
}
char buf[200];
size_t count;
while ((count = read(pipe_filtered[0], buf, 200)) != 0) {
write(1, buf, count);
}
int stat_loc;
if (waitpid(pid, &stat_loc, 0) < 0) {
perror("waitpid for filter\n");
exit(EXIT_FAILURE);
}
if (close(pipe_filtered[0]) != 0) {
perror("close output from filter");
exit(EXIT_FAILURE);
}
void *ret;
if (pthread_join(writer, &ret) != 0) {
perror("pthread_join filter writer");
exit(EXIT_FAILURE);
}
}
return layer;
}
struct lonlat {
int op;
double lon;

View File

@ -1,2 +1,3 @@
void layer_to_geojson(FILE *fp, mvt_layer &layer, unsigned z, unsigned x, unsigned y);
mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y);
void fprintq(FILE *f, const char *s);

View File

@ -29,6 +29,7 @@
#include "serial.hpp"
#include "options.hpp"
#include "main.hpp"
#include "plugin.hpp"
#define CMD_BITS 3