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

svn at osgeo.org svn at osgeo.org
Thu Oct 20 12:09:08 EDT 2011


Author: tbonfort
Date: 2011-10-20 09:09:08 -0700 (Thu, 20 Oct 2011)
New Revision: 12680

Modified:
   trunk/mapserver/mapcache/include/mapcache.h
   trunk/mapserver/mapcache/src/cache_disk.c
   trunk/mapserver/mapcache/src/cache_tiff.c
   trunk/mapserver/mapcache/src/fastcgi_mapcache.c
   trunk/mapserver/mapcache/src/lock.c
   trunk/mapserver/mapcache/src/mapcache_seed.c
   trunk/mapserver/mapcache/src/mod_mapcache.c
   trunk/mapserver/mapcache/src/tileset.c
Log:
completely rework and simplify resource locking strategy.



Modified: trunk/mapserver/mapcache/include/mapcache.h
===================================================================
--- trunk/mapserver/mapcache/include/mapcache.h	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/include/mapcache.h	2011-10-20 16:09:08 UTC (rev 12680)
@@ -182,32 +182,6 @@
      */
     void (*log)(mapcache_context *ctx, mapcache_log_level level, char *message, ...);
 
-    /**
-     * \brief aquire a lock shared between all instances of mapcache.
-     *
-     * depending on the underlying backend, this lock should be effective between threads and/or processes
-     * \memberof mapcache_context
-     * \param c
-     * \param nonblocking should the call block while waiting for the lock. if set to 0, the function will
-     *        return once the lock has been aquired. if set to 1, the function will return immediately, and
-     *        the return value should be checked to verify if the lock was successfully aquired, or if
-     *        another instance of mapcache had already quired the lock
-     * \returns MAPCACHE_SUCCESS if the lock was aquired
-     * \returns MAPCACHE_FAILURE if there was an error aquiring the lock
-     * \returns MAPCACHE_LOCKED if \param nonblocking was set to 1 and another instance has already aquired
-     *          the lock
-     */
-    void (*global_lock_aquire)(mapcache_context *ctx);
-
-    /**
-     * \brief release a previously aquired lock
-     *
-     * \memberof mapcache_context
-     * calling this function after an unsuccessful call to global_lock_aquire() or from a different thread
-     * or process that has called global_lock_aquire() has undefined behavior
-     */
-    void (*global_lock_release)(mapcache_context * ctx);
-
     const char* (*get_instance_id)(mapcache_context * ctx);
     int has_threads;
     apr_pool_t *pool;
@@ -412,7 +386,6 @@
     int count_x;
     int count_y;
     mapcache_image_format_jpeg *format;
-    apr_thread_mutex_t **threadlocks;
 };
 #endif
 
@@ -1033,7 +1006,6 @@
    int metasize_x, metasize_y;
    int ntiles; /**< the number of mapcache_metatile::tiles contained in this metatile */
    mapcache_tile *tiles; /**< the list of mapcache_tile s contained in this metatile */
-   void *lock; /**< pointer to opaque structure set by the locking mechanism */
 };
 
 
@@ -1240,31 +1212,12 @@
 void mapcache_tileset_add_watermark(mapcache_context *ctx, mapcache_tileset *tileset, const char *filename);
 
 
-/**
- * lock the tile
- */
-void mapcache_tileset_metatile_lock(mapcache_context *ctx, mapcache_metatile *tile);
+int mapcache_lock_or_wait_for_resource(mapcache_context *ctx, char *resource);
+void mapcache_unlock_resource(mapcache_context *ctx, char *resource);
 
 mapcache_metatile* mapcache_tileset_metatile_get(mapcache_context *ctx, mapcache_tile *tile);
 
-/**
- * unlock the tile
- */
-void mapcache_tileset_metatile_unlock(mapcache_context *ctx, mapcache_metatile *tile);
 
-/**
- * check if there is a lock on the tile (the lock will have been set by another process/thread)
- * \returns MAPCACHE_TRUE if the tile is locked by another process/thread
- * \returns MAPCACHE_FALSE if there is no lock on the tile
- */
-int mapcache_tileset_metatile_lock_exists(mapcache_context *ctx, mapcache_metatile *tile);
-
-/**
- * wait for the lock set on the tile (the lock will have been set by another process/thread)
- */
-void mapcache_tileset_metatile_lock_wait(mapcache_context *ctx, mapcache_metatile *tile);
-
-
 /** @} */
 
 
@@ -1328,13 +1281,6 @@
 char *mapcache_util_str_replace(apr_pool_t *pool, const char *string, const char *substr,
       const char *replacement );
 
-/*
-int mapcache_util_mutex_aquire(mapcache_context *r);
-int mapcache_util_mutex_release(mapcache_context *r);
- */
-
-
-
 /**\defgroup imageio Image IO */
 /** @{ */
 

Modified: trunk/mapserver/mapcache/src/cache_disk.c
===================================================================
--- trunk/mapserver/mapcache/src/cache_disk.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/cache_disk.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -332,9 +332,6 @@
       if(mapcache_image_blank_color(image) != MAPCACHE_FALSE) {
          char *blankname;
          _mapcache_cache_disk_blank_tile_key(ctx,tile,image->data,&blankname);
-         GC_CHECK_ERROR(ctx);
-         ctx->global_lock_aquire(ctx);
-         GC_CHECK_ERROR(ctx);
          if(apr_file_open(&f, blankname, APR_FOPEN_READ, APR_OS_DEFAULT, ctx->pool) != APR_SUCCESS) {
             /* create the blank file */
             char *blankdirname = apr_psprintf(ctx->pool, "%s/%s/%s/blanks",
@@ -342,43 +339,48 @@
                         tile->tileset->name,
                         tile->grid_link->grid->name);
             if(APR_SUCCESS != (ret = apr_dir_make_recursive(
-                  blankdirname,
-                  APR_OS_DEFAULT,ctx->pool))) {
-                  if(!APR_STATUS_IS_EEXIST(ret)) {
-                     ctx->set_error(ctx, 500,  "failed to create directory %s for blank tiles",blankdirname, apr_strerror(ret,errmsg,120));
-                     ctx->global_lock_release(ctx);
-                     return;
-                  }
+                        blankdirname, APR_OS_DEFAULT,ctx->pool))) {
+               if(!APR_STATUS_IS_EEXIST(ret)) {
+                  ctx->set_error(ctx, 500,  "failed to create directory %s for blank tiles",blankdirname, apr_strerror(ret,errmsg,120));
+                  return;
+               }
             }
