[mapserver-commits] r12130 - in trunk/mapserver/mapcache: include src

svn at osgeo.org svn at osgeo.org
Fri Aug 26 07:00:20 EDT 2011


Author: tbonfort
Date: 2011-08-26 04:00:20 -0700 (Fri, 26 Aug 2011)
New Revision: 12130

Modified:
   trunk/mapserver/mapcache/include/geocache.h
   trunk/mapserver/mapcache/src/cache_disk.c
   trunk/mapserver/mapcache/src/tileset.c
   trunk/mapserver/mapcache/src/util.c
Log:
add jpeg encoding and decoding
closes issue 1.
thomas.bonfort | 2010-10-19 10:19:42 +0200 (Tue, 19 Oct 2010)

Modified: trunk/mapserver/mapcache/include/geocache.h
===================================================================
--- trunk/mapserver/mapcache/include/geocache.h	2011-08-26 11:00:13 UTC (rev 12129)
+++ trunk/mapserver/mapcache/include/geocache.h	2011-08-26 11:00:20 UTC (rev 12130)
@@ -29,11 +29,13 @@
 
 #define GEOCACHE_SUCCESS 0
 #define GEOCACHE_FAILURE 1
+#define GEOCACHE_TRUE 1
+#define GEOCACHE_FALSE 0
 #define GEOCACHE_TILESET_WRONG_SIZE 2
 #define GEOCACHE_TILESET_WRONG_RESOLUTION 3
 #define GEOCACHE_TILESET_WRONG_EXTENT 4
 #define GEOCACHE_CACHE_MISS 5
-#define GEOCACHE_FILE_EXISTS 6
+#define GEOCACHE_FILE_LOCKED 6
 
 #define GEOCACHE_SERVICES_COUNT 2
 typedef enum {GEOCACHE_SERVICE_WMS=0, GEOCACHE_SERVICE_TMS} geocache_service_type;
@@ -105,6 +107,8 @@
    char* (*configuration_check)(geocache_cache *cache, apr_pool_t *pool);  
    int (*tile_lock)(geocache_tile *tile, request_rec *r);
    int (*tile_unlock)(geocache_tile *tile, request_rec *r);
+   int (*tile_lock_exists)(geocache_tile *tile, request_rec *r);
+   int (*tile_lock_wait)(geocache_tile *tile, request_rec *r);
 };
 
 typedef struct {
@@ -199,7 +203,6 @@
 /* functions exported in tileset.c */
 int geocache_tileset_tile_lookup(geocache_tile *tile, double *bbox, request_rec *r);
 int geocache_tileset_tile_get(geocache_tile *tile, request_rec *r);
-int geocache_tileset_tile_render(geocache_tile *tile, request_rec *r);
 geocache_tile* geocache_tileset_tile_create(geocache_tileset *tileset, apr_pool_t *pool);
 geocache_tileset* geocache_tileset_create(apr_pool_t *pool);
 void geocache_tileset_tile_bbox(geocache_tile *tile, double *bbox);
@@ -215,6 +218,8 @@
       int *numbers_count, apr_pool_t *pool);
 int geocache_util_extract_double_list(char* args, const char sep, double **numbers,
       int *numbers_count, apr_pool_t *pool);
+int geocache_util_mutex_aquire(request_rec *r);
+int geocache_util_mutex_release(request_rec *r);
 
 typedef struct {
    geocache_buffer *buffer;

Modified: trunk/mapserver/mapcache/src/cache_disk.c
===================================================================
--- trunk/mapserver/mapcache/src/cache_disk.c	2011-08-26 11:00:13 UTC (rev 12129)
+++ trunk/mapserver/mapcache/src/cache_disk.c	2011-08-26 11:00:20 UTC (rev 12130)
@@ -41,7 +41,7 @@
    return GEOCACHE_SUCCESS;
 }
 
