Example #1
0
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);
  }
}
Example #2
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 #3
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
   }
}
Example #6
0
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;
   }
}
Example #8
0
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;
}
Example #9
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);
}
Example #10
0
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);
}
Example #11
0
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);
   }
}
Example #12
0
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;
}
Example #14
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);
}
Example #15
0
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;
   }
}
Example #16
0
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;
}
Example #17
0
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);
  }
}
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
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);
}
Example #21
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 #22
0
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);
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
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;
}
Example #26
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 #27
0
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;
}
Example #28
0
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);
}
Example #29
0
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);
}
Example #30
0
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

}