Example #1
0
static int _mapcache_cache_bdb_get(mapcache_context *ctx, mapcache_tile *tile) {
   DBT key,data;
   struct bdb_env *benv = _bdb_get_conn(ctx,tile,1);
   mapcache_cache_bdb *cache = (mapcache_cache_bdb*)tile->tileset->cache;
   char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
   if(GC_HAS_ERROR(ctx)) return MAPCACHE_FAILURE;
   memset(&key, 0, sizeof(DBT));
   memset(&data, 0, sizeof(DBT));
   data.flags = DB_DBT_MALLOC;
   key.data = skey;
   key.size = strlen(skey)+1;

   int ret = benv->db->get(benv->db, NULL, &key, &data, 0);


   if(ret == 0) {
      tile->encoded_data = mapcache_buffer_create(0,ctx->pool);
      tile->encoded_data->buf = data.data;
      tile->encoded_data->size = data.size-sizeof(apr_time_t);
      tile->encoded_data->avail = data.size;
      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 if(ret == DB_NOTFOUND) {
      ret = MAPCACHE_CACHE_MISS;
   } else {
      ctx->set_error(ctx,500,"bdb backend failure on tile_get: %s",db_strerror(ret));
      ret = MAPCACHE_FAILURE;
   }
   _bdb_release_conn(ctx,tile,benv);
   return ret;
}
Example #2
0
void _mapcache_source_wms_query(mapcache_context *ctx, mapcache_feature_info *fi)
{
  mapcache_map *map = (mapcache_map*)fi;
  mapcache_source_wms *wms = (mapcache_source_wms*)map->tileset->source;

  apr_table_t *params = apr_table_clone(ctx->pool,wms->wms_default_params);
  apr_table_overlap(params,wms->getmap_params,0);
  apr_table_setn(params,"BBOX",apr_psprintf(ctx->pool,"%f,%f,%f,%f",
                 map->extent.minx,map->extent.miny,map->extent.maxx,map->extent.maxy));
  apr_table_setn(params,"REQUEST","GetFeatureInfo");
  apr_table_setn(params,"WIDTH",apr_psprintf(ctx->pool,"%d",map->width));
  apr_table_setn(params,"HEIGHT",apr_psprintf(ctx->pool,"%d",map->height));
  apr_table_setn(params,"SRS",map->grid_link->grid->srs);
  apr_table_setn(params,"X",apr_psprintf(ctx->pool,"%d",fi->i));
  apr_table_setn(params,"Y",apr_psprintf(ctx->pool,"%d",fi->j));
  apr_table_setn(params,"INFO_FORMAT",fi->format);

  apr_table_overlap(params,wms->getfeatureinfo_params,0);
  if(map->dimensions && !apr_is_empty_table(map->dimensions)) {
    const apr_array_header_t *elts = apr_table_elts(map->dimensions);
    int i;
    for(i=0; i<elts->nelts; i++) {
      apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
      apr_table_setn(params,entry.key,entry.val);
    }

  }

  fi->data = mapcache_buffer_create(30000,ctx->pool);
  mapcache_http_do_request_with_params(ctx,wms->http,params,fi->data,NULL,NULL);
  GC_CHECK_ERROR(ctx);

}
Example #3
0
/**
 * \brief get content of given tile
 * 
 * fills the mapcache_tile::data of the given tile with content stored on the memcache server
 * \private \memberof mapcache_cache_memcache
 * \sa mapcache_cache::tile_get()
 */
static int _mapcache_cache_memcache_get(mapcache_context *ctx, mapcache_tile *tile) {
   char *key;
   int rv;
   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_FAILURE;
   }
   tile->encoded_data = mapcache_buffer_create(0,ctx->pool);
   rv = apr_memcache_getp(cache->memcache,ctx->pool,key,(char**)&tile->encoded_data->buf,&tile->encoded_data->size,NULL);
   if(rv != APR_SUCCESS) {
      return MAPCACHE_CACHE_MISS;
   }
   if(tile->encoded_data->size == 0) {
      ctx->set_error(ctx,500,"memcache cache returned 0-length data for tile %d %d %d\n",tile->x,tile->y,tile->z);
      return MAPCACHE_FAILURE;
   }
   /* extract the tile modification time from the end of the data returned */
   memcpy(
         &tile->mtime,
         &(((char*)tile->encoded_data->buf)[tile->encoded_data->size-sizeof(apr_time_t)]),
         sizeof(apr_time_t));
   ((char*)tile->encoded_data->buf)[tile->encoded_data->size+sizeof(apr_time_t)]='\0';
   tile->encoded_data->avail = tile->encoded_data->size;
   tile->encoded_data->size -= sizeof(apr_time_t);
   return MAPCACHE_SUCCESS;
}
Example #4
0
/**
 * \brief encode an image to RGB(A) PNG format
 * \private \memberof mapcache_image_format_png
 * \sa mapcache_image_format::write()
 */
