[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