-int _geocache_cache_disk_create_and_lock(geocache_tile *tile, request_rec *r) {
+int _geocache_cache_disk_tile_lock(geocache_tile *tile, request_rec *r) {
    char *filename;
    char *basename;
    char *dirname;
@@ -53,7 +53,7 @@
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to create directory %s",dirname);
       return GEOCACHE_FAILURE;
    }
-   filename = apr_psprintf(r->pool,"%s/%s",dirname,basename);
+   filename = apr_psprintf(r->pool,"%s/%s.lck",dirname,basename);
    /*create file, and fail if it already exists*/
    if(apr_file_open(&f, filename,
          APR_FOPEN_CREATE|APR_FOPEN_EXCL|APR_FOPEN_WRITE|APR_FOPEN_SHARELOCK|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,
@@ -66,10 +66,9 @@
          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to create file %s",filename);
          return GEOCACHE_FAILURE; /* we could not create the file */
       } else {
-         /* this shouldn't happen if the caller has properly mutex protected the call ? */
-         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "asked to create file %s, but it already exists",filename);
+         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "failed to create lockfile %s, because it already exists",filename);
          apr_file_close(f);
-         return GEOCACHE_FILE_EXISTS; /* we have write access, but the file already exists */
+         return GEOCACHE_FILE_LOCKED; /* we have write access, but the file already exists */
       }
    }
    rv = apr_file_lock(f, APR_FLOCK_EXCLUSIVE|APR_FLOCK_NONBLOCK);
@@ -85,20 +84,27 @@
    return GEOCACHE_SUCCESS;
 }
 
-int _geocache_cache_disk_unlock(geocache_tile *tile, request_rec *r) {
+int _geocache_cache_disk_tile_unlock(geocache_tile *tile, request_rec *r) {
+   apr_file_t *f = (apr_file_t*)tile->lock;
+   const char *fname;
    if(!tile->lock) {
-      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "attempting to unlock an already unlocked tile");
-      return GEOCACHE_FAILURE;
+      char *filename;
+      char *lockname;
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "###### TILE UNLOCK ######### attempting to unlock a tile not created by this thread");
+      _geocache_cache_disk_tile_key(r, tile, &filename);
+      lockname = apr_psprintf(r->pool,"%s.lck",filename);
+      /*create file, and fail if it already exists*/
+      if(apr_file_open(&f, lockname,APR_FOPEN_READ,APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "###### TILE UNLOCK ######### tile is not locked");
+         return GEOCACHE_FAILURE;
+      }
+   } else {
+      f = (apr_file_t*)tile->lock;
    }
-   apr_finfo_t finfo;
-   apr_file_t *f = (apr_file_t*)tile->lock;
-   apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
-   if(!finfo.size) {
-      ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "unlocking an empty tile, we will remove it");
-      const char *fname;
-      apr_file_name_get(&fname,f);
-      apr_file_remove(fname,r->pool);
-   }
+
+   apr_file_name_get(&fname,f);
+   apr_file_remove(fname,r->pool);
+
    int rv = apr_file_unlock(f);
    if(rv != APR_SUCCESS) {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to unlock file");
@@ -113,6 +119,43 @@
    return rv;
 }
 