mapcache_buffer* _mapcache_imageio_png_encode(mapcache_context *ctx, mapcache_image *img, mapcache_image_format *format) {
   png_infop info_ptr;
   int color_type;
   size_t row;
   mapcache_buffer *buffer = NULL;
   int compression = ((mapcache_image_format_png*)format)->compression_level;
   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
   if (!png_ptr) {
      ctx->set_error(ctx, 500, "failed to allocate png_struct structure");
      return NULL;
   }

   info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr)
   {
      png_destroy_write_struct(&png_ptr,
            (png_infopp)NULL);
      ctx->set_error(ctx, 500, "failed to allocate png_info structure");
      return NULL;
   }

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      ctx->set_error(ctx, 500, "failed to setjmp(png_jmpbuf(png_ptr))");
      png_destroy_write_struct(&png_ptr, &info_ptr);
      return NULL;
   }

   buffer = mapcache_buffer_create(5000,ctx->pool);

   png_set_write_fn(png_ptr, buffer, _mapcache_imageio_png_write_func, _mapcache_imageio_png_flush_func);

   if(mapcache_image_has_alpha(img))
      color_type = PNG_COLOR_TYPE_RGB_ALPHA;
   else
      color_type = PNG_COLOR_TYPE_RGB;
      
   png_set_IHDR(png_ptr, info_ptr, img->w, img->h,
         8, color_type, PNG_INTERLACE_NONE,
         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
   if(compression == MAPCACHE_COMPRESSION_BEST)
      png_set_compression_level (png_ptr, Z_BEST_COMPRESSION);
   else if(compression == MAPCACHE_COMPRESSION_FAST)
      png_set_compression_level (png_ptr, Z_BEST_SPEED);

   png_write_info(png_ptr, info_ptr);
   if(color_type == PNG_COLOR_TYPE_RGB)
       png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);

   png_bytep rowptr = img->data;
   for(row=0;row<img->h;row++) {
      png_write_row(png_ptr,rowptr);
      rowptr += img->stride;
   }
   png_write_end(png_ptr, info_ptr);
   png_destroy_write_struct(&png_ptr, &info_ptr);
   return buffer;
}
Example #5
0
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;
    }
}
Example #6
0
/**
 * \brief push tile data to memcached
 *
 * writes the content of mapcache_tile::data to the configured memcached instance(s)
 * \returns MAPCACHE_FAILURE if there is no data to write, or if the tile isn't locked
 * \returns MAPCACHE_SUCCESS if the tile has been successfully written
 * \private \memberof mapcache_cache_memcache
 * \sa mapcache_cache::tile_set()
 */
