[mod_tile] support storage of gzip compressed content in metatiles

In some cases (e.g. geojson vector tiles) storing the content of metatiles in compressed form can be benefitial.
In this case, make sure that the Content-Encoding header is set to gzip, so that clients can correctly
decode the data.

Wether data in a metatile is stored in compressed form or not is defined by the first 4 magic bytes, which are either
META for uncompressed data or METZ for compressed date.

Currently mod_tile does not yet support decompressing the data it self. So if a client doesn't send the
Accept-Encoding: gzip header, they will get jumbled (still compressed) content back.
This commit is contained in:
Kai Krueger
2012-11-06 19:10:25 +00:00
parent 777720c2b4
commit 595ffc9e27
3 changed files with 29 additions and 11 deletions

View File

@ -929,6 +929,7 @@ static int tile_handler_serve(request_rec *r)
unsigned char err_msg[4096];
unsigned char *buf;
int len;
int compressed;
apr_status_t errstatus;
ap_conf_vector_t *sconf = r->server->module_config;
@ -961,8 +962,19 @@ static int tile_handler_serve(request_rec *r)
}
err_msg[0] = 0;
len = tile_read(scfg->tile_dir, cmd->xmlname, cmd->x, cmd->y, cmd->z, buf, tile_max, err_msg);
len = tile_read(scfg->tile_dir, cmd->xmlname, cmd->x, cmd->y, cmd->z, buf, tile_max, &compressed, err_msg);
if (len > 0) {
if (compressed) {
const char* accept_encoding = apr_table_get(r->headers_in,"Accept-Encoding");
if (accept_encoding && strstr(accept_encoding,"gzip")) {
r->content_encoding = "gzip";
} else {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"Tile data is compressed, but user agent doesn't support Content-Encoding and we don't know how to decompress it server side");
//TODO: decompress the output stream before sending it to client
}
}
#if 0
// Set default Last-Modified and Etag headers
ap_update_mtime(r, r->finfo.mtime);

21
store.c
View File

@ -24,7 +24,7 @@
#include "protocol.h"
#ifdef METATILE
int read_from_meta(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, size_t sz, unsigned char * log_msg)
int read_from_meta(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, size_t sz, int * compressed, unsigned char * log_msg)
{
char path[PATH_MAX];
int meta_offset, fd;
@ -61,10 +61,14 @@ int read_from_meta(const char *tilepath, const char *xmlconfig, int x, int y, in
return -3;
}
if (memcmp(m->magic, META_MAGIC, strlen(META_MAGIC))) {
snprintf(log_msg,1024, "Meta file %s header magic mismatch\n", path);
close(fd);
return -4;
}
if (memcmp(m->magic, META_MAGIC_COMPRESSED, strlen(META_MAGIC_COMPRESSED))) {
snprintf(log_msg,1024, "Meta file %s header magic mismatch\n", path);
close(fd);
return -4;
} else {
*compressed = 1;
}
} else *compressed = 0;
#if 1
// Currently this code only works with fixed metatile sizes (due to xyz_to_meta above)
if (m->count != (METATILE * METATILE)) {
@ -142,12 +146,12 @@ int read_from_file(const char *tilepath, const char *xmlconfig, int x, int y, in
return pos;
}
int tile_read(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, int sz, unsigned char *err_msg)
int tile_read(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, int sz, int * compressed, unsigned char *err_msg)
{
#ifdef METATILE
int r;
r = read_from_meta(tilepath, xmlconfig, x, y, z, buf, sz, err_msg);
r = read_from_meta(tilepath, xmlconfig, x, y, z, buf, sz, compressed, err_msg);
if (r >= 0)
return r;
#endif
@ -320,6 +324,7 @@ void process_unpack(const char *tilepath, const char *name)
const int buf_len = 1024 * 1024;
unsigned char *buf;
struct stat s;
int compressed;
// path_to_xyz is valid for meta tile names as well
if (path_to_xyz(tilepath, name, xmlconfig, &x, &y, &z))
@ -336,7 +341,7 @@ void process_unpack(const char *tilepath, const char *name)
for (ox=0; ox < limit; ox++) {
for (oy=0; oy < limit; oy++) {
err_msg[0] = 0;
int len = read_from_meta(tilepath, xmlconfig, x + ox, y + oy, z, buf, buf_len, err_msg);
int len = read_from_meta(tilepath, xmlconfig, x + ox, y + oy, z, buf, buf_len, &compressed, err_msg);
if (len <= 0)
fprintf(stderr, "Failed to get tile x(%d) y(%d) z(%d)\n %s", x + ox, y + oy, z, err_msg);

View File

@ -7,9 +7,10 @@ extern "C" {
#include <stdlib.h>
#include "render_config.h"
int tile_read(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, int sz, unsigned char * err_msg);
int tile_read(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, int sz, int * compressed, unsigned char * err_msg);
#define META_MAGIC "META"
#define META_MAGIC_COMPRESSED "METZ"
//static const char meta_magic[4] = { 'M', 'E', 'T', 'A' };
struct entry {
@ -30,7 +31,7 @@ struct meta_layout {
int read_from_file(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, size_t sz);
#ifdef METATILE
int read_from_meta(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, size_t sz, unsigned char * log_msg);
int read_from_meta(const char *tilepath, const char *xmlconfig, int x, int y, int z, unsigned char *buf, size_t sz, int * compressed, unsigned char * log_msg);
void process_meta(const char *tilepath, const char *xmlconfig, int x, int y, int z);
void process_pack(const char *tilepath, const char *name);
void process_unpack(const char *tilepath, const char *name);