+int _geocache_cache_disk_tile_is_locked(geocache_tile *tile, request_rec *r) {
+   char *filename;
+   char *lockname;
+   apr_file_t *f;
+   if(tile->lock)
+      return GEOCACHE_TRUE;
+   _geocache_cache_disk_tile_key(r, tile, &filename);
+   lockname = apr_psprintf(r->pool,"%s.lck",filename);
+   if(apr_file_open(&f, lockname,APR_FOPEN_READ,APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+      return GEOCACHE_FALSE;
+   } else {
+      apr_file_close(f);
+      return GEOCACHE_TRUE;
+   }
+}
+
+int _geocache_cache_disk_tile_wait_for_lock(geocache_tile *tile, request_rec *r) {
+   char *filename;
+   char *lockname;
+   apr_file_t *f;
+#ifdef DEBUG
+   if(tile->lock) {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "### BUG ### waiting for a lock we have created ourself");
+      return GEOCACHE_FAILURE;
+   }
+#endif
+   _geocache_cache_disk_tile_key(r, tile, &filename);
+   lockname = apr_psprintf(r->pool,"%s.lck",filename);
+   if(apr_file_open(&f, lockname,APR_FOPEN_READ,APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "### BUG ### waiting for a lock on an unlocked file");
+      return GEOCACHE_FAILURE;
+   }
+   apr_file_lock(f,APR_FLOCK_SHARED);
+   apr_file_close(f);
+   return GEOCACHE_SUCCESS;
+}
+
 int _geocache_cache_disk_get(geocache_tile *tile, request_rec *r) {
    char *filename;
    apr_file_t *f;
@@ -121,70 +164,60 @@
    apr_size_t size;
    _geocache_cache_disk_tile_key(r, tile, &filename);
    if(apr_file_open(&f, filename, APR_FOPEN_READ|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,
-         APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
-      /* the file doesn't exist on the disk */
-      return GEOCACHE_CACHE_MISS;
-   }
-   apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
-   if(!finfo.size) {
-      /* 
-       * the file exists on the disk, but it has 0 length. This is normally because another
-       * thread / process has indicated it is doing the rendering.
-       * we put a shared lock on the resource, to wait until the other thread has finished
-       */
-      rv = apr_file_lock(f, APR_FLOCK_SHARED);
-      if(rv != APR_SUCCESS) {
-         const char *filename;
-         apr_file_name_get(&filename,f);
-         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "failed to set read lock on %s",filename);
-         return GEOCACHE_FAILURE;
-      }
-      apr_file_unlock(f);
-      /* should we reopen the file now ? */
-      apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
+         APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
+      rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
       if(!finfo.size) {
-         const char *filename;
-         apr_file_name_get(&filename,f);
          ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "tile %s has no data",filename);
          return GEOCACHE_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.
+       * 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->data = geocache_buffer_create(size,r->pool);
+      //manually add the data to our buffer
+      apr_file_read(f,(void*)tile->data->buf,&size);
+      tile->data->size = size;
+      apr_file_close(f);
+      if(size != finfo.size) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to copy image data, got %d of %d bytes",(int)size, (int)finfo.size);
+         return GEOCACHE_FAILURE;
+      }
+      return GEOCACHE_SUCCESS;
    }
-   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.
-    * 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->data = geocache_buffer_create(size,r->pool);
-   //manually add the data to our buffer
-   apr_file_read(f,(void*)tile->data->buf,&size);
-   tile->data->size = size;
-   apr_file_close(f);
-   if(size != finfo.size) {
-      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to copy image data, got %d of %d bytes",(int)size, (int)finfo.size);
-      return GEOCACHE_FAILURE;
-   }
-
-   return GEOCACHE_SUCCESS;
+   /* the file doesn't exist on the disk */
+   return GEOCACHE_CACHE_MISS;
 }
 
 int _geocache_cache_disk_set(geocache_tile *tile, request_rec *r) {
    apr_size_t bytes;
-   apr_file_t *f = (apr_file_t*)tile->lock;
+   apr_file_t *f;
+   char *filename;
 #ifdef DEBUG
    /* all this should be checked at a higher level */
    if(!tile->data || !tile->data->size) {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "attempting to write empty tile to disk");
       return GEOCACHE_FAILURE;
    }
-   if(!f) {
+   if(!tile->lock) {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "attempting to write to an unlocked tile");
       return GEOCACHE_FAILURE;
    }
 #endif
+   _geocache_cache_disk_tile_key(r, tile, &filename);
+   if(apr_file_open(&f, filename,
+         APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,
+         APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to create file %s",filename);
+      return GEOCACHE_FAILURE; /* we could not create the file */
+   }
+
    bytes = (apr_size_t)tile->data->size;
    apr_file_write(f,(void*)tile->data->buf,&bytes);
 
@@ -192,6 +225,8 @@
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed to write image data to disk, wrote %d of %d bytes",(int)bytes, (int)tile->data->size);
       return GEOCACHE_FAILURE;
    }
+
+   apr_file_close(f);
    return GEOCACHE_SUCCESS;
 }
 
@@ -234,8 +269,10 @@
    cache->cache.tile_set = _geocache_cache_disk_set;
    cache->cache.configuration_check = _geocache_cache_disk_configuration_check;
    cache->cache.configuration_parse = _geocache_cache_disk_configuration_parse;
