@@ -780,15 +780,12 @@ void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile)
780780 apr_time_t now = apr_time_now ();
781781 apr_time_t stale = tile -> mtime + apr_time_from_sec (tile -> tileset -> auto_expire );
782782 if (stale < now ) {
783- mapcache_tileset_tile_delete (ctx ,tile ,MAPCACHE_TRUE );
784- GC_CHECK_ERROR (ctx );
785- ret = MAPCACHE_CACHE_MISS ;
783+ /* Indicate that we need to re-render the tile */
784+ ret = MAPCACHE_CACHE_RELOAD ;
786785 }
787786 }
788787
789- if (ret == MAPCACHE_CACHE_MISS ) {
790- int isLocked ;
791- void * lock ;
788+ if (ret == MAPCACHE_CACHE_MISS ) {
792789 /* bail out straight away if the tileset has no source or is read-only */
793790 if (tile -> tileset -> read_only || !tile -> tileset -> source ) {
794791 /* there is no source configured for this tile. not an error, let caller now*/
@@ -805,54 +802,71 @@ void mapcache_tileset_tile_get(mapcache_context *ctx, mapcache_tile *tile)
805802 ctx -> set_error (ctx ,404 ,"tile not in cache, and configured for readonly mode" );
806803 return ;
807804 }
805+ }
806+
807+
808+ if (ret == MAPCACHE_CACHE_MISS || ret == MAPCACHE_CACHE_RELOAD ) {
809+ int isLocked ;
810+ void * lock ;
808811
809- /* the tile does not exist, we must take action before re-asking for it */
810- /*
811- * is the tile already being rendered by another thread ?
812- * the call is protected by the same mutex that sets the lock on the tile,
813- * so we can assure that:
814- * - if the lock does not exist, then this thread should do the rendering
815- * - if the lock exists, we should wait for the other thread to finish
816- */
812+ /* If the tile does not exist or stale, we must take action before re-asking for it */
813+ if ( !tile -> tileset -> read_only && tile -> tileset -> source && !ctx -> config -> non_blocking ) {
814+ /*
815+ * is the tile already being rendered by another thread ?
816+ * the call is protected by the same mutex that sets the lock on the tile,
817+ * so we can assure that:
818+ * - if the lock does not exist, then this thread should do the rendering
819+ * - if the lock exists, we should wait for the other thread to finish
820+ */
817821
818- /* aquire a lock on the metatile */
819- mt = mapcache_tileset_metatile_get (ctx , tile );
820- isLocked = mapcache_lock_or_wait_for_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), & lock );
821- GC_CHECK_ERROR (ctx );
822+ /* aquire a lock on the metatile */
823+ mt = mapcache_tileset_metatile_get (ctx , tile );
824+ isLocked = mapcache_lock_or_wait_for_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), & lock );
825+ GC_CHECK_ERROR (ctx );
822826
823827
824- if (isLocked == MAPCACHE_TRUE ) {
825- /* no other thread is doing the rendering, do it ourselves */
828+ if (isLocked == MAPCACHE_TRUE ) {
829+ /* no other thread is doing the rendering, do it ourselves */
826830#ifdef DEBUG
827- ctx -> log (ctx , MAPCACHE_DEBUG , "cache miss: tileset %s - tile %d %d %d" ,
828- tile -> tileset -> name ,tile -> x , tile -> y ,tile -> z );
831+ ctx -> log (ctx , MAPCACHE_DEBUG , "cache miss/reload : tileset %s - tile %d %d %d" ,
832+ tile -> tileset -> name ,tile -> x , tile -> y ,tile -> z );
829833#endif
830- /* this will query the source to create the tiles, and save them to the cache */
831- mapcache_tileset_render_metatile (ctx , mt );
832-
833- if (GC_HAS_ERROR (ctx )) {
834- /* temporarily clear error state so we don't mess up with error handling in the locker */
835- void * error ;
836- ctx -> pop_errors (ctx ,& error );
837- mapcache_unlock_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), lock );
838- ctx -> push_errors (ctx ,error );
839- } else {
840- mapcache_unlock_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), lock );
834+ /* this will query the source to create the tiles, and save them to the cache */
835+ mapcache_tileset_render_metatile (ctx , mt );
836+
837+ if (GC_HAS_ERROR (ctx )) {
838+ /* temporarily clear error state so we don't mess up with error handling in the locker */
839+ void * error ;
840+ ctx -> pop_errors (ctx ,& error );
841+ mapcache_unlock_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), lock );
842+ ctx -> push_errors (ctx ,error );
843+ } else {
844+ mapcache_unlock_resource (ctx , ctx -> config -> locker , mapcache_tileset_metatile_resource_key (ctx ,mt ), lock );
845+ }
841846 }
842847 }
843- GC_CHECK_ERROR (ctx );
844848
845- /* the previous step has successfully finished, we can now query the cache to return the tile content */
846- ret = tile -> tileset -> _cache -> tile_get (ctx , tile -> tileset -> _cache , tile );
847- GC_CHECK_ERROR (ctx );
849+ if (ret == MAPCACHE_CACHE_RELOAD && GC_HAS_ERROR (ctx ))
850+ /* If we tried to reload a stale tile but failed, we know we have already
851+ * fetched it from the cache. We can then ignore errors and just use old tile.
852+ */
853+ ctx -> clear_errors (ctx );
848854
849- if (ret != MAPCACHE_SUCCESS ) {
850- if (isLocked == MAPCACHE_FALSE ) {
851- ctx -> set_error (ctx , 500 , "tileset %s: unknown error (another thread/process failed to create the tile I was waiting for)" ,
852- tile -> tileset -> name );
853- } else {
854- /* shouldn't really happen, as the error ought to have been caught beforehand */
855- ctx -> set_error (ctx , 500 , "tileset %s: failed to re-get tile %d %d %d from cache after set" , tile -> tileset -> name ,tile -> x ,tile -> y ,tile -> z );
855+ else {
856+ /* Else, check for errors and try to fetch the tile from the cache.
857+ */
858+ GC_CHECK_ERROR (ctx );
859+ ret = tile -> tileset -> _cache -> tile_get (ctx , tile -> tileset -> _cache , tile );
860+ GC_CHECK_ERROR (ctx );
861+
862+ if (ret != MAPCACHE_SUCCESS ) {
863+ if (isLocked == MAPCACHE_FALSE ) {
864+ ctx -> set_error (ctx , 500 , "tileset %s: unknown error (another thread/process failed to create the tile I was waiting for)" ,
865+ tile -> tileset -> name );
866+ } else {
867+ /* shouldn't really happen, as the error ought to have been caught beforehand */
868+ ctx -> set_error (ctx , 500 , "tileset %s: failed to re-get tile %d %d %d from cache after set" , tile -> tileset -> name ,tile -> x ,tile -> y ,tile -> z );
869+ }
856870 }
857871 }
858872 }
0 commit comments