static void _mapcache_cache_memcache_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
  char *key;
  int rv;
  /* set no expiration if not configured */
  int expires =0;
  mapcache_buffer *encoded_data = NULL;
  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;
  
  if(tile->tileset->auto_expire)
    expires = tile->tileset->auto_expire;

  if(cache->detect_blank) {
    if(!tile->raw_image) {
      tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data);
      GC_CHECK_ERROR(ctx);
    }
    if(mapcache_image_blank_color(tile->raw_image) != MAPCACHE_FALSE) {
      encoded_data = mapcache_buffer_create(5,ctx->pool);
      ((char*)encoded_data->buf)[0] = '#';
      memcpy(((char*)encoded_data->buf)+1,tile->raw_image->data,4);
      encoded_data->size = 5;
    }
  }
  if(!encoded_data) {
    if(!tile->encoded_data) {
      tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format);
      if(GC_HAS_ERROR(ctx)) goto cleanup;
    }
    encoded_data = tile->encoded_data;
  }

  /* concatenate the current time to the end of the memcache data so we can extract it out
   * when we re-get the tile */
  char *data = calloc(1,encoded_data->size+sizeof(apr_time_t));
  apr_time_t now = apr_time_now();
  apr_pool_cleanup_register(ctx->pool, data, (void*)free, apr_pool_cleanup_null);
  memcpy(data,encoded_data->buf,encoded_data->size);
  memcpy(&(data[encoded_data->size]),&now,sizeof(apr_time_t));

  rv = apr_memcache_set(mpc->memcache,key,data,encoded_data->size+sizeof(apr_time_t),expires,0);
  if(rv != APR_SUCCESS) {
    ctx->set_error(ctx,500,"failed to store tile %d %d %d to memcache cache %s",
                   tile->x,tile->y,tile->z,cache->cache.name);
    goto cleanup;
  }

cleanup:
  _mapcache_memcache_release_conn(ctx,pc);
}
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;
   }
}
Example #8
0
/**
 * \brief get content of given tile
 * 
 * fills the mapcache_tile::data of the given tile with content stored on the couchbase server
 * \private \memberof mapcache_cache_couchbase
 * \sa mapcache_cache::tile_get()
 */
static int _mapcache_cache_couchbase_get(mapcache_context *ctx, mapcache_tile *tile) {
   char *key[1];
   size_t keySize[1];
   libcouchbase_t *instance;
   libcouchbase_error_t error;
   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_FAILURE;
   }
   
   keySize[0] = strlen(key[0]);

   tile->encoded_data = mapcache_buffer_create(0, ctx->pool);

   libcouchbase_time_t expires = 86400;
   if(tile->tileset->auto_expire)
      expires = tile->tileset->auto_expire;

   instance = _couchbase_get_connection(ctx, tile);
   if (GC_HAS_ERROR(ctx)) {
      return MAPCACHE_FAILURE;
   }

   request.tileBuffer = tile->encoded_data;
   error = libcouchbase_mget(*instance, &request, 1, (const void * const*)key, keySize, &expires);
   if (error != LIBCOUCHBASE_SUCCESS) {
      ctx->set_error(ctx, 500, "couchbase cache returned error on mget %s", libcouchbase_strerror(*instance, error));
      _couchbase_invalidate_connection(tile, instance);
      return MAPCACHE_FAILURE;
   }
   
   libcouchbase_wait(*instance);

   if(request.error != LIBCOUCHBASE_SUCCESS) {
       _couchbase_release_connection(tile, instance);
       return MAPCACHE_CACHE_MISS;
   }

   if (tile->encoded_data->size == 0) {
      _couchbase_release_connection(tile, instance);
      ctx->set_error(ctx, 500, "couchbase cache returned 0-length data for tile %d %d %d", tile->x, tile->y, tile->z);
      return MAPCACHE_FAILURE;
   }
   
   apr_time_t now = apr_time_now();
   tile->mtime = now;

   _couchbase_release_connection(tile, instance);
   return MAPCACHE_SUCCESS;
}
Example #9
0
/**
 * \brief get content of given tile
 *
 * fills the mapcache_tile::data of the given tile with content stored on the memcache server
 * \private \memberof mapcache_cache_memcache
 * \sa mapcache_cache::tile_get()
 */