-   cache->cache.tile_lock = _geocache_cache_disk_create_and_lock;
-   cache->cache.tile_unlock = _geocache_cache_disk_unlock;
+   cache->cache.tile_lock = _geocache_cache_disk_tile_lock;
+   cache->cache.tile_unlock = _geocache_cache_disk_tile_unlock;
+   cache->cache.tile_lock_exists = _geocache_cache_disk_tile_is_locked;
+   cache->cache.tile_lock_wait = _geocache_cache_disk_tile_wait_for_lock;
    return cache;
 }
 

Modified: trunk/mapserver/mapcache/src/tileset.c
===================================================================
--- trunk/mapserver/mapcache/src/tileset.c	2011-08-26 11:00:13 UTC (rev 12129)
+++ trunk/mapserver/mapcache/src/tileset.c	2011-08-26 11:00:20 UTC (rev 12130)
@@ -52,14 +52,69 @@
    return GEOCACHE_SUCCESS;
 }
 
+void _geocache_tileset_metatile_lock(geocache_metatile *mt, request_rec *r) {
+   int i;
+   for(i=0; i<mt->ntiles; i++) {
+      geocache_tile *tile = &(mt->tiles[i]);
+      mt->tile.tileset->cache->tile_lock(tile,r);
+   }
+}
+
+void _geocache_tileset_metatile_unlock(geocache_metatile *mt, request_rec *r) {
+   int i;
+   for(i=0; i<mt->ntiles; i++) {
+      geocache_tile *tile = &(mt->tiles[i]);
+      mt->tile.tileset->cache->tile_unlock(tile,r);
+   }
+}
+
+//return the list of tiles that should be rendered for a metatile request
+static geocache_metatile* _geocache_tileset_metatile_get(geocache_tile *tile, request_rec *r) {
+   geocache_metatile *mt = (geocache_metatile*)apr_pcalloc(r->pool, sizeof(geocache_metatile));
+   int i,j,blx,bly;
+   double res = tile->tileset->resolutions[tile->z];
+   double gbuffer,gwidth,gheight;
+   mt->tile.tileset = tile->tileset;
+   mt->ntiles = mt->tile.tileset->metasize_x * mt->tile.tileset->metasize_y;
+   mt->tiles = (geocache_tile*)apr_pcalloc(r->pool, mt->ntiles * sizeof(geocache_tile));
+   mt->tile.sx =  mt->tile.tileset->metasize_x * tile->sx + 2 * mt->tile.tileset->metabuffer;
+   mt->tile.sy =  mt->tile.tileset->metasize_y * tile->sy + 2 * mt->tile.tileset->metabuffer;
+   mt->tile.z = tile->z;
+   mt->tile.x = tile->x / mt->tile.tileset->metasize_x;
+   mt->tile.y = tile->y / mt->tile.tileset->metasize_y;
+
+   //tilesize   = self.actualSize()
+   gbuffer = res * mt->tile.tileset->metabuffer;
+   gwidth = res * mt->tile.tileset->metasize_x * tile->sx;
+   gheight = res * mt->tile.tileset->metasize_y * tile->sy;
+   mt->bbox[0] = mt->tile.tileset->extent[0] + mt->tile.x * gwidth - gbuffer;
+   mt->bbox[1] = mt->tile.tileset->extent[1] + mt->tile.y * gheight - gbuffer;
+   mt->bbox[2] = mt->bbox[0] + gwidth + 2 * gbuffer;
+   mt->bbox[3] = mt->bbox[1] + gheight + 2 * gbuffer;
+
+   blx = mt->tile.x * mt->tile.tileset->metasize_x;
+   bly = mt->tile.y * mt->tile.tileset->metasize_y;
+   for(i=0; i<mt->tile.tileset->metasize_x; i++) {
+      for(j=0; j<mt->tile.tileset->metasize_y; j++) {
+         geocache_tile *t = &(mt->tiles[i*mt->tile.tileset->metasize_x+j]);
+         t->z = tile->z;
+         t->x = blx + i;
+         t->y = bly + j;
+         t->tileset = tile->tileset;
+         t->sx = tile->sx;
+         t->sy = tile->sy;
+      }
+   }
+
+   return mt;
+}
+
 void geocache_tileset_tile_bbox(geocache_tile *tile, double *bbox) {
-
    double res  = tile->tileset->resolutions[tile->z];
    bbox[0] = tile->tileset->extent[0] + (res * tile->x * tile->sx);
    bbox[1] = tile->tileset->extent[1] + (res * tile->y * tile->sy);
    bbox[2] = tile->tileset->extent[0] + (res * (tile->x + 1) * tile->sx);
    bbox[3] = tile->tileset->extent[1] + (res * (tile->y + 1) * tile->sy);
-
 }
 
 geocache_tileset* geocache_tileset_create(apr_pool_t *pool) {
@@ -90,7 +145,9 @@
 }
 
 int geocache_tileset_tile_get(geocache_tile *tile, request_rec *r) {
-   int ret;
+   int ret,i;
+   int isLocked;
+   geocache_metatile *mt;
    if(tile->sx != tile->tileset->tile_sx || tile->sy != tile->tileset->tile_sy) {
       ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
             "tileset %s: asked for a %dx%d tile from a %dx%d tileset",tile->tileset->name,
@@ -99,133 +156,79 @@
    }
    ret = tile->tileset->cache->tile_get(tile, r);
    if(ret == GEOCACHE_CACHE_MISS) {
-      ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-            "cache miss: tileset %s - tile %d %d %d",tile->tileset->name,tile->x, tile->y,tile->z);
-      ret = geocache_tileset_tile_render(tile, r);
+      /* the tile does not exist, we must take action before re-asking for it */
+
+      /*
+       * is the tile already being rendered by another thread ?
+       * the call is protected by the same mutex that sets the lock on the tile,
+       * so we can assure that:
+       * - if the lock does not exist, then this thread should do the rendering
+       * - if the lock exists, we should wait for the other thread to finish
+       */
+      ret = geocache_util_mutex_aquire(r);
       if(ret != GEOCACHE_SUCCESS) return ret;
-      //if successful, the cache will now contain the tile
-      ret = tile->tileset->cache->tile_get(tile, r);
-      if(ret != GEOCACHE_SUCCESS) {
-         ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "tileset %s: failed to re-get tile from cache after set", tile->tileset->name);
-         return ret;
-      }
-      return GEOCACHE_SUCCESS;
-   } else {
-      return ret;
-   }
-}
 
