Пример #1
0
static void* APR_THREAD_FUNC _thread_get_tile(apr_thread_t *thread, void *data)
{
  _thread_tile* t = (_thread_tile*)data;
  mapcache_tileset_tile_get(t->ctx, t->tile);
#if !USE_THREADPOOL
  apr_thread_exit(thread, APR_SUCCESS);
#endif
  return NULL;
}
Пример #2
0
static void* APR_THREAD_FUNC seed_thread(apr_thread_t *thread, void *data)
#endif
{
  mapcache_tile *tile;
   mapcache_context seed_ctx = ctx;
   seed_ctx.log = seed_log;
   apr_pool_create(&seed_ctx.pool,ctx.pool);
   tile = mapcache_tileset_tile_create(ctx.pool, tileset, grid_link);
   tile->dimensions = dimensions;
   while(1) {
     struct seed_cmd cmd;
      apr_status_t ret;
      apr_pool_clear(seed_ctx.pool);
      
      ret = pop_queue(&cmd);
      if(ret != APR_SUCCESS || cmd.command == MAPCACHE_CMD_STOP) break;
      tile->x = cmd.x;
      tile->y = cmd.y;
      tile->z = cmd.z;
      if(cmd.command == MAPCACHE_CMD_SEED) {
         /* aquire a lock on the metatile ?*/
         mapcache_metatile *mt = mapcache_tileset_metatile_get(&seed_ctx, tile);
         int isLocked = mapcache_lock_or_wait_for_resource(&seed_ctx, mapcache_tileset_metatile_resource_key(&seed_ctx,mt));
         if(isLocked == MAPCACHE_TRUE) {
            /* this will query the source to create the tiles, and save them to the cache */
            mapcache_tileset_render_metatile(&seed_ctx, mt);
            mapcache_unlock_resource(&seed_ctx, mapcache_tileset_metatile_resource_key(&seed_ctx,mt));
         }
      } else if (cmd.command == MAPCACHE_CMD_TRANSFER) {
         int i;
         mapcache_metatile *mt = mapcache_tileset_metatile_get(&seed_ctx, tile);
         for (i = 0; i < mt->ntiles; i++) {
            mapcache_tile *subtile = &mt->tiles[i];
            mapcache_tileset_tile_get(&seed_ctx, subtile);
            subtile->tileset = tileset_transfer;
            tileset_transfer->cache->tile_set(&seed_ctx, subtile);
         }
      }
      else { //CMD_DELETE
         mapcache_tileset_tile_delete(&seed_ctx,tile,MAPCACHE_TRUE);
      }
      if(seed_ctx.get_error(&seed_ctx)) {
         error_detected++;
         ctx.log(&ctx,MAPCACHE_INFO,seed_ctx.get_error_message(&seed_ctx));
      }
   }
#ifdef USE_FORK
   return 0;
#else
   apr_thread_exit(thread,MAPCACHE_SUCCESS);
   return NULL;
#endif
}
Пример #3
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

}