static char * ngx_http_mapcache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { mapcache_context *ctx = conf; ngx_str_t *value; value = cf->args->elts; char *conffile = (char*)value[1].data; ctx->config = mapcache_configuration_create(ctx->pool); mapcache_configuration_parse(ctx,conffile,ctx->config,1); if(GC_HAS_ERROR(ctx)) return NGX_CONF_ERROR; mapcache_configuration_post_config(ctx, ctx->config); if(GC_HAS_ERROR(ctx)) return NGX_CONF_ERROR; ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_mapcache_handler; pathinfo_index = ngx_http_get_variable_index(cf, &pathinfo_str); if (pathinfo_index == NGX_ERROR) { return NGX_CONF_ERROR; } urlprefix_index = ngx_http_get_variable_index(cf, &urlprefix_str); if (urlprefix_index == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static const char* mapcache_add_alias(cmd_parms *cmd, void *cfg, const char *alias, const char* configfile) { mapcache_server_cfg *sconfig = ap_get_module_config(cmd->server->module_config, &mapcache_module); mapcache_cfg *config = mapcache_configuration_create(cmd->pool); mapcache_context *ctx = (mapcache_context*)apache_server_context_create(cmd->server,cmd->pool); char *msg = NULL; config->configFile = apr_pstrdup(cmd->pool,configfile); config->endpoint = alias; mapcache_configuration_parse(ctx,configfile,config,0); if(GC_HAS_ERROR(ctx)) { return ctx->get_error_message(ctx); } mapcache_configuration_post_config(ctx, config); if(GC_HAS_ERROR(ctx)) { return ctx->get_error_message(ctx); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, "loaded mapcache configuration file from %s on alias %s", config->configFile, alias); if(!sconfig->aliases) { sconfig->aliases = apr_hash_make(cmd->pool); } apr_hash_set(sconfig->aliases,configfile,APR_HASH_KEY_STRING,config); return msg; }
int main(int argc, const char **argv) { /* initialize apr_getopt_t */ apr_getopt_t *opt; const char *configfile=NULL; #ifndef USE_FORK apr_thread_t **threads; apr_threadattr_t *thread_attrs; #endif const char *tileset_name=NULL; const char *tileset_transfer_name=NULL; const char *grid_name = NULL; int *zooms = NULL;//[2]; double *extent = NULL;//[4]; int optch; int rv,n; const char *old = NULL; const char *optarg; apr_table_t *argdimensions; char *dimkey=NULL, *dimvalue=NULL,*key, *last, *optargcpy=NULL; int keyidx; int *metasizes = NULL;//[2]; int metax=-1,metay=-1; #ifdef USE_CLIPPERS const char *ogr_where = NULL; const char *ogr_layer = NULL; const char *ogr_sql = NULL; const char *ogr_datasource = NULL; #endif apr_initialize(); (void) signal(SIGINT,handle_sig_int); apr_pool_create(&ctx.pool,NULL); mapcache_context_init(&ctx); ctx.process_pool = ctx.pool; #ifndef USE_FORK apr_thread_mutex_create((apr_thread_mutex_t**)&ctx.threadlock,APR_THREAD_MUTEX_DEFAULT,ctx.pool); #else ctx.threadlock = NULL; #endif cfg = mapcache_configuration_create(ctx.pool); ctx.config = cfg; ctx.log= mapcache_context_seeding_log; apr_getopt_init(&opt, ctx.pool, argc, argv); seededtiles=seededtilestot=queuedtilestot=0; mapcache_gettimeofday(&starttime,NULL); lastlogtime=starttime; argdimensions = apr_table_make(ctx.pool,3); /* parse the all options based on opt_option[] */ while ((rv = apr_getopt_long(opt, seed_options, &optch, &optarg)) == APR_SUCCESS) { switch (optch) { case 'h': return usage(argv[0],NULL); break; case 'f': force = 1; break; case 'q': quiet = 1; break; case 'v': verbose = 1; break; case 'c': configfile = optarg; break; case 'g': grid_name = optarg; break; case 't': tileset_name = optarg; break; case 'x': tileset_transfer_name = optarg; break; case 'm': if(!strcmp(optarg,"delete")) { mode = MAPCACHE_CMD_DELETE; } else if(!strcmp(optarg,"transfer")){ mode = MAPCACHE_CMD_TRANSFER; } else if(strcmp(optarg,"seed")){ return usage(argv[0],"invalid mode, expecting \"seed\", \"delete\" or \"transfer\""); } else { mode = MAPCACHE_CMD_SEED; } break; case 'n': nthreads = (int)strtol(optarg, NULL, 10); break; case 'e': if ( MAPCACHE_SUCCESS != mapcache_util_extract_double_list(&ctx, (char*)optarg, ",", &extent, &n) || n != 4 || extent[0] >= extent[2] || extent[1] >= extent[3] ) { return usage(argv[0], "failed to parse extent, expecting comma separated 4 doubles"); } break; case 'z': if ( MAPCACHE_SUCCESS != mapcache_util_extract_int_list(&ctx, (char*)optarg, ",", &zooms, &n) || n != 2 || zooms[0] > zooms[1]) { return usage(argv[0], "failed to parse zooms, expecting comma separated 2 ints"); } else { minzoom = zooms[0]; maxzoom = zooms[1]; } break; case 'M': if ( MAPCACHE_SUCCESS != mapcache_util_extract_int_list(&ctx, (char*)optarg, ",", &metasizes, &n) || n != 2 || metasizes[0] <= 0 || metasizes[1] <=0) { return usage(argv[0], "failed to parse metasize, expecting comma separated 2 positive ints (e.g. -M 8,8"); } else { metax = metasizes[0]; metay = metasizes[1]; } break; case 'o': old = optarg; break; case 'D': optargcpy = apr_pstrdup(ctx.pool,optarg); keyidx = 0; for (key = apr_strtok(optargcpy, "=", &last); key != NULL; key = apr_strtok(NULL, "=", &last)) { if(keyidx == 0) { dimkey = key; } else { dimvalue = key; } keyidx++; } if(keyidx!=2 || !dimkey || !dimvalue || !*dimkey || !*dimvalue) { return usage(argv[0], "failed to parse dimension, expecting DIMNAME=DIMVALUE"); } apr_table_set(argdimensions,dimkey,dimvalue); break; #ifdef USE_CLIPPERS case 'd': ogr_datasource = optarg; break; case 's': ogr_sql = optarg; break; case 'l': ogr_layer = optarg; break; case 'w': ogr_where = optarg; break; #endif } } if (rv != APR_EOF) { return usage(argv[0],"bad options"); } if( ! configfile ) { return usage(argv[0],"config not specified"); } else { mapcache_configuration_parse(&ctx,configfile,cfg,0); if(ctx.get_error(&ctx)) return usage(argv[0],ctx.get_error_message(&ctx)); mapcache_configuration_post_config(&ctx,cfg); if(ctx.get_error(&ctx)) return usage(argv[0],ctx.get_error_message(&ctx)); } #ifdef USE_CLIPPERS if(extent && ogr_datasource) { return usage(argv[0], "cannot specify both extent and ogr-datasource"); } if( ogr_sql && ( ogr_where || ogr_layer )) { return usage(argv[0], "ogr-where or ogr_layer cannot be used in conjunction with ogr-sql"); } if(ogr_datasource) { OGRDataSourceH hDS = NULL; OGRLayerH layer = NULL; OGRRegisterAll(); hDS = OGROpen( ogr_datasource, FALSE, NULL ); if( hDS == NULL ) { printf( "OGR Open failed\n" ); exit( 1 ); } if(ogr_sql) { layer = OGR_DS_ExecuteSQL( hDS, ogr_sql, NULL, NULL); if(!layer) { return usage(argv[0],"aborting"); } } else { int nLayers = OGR_DS_GetLayerCount(hDS); if(nLayers>1 && !ogr_layer) { return usage(argv[0],"ogr datastore contains more than one layer. please specify which one to use with --ogr-layer"); } else { if(ogr_layer) { layer = OGR_DS_GetLayerByName(hDS,ogr_layer); } else { layer = OGR_DS_GetLayer(hDS,0); } if(!layer) { return usage(argv[0],"aborting"); } if(ogr_where) { if(OGRERR_NONE != OGR_L_SetAttributeFilter(layer, ogr_where)) { return usage(argv[0],"aborting"); } } } } if((nClippers=OGR_L_GetFeatureCount(layer, TRUE)) == 0) { return usage(argv[0],"no features in provided ogr parameters, cannot continue"); } initGEOS(notice, log_and_exit); clippers = (const GEOSPreparedGeometry**)malloc(nClippers*sizeof(GEOSPreparedGeometry*)); OGRFeatureH hFeature; GEOSWKTReader *geoswktreader = GEOSWKTReader_create(); OGR_L_ResetReading(layer); extent = apr_pcalloc(ctx.pool,4*sizeof(double)); int f=0; while( (hFeature = OGR_L_GetNextFeature(layer)) != NULL ) { OGRGeometryH geom = OGR_F_GetGeometryRef(hFeature); if(!geom || !OGR_G_IsValid(geom)) continue; char *wkt; OGR_G_ExportToWkt(geom,&wkt); GEOSGeometry *geosgeom = GEOSWKTReader_read(geoswktreader,wkt); free(wkt); clippers[f] = GEOSPrepare(geosgeom); //GEOSGeom_destroy(geosgeom); OGREnvelope ogr_extent; OGR_G_GetEnvelope (geom, &ogr_extent); if(f == 0) { extent[0] = ogr_extent.MinX; extent[1] = ogr_extent.MinY; extent[2] = ogr_extent.MaxX; extent[3] = ogr_extent.MaxY; } else { extent[0] = MAPCACHE_MIN(ogr_extent.MinX, extent[0]); extent[1] = MAPCACHE_MIN(ogr_extent.MinY, extent[1]); extent[2] = MAPCACHE_MAX(ogr_extent.MaxX, extent[2]); extent[3] = MAPCACHE_MAX(ogr_extent.MaxY, extent[3]); } OGR_F_Destroy( hFeature ); f++; } nClippers = f; } #endif if( ! tileset_name ) { return usage(argv[0],"tileset not specified"); } else { tileset = mapcache_configuration_get_tileset(cfg,tileset_name); if(!tileset) { return usage(argv[0], "tileset not found in configuration"); } if( ! grid_name ) { grid_link = APR_ARRAY_IDX(tileset->grid_links,0,mapcache_grid_link*); } else {
static void load_config(mapcache_context *ctx, char *filename) { apr_file_t *f; apr_finfo_t finfo; mapcache_cfg *old_cfg; mapcache_cfg *cfg; if((apr_file_open(&f, filename, APR_FOPEN_READ, APR_UREAD | APR_GREAD, global_pool)) == APR_SUCCESS) { apr_file_info_get(&finfo, APR_FINFO_MTIME, f); apr_file_close(f); } else { if(!ctx->pool) ctx->pool = global_pool; ctx->set_error(ctx,500,"failed to open config file %s",filename); return; } if(ctx->config) { //we already have a loaded configuration, check that the config file hasn't changed if(finfo.mtime > mtime) { ctx->log(ctx,MAPCACHE_INFO,"config file has changed, reloading"); } else { return; } } mtime = finfo.mtime; /* either we have no config, or it has changed */ old_cfg = ctx->config; apr_pool_create(&tmp_config_pool,global_pool); cfg = mapcache_configuration_create(tmp_config_pool); ctx->config = cfg; ctx->pool = tmp_config_pool; mapcache_configuration_parse(ctx,conffile,cfg,1); if(GC_HAS_ERROR(ctx)) goto failed_load; mapcache_configuration_post_config(ctx, cfg); if(GC_HAS_ERROR(ctx)) goto failed_load; if(mapcache_config_services_enabled(ctx,cfg) <= 0) { ctx->set_error(ctx,500,"no mapcache <service>s configured/enabled, no point in continuing."); goto failed_load; } /* no error, destroy the previous pool if we are reloading the config */ if(config_pool) { apr_pool_destroy(config_pool); } config_pool = tmp_config_pool; mapcache_connection_pool_create(&ctx->connection_pool, config_pool); return; failed_load: /* we failed to load the config file */ if(config_pool) { /* we already have a running configuration, keep it and only log the error to not * interrupt the already running service */ ctx->log(ctx,MAPCACHE_ERROR,"failed to reload config file %s: %s", conffile,ctx->get_error_message(ctx)); ctx->clear_errors(ctx); ctx->config = old_cfg; ctx->pool = config_pool; apr_pool_destroy(tmp_config_pool); } }
static int mod_mapcache_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { apr_status_t rc; mapcache_server_cfg* cfg = ap_get_module_config(s->module_config, &mapcache_module); apr_lockmech_e lock_type = APR_LOCK_DEFAULT; server_rec *sconf; if(!cfg) { ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, "configuration not found in server context"); return 1; } #if APR_HAS_PROC_PTHREAD_SERIALIZE lock_type = APR_LOCK_PROC_PTHREAD; #endif rc = apr_global_mutex_create(&cfg->mutex,cfg->mutex_name,lock_type,p); if(rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s, "Could not create global parent mutex %s", cfg->mutex_name); return rc; } #ifdef AP_NEED_SET_MUTEX_PERMS rc = unixd_set_global_mutex_perms(cfg->mutex); if(rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s, "Could not set permissions on global parent mutex %s", cfg->mutex_name); return rc; } #endif apr_pool_cleanup_register(p,cfg->mutex, (void*)apr_global_mutex_destroy, apr_pool_cleanup_null); #ifndef DISABLE_VERSION_STRING ap_add_version_component(p, MAPCACHE_USERAGENT); #endif for (sconf = s->next; sconf; sconf = sconf->next) { mapcache_server_cfg* config = ap_get_module_config(sconf->module_config, &mapcache_module); config->mutex = cfg->mutex; } #if APR_HAS_FORK /* fork a child process to let it accomplish post-configuration tasks with the uid of the runtime user */ apr_proc_t proc; apr_status_t rv; rv = apr_proc_fork(&proc, ptemp); if (rv == APR_INCHILD) { #define ap_unixd_setup_child unixd_setup_child ap_unixd_setup_child(); mapcache_context *ctx = (mapcache_context*)apache_server_context_create(s,p); for (sconf = s; sconf; sconf = sconf->next) { mapcache_server_cfg* config = ap_get_module_config(sconf->module_config, &mapcache_module); if(config->aliases) { apr_hash_index_t *entry = apr_hash_first(ptemp,config->aliases); /* loop through the configured configurations */ while (entry) { const char *alias; apr_ssize_t aliaslen; mapcache_cfg *c; apr_hash_this(entry,(const void**)&alias,&aliaslen,(void**)&c); mapcache_configuration_post_config(ctx, c); if(GC_HAS_ERROR(ctx)) { ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL, s, "post config for %s failed: %s", alias, ctx->get_error_message(ctx)); exit(APR_EGENERAL); } entry = apr_hash_next(entry); } } } exit(0); } else if (rv == APR_INPARENT) { apr_exit_why_e exitwhy; int exitcode; apr_proc_wait(&proc,&exitcode,&exitwhy,APR_WAIT); if(exitwhy != APR_PROC_EXIT) { ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL, s, "mapcache post-config child terminated abnormally"); return APR_EGENERAL; } else { if(exitcode != 0) { return APR_EGENERAL; } } return OK; } else { ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL, s, "failed to fork mapcache post-config child"); return APR_EGENERAL; } #else /* APR_HAS_FORK */ mapcache_context *ctx = (mapcache_context*)apache_server_context_create(s,p); for (sconf = s; sconf; sconf = sconf->next) { mapcache_server_cfg* config = ap_get_module_config(sconf->module_config, &mapcache_module); if(config->aliases) { apr_hash_index_t *entry = apr_hash_first(ptemp,config->aliases); /* loop through the configured configurations */ while (entry) { const char *alias; apr_ssize_t aliaslen; mapcache_cfg *c; apr_hash_this(entry,(const void**)&alias,&aliaslen,(void**)&c); mapcache_configuration_post_config(ctx, c); if(GC_HAS_ERROR(ctx)) { ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL, s, "post config for %s failed: %s", alias, ctx->get_error_message(ctx)); return APR_EGENERAL; } entry = apr_hash_next(entry); } } } return OK; #endif }