1 /******************************************************************************
2 *
3 * Project: MapServer
4 * Purpose: MapCache tile caching: generic cache access
5 * Author: Thomas Bonfort and the MapServer team.
6 *
7 ******************************************************************************
8 * Copyright (c) 1996-2015 Regents of the University of Minnesota.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without compositeriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies of this Software or works derived from this Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *****************************************************************************/
28 #include "mapcache.h"
29 #include <apr_time.h>
30
mapcache_cache_tile_get(mapcache_context * ctx,mapcache_cache * cache,mapcache_tile * tile)31 int mapcache_cache_tile_get(mapcache_context *ctx, mapcache_cache *cache, mapcache_tile *tile) {
32 int i,rv;
33 mapcache_rule *rule = mapcache_ruleset_rule_get(tile->grid_link->rules, tile->z);
34 #ifdef DEBUG
35 ctx->log(ctx,MAPCACHE_DEBUG,"calling tile_get on cache (%s): (tileset=%s, grid=%s, z=%d, x=%d, y=%d",cache->name,tile->tileset->name,tile->grid_link->grid->name,tile->z,tile->x, tile->y);
36 #endif
37
38 /* if tile is outside visible limits, return a blank tile */
39 if (mapcache_ruleset_is_visible_tile(rule, tile) == MAPCACHE_FALSE) {
40 tile->encoded_data = mapcache_buffer_create(0, ctx->pool);
41 mapcache_buffer_append(tile->encoded_data, rule->hidden_tile->size, rule->hidden_tile->buf);
42 return MAPCACHE_SUCCESS;
43 }
44
45 for(i=0;i<=cache->retry_count;i++) {
46 if(i) {
47 ctx->log(ctx,MAPCACHE_INFO,"cache (%s) get retry %d of %d. previous try returned error: %s",cache->name,i,cache->retry_count,ctx->get_error_message(ctx));
48 ctx->clear_errors(ctx);
49 if(cache->retry_delay > 0) {
50 double wait = cache->retry_delay;
51 int j = 0;
52 for(j=1;j<i;j++) /* sleep twice as long as before previous retry */
53 wait *= 2;
54 apr_sleep((int)(wait*1000000)); /* apr_sleep expects microseconds */
55 }
56 }
57 rv = cache->_tile_get(ctx,cache,tile);
58 if(!GC_HAS_ERROR(ctx))
59 break;
60 }
61 return rv;
62 }
63
mapcache_cache_tile_delete(mapcache_context * ctx,mapcache_cache * cache,mapcache_tile * tile)64 void mapcache_cache_tile_delete(mapcache_context *ctx, mapcache_cache *cache, mapcache_tile *tile) {
65 int i;
66 #ifdef DEBUG
67 ctx->log(ctx,MAPCACHE_DEBUG,"calling tile_delete on cache (%s): (tileset=%s, grid=%s, z=%d, x=%d, y=%d",cache->name,tile->tileset->name,tile->grid_link->grid->name,tile->z,tile->x, tile->y);
68 #endif
69 if(tile->tileset->read_only)
70 return;
71 for(i=0;i<=cache->retry_count;i++) {
72 if(i) {
73 ctx->log(ctx,MAPCACHE_INFO,"cache (%s) delete retry %d of %d. previous try returned error: %s",cache->name,i,cache->retry_count,ctx->get_error_message(ctx));
74 ctx->clear_errors(ctx);
75 if(cache->retry_delay > 0) {
76 double wait = cache->retry_delay;
77 int j = 0;
78 for(j=1;j<i;j++) /* sleep twice as long as before previous retry */
79 wait *= 2;
80 apr_sleep((int)(wait*1000000)); /* apr_sleep expects microseconds */
81 }
82 }
83 cache->_tile_delete(ctx,cache,tile);
84 if(!GC_HAS_ERROR(ctx))
85 break;
86 }
87 }
88
mapcache_cache_tile_exists(mapcache_context * ctx,mapcache_cache * cache,mapcache_tile * tile)89 int mapcache_cache_tile_exists(mapcache_context *ctx, mapcache_cache *cache, mapcache_tile *tile) {
90 int i,rv;
91 mapcache_rule *rule = mapcache_ruleset_rule_get(tile->grid_link->rules, tile->z);
92 #ifdef DEBUG
93 ctx->log(ctx,MAPCACHE_DEBUG,"calling tile_exists on cache (%s): (tileset=%s, grid=%s, z=%d, x=%d, y=%d",cache->name,tile->tileset->name,tile->grid_link->grid->name,tile->z,tile->x, tile->y);
94 #endif
95
96 /* if tile is outside visible limits return TRUE
97 a blank tile will be returned on subsequent get call on cache */
98 if (mapcache_ruleset_is_visible_tile(rule, tile) == MAPCACHE_FALSE) {
99 return MAPCACHE_TRUE;
100 }
101
102 for(i=0;i<=cache->retry_count;i++) {
103 if(i) {
104 ctx->log(ctx,MAPCACHE_INFO,"cache (%s) exists retry %d of %d. previous try returned error: %s",cache->name,i,cache->retry_count,ctx->get_error_message(ctx));
105 ctx->clear_errors(ctx);
106 if(cache->retry_delay > 0) {
107 double wait = cache->retry_delay;
108 int j = 0;
109 for(j=1;j<i;j++) /* sleep twice as long as before previous retry */
110 wait *= 2;
111 apr_sleep((int)(wait*1000000)); /* apr_sleep expects microseconds */
112 }
113 }
114 rv = cache->_tile_exists(ctx,cache,tile);
115 if(!GC_HAS_ERROR(ctx))
116 break;
117 }
118 return rv;
119 }
120
mapcache_cache_tile_set(mapcache_context * ctx,mapcache_cache * cache,mapcache_tile * tile)121 void mapcache_cache_tile_set(mapcache_context *ctx, mapcache_cache *cache, mapcache_tile *tile) {
122 int i;
123 #ifdef DEBUG
124 ctx->log(ctx,MAPCACHE_DEBUG,"calling tile_set on cache (%s): (tileset=%s, grid=%s, z=%d, x=%d, y=%d",cache->name,tile->tileset->name,tile->grid_link->grid->name,tile->z,tile->x, tile->y);
125 #endif
126 if(tile->tileset->read_only)
127 return;
128 for(i=0;i<=cache->retry_count;i++) {
129 if(i) {
130 ctx->log(ctx,MAPCACHE_INFO,"cache (%s) set retry %d of %d. previous try returned error: %s",cache->name,i,cache->retry_count,ctx->get_error_message(ctx));
131 ctx->clear_errors(ctx);
132 if(cache->retry_delay > 0) {
133 double wait = cache->retry_delay;
134 int j = 0;
135 for(j=1;j<i;j++) /* sleep twice as long as before previous retry */
136 wait *= 2;
137 apr_sleep((int)(wait*1000000)); /* apr_sleep expects microseconds */
138 }
139 }
140 cache->_tile_set(ctx,cache,tile);
141 if(!GC_HAS_ERROR(ctx))
142 break;
143 }
144 }
145
mapcache_cache_tile_multi_set(mapcache_context * ctx,mapcache_cache * cache,mapcache_tile * tiles,int ntiles)146 void mapcache_cache_tile_multi_set(mapcache_context *ctx, mapcache_cache *cache, mapcache_tile *tiles, int ntiles) {
147 int i;
148 #ifdef DEBUG
149 ctx->log(ctx,MAPCACHE_DEBUG,"calling tile_multi_set on cache (%s): (tileset=%s, grid=%s, first tile: z=%d, x=%d, y=%d",cache->name,tiles[0].tileset->name,tiles[0].grid_link->grid->name,
150 tiles[0].z,tiles[0].x, tiles[0].y);
151 #endif
152 if((&tiles[0])->tileset->read_only)
153 return;
154 if(cache->_tile_multi_set) {
155 for(i=0;i<=cache->retry_count;i++) {
156 if(i) {
157 ctx->log(ctx,MAPCACHE_INFO,"cache (%s) multi-set retry %d of %d. previous try returned error: %s",cache->name,i,cache->retry_count,ctx->get_error_message(ctx));
158 ctx->clear_errors(ctx);
159 if(cache->retry_delay > 0) {
160 double wait = cache->retry_delay;
161 int j = 0;
162 for(j=1;j<i;j++) /* sleep twice as long as before previous retry */
163 wait *= 2;
164 apr_sleep((int)(wait*1000000)); /* apr_sleep expects microseconds */
165 }
166 }
167 cache->_tile_multi_set(ctx,cache,tiles,ntiles);
168 if(!GC_HAS_ERROR(ctx))
169 break;
170 }
171 } else {
172 for( i=0;i<ntiles;i++ ) {
173 mapcache_cache_tile_set(ctx, cache, tiles+i);
174 }
175 }
176 }
177