-//return the list of tiles that should be rendered for a metatile request
-static geocache_metatile* _geocache_tileset_metatile_get(geocache_tile *tile, request_rec *r) {
-   geocache_metatile *mt = (geocache_metatile*)apr_pcalloc(r->pool, sizeof(geocache_metatile));
-   int i,j,blx,bly;
-   double res = tile->tileset->resolutions[tile->z];
-   double gbuffer,gwidth,gheight;
-   mt->tile.tileset = tile->tileset;
-   mt->ntiles = mt->tile.tileset->metasize_x * mt->tile.tileset->metasize_y;
-   mt->tiles = (geocache_tile*)apr_pcalloc(r->pool, mt->ntiles * sizeof(geocache_tile));
-   mt->tile.sx =  mt->tile.tileset->metasize_x * tile->sx + 2 * mt->tile.tileset->metabuffer;
-   mt->tile.sy =  mt->tile.tileset->metasize_y * tile->sy + 2 * mt->tile.tileset->metabuffer;
-   mt->tile.z = tile->z;
-   mt->tile.x = tile->x / mt->tile.tileset->metasize_x;
-   mt->tile.y = tile->y / mt->tile.tileset->metasize_y;
-
-   //tilesize   = self.actualSize()
-   gbuffer = res * mt->tile.tileset->metabuffer;
-   gwidth = res * mt->tile.tileset->metasize_x * tile->sx;
-   gheight = res * mt->tile.tileset->metasize_y * tile->sy;
-   mt->bbox[0] = mt->tile.tileset->extent[0] + mt->tile.x * gwidth - gbuffer;
-   mt->bbox[1] = mt->tile.tileset->extent[1] + mt->tile.y * gheight - gbuffer;
-   mt->bbox[2] = mt->bbox[0] + gwidth + 2 * gbuffer;
-   mt->bbox[3] = mt->bbox[1] + gheight + 2 * gbuffer;
-
-   blx = mt->tile.x * mt->tile.tileset->metasize_x;
-   bly = mt->tile.y * mt->tile.tileset->metasize_y;
-   for(i=0; i<mt->tile.tileset->metasize_x; i++) {
-      for(j=0; j<mt->tile.tileset->metasize_y; j++) {
-         geocache_tile *t = &(mt->tiles[i*mt->tile.tileset->metasize_x+j]);
-         t->z = tile->z;
-         t->x = blx + i;
-         t->y = bly + j;
-         t->tileset = tile->tileset;
-         t->sx = tile->sx;
-         t->sy = tile->sy;
+      isLocked = tile->tileset->cache->tile_lock_exists(tile,r);
+      if(isLocked == GEOCACHE_FALSE) {
+         /* no other thread is doing the rendering, we aquire and lock a list of tiles to render */
+         mt = _geocache_tileset_metatile_get(tile,r);
+         _geocache_tileset_metatile_lock(mt,r);
       }
-   }
 
-   return mt;
-}
+      ret = geocache_util_mutex_release(r);
+      if(ret != GEOCACHE_SUCCESS) return ret;
 
-int geocache_tileset_tile_render(geocache_tile *tile, request_rec *r) {
-   int ret;
-   if(tile->tileset->source->supports_metatiling) {
-      geocache_metatile *mt = _geocache_tileset_metatile_get(tile, r);
-      geocache_server_cfg *cfg = ap_get_module_config(r->server->module_config, &geocache_module);
-      int i;
-#ifdef DEBUG
-      if(!cfg) {
-         ap_log_error(APLOG_MARK, APLOG_CRIT, 0, r->server, "configuration not found in server context");
-         return HTTP_INTERNAL_SERVER_ERROR;
-      }
-#endif
-      ret = apr_global_mutex_lock(cfg->mutex);
-      if(ret != APR_SUCCESS) {
-         ap_log_error(APLOG_MARK, APLOG_CRIT, 0, r->server, "failed to aquire mutex lock");
-         return HTTP_INTERNAL_SERVER_ERROR;
-      }
-      apr_pool_cleanup_register(r->pool, cfg->mutex, (void*)apr_global_mutex_unlock, apr_pool_cleanup_null);
+      if(isLocked == GEOCACHE_TRUE) {
+         /* another thread is rendering the tile, we should wait for it to finish */
+         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,"cache wait: tileset %s - tile %d %d %d",
+               tile->tileset->name,tile->x, tile->y,tile->z);
+         tile->tileset->cache->tile_lock_wait(tile,r);
+      } else {
+         /* no other thread is doing the rendering, do it ourselves */
+         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,"cache miss: tileset %s - tile %d %d %d",
+               tile->tileset->name,tile->x, tile->y,tile->z);
 
-      for(i=0;i<mt->ntiles;i++) {
-         geocache_tile *tile = &(mt->tiles[i]);
-         ret = tile->tileset->cache->tile_lock(tile,r);
+         ret = tile->tileset->source->render_metatile(mt, r);
          if(ret != GEOCACHE_SUCCESS) {
-            if(i != 0 || ret != GEOCACHE_FILE_EXISTS) {
-               /* we have managed to lock some tiles, but not all, we have a threading mixup issue */
-               ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,"############ THREADING BUG ##############");
-               return GEOCACHE_FAILURE;
-            } else {
-               /* oh well, another thread has already started rendering this tile */
-               break;
-            }
+            geocache_util_mutex_aquire(r);
+            _geocache_tileset_metatile_unlock(mt,r);
+            geocache_util_mutex_release(r);
+            return ret;
          }
-      }
-      ret = apr_global_mutex_unlock(cfg->mutex);
-      if(ret != APR_SUCCESS) {
-         ap_log_error(APLOG_MARK, APLOG_CRIT, 0, r->server, "failed to release mutex");
-         return HTTP_INTERNAL_SERVER_ERROR;
-      }
-      apr_pool_cleanup_kill(r->pool, cfg->mutex, (void*)apr_global_mutex_unlock);
-      if(i != mt->ntiles) {
-         return GEOCACHE_SUCCESS;
-      }
+         ret = geocache_image_metatile_split(mt,r);
+         if(ret != GEOCACHE_SUCCESS) {
+            geocache_util_mutex_aquire(r);
+            _geocache_tileset_metatile_unlock(mt,r);
+            geocache_util_mutex_release(r);
+            return ret;
+         }
 
-
-      ret = tile->tileset->source->render_metatile(mt, r);
-      if(ret != GEOCACHE_SUCCESS) {
          for(i=0;i<mt->ntiles;i++) {
             geocache_tile *tile = &(mt->tiles[i]);
-            tile->tileset->cache->tile_unlock(tile,r);
+            ret = tile->tileset->cache->tile_set(tile, r);
+            if(ret != GEOCACHE_SUCCESS) {
+               geocache_util_mutex_aquire(r);
+               _geocache_tileset_metatile_unlock(mt,r);
+               geocache_util_mutex_release(r);
+               return ret;
+            }
          }
-         return ret;
-      }
-      geocache_image_metatile_split(mt,r);
 
-      for(i=0;i<mt->ntiles;i++) {
-         geocache_tile *tile = &(mt->tiles[i]);
-         ret = tile->tileset->cache->tile_set(tile, r);
+         geocache_util_mutex_aquire(r);
+         _geocache_tileset_metatile_unlock(mt,r);
+         geocache_util_mutex_release(r);
+
          if(ret != GEOCACHE_SUCCESS) return ret;
-         ret = tile->tileset->cache->tile_unlock(tile,r);
-         if(ret != GEOCACHE_SUCCESS) return ret;
-         //TODO: unlock and delete tiles if error
       }
-      return ret;
+
+      ret = tile->tileset->cache->tile_get(tile, r);
+      if(ret != GEOCACHE_SUCCESS) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+               "tileset %s: failed to re-get tile from cache after set", tile->tileset->name);
+         return ret;
+      }
+      return GEOCACHE_SUCCESS;
    } else {
-      //lock the file before rendering ?
-      tile->tileset->cache->tile_lock(tile,r);
-      ret = tile->tileset->source->render_tile(tile, r);
-      if(ret != GEOCACHE_SUCCESS) return ret;
-      ret = tile->tileset->cache->tile_set(tile, r);
-      tile->tileset->cache->tile_unlock(tile,r);
       return ret;
    }
 }

