[mapserver-commits] r12335 - in trunk/mapserver/mapcache: . include
src
svn at osgeo.org
svn at osgeo.org
Fri Aug 26 07:17:46 EDT 2011
Author: tbonfort
Date: 2011-08-26 04:17:46 -0700 (Fri, 26 Aug 2011)
New Revision: 12335
Modified:
trunk/mapserver/mapcache/geocache.xml
trunk/mapserver/mapcache/include/geocache.h
trunk/mapserver/mapcache/src/configuration.c
trunk/mapserver/mapcache/src/lock.c
Log:
add mixed image format
closes issue 63.
thomas.bonfort | 2011-03-11 10:52:08 +0100 (Fri, 11 Mar 2011)
Modified: trunk/mapserver/mapcache/geocache.xml
===================================================================
--- trunk/mapserver/mapcache/geocache.xml 2011-08-26 11:17:40 UTC (rev 12334)
+++ trunk/mapserver/mapcache/geocache.xml 2011-08-26 11:17:46 UTC (rev 12335)
@@ -540,6 +540,13 @@
- assemble: build the full image by assembling the tiles from the cache
- forward: forward the request to the configured source.
-->
- <full_wms>forward</full_wms>
+ <full_wms>assemble</full_wms>
+
+ <!--
+ location to put lockfiles (to block other clients while a metatile is being rendered.
+ defaults to /tmp
+ this location should be writable by the apache user
+ -->
+ <lock_dir>/tmp</lock_dir>
</geocache>
Modified: trunk/mapserver/mapcache/include/geocache.h
===================================================================
--- trunk/mapserver/mapcache/include/geocache.h 2011-08-26 11:17:40 UTC (rev 12334)
+++ trunk/mapserver/mapcache/include/geocache.h 2011-08-26 11:17:46 UTC (rev 12335)
@@ -58,8 +58,10 @@
#define GEOCACHE_VERSION "0.3-dev"
#define GEOCACHE_USERAGENT "mod-geocache/"GEOCACHE_VERSION
+#define GEOCACHE_LOCKFILE_PREFIX "_gc_lock"
+
typedef struct geocache_image_format geocache_image_format;
typedef struct geocache_image_format_png geocache_image_format_png;
typedef struct geocache_image_format_png_q geocache_image_format_png_q;
@@ -762,6 +764,8 @@
geocache_getmap_strategy getmap_strategy;
apr_table_t *metadata;
+
+ const char *lockdir;
};
/**
Modified: trunk/mapserver/mapcache/src/configuration.c
===================================================================
--- trunk/mapserver/mapcache/src/configuration.c 2011-08-26 11:17:40 UTC (rev 12334)
+++ trunk/mapserver/mapcache/src/configuration.c 2011-08-26 11:17:46 UTC (rev 12335)
@@ -971,7 +971,39 @@
}
}
+ if((node = ezxml_child(doc,"lock_dir")) != NULL) {
+ config->lockdir = apr_pstrdup(ctx->pool, node->txt);
+ } else {
+ config->lockdir = apr_pstrdup(ctx->pool,"/tmp");
+ }
+ apr_dir_t *lockdir;
+ apr_status_t rv;
+ rv = apr_dir_open(&lockdir,config->lockdir,ctx->pool);
+ char errmsg[120];
+ if(rv != APR_SUCCESS) {
+ ctx->set_error(ctx,500, "failed to open lock directory %s: %s"
+ ,config->lockdir,apr_strerror(rv,errmsg,120));
+ goto cleanup;
+ }
+ apr_finfo_t finfo;
+ while ((apr_dir_read(&finfo, APR_FINFO_DIRENT|APR_FINFO_TYPE|APR_FINFO_NAME, lockdir)) == APR_SUCCESS) {
+ if(finfo.filetype == APR_REG) {
+ if(!strncmp(finfo.name, GEOCACHE_LOCKFILE_PREFIX, strlen(GEOCACHE_LOCKFILE_PREFIX))) {
+ ctx->log(ctx,GEOCACHE_WARNING,"found old lockfile %s/%s, deleting it",config->lockdir,
+ finfo.name);
+ rv = apr_file_remove(apr_psprintf(ctx->pool,"%s/%s",config->lockdir, finfo.name),ctx->pool);
+ if(rv != APR_SUCCESS) {
+ ctx->set_error(ctx,500, "failed to remove lockfile %s: %s",finfo.name,apr_strerror(rv,errmsg,120));
+ goto cleanup;
+ }
+ }
+
+ }
+ }
+ apr_dir_close(lockdir);
+
+
cleanup:
ezxml_free(doc);
return;
Modified: trunk/mapserver/mapcache/src/lock.c
===================================================================
--- trunk/mapserver/mapcache/src/lock.c 2011-08-26 11:17:40 UTC (rev 12334)
+++ trunk/mapserver/mapcache/src/lock.c 2011-08-26 11:17:46 UTC (rev 12335)
@@ -22,6 +22,7 @@
#include <fcntl.h>
+#ifdef USE_SEMLOCK
static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
@@ -47,11 +48,20 @@
return ret;
}
+#endif
+
char *geocache_tileset_metatile_lock_key(geocache_context *ctx, geocache_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), mt->map.tileset->name);
+ num_encode(ctx->pool,mt->z),
+#else
+ "%s/"GEOCACHE_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) {
@@ -74,6 +84,7 @@
}
+#ifdef USE_SEMLOCK
#ifdef __APPLE__
#ifndef SEM_NAME_LEN
#define SEM_NAME_LEN 31
@@ -87,6 +98,8 @@
lockname[SEM_NAME_LEN-1]='\0';
}
#endif
+#endif
+
return lockname;
}
/**
@@ -98,6 +111,7 @@
*/
void geocache_tileset_metatile_lock(geocache_context *ctx, geocache_metatile *mt) {
char *lockname = geocache_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));
@@ -105,6 +119,26 @@
}
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_SHARELOCK|APR_XTHREAD,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;
+ }
+
+ /* 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;
+ }
+ mt->lock = lock;
+#endif
}
/**
@@ -116,8 +150,9 @@
* \sa geocache_cache::tile_lock_exists()
*/
void geocache_tileset_metatile_unlock(geocache_context *ctx, geocache_metatile *mt) {
+ const char *lockname = geocache_tileset_metatile_lock_key(ctx,mt);
+#ifdef USE_SEMLOCK
sem_t *lock = (sem_t*) mt->lock;
- const char *lockname = geocache_tileset_metatile_lock_key(ctx,mt);
if (!mt->lock) {
ctx->set_error(ctx,500,"###### TILE UNLOCK ######### attempting to unlock tile %s not created by this thread", lockname);
return;
@@ -126,6 +161,30 @@
sem_close(lock);
sem_unlink(lockname);
mt->lock = NULL;
+#else
+ char errmsg[120];
+ 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;
+ 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));
+ }
+ 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
}
/**
@@ -141,6 +200,7 @@
if (mt->lock)
return GEOCACHE_TRUE;
lockname = geocache_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) {
@@ -153,6 +213,58 @@
sem_close(lock);
return GEOCACHE_TRUE;
}
+#else
+ apr_status_t rv;
+ char errmsg[120];
+ apr_file_t *lock;
+ rv = apr_file_open(&lock,lockname,APR_READ|APR_SHARELOCK|APR_XTHREAD,APR_OS_DEFAULT,ctx->pool);
+ if(APR_STATUS_IS_ENOENT(rv)) {
+ /* the lock file does not exist, the metatile is not locked */
+ return GEOCACHE_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 GEOCACHE_FALSE;
+ } 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 GEOCACHE_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 GEOCACHE_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));
+ }
+ return GEOCACHE_FALSE;
+ }
+
+ }
+ }
+#endif
}
/**
@@ -163,14 +275,17 @@
*/
void geocache_tileset_metatile_lock_wait(geocache_context *ctx, geocache_metatile *mt) {
char *lockname;
- sem_t *lock;
+ lockname = geocache_tileset_metatile_lock_key(ctx, mt);
+
#ifdef DEBUG
if (mt->lock) {
- ctx->set_error(ctx, 500, "### BUG ### waiting for a lock we have created ourself");
+ ctx->set_error(ctx, 500, "### BUG ### lock_wait: waiting for a lock we have created ourself");
return;
}
#endif
- lockname = geocache_tileset_metatile_lock_key(ctx, mt);
+
+#ifdef USE_SEMLOCK
+ sem_t *lock;
lock = sem_open(lockname, 0, 0644, 1) ;
if( lock == SEM_FAILED ) {
if(errno == ENOENT) {
@@ -185,6 +300,36 @@
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_SHARELOCK|APR_XTHREAD,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;
+ }
+ }
+
+ 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
}
/* vim: ai ts=3 sts=3 et sw=3
More information about the mapserver-commits
mailing list