static int _mapcache_cache_memcache_get(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
  char *key;
  int rv;
  mapcache_cache_memcache *cache = (mapcache_cache_memcache*)pcache;
  mapcache_pooled_connection *pc;
  mapcache_buffer *encoded_data;
  struct mapcache_memcache_pooled_connection *mpc;
  pc = _mapcache_memcache_get_conn(ctx,cache,tile);
  if(GC_HAS_ERROR(ctx)) {
    return MAPCACHE_FAILURE;
  }
  mpc = pc->connection;
  key = mapcache_util_get_tile_key(ctx, tile,NULL," \r\n\t\f\e\a\b","#");
  if(GC_HAS_ERROR(ctx)) {
    rv = MAPCACHE_FAILURE;
    goto cleanup;
  }
  encoded_data = mapcache_buffer_create(0,ctx->pool);
  rv = apr_memcache_getp(mpc->memcache,ctx->pool,key,(char**)&encoded_data->buf,&encoded_data->size,NULL);
  if(rv != APR_SUCCESS) {
    rv = MAPCACHE_CACHE_MISS;
    goto cleanup;
  }
  if(encoded_data->size == 0) {
    ctx->set_error(ctx,500,"memcache cache returned 0-length data for tile %d %d %d\n",tile->x,tile->y,tile->z);
    rv = MAPCACHE_FAILURE;
    goto cleanup;
  }
  /* extract the tile modification time from the end of the data returned */
  memcpy(
    &tile->mtime,
    &(((char*)encoded_data->buf)[encoded_data->size-sizeof(apr_time_t)]),
    sizeof(apr_time_t));
  
  ((char*)encoded_data->buf)[encoded_data->size+sizeof(apr_time_t)]='\0';
  encoded_data->avail = encoded_data->size;
  encoded_data->size -= sizeof(apr_time_t);
  if(((char*)encoded_data->buf)[0] == '#' && encoded_data->size > 1) {
    tile->encoded_data = mapcache_empty_png_decode(ctx,tile->grid_link->grid->tile_sx, tile->grid_link->grid->tile_sy ,encoded_data->buf,&tile->nodata);
  } else {
    tile->encoded_data = encoded_data;
  }
  rv = MAPCACHE_SUCCESS;
  
cleanup:
  _mapcache_memcache_release_conn(ctx,pc);
  
  return rv;
}
Example #10
0
/**
 * \private \memberof mapcache_source_wms
 * \sa mapcache_source::render_map()
 */