Modified: trunk/mapserver/mapcache/src/util.c
===================================================================
--- trunk/mapserver/mapcache/src/util.c	2011-08-26 11:00:13 UTC (rev 12129)
+++ trunk/mapserver/mapcache/src/util.c	2011-08-26 11:00:20 UTC (rev 12130)
@@ -17,6 +17,7 @@
 #include <geocache.h>
 #include <apr_strings.h>
 #include <apr_tables.h>
+#include <http_log.h>
 
 int geocache_util_extract_int_list(char* args, const char sep, int **numbers,
       int *numbers_count, apr_pool_t *pool) {
@@ -64,4 +65,28 @@
    return GEOCACHE_SUCCESS;
 }
 
+int geocache_util_mutex_aquire(request_rec *r) {
+   int ret;
+   geocache_server_cfg *cfg = ap_get_module_config(r->server->module_config, &geocache_module);
+   ret = apr_global_mutex_lock(cfg->mutex);
+   if(ret != APR_SUCCESS) {
+      ap_log_error(APLOG_MARK, APLOG_CRIT, 0, r->server, "failed to aquire mutex lock");
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+   apr_pool_cleanup_register(r->pool, cfg->mutex, (void*)apr_global_mutex_unlock, apr_pool_cleanup_null);
+   return GEOCACHE_SUCCESS;
+}
 
+int geocache_util_mutex_release(request_rec *r) {
+   int ret;
+   geocache_server_cfg *cfg = ap_get_module_config(r->server->module_config, &geocache_module);
+   ret = apr_global_mutex_unlock(cfg->mutex);
+   if(ret != APR_SUCCESS) {
+      ap_log_error(APLOG_MARK, APLOG_CRIT, 0, r->server, "failed to release mutex");
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+   apr_pool_cleanup_kill(r->pool, cfg->mutex, (void*)apr_global_mutex_unlock);
+   return GEOCACHE_SUCCESS;
+}
+
+



More information about the mapserver-commits mailing list