static void _sqlite_dimension_release_conn(mapcache_context *ctx, mapcache_pooled_connection *pc) { if(GC_HAS_ERROR(ctx)) { mapcache_connection_pool_invalidate_connection(ctx,pc); } else { mapcache_connection_pool_release_connection(ctx,pc); } }
static int _mapcache_cache_sqlite_get(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*) pcache; struct sqlite_conn *conn; sqlite3_stmt *stmt; int ret; mapcache_pooled_connection *pc = mapcache_sqlite_get_conn(ctx,cache,tile,1); if (GC_HAS_ERROR(ctx)) { if(tile->tileset->read_only || !tile->tileset->source) { mapcache_sqlite_release_conn(ctx, pc); return MAPCACHE_FAILURE; } else { /* not an error in this case, as the db file may not have been created yet */ ctx->clear_errors(ctx); mapcache_sqlite_release_conn(ctx, pc); return MAPCACHE_CACHE_MISS; } } conn = SQLITE_CONN(pc); stmt = conn->prepared_statements[GET_TILE_STMT_IDX]; if(!stmt) { sqlite3_prepare(conn->handle, cache->get_stmt.sql, -1, &conn->prepared_statements[GET_TILE_STMT_IDX], NULL); stmt = conn->prepared_statements[GET_TILE_STMT_IDX]; } cache->bind_stmt(ctx, stmt, cache, tile); do { ret = sqlite3_step(stmt); if (ret != SQLITE_DONE && ret != SQLITE_ROW && ret != SQLITE_BUSY && ret != SQLITE_LOCKED) { ctx->set_error(ctx, 500, "sqlite backend failed on get: %s", sqlite3_errmsg(conn->handle)); sqlite3_reset(stmt); mapcache_sqlite_release_conn(ctx, pc); return MAPCACHE_FAILURE; } } while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED); if (ret == SQLITE_DONE) { sqlite3_reset(stmt); mapcache_sqlite_release_conn(ctx, pc); return MAPCACHE_CACHE_MISS; } else { const void *blob = sqlite3_column_blob(stmt, 0); int size = sqlite3_column_bytes(stmt, 0); if(size>0 && ((char*)blob)[0] == '#') { tile->encoded_data = mapcache_empty_png_decode(ctx,tile->grid_link->grid->tile_sx, tile->grid_link->grid->tile_sy ,blob,&tile->nodata); } else { tile->encoded_data = mapcache_buffer_create(size, ctx->pool); memcpy(tile->encoded_data->buf, blob, size); tile->encoded_data->size = size; } if (sqlite3_column_count(stmt) > 1) { time_t mtime = sqlite3_column_int64(stmt, 1); apr_time_ansi_put(&(tile->mtime), mtime); } sqlite3_reset(stmt); mapcache_sqlite_release_conn(ctx, pc); return MAPCACHE_SUCCESS; } }
static void _mapcache_cache_sqlite_multi_set(mapcache_context *ctx, mapcache_tile *tiles, int ntiles) { struct sqlite_conn *conn = _sqlite_get_conn(ctx, &tiles[0], 0); int i; GC_CHECK_ERROR(ctx); sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); for (i = 0; i < ntiles; i++) { mapcache_tile *tile = &tiles[i]; _single_sqlitetile_set(ctx,tile,conn); if(GC_HAS_ERROR(ctx)) break; } if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } _sqlite_release_conn(ctx, &tiles[0], conn); }
static void _mapcache_cache_sqlite_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*)pcache; struct sqlite_conn *conn; mapcache_pooled_connection *pc = mapcache_sqlite_get_conn(ctx,cache,tile,0); if (GC_HAS_ERROR(ctx)) { mapcache_sqlite_release_conn(ctx, pc); return; } conn = SQLITE_CONN(pc); sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); _single_sqlitetile_set(ctx,cache, tile,conn); if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } mapcache_sqlite_release_conn(ctx, pc); }
static void _release_mapboj(mapcache_context *ctx, mapcache_map *map, struct mc_mapobj *mcmap) { mapcache_source_mapserver *src = (mapcache_source_mapserver*) map->tileset->source; msFreeLabelCache(&mcmap->map->labelcache); apr_reslist_t *mapobjs = apr_hash_get(mapobj_container,src->source.name, APR_HASH_KEY_STRING); assert(mapobjs); if (GC_HAS_ERROR(ctx)) { apr_reslist_invalidate(mapobjs, (void*) mcmap); } else { apr_reslist_release(mapobjs, (void*) mcmap); } }
static void _mapcache_cache_mbtiles_set(mapcache_context *ctx, mapcache_tile *tile) { struct sqlite_conn *conn = _sqlite_get_conn(ctx, tile, 0); GC_CHECK_ERROR(ctx); if(!tile->raw_image) { tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data); if(GC_HAS_ERROR(ctx)) { _sqlite_release_conn(ctx, tile, conn); return; } } sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); _single_mbtile_set(ctx,tile,conn); if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } _sqlite_release_conn(ctx, tile, conn); }
static int _mapcache_cache_sqlite_get(mapcache_context *ctx, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*)tile->tileset->cache; sqlite3 *handle; sqlite3_stmt *stmt; int ret; if(cache->hitstats) { handle = _get_conn(ctx,tile,0); } else { handle = _get_conn(ctx,tile,1); } if(GC_HAS_ERROR(ctx)) { sqlite3_close(handle); return MAPCACHE_FAILURE; } sqlite3_prepare(handle,cache->get_stmt.sql,-1,&stmt,NULL); _bind_sqlite_params(ctx,stmt,tile); do { ret = sqlite3_step(stmt); if(ret!=SQLITE_DONE && ret != SQLITE_ROW && ret!=SQLITE_BUSY && ret !=SQLITE_LOCKED) { ctx->set_error(ctx,500,"sqlite backend failed on get: %s",sqlite3_errmsg(handle)); sqlite3_finalize(stmt); sqlite3_close(handle); return MAPCACHE_FAILURE; } } while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED); if(ret == SQLITE_DONE) { sqlite3_finalize(stmt); sqlite3_close(handle); return MAPCACHE_CACHE_MISS; } else { const void *blob = sqlite3_column_blob(stmt,0); int size = sqlite3_column_bytes(stmt, 0); tile->encoded_data = mapcache_buffer_create(size,ctx->pool); memcpy(tile->encoded_data->buf, blob,size); tile->encoded_data->size = size; if(sqlite3_column_count(stmt) > 1) { time_t mtime = sqlite3_column_int64(stmt, 1); apr_time_ansi_put(&(tile->mtime),mtime); } sqlite3_finalize(stmt); /* update the hitstats if we're configured for that */ if(cache->hitstats) { sqlite3_stmt *hitstmt; sqlite3_prepare(handle,cache->hitstat_stmt.sql,-1,&hitstmt,NULL); _bind_sqlite_params(ctx,stmt,tile); sqlite3_step(hitstmt); /* we ignore the return value , TODO?*/ sqlite3_finalize(hitstmt); } sqlite3_close(handle); return MAPCACHE_SUCCESS; } }
static mapcache_pooled_connection* _mapserver_get_connection(mapcache_context *ctx, mapcache_map *map) { mapcache_pooled_connection *pc; char *key = apr_psprintf(ctx->pool, "ms_src_%s", map->tileset->source->name); pc = mapcache_connection_pool_get_connection(ctx, key, mapcache_mapserver_connection_constructor, mapcache_mapserver_connection_destructor, map->tileset->source); if(!GC_HAS_ERROR(ctx) && pc && pc->connection) { } return pc; }
static void _mapcache_cache_mbtiles_multi_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tiles, int ntiles) { int i; mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*)pcache; mapcache_pooled_connection *pc; struct sqlite_conn *conn; /* decode/encode image data before going into the sqlite write lock */ for (i = 0; i < ntiles; i++) { mapcache_tile *tile = &tiles[i]; if(!tile->raw_image) { tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data); GC_CHECK_ERROR(ctx); } /* only encode to image format if tile is not blank */ if (mapcache_image_blank_color(tile->raw_image) != MAPCACHE_TRUE && !tile->encoded_data) { tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format); GC_CHECK_ERROR(ctx); } } pc = mapcache_sqlite_get_conn(ctx,cache,&tiles[0],0); if (GC_HAS_ERROR(ctx)) { mapcache_sqlite_release_conn(ctx, pc); return; } conn = SQLITE_CONN(pc); sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); for (i = 0; i < ntiles; i++) { mapcache_tile *tile = &tiles[i]; _single_mbtile_set(ctx,cache,tile,conn); if(GC_HAS_ERROR(ctx)) break; } if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } mapcache_sqlite_release_conn(ctx, pc); }
static void _mapcache_cache_sqlite_set(mapcache_context *ctx, mapcache_tile *tile) { struct sqlite_conn *conn = _sqlite_get_conn(ctx, tile, 0); GC_CHECK_ERROR(ctx); sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); _single_sqlitetile_set(ctx,tile,conn); if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } _sqlite_release_conn(ctx, tile, conn); }
static void _bdb_release_conn(mapcache_context *ctx, mapcache_tile *tile, struct bdb_env *benv) { mapcache_cache_bdb* cache = (mapcache_cache_bdb*)tile->tileset->cache; apr_reslist_t *pool; if(benv->readonly) pool = cache->ro_connection_pool; else pool = cache->rw_connection_pool; if(GC_HAS_ERROR(ctx)) { apr_reslist_invalidate(pool,(void*)benv); } else { apr_reslist_release(pool, (void*)benv); } }
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; }
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)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,ctx->get_error_message(ctx)); return NGX_CONF_ERROR; } mapcache_configuration_post_config(ctx, ctx->config); if(GC_HAS_ERROR(ctx)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,ctx->get_error_message(ctx)); return NGX_CONF_ERROR; } mapcache_connection_pool_create(&ctx->connection_pool,ctx->pool); ctx->config->non_blocking = 1; 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 void _mapcache_cache_sqlite_multi_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tiles, int ntiles) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*)pcache; int i; struct sqlite_conn *conn; mapcache_pooled_connection *pc = mapcache_sqlite_get_conn(ctx,cache,&tiles[0],0); if (GC_HAS_ERROR(ctx)) { mapcache_sqlite_release_conn(ctx, pc); return; } conn = SQLITE_CONN(pc); sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0); for (i = 0; i < ntiles; i++) { mapcache_tile *tile = &tiles[i]; _single_sqlitetile_set(ctx,cache, tile,conn); if(GC_HAS_ERROR(ctx)) break; } if (GC_HAS_ERROR(ctx)) { sqlite3_exec(conn->handle, "ROLLBACK TRANSACTION", 0, 0, 0); } else { sqlite3_exec(conn->handle, "END TRANSACTION", 0, 0, 0); } mapcache_sqlite_release_conn(ctx, pc); }
static int _mapcache_cache_disk_has_tile(mapcache_context *ctx, mapcache_tile *tile) { char *filename; apr_finfo_t finfo; int rv; ((mapcache_cache_disk*)tile->tileset->cache)->tile_key(ctx, tile, &filename); if(GC_HAS_ERROR(ctx)) { return MAPCACHE_FALSE; } rv = apr_stat(&finfo,filename,0,ctx->pool); if(rv != APR_SUCCESS) { return MAPCACHE_FALSE; } else { return MAPCACHE_TRUE; } }
static int _mapcache_cache_tc_has_tile(mapcache_context *ctx, mapcache_tile *tile) { int ret; struct tc_conn conn; int nrecords = 0; mapcache_cache_tc *cache = (mapcache_cache_tc*)tile->tileset->cache; char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); conn = _tc_get_conn(ctx,tile,1); if(GC_HAS_ERROR(ctx)) return MAPCACHE_FALSE; nrecords = tcbdbvnum2(conn.bdb, skey); if(nrecords == 0) ret = MAPCACHE_FALSE; else ret = MAPCACHE_TRUE; _tc_release_conn(ctx,tile,conn); return ret; }
static void _sqlite_release_conn(mapcache_context *ctx, mapcache_tile *tile, struct sqlite_conn *conn) { apr_reslist_t *pool; apr_hash_t *pool_container; if(conn->readonly) { pool_container = ro_connection_pools; } else { pool_container = rw_connection_pools; } pool = apr_hash_get(pool_container,tile->tileset->cache->name, APR_HASH_KEY_STRING); if (GC_HAS_ERROR(ctx)) { apr_reslist_invalidate(pool, (void*) conn); } else { apr_reslist_release(pool, (void*) conn); } }
static int _mapcache_cache_memcache_has_tile(mapcache_context *ctx, mapcache_tile *tile) { char *key; char *tmpdata; int rv; size_t tmpdatasize; mapcache_cache_memcache *cache = (mapcache_cache_memcache*)tile->tileset->cache; key = mapcache_util_get_tile_key(ctx, tile,NULL," \r\n\t\f\e\a\b","#"); if(GC_HAS_ERROR(ctx)) { return MAPCACHE_FALSE; } rv = apr_memcache_getp(cache->memcache,ctx->pool,key,&tmpdata,&tmpdatasize,NULL); if(rv != APR_SUCCESS) { return MAPCACHE_FALSE; } if(tmpdatasize == 0) { return MAPCACHE_FALSE; } return MAPCACHE_TRUE; }
mapcache_lock_result mapcache_locker_fallback_aquire_lock(mapcache_context *ctx, mapcache_locker *self, char *resource, void **lock) { int i; mapcache_locker_fallback *locker = (mapcache_locker_fallback*)self; struct mapcache_locker_fallback_lock *fallback_lock = apr_pcalloc(ctx->pool, sizeof(struct mapcache_locker_fallback_lock)); *lock = fallback_lock; for(i=0;i<locker->lockers->nelts;i++) { mapcache_lock_result lock_result; mapcache_locker *child_locker = APR_ARRAY_IDX(locker->lockers, i, mapcache_locker*); void *error; ctx->pop_errors(ctx,&error); lock_result = child_locker->aquire_lock(ctx, child_locker, resource, &(fallback_lock->lock)); if(!GC_HAS_ERROR(ctx)) { fallback_lock->locker = child_locker; ctx->push_errors(ctx,error); return lock_result; } ctx->push_errors(ctx,error); } return MAPCACHE_LOCK_NOENT; }
static void _mapcache_cache_sqlite_delete(mapcache_context *ctx, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*) tile->tileset->cache; struct sqlite_conn *conn = _sqlite_get_conn(ctx, tile, 0); sqlite3_stmt *stmt = conn->prepared_statements[SQLITE_DEL_TILE_STMT_IDX]; int ret; if (GC_HAS_ERROR(ctx)) { _sqlite_release_conn(ctx, tile, conn); return; } if(!stmt) { sqlite3_prepare(conn->handle, cache->delete_stmt.sql, -1, &conn->prepared_statements[SQLITE_DEL_TILE_STMT_IDX], NULL); stmt = conn->prepared_statements[SQLITE_DEL_TILE_STMT_IDX]; } cache->bind_stmt(ctx, stmt, tile); ret = sqlite3_step(stmt); if (ret != SQLITE_DONE && ret != SQLITE_ROW) { ctx->set_error(ctx, 500, "sqlite backend failed on delete: %s", sqlite3_errmsg(conn->handle)); } sqlite3_reset(stmt); _sqlite_release_conn(ctx, tile, conn); }
static int _mapcache_cache_tc_get(mapcache_context *ctx, mapcache_tile *tile) { int ret; struct tc_conn conn; mapcache_cache_tc *cache = (mapcache_cache_tc*)tile->tileset->cache; char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); conn = _tc_get_conn(ctx,tile,1); int size; if(GC_HAS_ERROR(ctx)) return MAPCACHE_FAILURE; tile->encoded_data = mapcache_buffer_create(0,ctx->pool); tile->encoded_data->buf = tcbdbget(conn.bdb, skey, strlen(skey), &size); if(tile->encoded_data->buf) { tile->encoded_data->avail = size; tile->encoded_data->size = size - sizeof(apr_time_t); apr_pool_cleanup_register(ctx->pool, tile->encoded_data->buf,(void*)free, apr_pool_cleanup_null); tile->mtime = *((apr_time_t*)(&tile->encoded_data->buf[tile->encoded_data->size])); ret = MAPCACHE_SUCCESS; } else { ret = MAPCACHE_CACHE_MISS; } _tc_release_conn(ctx,tile,conn); return ret; }
static void _mapcache_cache_memcache_delete(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) { char *key; int rv; char errmsg[120]; mapcache_cache_memcache *cache = (mapcache_cache_memcache*)pcache; mapcache_pooled_connection *pc; struct mapcache_memcache_pooled_connection *mpc; pc = _mapcache_memcache_get_conn(ctx,cache,tile); GC_CHECK_ERROR(ctx); mpc = pc->connection; key = mapcache_util_get_tile_key(ctx, tile,NULL," \r\n\t\f\e\a\b","#"); if(GC_HAS_ERROR(ctx)) goto cleanup; rv = apr_memcache_delete(mpc->memcache,key,0); if(rv != APR_SUCCESS && rv!= APR_NOTFOUND) { ctx->set_error(ctx,500,"memcache: failed to delete key %s: %s", key, apr_strerror(rv,errmsg,120)); goto cleanup; } cleanup: _mapcache_memcache_release_conn(ctx,pc); }
void mapcache_sqlite_connection_constructor(mapcache_context *ctx, void **conn_, void *params, apr_pool_t *process_pool) { int ret; int flags; struct sqlite_conn_params *sq_params = (struct sqlite_conn_params*)params; struct sqlite_conn *conn = calloc(1, sizeof (struct sqlite_conn)); *conn_ = conn; if(sq_params->readonly) { flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX; } else { flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_CREATE; } ret = sqlite3_open_v2(sq_params->dbfile, &conn->handle, flags, NULL); if (ret != SQLITE_OK) { ctx->set_error(ctx,500,"sqlite backend failed to open db %s: %s", sq_params->dbfile, sqlite3_errmsg(conn->handle)); return; } sqlite3_busy_timeout(conn->handle, 300000); do { ret = sqlite3_exec(conn->handle, sq_params->cache->create_stmt.sql, 0, 0, NULL); if (ret != SQLITE_OK && ret != SQLITE_BUSY && ret != SQLITE_LOCKED) { break; } } while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED); if (ret != SQLITE_OK) { ctx->set_error(ctx,500, "sqlite backend failed to create db schema on %s: %s", sq_params->dbfile, sqlite3_errmsg(conn->handle)); sqlite3_close(conn->handle); return; } _sqlite_set_pragmas(ctx, sq_params->cache, conn); if(GC_HAS_ERROR(ctx)) { sqlite3_close(conn->handle); return; } conn->prepared_statements = calloc(sq_params->cache->n_prepared_statements,sizeof(sqlite3_stmt*)); conn->nstatements = sq_params->cache->n_prepared_statements; }
static int _mapcache_cache_couchbase_has_tile(mapcache_context *ctx, mapcache_tile *tile) { char *key[1]; libcouchbase_t *instance; libcouchbase_error_t error; size_t keySize[1]; getStruct_t request; key[0] = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#"); if(GC_HAS_ERROR(ctx)) { return MAPCACHE_FALSE; } keySize[0] = strlen(key[0]); instance = _couchbase_get_connection(ctx, tile); request.tileBuffer = 0; request.error = LIBCOUCHBASE_KEY_ENOENT; error = libcouchbase_mget(*instance, &request, 1, (const void * const*)key, keySize, 0); if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to get key %s: %s", key, libcouchbase_strerror(*instance, error)); _couchbase_invalidate_connection(tile, instance); return MAPCACHE_FALSE; } libcouchbase_wait(*instance); error = request.error; if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to get key %s: %s", key, libcouchbase_strerror(*instance, error)); _couchbase_invalidate_connection(tile, instance); return MAPCACHE_FALSE; } _couchbase_release_connection(tile, instance); return MAPCACHE_TRUE; }
static int _mapcache_cache_sqlite_has_tile(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*) pcache; mapcache_pooled_connection *pc; struct sqlite_conn *conn; sqlite3_stmt *stmt; int ret; pc = mapcache_sqlite_get_conn(ctx,cache,tile,1); if (GC_HAS_ERROR(ctx)) { if(pc) mapcache_sqlite_release_conn(ctx, pc); if(!tile->tileset->read_only && tile->tileset->source) { /* not an error in this case, as the db file may not have been created yet */ ctx->clear_errors(ctx); } return MAPCACHE_FALSE; } conn = SQLITE_CONN(pc); stmt = conn->prepared_statements[HAS_TILE_STMT_IDX]; if(!stmt) { sqlite3_prepare(conn->handle, cache->exists_stmt.sql, -1, &conn->prepared_statements[HAS_TILE_STMT_IDX], NULL); stmt = conn->prepared_statements[HAS_TILE_STMT_IDX]; } cache->bind_stmt(ctx, stmt, cache, tile); ret = sqlite3_step(stmt); if (ret != SQLITE_DONE && ret != SQLITE_ROW) { ctx->set_error(ctx, 500, "sqlite backend failed on has_tile: %s", sqlite3_errmsg(conn->handle)); } if (ret == SQLITE_DONE) { ret = MAPCACHE_FALSE; } else if (ret == SQLITE_ROW) { ret = MAPCACHE_TRUE; } sqlite3_reset(stmt); mapcache_sqlite_release_conn(ctx, pc); return ret; }
mapcache_http_response *mapcache_core_proxy_request(mapcache_context *ctx, mapcache_request_proxy *req_proxy) { mapcache_http *http; mapcache_http_response *response = mapcache_http_response_create(ctx->pool); response->data = mapcache_buffer_create(30000,ctx->pool); http = req_proxy->http; if(req_proxy->pathinfo) { http = mapcache_http_clone(ctx,http); if( (*(req_proxy->pathinfo)) == '/' || http->url[strlen(http->url)-1] == '/') http->url = apr_pstrcat(ctx->pool,http->url,req_proxy->pathinfo,NULL); else http->url = apr_pstrcat(ctx->pool,http->url,"/",req_proxy->pathinfo,NULL); } mapcache_http_do_request_with_params(ctx,http,req_proxy->params,response->data,response->headers,&response->code); if(response->code !=0 && GC_HAS_ERROR(ctx)) { /* the http request was successful, but the server returned an error */ ctx->clear_errors(ctx); } /*remove some headers that should not be sent back to the client*/ apr_table_unset(response->headers,"Transfer-Encoding"); apr_table_unset(response->headers,"Connection"); return response; }
static int _mapcache_cache_bdb_has_tile(mapcache_context *ctx, mapcache_tile *tile) { int ret; DBT key; mapcache_cache_bdb *cache = (mapcache_cache_bdb*)tile->tileset->cache; char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); struct bdb_env *benv = _bdb_get_conn(ctx,tile,1); if(GC_HAS_ERROR(ctx)) return MAPCACHE_FALSE; memset(&key, 0, sizeof(DBT)); key.data = skey; key.size = strlen(skey)+1; ret = benv->db->exists(benv->db, NULL, &key, 0); if(ret == 0) { ret = MAPCACHE_TRUE; } else if(ret == DB_NOTFOUND) { ret = MAPCACHE_FALSE; } else { ctx->set_error(ctx,500,"bdb backend failure on tile_exists: %s",db_strerror(ret)); ret= MAPCACHE_FALSE; } _bdb_release_conn(ctx,tile,benv); return ret; }
static void _mapcache_cache_mbtiles_delete(mapcache_context *ctx, mapcache_tile *tile) { mapcache_cache_sqlite *cache = (mapcache_cache_sqlite*) tile->tileset->cache; struct sqlite_conn *conn = _sqlite_get_conn(ctx, tile, 0); sqlite3_stmt *stmt1,*stmt2,*stmt3; int ret; const char *tile_id; size_t tile_id_size; if (GC_HAS_ERROR(ctx)) { _sqlite_release_conn(ctx, tile, conn); return; } stmt1 = conn->prepared_statements[MBTILES_DEL_TILE_SELECT_STMT_IDX]; stmt2 = conn->prepared_statements[MBTILES_DEL_TILE_STMT1_IDX]; stmt3 = conn->prepared_statements[MBTILES_DEL_TILE_STMT2_IDX]; if(!stmt1) { sqlite3_prepare(conn->handle, "select tile_id from map where tile_col=:x and tile_row=:y and zoom_level=:z",-1,&conn->prepared_statements[MBTILES_DEL_TILE_SELECT_STMT_IDX], NULL); sqlite3_prepare(conn->handle, "delete from map where tile_col=:x and tile_row=:y and zoom_level=:z", -1, &conn->prepared_statements[MBTILES_DEL_TILE_STMT1_IDX], NULL); sqlite3_prepare(conn->handle, "delete from images where tile_id=:foobar", -1, &conn->prepared_statements[MBTILES_DEL_TILE_STMT2_IDX], NULL); stmt1 = conn->prepared_statements[MBTILES_DEL_TILE_SELECT_STMT_IDX]; stmt2 = conn->prepared_statements[MBTILES_DEL_TILE_STMT1_IDX]; stmt3 = conn->prepared_statements[MBTILES_DEL_TILE_STMT2_IDX]; } /* first extract tile_id from the tile we will delete. We need this because we do not know * if the tile is empty or not. * If it is empty, we will not delete the image blob data from the images table */ cache->bind_stmt(ctx, stmt1, tile); do { ret = sqlite3_step(stmt1); if (ret != SQLITE_DONE && ret != SQLITE_ROW && ret != SQLITE_BUSY && ret != SQLITE_LOCKED) { ctx->set_error(ctx, 500, "sqlite backend failed on mbtile del 1: %s", sqlite3_errmsg(conn->handle)); sqlite3_reset(stmt1); _sqlite_release_conn(ctx, tile, conn); return; } } while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED); if (ret == SQLITE_DONE) { /* tile does not exist, ignore */ sqlite3_reset(stmt1); _sqlite_release_conn(ctx, tile, conn); return; } else { tile_id = (const char*) sqlite3_column_text(stmt1, 0); tile_id_size = sqlite3_column_bytes(stmt1, 0); } /* delete the tile from the "map" table */ cache->bind_stmt(ctx,stmt2, tile); ret = sqlite3_step(stmt2); if (ret != SQLITE_DONE && ret != SQLITE_ROW) { ctx->set_error(ctx, 500, "sqlite backend failed on mbtile del 2: %s", sqlite3_errmsg(conn->handle)); sqlite3_reset(stmt1); sqlite3_reset(stmt2); _sqlite_release_conn(ctx, tile, conn); return; } if(tile_id[0] != '#') { /* the tile isn't empty, we must also delete from the images table */ int paramidx = sqlite3_bind_parameter_index(stmt3, ":foobar"); if (paramidx) { sqlite3_bind_text(stmt3, paramidx, tile_id, tile_id_size, SQLITE_STATIC); } ret = sqlite3_step(stmt3); if (ret != SQLITE_DONE && ret != SQLITE_ROW) { ctx->set_error(ctx, 500, "sqlite backend failed on mbtile del 3: %s", sqlite3_errmsg(conn->handle)); sqlite3_reset(stmt1); sqlite3_reset(stmt2); sqlite3_reset(stmt3); _sqlite_release_conn(ctx, tile, conn); return; } } sqlite3_reset(stmt1); sqlite3_reset(stmt2); sqlite3_reset(stmt3); _sqlite_release_conn(ctx, tile, conn); }
static int mod_mapcache_request_handler(request_rec *r) { apr_table_t *params; mapcache_request *request = NULL; mapcache_context_apache_request *apache_ctx = NULL; mapcache_http_response *http_response = NULL; mapcache_context *global_ctx = NULL; if (!r->handler || strcmp(r->handler, "mapcache")) { return DECLINED; } if (r->method_number != M_GET) { return HTTP_METHOD_NOT_ALLOWED; } apache_ctx = apache_request_context_create(r); global_ctx = (mapcache_context*)apache_ctx; params = mapcache_http_parse_param_string(global_ctx, r->args); mapcache_service_dispatch_request(global_ctx,&request,r->path_info,params,global_ctx->config); if(GC_HAS_ERROR(global_ctx) || !request) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } if(request->type == MAPCACHE_REQUEST_GET_CAPABILITIES) { mapcache_request_get_capabilities *req_caps = (mapcache_request_get_capabilities*)request; request_rec *original; char *url; if(r->main) original = r->main; else original = r; url = ap_construct_url(r->pool,original->uri,original); /* * remove the path_info from the end of the url (we want the url of the base of the service) * TODO: is there an apache api to access this ? */ if(*(original->path_info) && strcmp(original->path_info,"/")) { char *end = strstr(url,original->path_info); if(end) { /* make sure our url ends with a single '/' */ if(*end == '/') { char *slash = end; while((*(--slash))=='/') end--; end++; } *end = '\0'; } } http_response = mapcache_core_get_capabilities(global_ctx,request->service,req_caps, url,original->path_info,global_ctx->config); } else if( request->type == MAPCACHE_REQUEST_GET_TILE) { mapcache_request_get_tile *req_tile = (mapcache_request_get_tile*)request; http_response = mapcache_core_get_tile(global_ctx,req_tile); } else if( request->type == MAPCACHE_REQUEST_PROXY ) { mapcache_request_proxy *req_proxy = (mapcache_request_proxy*)request; http_response = mapcache_core_proxy_request(global_ctx, req_proxy); } else if( request->type == MAPCACHE_REQUEST_GET_MAP) { mapcache_request_get_map *req_map = (mapcache_request_get_map*)request; http_response = mapcache_core_get_map(global_ctx,req_map); } else if( request->type == MAPCACHE_REQUEST_GET_FEATUREINFO) { mapcache_request_get_feature_info *req_fi = (mapcache_request_get_feature_info*)request; http_response = mapcache_core_get_featureinfo(global_ctx,req_fi); } else { global_ctx->set_error(global_ctx,500,"###BUG### unknown request type"); } if(GC_HAS_ERROR(global_ctx)) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } return write_http_response(apache_ctx,http_response); }
void mapcache_prefetch_tiles(mapcache_context *ctx, mapcache_tile **tiles, int ntiles) { apr_thread_t **threads; apr_threadattr_t *thread_attrs; int nthreads; #if !APR_HAS_THREADS int i; for(i=0; i<ntiles; i++) { mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } #else int i,rv; _thread_tile* thread_tiles; if(ntiles==1 || ctx->config->threaded_fetching == 0) { /* if threads disabled, or only fetching a single tile, don't launch a thread for the operation */ for(i=0; i<ntiles; i++) { mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } return; } /* allocate a thread struct for each tile. Not all will be used */ thread_tiles = (_thread_tile*)apr_pcalloc(ctx->pool,ntiles*sizeof(_thread_tile)); #if 1 || !USE_THREADPOOL /* use multiple threads, to fetch from multiple metatiles and/or multiple tilesets */ apr_threadattr_create(&thread_attrs, ctx->pool); threads = (apr_thread_t**)apr_pcalloc(ctx->pool, ntiles*sizeof(apr_thread_t*)); nthreads = 0; for(i=0; i<ntiles; i++) { int j; thread_tiles[i].tile = tiles[i]; thread_tiles[i].launch = 1; j=i-1; /* * we only launch one thread per metatile as in the unseeded case the threads * for a same metatile will lock while only a single thread launches the actual * rendering request */ while(j>=0) { /* check that the given metatile hasn't been rendered yet */ if(thread_tiles[j].launch && (thread_tiles[i].tile->tileset == thread_tiles[j].tile->tileset) && (thread_tiles[i].tile->x / thread_tiles[i].tile->tileset->metasize_x == thread_tiles[j].tile->x / thread_tiles[j].tile->tileset->metasize_x)&& (thread_tiles[i].tile->y / thread_tiles[i].tile->tileset->metasize_y == thread_tiles[j].tile->y / thread_tiles[j].tile->tileset->metasize_y)) { thread_tiles[i].launch = 0; /* this tile will not have a thread spawned for it */ break; } j--; } if(thread_tiles[i].launch) thread_tiles[i].ctx = ctx->clone(ctx); } for(i=0; i<ntiles; i++) { if(!thread_tiles[i].launch) continue; /* skip tiles that have been marked */ rv = apr_thread_create(&threads[i], thread_attrs, _thread_get_tile, (void*)&(thread_tiles[i]), thread_tiles[i].ctx->pool); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "failed to create thread %d of %d\n",i,ntiles); break; } nthreads++; } /* wait for launched threads to finish */ for(i=0; i<ntiles; i++) { if(!thread_tiles[i].launch) continue; apr_thread_join(&rv, threads[i]); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "thread %d of %d failed on exit\n",i,ntiles); } if(GC_HAS_ERROR(thread_tiles[i].ctx)) { /* transfer error message from child thread to main context */ ctx->set_error(ctx,thread_tiles[i].ctx->get_error(thread_tiles[i].ctx), thread_tiles[i].ctx->get_error_message(thread_tiles[i].ctx)); } } for(i=0; i<ntiles; i++) { /* fetch the tiles that did not get a thread launched for them */ if(thread_tiles[i].launch) continue; mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } #else /* experimental version using a threadpool, disabled for stability reasons */ apr_thread_pool_t *thread_pool; apr_thread_pool_create(&thread_pool,2,ctx->config->download_threads,ctx->pool); for(i=0; i<ntiles; i++) { ctx->log(ctx,MAPCACHE_DEBUG,"starting thread for tile %s",tiles[i]->tileset->name); thread_tiles[i].tile = tiles[i]; thread_tiles[i].ctx = ctx->clone(ctx); rv = apr_thread_pool_push(thread_pool,_thread_get_tile,(void*)&(thread_tiles[i]), 0,NULL); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "failed to push thread %d of %d in thread pool\n",i,ntiles); break; } } GC_CHECK_ERROR(ctx); while(apr_thread_pool_tasks_run_count(thread_pool) != ntiles || apr_thread_pool_busy_count(thread_pool)>0) apr_sleep(10000); apr_thread_pool_destroy(thread_pool); for(i=0; i<ntiles; i++) { if(GC_HAS_ERROR(thread_tiles[i].ctx)) { ctx->set_error(ctx,thread_tiles[i].ctx->get_error(thread_tiles[i].ctx), thread_tiles[i].ctx->get_error_message(thread_tiles[i].ctx)); } } #endif #endif }