-            if((ret = apr_file_open(&f, blankname,
-                  APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,
-                  APR_OS_DEFAULT, ctx->pool)) != APR_SUCCESS) {
-               ctx->set_error(ctx, 500,  "failed to create file %s: %s",blankname, apr_strerror(ret,errmsg,120));
-               ctx->global_lock_release(ctx);
-               return; /* we could not create the file */
-            }
 
-            bytes = (apr_size_t)tile->data->size;
-            ret = apr_file_write(f,(void*)tile->data->buf,&bytes);
-            if(ret != APR_SUCCESS) {
-               ctx->set_error(ctx, 500,  "failed to write data to file %s (wrote %d of %d bytes): %s",blankname, (int)bytes, (int)tile->data->size, apr_strerror(ret,errmsg,120));
-               ctx->global_lock_release(ctx);
-               return; /* we could not create the file */
-            }
+            /* aquire a lock on the blank file */
+            int isLocked = mapcache_lock_or_wait_for_resource(ctx,blankname);
 
-            if(bytes != tile->data->size) {
-               ctx->set_error(ctx, 500,  "failed to write image data to %s, wrote %d of %d bytes", blankname, (int)bytes, (int)tile->data->size);
-               ctx->global_lock_release(ctx);
-               return;
-            }
-            apr_file_close(f);
+            if(isLocked == MAPCACHE_TRUE) {
+
+               if((ret = apr_file_open(&f, blankname,
+                           APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,
+                           APR_OS_DEFAULT, ctx->pool)) != APR_SUCCESS) {
+                  ctx->set_error(ctx, 500,  "failed to create file %s: %s",blankname, apr_strerror(ret,errmsg,120));
+                  mapcache_unlock_resource(ctx,blankname);
+                  return; /* we could not create the file */
+               }
+
+               bytes = (apr_size_t)tile->data->size;
+               ret = apr_file_write(f,(void*)tile->data->buf,&bytes);
+               if(ret != APR_SUCCESS) {
+                  ctx->set_error(ctx, 500,  "failed to write data to file %s (wrote %d of %d bytes): %s",blankname, (int)bytes, (int)tile->data->size, apr_strerror(ret,errmsg,120));
+                  mapcache_unlock_resource(ctx,blankname);
+                  return; /* we could not create the file */
+               }
+
+               if(bytes != tile->data->size) {
+                  ctx->set_error(ctx, 500,  "failed to write image data to %s, wrote %d of %d bytes", blankname, (int)bytes, (int)tile->data->size);
+                  mapcache_unlock_resource(ctx,blankname);
+                  return;
+               }
+               apr_file_close(f);
+               mapcache_unlock_resource(ctx,blankname);
 #ifdef DEBUG
-            ctx->log(ctx,MAPCACHE_DEBUG,"created blank tile %s",blankname);
+               ctx->log(ctx,MAPCACHE_DEBUG,"created blank tile %s",blankname);
 #endif
+            }
          } else {
             apr_file_close(f);
          }