void _mapcache_source_wms_render_map(mapcache_context *ctx, mapcache_map *map)
{
  mapcache_source_wms *wms = (mapcache_source_wms*)map->tileset->source;
  mapcache_http *http;
  apr_table_t *params = apr_table_clone(ctx->pool,wms->wms_default_params);
  apr_table_setn(params,"BBOX",apr_psprintf(ctx->pool,"%f,%f,%f,%f",
                 map->extent.minx,map->extent.miny,map->extent.maxx,map->extent.maxy));
  apr_table_setn(params,"WIDTH",apr_psprintf(ctx->pool,"%d",map->width));
  apr_table_setn(params,"HEIGHT",apr_psprintf(ctx->pool,"%d",map->height));
  apr_table_setn(params,"FORMAT","image/png");
  apr_table_setn(params,"SRS",map->grid_link->grid->srs);

  apr_table_overlap(params,wms->getmap_params,APR_OVERLAP_TABLES_SET);
  if(map->dimensions && !apr_is_empty_table(map->dimensions)) {
    const apr_array_header_t *elts = apr_table_elts(map->dimensions);
    int i;
    for(i=0; i<elts->nelts; i++) {
      apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
      /* set both DIM_key=val and key=val KVP params */
      apr_table_setn(params,entry.key,entry.val);
      if(strcasecmp(entry.key,"TIME") && strcasecmp(entry.key,"ELEVATION")) {
        char *dim_name = apr_pstrcat(ctx->pool,"DIM_",entry.key,NULL);
        apr_table_setn(params,dim_name,entry.val);
      }
    }

  }

  /* if the source has no LAYERS parameter defined, then use the tileset name
   * as the LAYERS to request. When using mirror-mode, the source has no layers
   * defined, it is added based on the incoming request
   */
  if(!apr_table_get(params,"layers")) {
    apr_table_set(params,"LAYERS",map->tileset->name);
  }

  map->encoded_data = mapcache_buffer_create(30000,ctx->pool);
  http = mapcache_http_clone(ctx, wms->http);
  http->url = mapcache_http_build_url(ctx,http->url,params);
  mapcache_http_do_request(ctx,http,map->encoded_data,NULL,NULL);
  GC_CHECK_ERROR(ctx);

  if(!mapcache_imageio_is_valid_format(ctx,map->encoded_data)) {
    char *returned_data = apr_pstrndup(ctx->pool,(char*)map->encoded_data->buf,map->encoded_data->size);
    ctx->set_error(ctx, 502, "wms request for tileset %s returned an unsupported format:\n%s",
                   map->tileset->name, returned_data);
  }
}
Example #11
0
//------------------------------------------------------------------------------
void _mapcache_source_tms_render_map_elevation(mapcache_context *ctx, mapcache_map *map)
{
    mapcache_source_tms *tms;
    int elevationblock;
    int zoom, x, y;
    char* url;
    double dx, dy;

    tms = (mapcache_source_tms*)map->tileset->source;
    elevationblock = map->grid_link->grid->elevationblock;

    _GetTileCoords(map, &zoom, &x, &y, tms->flipy);

    url = apr_psprintf(ctx->pool,"%s/1.0.0/%s/%i/%i/%i.%s", tms->url,tms->layer,zoom,x,y,tms->format);
    tms->http->url = apr_pstrdup(ctx->pool,url);

    map->encoded_data = mapcache_buffer_create(30000,ctx->pool);
    mapcache_http_do_request(ctx, tms->http, map->encoded_data, NULL, NULL);
    GC_CHECK_ERROR(ctx);

    if(!mapcache_imageio_is_valid_format(ctx,map->encoded_data)) {
        char *returned_data = apr_pstrndup(ctx->pool,(char*)map->encoded_data->buf,map->encoded_data->size);
        ctx->set_error(ctx, 502, "tms request for tileset %s returned an unsupported format:\n%s",
                       map->tileset->name, returned_data);
        return;
    }

    map->raw_image = mapcache_imageio_decode(ctx, map->encoded_data);
    map->raw_image->is_elevation = MC_ELEVATION_YES;
    GC_CHECK_ERROR(ctx);

    //map->raw_image->stride = 4 * elevationblock;
    dx = fabs(map->grid_link->grid->extent.maxx-map->grid_link->grid->extent.minx);
    dy = fabs(map->grid_link->grid->extent.maxx-map->grid_link->grid->extent.minx);
    map->raw_image->x0 = map->extent.minx / dx * 2.0;
    map->raw_image->y0 = map->extent.miny / dy * 2.0;
    map->raw_image->x1 = map->extent.maxx / dx * 2.0;
    map->raw_image->y1 = map->extent.maxy / dy * 2.0;

    if (map->raw_image->w != elevationblock || map->raw_image->h != elevationblock)
    {
        ctx->set_error(ctx,500,"Error: size of heightmap from source is not configured propery!");
    }

}
Example #12
0
//------------------------------------------------------------------------------
void _mapcache_source_tms_render_map_image(mapcache_context *ctx, mapcache_map *map)
{
    int zoom, x, y;
    mapcache_source_tms *tms;
    char* url;

    tms = (mapcache_source_tms*)map->tileset->source;

    _GetTileCoords(map, &zoom, &x, &y, tms->flipy);

    url = apr_psprintf(ctx->pool,"%s/1.0.0/%s/%i/%i/%i.%s", tms->url,tms->layer,zoom,x,y,tms->format);
    tms->http->url = apr_pstrdup(ctx->pool,url);

    map->encoded_data = mapcache_buffer_create(30000,ctx->pool);
    mapcache_http_do_request(ctx, tms->http, map->encoded_data, NULL, NULL);
    GC_CHECK_ERROR(ctx);

    if(!mapcache_imageio_is_valid_format(ctx,map->encoded_data)) {
        char *returned_data = apr_pstrndup(ctx->pool,(char*)map->encoded_data->buf,map->encoded_data->size);
        ctx->set_error(ctx, 502, "tms request for tileset %s returned an unsupported format:\n%s",
                       map->tileset->name, returned_data);
    }
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #15
0
/**
 * \brief get content of given tile
 *
 * fills the mapcache_tile::data of the given tile with content stored on the riak server
 * \private \memberof mapcache_cache_riak
 * \sa mapcache_cache::tile_get()
 */
static int _mapcache_cache_riak_get(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) {
    int error;
    int connect_error = RIACK_SUCCESS;
    int retries = 3;
    RIACK_STRING key;
    struct RIACK_GET_OBJECT obj;
    struct RIACK_GET_PROPERTIES properties;
    struct RIACK_CLIENT *client;
    mapcache_pooled_connection *pc;
    mapcache_cache_riak *cache = (mapcache_cache_riak*)pcache;

    memset(&properties, 0, sizeof(struct RIACK_GET_PROPERTIES));

    //Use Buckets defaults instead of setting the read/write attributes
    /*
    properties.r_use = 1;
    properties.r = 1;
    */


    key.value = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#");
    if (GC_HAS_ERROR(ctx)) {
        return MAPCACHE_FAILURE;
    }
    key.len = strlen(key.value);

    tile->encoded_data = mapcache_buffer_create(0, ctx->pool);

    pc = _riak_get_connection(ctx, cache, tile);
    if (GC_HAS_ERROR(ctx)) {
        return MAPCACHE_FAILURE;
    }
    client = pc->connection;

    // If we get an error it is advised that we call reconnect.  It also appears
    // that every now and then we get an error and need to retry once again to
    // get it to work.
    do
    {
        error = riack_get(client, cache->bucket, key, &properties, &obj);
        if (error != RIACK_SUCCESS) {
            ctx->log(ctx, MAPCACHE_WARN, "Retry %d in riak_get for tile %s from cache %s due to error %d", (4-retries), key.value, cache->cache.name, error);
            for (connect_error = riack_reconnect(client);
                    connect_error != RIACK_SUCCESS && retries > 0;
                    connect_error = riack_reconnect(client))
            {
                --retries;
            }

            --retries;
        }
    }
    while (error != RIACK_SUCCESS && retries >= 0);

    if (error != RIACK_SUCCESS)
    {
        if (connect_error != RIACK_SUCCESS)
            mapcache_connection_pool_invalidate_connection(ctx,pc);
        else
            mapcache_connection_pool_release_connection(ctx,pc);

        ctx->set_error(ctx, 500, "Failed to get tile %s from cache %s due to error %d", key.value, cache->cache.name, error);
        return MAPCACHE_FAILURE;
    }

    // Check if tile exists.  If it doesn't we need to return CACHE_MISS or things go wrong.
    // Mapcache doesn't appear to use the has_tile function and uses _get instead so we need
    // to do this sort of test here instead of erroring.
    if (obj.object.content_count < 1 || obj.object.content[0].data_len == 0) {
        riack_free_get_object(client, &obj);  // Need to free the object here as well.
        mapcache_connection_pool_release_connection(ctx,pc);
        return MAPCACHE_CACHE_MISS;
    }

    // Copy the data into the buffer
    mapcache_buffer_append(tile->encoded_data, obj.object.content[0].data_len, obj.object.content[0].data);

    riack_free_get_object(client, &obj);    // riack_get allocates the returned object so we need to deallocate it.

    mapcache_connection_pool_release_connection(ctx,pc);

    return MAPCACHE_SUCCESS;
}
Example #16
0
/**
 * \private \memberof mapcache_source_gdal
 * \sa mapcache_source::render_metatile()
 */
void _mapcache_source_gdal_render_metatile(mapcache_context *ctx, mapcache_metatile *tile)
{
  mapcache_source_gdal *gdal = (mapcache_source_gdal*)tile->tile.tileset->source;
  char *srcSRS = "", *dstSRS;
  mapcache_buffer *data = mapcache_buffer_create(0,ctx->pool);
  GC_CHECK_ERROR(ctx);
  GDALDatasetH  hDataset;

  GDALAllRegister();
  OGRSpatialReferenceH hSRS;
  CPLErrorReset();

  hSRS = OSRNewSpatialReference( NULL );
  if( OSRSetFromUserInput( hSRS, tile->tile.grid->srs ) == OGRERR_NONE )
    OSRExportToWkt( hSRS, &dstSRS );
  else {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"failed to parse gdal srs %s",tile->tile.grid->srs);
    return;
  }

  OSRDestroySpatialReference( hSRS );

  hDataset = GDALOpen( gdal->datastr, GA_ReadOnly );
  if( hDataset == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"GDAL failed to open %s",gdal->datastr);
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Check that there's at least one raster band                     */
  /* -------------------------------------------------------------------- */
  if ( GDALGetRasterCount(hDataset) == 0 ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"raster %s has no bands",gdal->datastr);
    return;
  }

  if( GDALGetProjectionRef( hDataset ) != NULL
      && strlen(GDALGetProjectionRef( hDataset )) > 0 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetProjectionRef( hDataset ));

  else if( GDALGetGCPProjection( hDataset ) != NULL
           && strlen(GDALGetGCPProjection(hDataset)) > 0
           && GDALGetGCPCount( hDataset ) > 1 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetGCPProjection( hDataset ));

  GDALDriverH hDriver = GDALGetDriverByName( "MEM" );
  GDALDatasetH hDstDS;
  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  void *hTransformArg =
    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                                     NULL, dstSRS,
                                     TRUE, 1000.0, 0 );

  if( hTransformArg == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create SRS transformation object");
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Get approximate output definition.                              */
  /* -------------------------------------------------------------------- */
  int nPixels, nLines;
  double adfDstGeoTransform[6];
  if( GDALSuggestedWarpOutput( hDataset,
                               GDALGenImgProjTransform, hTransformArg,
                               adfDstGeoTransform, &nPixels, &nLines )
      != CE_None ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create suggested warp output");
    return;
  }

  GDALDestroyGenImgProjTransformer( hTransformArg );
  double dfXRes = (tile->bbox[2] - tile->bbox[0]) / tile->sx;
  double dfYRes = (tile->bbox[3] - tile->bbox[1]) / tile->sy;

  adfDstGeoTransform[0] = tile->bbox[0];
  adfDstGeoTransform[3] = tile->bbox[3];
  adfDstGeoTransform[1] = dfXRes;
  adfDstGeoTransform[5] = -dfYRes;
  hDstDS = GDALCreate( hDriver, "tempd_gdal_image", tile->sx, tile->sy, 4, GDT_Byte, NULL );

  /* -------------------------------------------------------------------- */
  /*      Write out the projection definition.                            */
  /* -------------------------------------------------------------------- */
  GDALSetProjection( hDstDS, dstSRS );
  GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
  char               **papszWarpOptions = NULL;
  papszWarpOptions = CSLSetNameValue( papszWarpOptions, "INIT", "0" );



  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  GDALTransformerFunc pfnTransformer = NULL;
  void               *hGenImgProjArg=NULL, *hApproxArg=NULL;
  hTransformArg = hGenImgProjArg =
                    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                        hDstDS, dstSRS,
                        TRUE, 1000.0, 0 );

  if( hTransformArg == NULL )
    exit( 1 );

  pfnTransformer = GDALGenImgProjTransform;

  hTransformArg = hApproxArg =
                    GDALCreateApproxTransformer( GDALGenImgProjTransform,
                        hGenImgProjArg, 0.125 );
  pfnTransformer = GDALApproxTransform;

  /* -------------------------------------------------------------------- */
  /*      Now actually invoke the warper to do the work.                  */
  /* -------------------------------------------------------------------- */
  GDALSimpleImageWarp( hDataset, hDstDS, 0, NULL,
                       pfnTransformer, hTransformArg,
                       GDALDummyProgress, NULL, papszWarpOptions );

  CSLDestroy( papszWarpOptions );

  if( hApproxArg != NULL )
    GDALDestroyApproxTransformer( hApproxArg );

  if( hGenImgProjArg != NULL )
    GDALDestroyGenImgProjTransformer( hGenImgProjArg );

  if(GDALGetRasterCount(hDstDS) != 4) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal did not create a 4 band image");
    return;
  }

  GDALRasterBandH *redband, *greenband, *blueband, *alphaband;

  redband = GDALGetRasterBand(hDstDS,1);
  greenband = GDALGetRasterBand(hDstDS,2);
  blueband = GDALGetRasterBand(hDstDS,3);
  alphaband = GDALGetRasterBand(hDstDS,4);

  unsigned char *rasterdata = apr_palloc(ctx->pool,tile->sx*tile->sy*4);
  data->buf = rasterdata;
  data->avail = tile->sx*tile->sy*4;
  data->size = tile->sx*tile->sy*4;

  GDALRasterIO(redband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(greenband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+1),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(blueband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+2),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  if(GDALGetRasterCount(hDataset)==4)
    GDALRasterIO(alphaband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+3),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  else {
    unsigned char *alphaptr;
    int i;
    for(alphaptr = rasterdata+3, i=0; i<tile->sx*tile->sy; i++, alphaptr+=4) {
      *alphaptr = 255;
    }
  }

  tile->imdata = mapcache_image_create(ctx);
  tile->imdata->w = tile->sx;
  tile->imdata->h = tile->sy;
  tile->imdata->stride = tile->sx * 4;
  tile->imdata->data = rasterdata;


  GDALClose( hDstDS );
  GDALClose( hDataset);
}
Example #17
0
/**
 * \brief get file content of given tile
 *
 * fills the mapcache_tile::data of the given tile with content stored in the file
 * \private \memberof mapcache_cache_disk
 * \sa mapcache_cache::tile_get()
 */
