示例#1
0
static void _mapcache_cache_mbtiles_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);
  if(!tile->raw_image) {
    tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data);
    if(GC_HAS_ERROR(ctx)) {
      mapcache_sqlite_release_conn(ctx, pc);
      return;
    }
  }
  sqlite3_exec(conn->handle, "BEGIN TRANSACTION", 0, 0, 0);
  _single_mbtile_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);
}
示例#2
0
static void _mapcache_cache_sqlite_delete(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,0);
  if (GC_HAS_ERROR(ctx)) {
    mapcache_sqlite_release_conn(ctx, pc);
    return;
  }
  conn = SQLITE_CONN(pc);
  stmt = conn->prepared_statements[SQLITE_DEL_TILE_STMT_IDX];
  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, cache, 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);
  mapcache_sqlite_release_conn(ctx, pc);
}
示例#3
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;
    }
}
示例#4
0
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);
}
示例#5
0
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);
}
示例#6
0
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;
}
示例#7
0
static void _mapcache_cache_mbtiles_delete(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 *stmt1,*stmt2,*stmt3;
    int ret;
    const char *tile_id;
    size_t tile_id_size;
    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);
    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, cache, 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);
            mapcache_sqlite_release_conn(ctx, pc);
            return;
        }
    } while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED);
    if (ret == SQLITE_DONE) { /* tile does not exist, ignore */
        sqlite3_reset(stmt1);
        mapcache_sqlite_release_conn(ctx, pc);
        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, cache, 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);
        mapcache_sqlite_release_conn(ctx, pc);
        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);
            mapcache_sqlite_release_conn(ctx, pc);
            return;
        }
    }

    sqlite3_reset(stmt1);
    sqlite3_reset(stmt2);
    sqlite3_reset(stmt3);
    mapcache_sqlite_release_conn(ctx, pc);
}