-         ctx->global_lock_release(ctx);
          if(symlink(blankname,filename) != 0) {
             char *error = strerror(errno);
             ctx->set_error(ctx, 500,  "failed to link tile %s to %s: %s",filename, blankname, error);

Modified: trunk/mapserver/mapcache/src/cache_tiff.c
===================================================================
--- trunk/mapserver/mapcache/src/cache_tiff.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/cache_tiff.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -53,22 +53,6 @@
 #endif
 
 
-
-#ifdef USE_TIFF_WRITE
-#if APR_HAS_THREADS
-#include <apr_thread_mutex.h>
-#define THREADLOCK_HASHARRAY_SIZE 64
-static unsigned int _hash_key(char *key) {
-  unsigned hashval;
-  
-  for(hashval=0; *key!='\0'; key++)
-    hashval = *key + 31 * hashval;
-
-  return(hashval % THREADLOCK_HASHARRAY_SIZE);
-}
-#endif
-#endif
-
 /**
  * \brief return filename for given tile
  * 
@@ -541,38 +525,44 @@
        }
    }
    *hackptr2 = '/';
+   
+   int tilew = tile->grid_link->grid->tile_sx;
+   int tileh = tile->grid_link->grid->tile_sy;
+   
+   mapcache_image *tileimg = mapcache_imageio_decode(ctx, tile->data);
 
-#if APR_HAS_THREADS
-   /*
-    * aquire a thread lock for the filename. The filename is hashed to avoid all
-    * threads locking here if they are to access different files
-    */
-   unsigned int threadkey;
-   if(ctx->has_threads) {
-      threadkey = _hash_key(filename);
-      rv = apr_thread_mutex_lock(dcache->threadlocks[threadkey]);
-      if(rv != APR_SUCCESS) {
-         ctx->set_error(ctx,500,"failed to lock threadlock %d for file %s",threadkey,filename);
-         return;
+   /* remap xrgb to rgb */
+   unsigned char *rgb = (unsigned char*)malloc(tilew*tileh*3);
+   int r,c;
+   for(r=0;r<tileimg->h;r++) {
+      unsigned char *imptr = tileimg->data + r * tileimg->stride;
+      unsigned char *rgbptr = rgb + r * tilew * 3;
+      for(c=0;c<tileimg->w;c++) {
+         rgbptr[0] = imptr[2];
+         rgbptr[1] = imptr[1];
+         rgbptr[2] = imptr[0];
+         rgbptr += 3;
+         imptr += 4;
       }
    }
-#endif
 
    /*
     * aquire a lock on the tiff file. This lock does not work for multiple threads of
     * a same process, but should work on network filesystems.
     * we previously aquired a thread lock so we should be ok here
     */
-   apr_file_t *flock;
-   rv = apr_file_open(&flock,filename,APR_FOPEN_READ|APR_FOPEN_CREATE,APR_OS_DEFAULT,ctx->pool);
+
+   while(mapcache_lock_or_wait_for_resource(ctx,filename) == MAPCACHE_FALSE);
+   
+   apr_file_t *ftiff;
+   rv = apr_file_open(&ftiff,filename,APR_FOPEN_READ|APR_FOPEN_CREATE,APR_OS_DEFAULT,ctx->pool);
    if(rv != APR_SUCCESS) {
       ctx->set_error(ctx, 500,  "failed to remove existing file %s: %s",filename, apr_strerror(rv,errmsg,120));
       return; /* we could not delete the file */
    }
 
-   apr_file_lock(flock,APR_FLOCK_EXCLUSIVE); /* aquire the lock (this call is blocking) */
    apr_finfo_t finfo;
-   rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, flock);
+   rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, ftiff);
 
    /*
     * check if the file exists by looking at its size
@@ -586,16 +576,11 @@
    }
    if(!hTIFF) {
       ctx->set_error(ctx,500,"failed to open/create tiff file %s\n",filename);
-      apr_file_unlock(flock);
-      apr_file_close(flock);
-      if(ctx->has_threads) {
-         apr_thread_mutex_unlock(dcache->threadlocks[threadkey]);
-      }
+      mapcache_unlock_resource(ctx,filename);
+      apr_file_close(ftiff);
       return;
    }
 
-   int tilew = tile->grid_link->grid->tile_sx;
-   int tileh = tile->grid_link->grid->tile_sy;
 
    /* 
     * compute the width and height of the full tiff file. This
@@ -703,23 +688,7 @@
    tiff_offy = ntilesy - (tile->y % ntilesy) -1;
    tiff_off = tiff_offy * ntilesx + tiff_offx;
 
-   mapcache_image *tileimg = mapcache_imageio_decode(ctx, tile->data);
 
-   /* remap xrgb to rgb */
-   unsigned char *rgb = (unsigned char*)malloc(tilew*tileh*3);
-   int r,c;
-   for(r=0;r<tileimg->h;r++) {
-      unsigned char *imptr = tileimg->data + r * tileimg->stride;
-      unsigned char *rgbptr = rgb + r * tilew * 3;
-      for(c=0;c<tileimg->w;c++) {
-         rgbptr[0] = imptr[2];
-         rgbptr[1] = imptr[1];
-         rgbptr[2] = imptr[0];
-         rgbptr += 3;
-         imptr += 4;
-      }
-   }
-
    TIFFWriteEncodedTile(hTIFF, tiff_off, rgb, tilew*tileh*3);
    free(rgb);
    TIFFWriteCheck( hTIFF, 1, "cache_set()");
@@ -731,14 +700,8 @@
 
    MyTIFFClose(hTIFF);
 
-   apr_file_unlock(flock);
-   apr_file_close(flock);
-
-#if APR_HAS_THREADS
-   if(ctx->has_threads) {
-      apr_thread_mutex_unlock(dcache->threadlocks[threadkey]);
-   }
-#endif
+   mapcache_unlock_resource(ctx,filename);
+   apr_file_close(ftiff);
 #else
    ctx->set_error(ctx,500,"tiff write support disabled by default");
 #endif
@@ -793,20 +756,6 @@
       return;
    }
    dcache->format = (mapcache_image_format_jpeg*)pformat;
-
-#ifdef USE_TIFF_WRITE
-#if APR_HAS_THREADS
-   if(ctx->has_threads) {
-      /* create an array of thread locks */
-      dcache->threadlocks = (apr_thread_mutex_t**)apr_pcalloc(ctx->pool,
-            THREADLOCK_HASHARRAY_SIZE*sizeof(apr_thread_mutex_t*));
-      int i;
-      for(i=0;i<THREADLOCK_HASHARRAY_SIZE;i++) {
-         apr_thread_mutex_create(&(dcache->threadlocks[i]),APR_THREAD_MUTEX_UNNESTED,ctx->pool);
-      }
-   }
-#endif
-#endif
 }
 
 /**

Modified: trunk/mapserver/mapcache/src/fastcgi_mapcache.c
===================================================================
--- trunk/mapserver/mapcache/src/fastcgi_mapcache.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/fastcgi_mapcache.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -81,54 +81,11 @@
    }
 }
 
-
-static void mapcache_fcgi_mutex_aquire(mapcache_context *gctx) {
-   mapcache_context_fcgi *ctx = (mapcache_context_fcgi*)gctx;
-   int ret;
-#ifdef DEBUG
-   if(ctx->mutex_file != NULL) {
-      gctx->set_error(gctx, 500, "SEVERE: fcgi recursive mutex acquire");
-      return; /* BUG ! */
-   }
-#endif
-   if (apr_file_open(&ctx->mutex_file, ctx->mutex_fname,
-             APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_SHARELOCK | APR_FOPEN_BINARY,
-             APR_OS_DEFAULT, gctx->pool) != APR_SUCCESS) {
-      gctx->set_error(gctx, 500, "failed to create fcgi mutex lockfile %s", ctx->mutex_fname);
-      return; /* we could not create the file */
-   }
-   ret = apr_file_lock(ctx->mutex_file, APR_FLOCK_EXCLUSIVE);
-   if (ret != APR_SUCCESS) {
-      gctx->set_error(gctx, 500, "failed to lock fcgi mutex file %s", ctx->mutex_fname);
-      return;
-   }
-}
-
 static void handle_signal(int signal) {
    apr_pool_destroy(global_pool);
    exit(signal);
 }
 