static int _mapcache_cache_disk_get(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
{
  char *filename;
  apr_file_t *f;
  apr_finfo_t finfo;
  apr_status_t rv;
  apr_size_t size;
  apr_mmap_t *tilemmap;
  mapcache_cache_disk *cache = (mapcache_cache_disk*)pcache;

  cache->tile_key(ctx, cache, tile, &filename);
  if(GC_HAS_ERROR(ctx)) {
    return MAPCACHE_FAILURE;
  }
  ctx->log(ctx,MAPCACHE_DEBUG,"checking for tile %s",filename);
  if((rv=apr_file_open(&f, filename,
#ifndef NOMMAP
                       APR_FOPEN_READ, APR_UREAD | APR_GREAD,
#else
                       APR_FOPEN_READ|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,APR_OS_DEFAULT,
#endif
                       ctx->pool)) == APR_SUCCESS) {
    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE|APR_FINFO_MTIME, f);
    if(!finfo.size) {
      ctx->set_error(ctx, 500, "tile %s has no data",filename);
      return MAPCACHE_FAILURE;
    }

    size = finfo.size;
    /*
     * at this stage, we have a handle to an open file that contains data.
     * idealy, we should aquire a read lock, in case the data contained inside the file
     * is incomplete (i.e. if another process is currently writing to the tile).
     * currently such a lock is not set, as we don't want to loose performance on tile accesses.
     * any error that might happen at this stage should only occur if the tile isn't already cached,
     * i.e. normally only once.
     */
    tile->mtime = finfo.mtime;
    tile->encoded_data = mapcache_buffer_create(size,ctx->pool);

#ifndef NOMMAP

    rv = apr_mmap_create(&tilemmap,f,0,finfo.size,APR_MMAP_READ,ctx->pool);
    if(rv != APR_SUCCESS) {
      char errmsg[120];
      ctx->set_error(ctx, 500,  "mmap error: %s",apr_strerror(rv,errmsg,120));
      return MAPCACHE_FAILURE;
    }
    tile->encoded_data->buf = tilemmap->mm;
    tile->encoded_data->size = tile->encoded_data->avail = finfo.size;
#else
    //manually add the data to our buffer
    apr_file_read(f,(void*)tile->encoded_data->buf,&size);
    tile->encoded_data->size = size;
    tile->encoded_data->avail = size;
#endif
    apr_file_close(f);
    if(tile->encoded_data->size != finfo.size) {
      ctx->set_error(ctx, 500,  "failed to copy image data, got %d of %d bytes",(int)size, (int)finfo.size);
      return MAPCACHE_FAILURE;
    }
    return MAPCACHE_SUCCESS;
  } else {
    if(APR_STATUS_IS_ENOENT(rv)) {
      /* the file doesn't exist on the disk */
      return MAPCACHE_CACHE_MISS;
    } else {
      char *error = strerror(rv);
      ctx->set_error(ctx, 500,  "failed to open file %s: %s",filename, error);
      return MAPCACHE_FAILURE;
    }
  }
}