예제 #1
0
파일: dimension.c 프로젝트: EOX-A/mapcache
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);
  }
}
예제 #2
0
static int _mapcache_cache_riak_has_tile(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) {
    int error;
    int retries = 3;
    RIACK_STRING key;
    struct RIACK_GET_OBJECT obj;
    struct RIACK_CLIENT *client;
    mapcache_pooled_connection *pc;
    mapcache_cache_riak *cache = (mapcache_cache_riak*)pcache;

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

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

    do
    {
        error = riack_get(client, cache->bucket, key, 0, &obj);
        if (error != RIACK_SUCCESS) {
            ctx->log(ctx, MAPCACHE_WARN, "Retry %d in riak_has_tile for tile %s from cache %s due to error %d", (4-retries), key.value, cache->cache.name, error);
            for (error = riack_reconnect(client);
                    error != RIACK_SUCCESS && retries > 0;
                    error = riack_reconnect(client))
            {
                --retries;
            }

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

    if (error != RIACK_SUCCESS) {
        riack_free_get_object(client, &obj);    // riack_get allocates the returned object so we need to deallocate it.
        mapcache_connection_pool_invalidate_connection(ctx,pc);
        ctx->set_error(ctx, 500, "riak: failed to get key %s: %d", key, error);
        return MAPCACHE_FALSE;
    }

    if (obj.object.content_count < 1 || obj.object.content[0].data_len == 0) {
        error = MAPCACHE_FALSE;
    } else {
        error = MAPCACHE_TRUE;
    }

    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 error;
}
예제 #3
0
/**
 * \brief push tile data to riak
 *
 * writes the content of mapcache_tile::data to the configured riak instance(s)
 * \private \memberof mapcache_cache_riak
 * \sa mapcache_cache::tile_set()
 */
static void _mapcache_cache_riak_set(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) {
    char *key,*content_type;
    int error;
    int connect_error = RIACK_SUCCESS;
    int retries = 3;
    struct RIACK_OBJECT object;
    struct RIACK_CONTENT content;
    struct RIACK_PUT_PROPERTIES properties;
    struct RIACK_CLIENT *client;
    mapcache_pooled_connection *pc;
    mapcache_cache_riak *cache = (mapcache_cache_riak*)pcache;

    memset(&content, 0, sizeof(struct RIACK_CONTENT));
    memset(&object, 0, sizeof(struct RIACK_OBJECT));
    memset(&properties, 0, sizeof(struct RIACK_PUT_PROPERTIES));

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

    properties.dw_use = 1;
    properties.dw = 0;*/


    key = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#");
    GC_CHECK_ERROR(ctx);

    if (!tile->encoded_data) {
        tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format);
        GC_CHECK_ERROR(ctx);
    }
    content_type = tile->tileset->format?(tile->tileset->format->mime_type?tile->tileset->format->mime_type:NULL):NULL;

    if(!content_type) {
        /* compute the content-type */
        mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,tile->encoded_data);
        if(t == GC_PNG)
            content_type = "image/png";
        else if(t == GC_JPEG)
            content_type = "image/jpeg";
    }

    pc = _riak_get_connection(ctx, cache, tile);
    GC_CHECK_ERROR(ctx);
    client = pc->connection;

    // Set up the riak object to put.  Need to do this after we get the client connection
    object.bucket.value = cache->bucket.value;
    object.bucket.len = cache->bucket.len;
    object.key.value = key;
    object.key.len = strlen(key);
    object.vclock.len = 0;
    object.content_count = 1;
    object.content = &content;
    content.content_type.value = content_type;
    content.content_type.len = content_type?strlen(content_type):0;
    content.data = (uint8_t*)tile->encoded_data->buf;
    content.data_len = tile->encoded_data->size;

    // 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_put(client, object, 0, &properties);
        if (error != RIACK_SUCCESS) {
            ctx->log(ctx, MAPCACHE_WARN, "Retry %d in riak_set for tile %s from cache %s due to eror %d", (4 - retries), key, 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 (connect_error != RIACK_SUCCESS)
        mapcache_connection_pool_invalidate_connection(ctx,pc);
    else
        mapcache_connection_pool_release_connection(ctx,pc);

    if (error != RIACK_SUCCESS)
    {
        ctx->set_error(ctx, 500, "failed to store tile %s to cache %s due to error %d.", key, cache->cache.name, error);
    }
}
예제 #4
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;
}
예제 #5
0
/**
 * \private \memberof mapcache_source_mapserver
 * \sa mapcache_source::render_map()
 */
void _mapcache_source_mapserver_render_map(mapcache_context *ctx, mapcache_map *map)
{
  errorObj *errors = NULL;
  mapcache_pooled_connection *pc;
  struct mc_mapobj *mcmap;
  double dx, dy;
  rasterBufferObj rb;
  imageObj *image;

  pc = _mapserver_get_connection(ctx, map);
  GC_CHECK_ERROR(ctx);

  mcmap = pc->connection;
  GC_CHECK_ERROR(ctx);

  if(mcmap->grid_link != map->grid_link) {
    if (msLoadProjectionString(&(mcmap->map->projection), map->grid_link->grid->srs) != 0) {
      ctx->set_error(ctx,500, "Unable to set projection on mapObj.");
      errors = msGetErrorObj();
      while(errors) {
        ctx->set_error(ctx,500, "Unable to set projection on mapObj. MapServer reports: %s", errors->message);
        errors = errors->next;
      }
      mapcache_connection_pool_invalidate_connection(ctx,pc);
      return;
    }
    switch(map->grid_link->grid->unit) {
      case MAPCACHE_UNIT_DEGREES:
        mcmap->map->units = MS_DD;
        break;
      case MAPCACHE_UNIT_FEET:
        mcmap->map->units = MS_FEET;
        break;
      case MAPCACHE_UNIT_METERS:
        mcmap->map->units = MS_METERS;
        break;
    }
    mcmap->grid_link = map->grid_link;
  }


  /*
  ** WMS extents are edge to edge while MapServer extents are center of
  ** pixel to center of pixel.  Here we try to adjust the WMS extents
  ** in by half a pixel.
  */
  dx = (map->extent.maxx - map->extent.minx) / (map->width*2);
  dy = (map->extent.maxy - map->extent.miny) / (map->height*2);

  mcmap->map->extent.minx = map->extent.minx + dx;
  mcmap->map->extent.miny = map->extent.miny + dy;
  mcmap->map->extent.maxx = map->extent.maxx - dx;
  mcmap->map->extent.maxy = map->extent.maxy - dy;
  msMapSetSize(mcmap->map, map->width, map->height);

  image = msDrawMap(mcmap->map, MS_FALSE);
  if(!image) {
    ctx->set_error(ctx,500, "MapServer failed to create image.");
    errors = msGetErrorObj();
    while(errors) {
      ctx->set_error(ctx,500, "MapServer reports: %s", errors->message);
      errors = errors->next;
    }
    mapcache_connection_pool_invalidate_connection(ctx,pc);
    return;
  }

  if(image->format->vtable->supports_pixel_buffer) {
    if( MS_SUCCESS != image->format->vtable->getRasterBufferHandle(image,&rb)) {
      ctx->set_error(ctx,500,"failed to get mapserver raster buffer handle");
      mapcache_connection_pool_invalidate_connection(ctx,pc);
      return;
    }
  } else {
    ctx->set_error(ctx,500,"format %s has no pixel export",image->format->name);
    mapcache_connection_pool_invalidate_connection(ctx,pc);
    return;
  }

  map->raw_image = mapcache_image_create(ctx);
  map->raw_image->w = map->width;
  map->raw_image->h = map->height;
  map->raw_image->stride = 4 * map->width;
  map->raw_image->data = malloc(map->width*map->height*4);
  memcpy(map->raw_image->data,rb.data.rgba.pixels,map->width*map->height*4);
  apr_pool_cleanup_register(ctx->pool, map->raw_image->data,(void*)free, apr_pool_cleanup_null);
  msFreeImage(image);
  mapcache_connection_pool_release_connection(ctx,pc);

}