-static void mapcache_fcgi_mutex_release(mapcache_context *gctx) {
-   int ret;
-   mapcache_context_fcgi *ctx = (mapcache_context_fcgi*)gctx;
-#ifdef DEBUG
-   if(ctx->mutex_file == NULL) {
-      gctx->set_error(gctx, 500, "SEVERE: fcgi mutex unlock on unlocked file");
-      return; /* BUG ! */
-   }
-#endif
-   ret = apr_file_unlock(ctx->mutex_file);
-   if(ret != APR_SUCCESS) {
-      gctx->set_error(gctx, 500,  "failed to unlock fcgi mutex file%s",ctx->mutex_fname);
-   }
-   ret = apr_file_close(ctx->mutex_file);
-   if(ret != APR_SUCCESS) {
-      gctx->set_error(gctx, 500,  "failed to close fcgi mutex file %s",ctx->mutex_fname);
-   }
-   ctx->mutex_file = NULL;
-}
-
 static mapcache_context_fcgi* fcgi_context_create() {
    mapcache_context_fcgi *ctx = apr_pcalloc(global_pool, sizeof(mapcache_context_fcgi));
    if(!ctx) {
@@ -138,8 +95,6 @@
    mapcache_context_init((mapcache_context*)ctx);
    ctx->ctx.log = fcgi_context_log;
    ctx->mutex_fname="/tmp/mapcache.fcgi.lock";
-   ctx->ctx.global_lock_aquire = mapcache_fcgi_mutex_aquire;
-   ctx->ctx.global_lock_release = mapcache_fcgi_mutex_release;
    ctx->ctx.config = NULL;
    return ctx;
 }

Modified: trunk/mapserver/mapcache/src/lock.c
===================================================================
--- trunk/mapserver/mapcache/src/lock.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/lock.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -30,344 +30,56 @@
 #include "mapcache.h"
 #include <apr_file_io.h>
 #include <apr_strings.h>
+#include <apr_time.h>
 
-#if THREADED_MPM
-#include <unistd.h>
-#endif
-
-
-#ifdef USE_SEMLOCK
-#include <semaphore.h>
-#include <errno.h>
-#include <fcntl.h>
-static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
-                       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                       "0123456789"
-                       "_";
-static int encbase = 63; /* 26 + 26+ 10 + 1 */
-
-static char* num_encode(apr_pool_t *pool, int num) {
-   int n = num,r;
-   int i = 0
-   /* allocate 10 chars, should be amply sufficient:
-    * yes, this *really* should be amply sufficient:
-    * 10 chars, in 63 base = 10^63 different values.
-    * the earth is 40000km wide, which means we will start having
-    * a problem if a tile is less than 40000 * 1000 / 10^63 = 4e-56 meters wide*/;
-   char *ret = apr_pcalloc(pool,10); 
-   while(1) {
-      r = n % encbase;
-      n = n / encbase;
-      ret[i] = alphabet[r];
-      if(n==0) break;
-      i++;
-   }
-   return ret;
-}
-
-#endif
-
-char *mapcache_tileset_metatile_lock_key(mapcache_context *ctx, mapcache_metatile *mt) {
-   char *lockname = apr_psprintf(ctx->pool,
-#ifdef USE_SEMLOCK
-         "/%s-%s-%s%s", /*x,y,z,tilesetname*/
-         num_encode(ctx->pool,mt->x), num_encode(ctx->pool,mt->y),
-         num_encode(ctx->pool,mt->z), 
-#else
-         "%s/"MAPCACHE_LOCKFILE_PREFIX"-%d-%d-%d-%s",
-         ctx->config->lockdir,
-         mt->z,mt->y,mt->x,
-#endif
-         mt->map.tileset->name);
-
-   /* if the tileset has multiple grids, add the name of the current grid to the lock key*/
-   if(mt->map.tileset->grid_links->nelts > 1) {
-      lockname = apr_pstrcat(ctx->pool,lockname,mt->map.grid_link->grid->name,NULL);
-   }
-
-   if(mt->map.dimensions && !apr_is_empty_table(mt->map.dimensions)) {
-      const apr_array_header_t *elts = apr_table_elts(mt->map.dimensions);
-      int i;
-      for(i=0;i<elts->nelts;i++) {
-         apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
-         char *dimvalue = apr_pstrdup(ctx->pool,entry.val);
-         char *iter = dimvalue;
-         while(*iter) {
-            if(*iter == '/') *iter='_';
-            iter++;
-         }
-         lockname = apr_pstrcat(ctx->pool,lockname,dimvalue,NULL);
+char* lock_filename_for_resource(mapcache_context *ctx, const char *resource) {
+   char *saferes = apr_pstrdup(ctx->pool,resource);
+   char *safeptr = saferes;
+   while(*safeptr) {
+      if(*safeptr==' ' || *safeptr == '/' || *safeptr == '~' || *safeptr == '.') {
+         *safeptr = '#';
       }
-
+      safeptr++;
    }
-
-#ifdef USE_SEMLOCK
-#ifdef __APPLE__
-#ifndef SEM_NAME_LEN
-#define SEM_NAME_LEN 31
-#endif
-#endif
-
-#ifdef SEM_NAME_LEN
-   /* truncate the lockname to the number of allowed characters */
-#warning "current platform only supports short semaphore names. you may see failed requests"
-   if(strlen(lockname) >= SEM_NAME_LEN) {
-      lockname[SEM_NAME_LEN-1]='\0';
-   }
-#endif
-#endif
-
-   return lockname;
+   return apr_psprintf(ctx->pool,"%s/"MAPCACHE_LOCKFILE_PREFIX"%s.lck",
+         ctx->config->lockdir,saferes);
 }
-/**
- * \brief lock the given metatile so other processes know it is being processed
- *
- * this function call is protected by a mutex
- *
- * this function creates a named semaphore and aquires a lock on it
- */
-void mapcache_tileset_metatile_lock(mapcache_context *ctx, mapcache_metatile *mt) {
-   char *lockname = mapcache_tileset_metatile_lock_key(ctx,mt);
-#ifdef USE_SEMLOCK
-   sem_t *lock;
-   if ((lock = sem_open(lockname, O_CREAT|O_EXCL, 0644, 1)) == SEM_FAILED) {
-      ctx->set_error(ctx,500, "failed to create posix semaphore %s: %s",lockname, strerror(errno));
-      return;
-   }
-   sem_wait(lock);
-   mt->lock = lock;
-#else
-   char errmsg[120];
-   apr_file_t *lock;
-   apr_status_t rv;
-   rv = apr_file_open(&lock,lockname,APR_WRITE|APR_CREATE|APR_EXCL,APR_OS_DEFAULT,ctx->pool);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "failed to create lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-      return;
-   }
-#if THREADED_MPM
-#else
-   /* we aquire an exclusive (i.e. write) lock on the file. For this to work, the file has to be opened with APR_WRITE mode */
-   rv = apr_file_lock(lock,APR_FLOCK_EXCLUSIVE|APR_FLOCK_NONBLOCK);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "failed to aquire an exclusive lock on lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-      return;
-   }
-#endif
-   mt->lock = lock;
-#endif
-}
 
-/**
- * \brief unlock a previously locked tile
- *
- * this function call is protected by a mutex
- *
- * \sa mapcache_cache::tile_unlock()
- * \sa mapcache_cache::tile_lock_exists()
- */
-void mapcache_tileset_metatile_unlock(mapcache_context *ctx, mapcache_metatile *mt) {
-   const char *lockname = mapcache_tileset_metatile_lock_key(ctx,mt);
-#ifdef USE_SEMLOCK
-   sem_t *lock = (sem_t*) mt->lock;
-   if (!mt->lock) {
-      ctx->set_error(ctx,500,"###### TILE UNLOCK ######### attempting to unlock tile %s not created by this thread", lockname);
-      return;
-   }
-   sem_post(lock);
-   sem_close(lock);
-   sem_unlink(lockname);
-   mt->lock = NULL;
-#else
-   char errmsg[120];
+int mapcache_lock_or_wait_for_resource(mapcache_context *ctx, char *resource) {
+   char *lockname = lock_filename_for_resource(ctx,resource);
+   apr_file_t *lockfile;
    apr_status_t rv;
-   if (!mt->lock) {
-      ctx->set_error(ctx,500,"###### TILE UNLOCK ######### attempting to unlock tile %s not created by this thread", lockname);
-      return;
-   }
-   apr_file_t *lock = (apr_file_t*)mt->lock;
-   mt->lock = NULL;
-#if THREADED_MPM
-#else
-   rv = apr_file_unlock(lock);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "failed to unlock lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-   }
-#endif
-   rv = apr_file_close(lock);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "failed to close lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-   }
-   rv = apr_file_remove(lockname,ctx->pool);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "failed to remove lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-   }
-#endif
-}
+   /* create the lockfile */
+   rv = apr_file_open(&lockfile,lockname,APR_WRITE|APR_CREATE|APR_EXCL,APR_OS_DEFAULT,ctx->pool);
 
-/**
- * \brief query tile to check if the corresponding lockfile exists
- * 
- * this function call is protected by a mutex
- *
- * \sa mapcache_cache::tile_lock()
- * \sa mapcache_cache::tile_unlock()
- */
-int mapcache_tileset_metatile_lock_exists(mapcache_context *ctx, mapcache_metatile *mt) {
-   char *lockname;
-   if (mt->lock)
-      return MAPCACHE_TRUE;
-   lockname = mapcache_tileset_metatile_lock_key(ctx, mt);
-#ifdef USE_SEMLOCK
-   sem_t *lock = sem_open(lockname, 0, 0644, 1) ;
-   if (lock == SEM_FAILED) {
-      if(errno == ENOENT) {
-         return MAPCACHE_FALSE;
-      } else {
-         ctx->set_error(ctx,500,"lock_exists: failed to open mutex %s",lockname);
-         return MAPCACHE_FALSE;
+   /* if the file already exists, wait for it to disappear */
+   /* TODO: check the lock isn't stale (i.e. too old) */
+   if( rv != APR_SUCCESS ) {
+      rv = apr_file_open(&lockfile,lockname,APR_READ,APR_OS_DEFAULT,ctx->pool);
+#ifdef DEBUG
+      if(!APR_STATUS_IS_ENOENT(rv)) {
+         ctx->log(ctx, MAPCACHE_DEBUG, "waiting on resource lock %s", resource);
       }
+#endif
+      while(!APR_STATUS_IS_ENOENT(rv)) {
+         /* sleep for a tenth of a second */
+         apr_sleep(1000);
+         rv = apr_file_open(&lockfile,lockname,APR_READ,APR_OS_DEFAULT,ctx->pool);
+         if(rv == APR_SUCCESS) {
+            apr_file_close(lockfile);
+         }
+      }
+      return MAPCACHE_FALSE;
    } else {
-      sem_close(lock);
+      /* we acquired the lock */
+      apr_file_close(lockfile);
       return MAPCACHE_TRUE;
    }
-#else
-   apr_status_t rv;
-   char errmsg[120];
-   apr_file_t *lock;
-   rv = apr_file_open(&lock,lockname,APR_READ,APR_OS_DEFAULT,ctx->pool);
-   if(APR_STATUS_IS_ENOENT(rv)) {
-      /* the lock file does not exist, the metatile is not locked */
-      return MAPCACHE_FALSE;
-   } else {
-      /* the file exists, or there was an error opening it */
-      if(rv != APR_SUCCESS) {
-         /* we failed to open the file, bail out */
-         ctx->set_error(ctx,500,"lock_exists: failed to open lockfile %s: %s",lockname,
-               apr_strerror(rv,errmsg,120));
-         return MAPCACHE_FALSE;
-      } else {
-#if THREADED_MPM
-         apr_file_close(lock);
-         return MAPCACHE_TRUE;
-#else
-         /* the file exists, which means there probably is a lock. make sure it isn't locked anyhow */
-         rv = apr_file_lock(lock,APR_FLOCK_SHARED|APR_FLOCK_NONBLOCK);
-         if(rv != APR_SUCCESS) {
-            if(rv == APR_EAGAIN) {
-               /* the file is locked */
-               apr_file_close(lock);
-               return MAPCACHE_TRUE;
-            } else {
-               ctx->set_error(ctx,500, "lock_exists: failed to aquire lock on lockfile %s: %s",
-                        lockname, apr_strerror(rv,errmsg,120));
-               rv = apr_file_close(lock);
-               if(rv!=APR_SUCCESS) {
-                  ctx->set_error(ctx,500, "lock_exists: failed to close lockfile %s: %s",
-                        lockname, apr_strerror(rv,errmsg,120));
-               }
-               return MAPCACHE_FALSE;
-            }
-         } else {
-            /* we managed to aquire a lock on the file, which means it isn't locked, even if it exists */
-            /* unlock the file */
-            rv = apr_file_unlock(lock);
-            if(rv!=APR_SUCCESS) {
-               ctx->set_error(ctx,500, "lock_exists: failed to unlock lockfile %s: %s",
-                     lockname, apr_strerror(rv,errmsg,120));
-            }
-            rv = apr_file_close(lock);
-            if(rv!=APR_SUCCESS) {
-               ctx->set_error(ctx,500, "lock_exists: failed to close lockfile %s: %s",
-                     lockname, apr_strerror(rv,errmsg,120));
-            }
-            //TODO: remove the file as we will fail later if not
-            return MAPCACHE_FALSE;
-         }
-#endif
-      }
-   }
-#endif
 }
 
-/**
- * \brief wait for a lock on given tile
- *
- * this function will not return until the lock on the tile has been removed
- * \sa mapcache_cache::tile_lock_wait()
- */
-void mapcache_tileset_metatile_lock_wait(mapcache_context *ctx, mapcache_metatile *mt) {
-  char *lockname;
-  lockname = mapcache_tileset_metatile_lock_key(ctx, mt);
-
-#ifdef DEBUG
-  if (mt->lock) {
-    ctx->set_error(ctx, 500, "### BUG ### lock_wait: waiting for a lock we have created ourself");
-    return;
-  }
-#endif
-
-#ifdef USE_SEMLOCK
-  sem_t *lock;
-  lock = sem_open(lockname, 0, 0644, 1) ;
-  if( lock == SEM_FAILED ) {
-     if(errno == ENOENT) {
-        /* the lock doesn't exist (anymore?) */
-        return; 
-     } else {
-        ctx->set_error(ctx,500, "lock_wait: failed to open semaphore %s",lockname);
-        return;
-     }
-  } else {
-     sem_wait(lock);
-     sem_post(lock);
-     sem_close(lock);
-  }
-#else
-   char errmsg[120];
-   apr_file_t *lock;
-   apr_status_t rv;
-   rv = apr_file_open(&lock,lockname,APR_READ,APR_OS_DEFAULT,ctx->pool);
-   if(rv != APR_SUCCESS) {
-      if(APR_STATUS_IS_ENOENT(rv)) {
-         /* the lock file does not exist, it might have been removed since we checked.
-          * anyhow, there's no use waiting anymore
-          */
-         return;
-      } else {
-         ctx->set_error(ctx,500, "lock_wait: failed to open lockfile %s: %s",
-               lockname, apr_strerror(rv,errmsg,120));
-         return;
-      }
-   }
-#if THREADED_MPM
-   apr_file_close(lock);
-   while(!APR_STATUS_IS_ENOENT(rv)) {
-      usleep(500000);
-      rv = apr_file_open(&lock,lockname,APR_READ,APR_OS_DEFAULT,ctx->pool);
-      if(rv == APR_SUCCESS) {
-         apr_file_close(lock);
-      }
-   }
-#else
-   rv = apr_file_lock(lock,APR_FLOCK_SHARED);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "lock_wait: failed to aquire a shared lock on lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-   }
-   rv = apr_file_close(lock);
-   if(rv!=APR_SUCCESS) {
-      ctx->set_error(ctx,500, "lock_wait: failed to close lockfile %s: %s",
-            lockname, apr_strerror(rv,errmsg,120));
-   }
-#endif
-
-#endif
+void mapcache_unlock_resource(mapcache_context *ctx, char *resource) {
+   char *lockname = lock_filename_for_resource(ctx,resource);
+   apr_file_remove(lockname,ctx->pool);
 }
 
 /* vim: ai ts=3 sts=3 et sw=3

Modified: trunk/mapserver/mapcache/src/mapcache_seed.c
===================================================================
--- trunk/mapserver/mapcache/src/mapcache_seed.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/mapcache_seed.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -67,8 +67,6 @@
 int seededtilestot=0, seededtiles=0, queuedtilestot=0;
 struct timeval lastlogtime,starttime;
 
-apr_thread_mutex_t *global_lock;
-
 typedef enum {
    MAPCACHE_CMD_SEED,
    MAPCACHE_CMD_STOP,
@@ -120,19 +118,6 @@
     }
 }
 
-void seed_lock_aquire(mapcache_context *ctx){
-   int rv = apr_thread_mutex_lock(global_lock);
-   if(rv != APR_SUCCESS) {
-      ctx->set_error(ctx,500,"failed to aquire seed mutex");
-   }
-}
-void seed_lock_release(mapcache_context *ctx){
-   int rv = apr_thread_mutex_unlock(global_lock);
-   if(rv != APR_SUCCESS) {
-      ctx->set_error(ctx,500,"failed to release seed mutex");
-   }
-}
-
 void seed_log(mapcache_context *ctx, mapcache_log_level level, char *msg, ...){
    if(verbose) {
       va_list args;
@@ -494,14 +479,9 @@
     cfg = mapcache_configuration_create(ctx.pool);
     ctx.config = cfg;
     ctx.log= mapcache_context_seeding_log;
-    ctx.global_lock_aquire = seed_lock_aquire;
-    ctx.global_lock_release = seed_lock_release;
     ctx.has_threads = 1;
     apr_getopt_init(&opt, ctx.pool, argc, argv);
 
-
-    apr_thread_mutex_create(&global_lock,APR_THREAD_MUTEX_UNNESTED,ctx.pool);
-    
     seededtiles=seededtilestot=queuedtilestot=0;
     gettimeofday(&starttime,NULL);
     lastlogtime=starttime;

Modified: trunk/mapserver/mapcache/src/mod_mapcache.c
===================================================================
--- trunk/mapserver/mapcache/src/mod_mapcache.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/mod_mapcache.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -144,41 +144,14 @@
    ap_log_rerror(APLOG_MARK, ap_log_level, 0, ctx->request, "%s", apr_pvsprintf(c->pool,message,args));
 }
 
-void mapcache_util_mutex_aquire(mapcache_context *gctx) {
-   int ret;
-   mapcache_context_apache_request *ctx = (mapcache_context_apache_request*)gctx;
-   mapcache_server_cfg *cfg = ap_get_module_config(ctx->request->server->module_config, &mapcache_module);
-   ret = apr_global_mutex_lock(cfg->mutex);
-   if(ret != APR_SUCCESS) {
-      gctx->set_error(gctx,500,"failed to lock mutex");
-      return;
-   }
-   apr_pool_cleanup_register(gctx->pool, cfg->mutex, (void*)apr_global_mutex_unlock, apr_pool_cleanup_null);
-}
-
-void mapcache_util_mutex_release(mapcache_context *gctx) {
-   int ret;
-   mapcache_context_apache_request *ctx = (mapcache_context_apache_request*)gctx;
-   mapcache_server_cfg *cfg = ap_get_module_config(ctx->request->server->module_config, &mapcache_module);
-   ret = apr_global_mutex_unlock(cfg->mutex);
-   if(ret != APR_SUCCESS) {
-      gctx->set_error(gctx,500,"failed to unlock mutex");
-   }
-   apr_pool_cleanup_kill(gctx->pool, cfg->mutex, (void*)apr_global_mutex_unlock);
-}
-
 void init_apache_request_context(mapcache_context_apache_request *ctx) {
    mapcache_context_init((mapcache_context*)ctx);
    ctx->ctx.ctx.log = apache_context_request_log;
-   ctx->ctx.ctx.global_lock_aquire = mapcache_util_mutex_aquire;
-   ctx->ctx.ctx.global_lock_release = mapcache_util_mutex_release;
 }
 
 void init_apache_server_context(mapcache_context_apache_server *ctx) {
    mapcache_context_init((mapcache_context*)ctx);
    ctx->ctx.ctx.log = apache_context_server_log;
-   ctx->ctx.ctx.global_lock_aquire = mapcache_util_mutex_aquire;
-   ctx->ctx.ctx.global_lock_release = mapcache_util_mutex_release;
 }
 
 static mapcache_context_apache_request* apache_request_context_create(request_rec *r) {
@@ -318,7 +291,6 @@
 static int mod_mapcache_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
    apr_status_t rc;
    mapcache_server_cfg* cfg = ap_get_module_config(s->module_config, &mapcache_module);
-   apr_lockmech_e lock_type = APR_LOCK_DEFAULT;
    server_rec *sconf;
 
    if(!cfg) {
@@ -326,30 +298,9 @@
       return 1;
    }
 
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
-   lock_type = APR_LOCK_PROC_PTHREAD;
-#endif
-   rc = apr_global_mutex_create(&cfg->mutex,cfg->mutex_name,lock_type,p);
-   if(rc != APR_SUCCESS) {
-      ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s, "Could not create global parent mutex %s", cfg->mutex_name);
-      return rc;
-   }
-#ifdef AP_NEED_SET_MUTEX_PERMS
-   rc = unixd_set_global_mutex_perms(cfg->mutex);
-   if(rc != APR_SUCCESS) {
-      ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s, "Could not set permissions on global parent mutex %s", cfg->mutex_name);
-      return rc;
-   }
-#endif
-   apr_pool_cleanup_register(p,cfg->mutex,
-         (void*)apr_global_mutex_destroy, apr_pool_cleanup_null);
 #ifndef DISABLE_VERSION_STRING
    ap_add_version_component(p, MAPCACHE_USERAGENT);
 #endif
-   for (sconf = s->next; sconf; sconf = sconf->next) {
-      mapcache_server_cfg* config = ap_get_module_config(sconf->module_config, &mapcache_module);
-      config->mutex = cfg->mutex;
-   }
 
 #if APR_HAS_FORK
    /* fork a child process to let it accomplish post-configuration tasks with the uid of the runtime user */
@@ -429,11 +380,6 @@
 }
 
 static void mod_mapcache_child_init(apr_pool_t *pool, server_rec *s) {
-   while(s) {
-      mapcache_server_cfg* cfg = ap_get_module_config(s->module_config, &mapcache_module);
-      apr_global_mutex_child_init(&(cfg->mutex),cfg->mutex_name, pool);
-      s = s->next;
-   }
 }
 
 static int mapcache_alias_matches(const char *uri, const char *alias_fakename)
@@ -523,8 +469,6 @@
 
 static void* mod_mapcache_create_server_conf(apr_pool_t *pool, server_rec *s) {
    mapcache_server_cfg *cfg = apr_pcalloc(pool, sizeof(mapcache_server_cfg));
-   char *mutex_unique_name = apr_psprintf(pool,"mapcachemutex-%d",getpid());
-   cfg->mutex_name = ap_server_root_relative(pool, mutex_unique_name);
    cfg->aliases = NULL;
    return cfg;
 }
@@ -535,8 +479,6 @@
    mapcache_server_cfg *base = (mapcache_server_cfg*)base_;
    mapcache_server_cfg *vhost = (mapcache_server_cfg*)vhost_;
    mapcache_server_cfg *cfg = apr_pcalloc(p,sizeof(mapcache_server_cfg));
-   cfg->mutex = base->mutex;
-   cfg->mutex_name = base->mutex_name;
    
    if (base->aliases && vhost->aliases) {
       cfg->aliases = apr_hash_overlay(p, vhost->aliases,base->aliases);

Modified: trunk/mapserver/mapcache/src/tileset.c
===================================================================
--- trunk/mapserver/mapcache/src/tileset.c	2011-10-20 08:22:22 UTC (rev 12679)
+++ trunk/mapserver/mapcache/src/tileset.c	2011-10-20 16:09:08 UTC (rev 12680)
@@ -33,6 +33,35 @@
 #include <apr_file_io.h>
 #include <math.h>
 
+char* mapcache_tileset_metatile_resource_key(mapcache_context *ctx, mapcache_metatile *mt) {
+   char *lockname = apr_psprintf(ctx->pool,
+         "%d-%d-%d-%s",
+         mt->z,mt->y,mt->x,
+         mt->map.tileset->name);
+
+   /* if the tileset has multiple grids, add the name of the current grid to the lock key*/
+   if(mt->map.tileset->grid_links->nelts > 1) {
+      lockname = apr_pstrcat(ctx->pool,lockname,mt->map.grid_link->grid->name,NULL);
+   }
+
+   if(mt->map.dimensions && !apr_is_empty_table(mt->map.dimensions)) {
+      const apr_array_header_t *elts = apr_table_elts(mt->map.dimensions);
+      int i;
+      for(i=0;i<elts->nelts;i++) {
+         apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
+         char *dimvalue = apr_pstrdup(ctx->pool,entry.val);
+         char *iter = dimvalue;
+         while(*iter) {
+            if(*iter == '/') *iter='_';
+            iter++;
+         }
+         lockname = apr_pstrcat(ctx->pool,lockname,dimvalue,NULL);
+      }
+
+   }
+   return lockname;
+}
+
 void mapcache_tileset_configuration_check(mapcache_context *ctx, mapcache_tileset *tileset) {
    
    /* check we have all we want */
@@ -477,29 +506,12 @@
        * - if the lock exists, we should wait for the other thread to finish
        */
 
-      ctx->global_lock_aquire(ctx);
-      GC_CHECK_ERROR(ctx);
-      
+      /* aquire a lock on the metatile */
       mt = mapcache_tileset_metatile_get(ctx, tile);
+      isLocked = mapcache_lock_or_wait_for_resource(ctx, mapcache_tileset_metatile_resource_key(ctx,mt));
 
-      isLocked = mapcache_tileset_metatile_lock_exists(ctx, mt);
-      if(isLocked == MAPCACHE_FALSE) {
-         /* no other thread is doing the rendering, we aquire and lock the metatile */
-         mapcache_tileset_metatile_lock(ctx, mt);
-      }
-      ctx->global_lock_release(ctx);
-      if(GC_HAS_ERROR(ctx))
-         return;
 
       if(isLocked == MAPCACHE_TRUE) {
-         /* another thread is rendering the tile, we should wait for it to finish */
-#ifdef DEBUG
-         ctx->log(ctx, MAPCACHE_DEBUG, "cache wait: tileset %s - tile %d %d %d",
-               tile->tileset->name,tile->x, tile->y,tile->z);
-#endif
-         mapcache_tileset_metatile_lock_wait(ctx,mt);
-         GC_CHECK_ERROR(ctx);
-      } else {
          /* no other thread is doing the rendering, do it ourselves */
 #ifdef DEBUG
          ctx->log(ctx, MAPCACHE_DEBUG, "cache miss: tileset %s - tile %d %d %d",
@@ -507,18 +519,16 @@
 #endif
          /* this will query the source to create the tiles, and save them to the cache */
          _mapcache_tileset_render_metatile(ctx, mt);
-         
-         /* remove the lockfiles */
-         ctx->global_lock_aquire(ctx);
-         mapcache_tileset_metatile_unlock(ctx,mt);
-         ctx->global_lock_release(ctx);
-         GC_CHECK_ERROR(ctx);
+
+         mapcache_unlock_resource(ctx, mapcache_tileset_metatile_resource_key(ctx,mt));
       }
       
       /* the previous step has successfully finished, we can now query the cache to return the tile content */
       ret = tile->tileset->cache->tile_get(ctx, tile);
+      GC_CHECK_ERROR(ctx);
+
       if(ret != MAPCACHE_SUCCESS) {
-         if(isLocked == MAPCACHE_TRUE) {
+         if(isLocked == MAPCACHE_FALSE) {
             ctx->set_error(ctx, 500, "tileset %s: unknown error (another thread/process failed to create the tile I was waiting for)",
                   tile->tileset->name);
          } else {



More information about the mapserver-commits mailing list