1 /******************************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: MapCache tile caching support file: Mapserver Mapfile datasource
6 * Author: Thomas Bonfort and the MapServer team.
7 *
8 ******************************************************************************
9 * Copyright (c) 1996-2011 Regents of the University of Minnesota.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies of this Software or works derived from this Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 *****************************************************************************/
29
30
31 #include "mapcache.h"
32 #include "ezxml.h"
33 #include <apr_tables.h>
34 #include <apr_strings.h>
35
36 typedef struct mapcache_source_fallback mapcache_source_fallback;
37 struct mapcache_source_fallback {
38 mapcache_source source;
39 apr_array_header_t *sources;
40 };
41
42 /**
43 * \private \memberof mapcache_source_fallback
44 * \sa mapcache_source::render_map()
45 */
_mapcache_source_fallback_render_map(mapcache_context * ctx,mapcache_source * psource,mapcache_map * map)46 void _mapcache_source_fallback_render_map(mapcache_context *ctx, mapcache_source *psource, mapcache_map *map)
47 {
48 mapcache_source_fallback *source = (mapcache_source_fallback*)psource;
49 mapcache_source *subsource;
50 int i;
51 subsource = APR_ARRAY_IDX(source->sources,0,mapcache_source*);
52 mapcache_source_render_map(ctx, subsource, map);
53
54 if(GC_HAS_ERROR(ctx)) {
55 int first_error = ctx->get_error(ctx);
56 char *first_error_message = ctx->get_error_message(ctx);
57 ctx->log(ctx,MAPCACHE_INFO,
58 "failed render on primary source \"%s\" on tileset \"%s\". Falling back on secondary sources",
59 subsource->name,map->tileset->name);
60 ctx->clear_errors(ctx);
61 for(i=1; i<source->sources->nelts; i++) {
62 subsource = APR_ARRAY_IDX(source->sources,i,mapcache_source*);
63 mapcache_source_render_map(ctx, subsource, map);
64 if(GC_HAS_ERROR(ctx)) {
65 ctx->log(ctx,MAPCACHE_INFO,
66 "failed render on fallback source \"%s\" of tileset \"%s\". Continuing with other fallback sources if available",
67 subsource->name,map->tileset->name);
68 ctx->clear_errors(ctx);
69 continue;
70 } else {
71 return;
72 }
73 }
74 /* all backends failed, return primary error message */
75 ctx->set_error(ctx,first_error,first_error_message);
76 return;
77 }
78 }
79
_mapcache_source_fallback_query(mapcache_context * ctx,mapcache_source * psource,mapcache_feature_info * fi)80 void _mapcache_source_fallback_query(mapcache_context *ctx, mapcache_source *psource, mapcache_feature_info *fi)
81 {
82 mapcache_source_fallback *source = (mapcache_source_fallback*)psource;
83 mapcache_source *subsource;
84 int i;
85 subsource = APR_ARRAY_IDX(source->sources,0,mapcache_source*);
86 mapcache_source_query_info(ctx, subsource, fi);
87
88 if(GC_HAS_ERROR(ctx)) {
89 int first_error = ctx->get_error(ctx);
90 char *first_error_message = ctx->get_error_message(ctx);
91 ctx->log(ctx,MAPCACHE_INFO,
92 "failed query_info on primary source \"%s\" on tileset \"%s\". Falling back on secondary sources",
93 subsource->name,fi->map.tileset->name);
94 ctx->clear_errors(ctx);
95 for(i=1; i<source->sources->nelts; i++) {
96 subsource = APR_ARRAY_IDX(source->sources,i,mapcache_source*);
97 mapcache_source_query_info(ctx, subsource, fi);
98 if(GC_HAS_ERROR(ctx)) {
99 ctx->log(ctx,MAPCACHE_INFO,
100 "failed query_info on fallback source \"%s\" of tileset \"%s\". Continuing with other fallback sources if available",
101 subsource->name,fi->map.tileset->name);
102 ctx->clear_errors(ctx);
103 continue;
104 } else {
105 return;
106 }
107 }
108 /* all backends failed, return primary error message */
109 ctx->set_error(ctx,first_error,first_error_message);
110 return;
111 }
112 ctx->set_error(ctx,500,"fallback source does not support queries");
113 }
114
115 /**
116 * \private \memberof mapcache_source_fallback
117 * \sa mapcache_source::configuration_parse()
118 */
_mapcache_source_fallback_configuration_parse_xml(mapcache_context * ctx,ezxml_t node,mapcache_source * psource,mapcache_cfg * config)119 void _mapcache_source_fallback_configuration_parse_xml(mapcache_context *ctx, ezxml_t node, mapcache_source *psource, mapcache_cfg *config)
120 {
121 ezxml_t cur_node;
122 mapcache_source_fallback *source = (mapcache_source_fallback*)psource;
123 source->sources = apr_array_make(ctx->pool,3,sizeof(mapcache_source*));
124 for(cur_node = ezxml_child(node,"source"); cur_node; cur_node = cur_node->next) {
125 mapcache_source *refsource = mapcache_configuration_get_source(config, cur_node->txt);
126 if(!refsource) {
127 ctx->set_error(ctx, 400, "fallback source \"%s\" references source \"%s\","
128 " but it is not configured (hint:referenced sources must be declared before this fallback source in the xml file)", psource->name, cur_node->txt);
129 return;
130 }
131 APR_ARRAY_PUSH(source->sources,mapcache_source*) = refsource;
132 }
133 if(source->sources->nelts == 0) {
134 ctx->set_error(ctx,400,"fallback source \"%s\" does not reference any child sources", psource->name);
135 }
136 }
137
138 /**
139 * \private \memberof mapcache_source_fallback
140 * \sa mapcache_source::configuration_check()
141 */
_mapcache_source_fallback_configuration_check(mapcache_context * ctx,mapcache_cfg * cfg,mapcache_source * source)142 void _mapcache_source_fallback_configuration_check(mapcache_context *ctx, mapcache_cfg *cfg,
143 mapcache_source *source)
144 {
145 }
146
mapcache_source_fallback_create(mapcache_context * ctx)147 mapcache_source* mapcache_source_fallback_create(mapcache_context *ctx)
148 {
149 mapcache_source_fallback *source = apr_pcalloc(ctx->pool, sizeof(mapcache_source_fallback));
150 if(!source) {
151 ctx->set_error(ctx, 500, "failed to allocate fallback source");
152 return NULL;
153 }
154 mapcache_source_init(ctx, &(source->source));
155 source->source.type = MAPCACHE_SOURCE_FALLBACK;
156 source->source._render_map = _mapcache_source_fallback_render_map;
157 source->source.configuration_check = _mapcache_source_fallback_configuration_check;
158 source->source.configuration_parse_xml = _mapcache_source_fallback_configuration_parse_xml;
159 source->source._query_info = _mapcache_source_fallback_query;
160 return (mapcache_source*)source;
161 }
162
163
164 /* vim: ts=2 sts=2 et sw=2
165 */
166