[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