X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fpazpar2_config.c;h=c93792761dbe87db8fb8c2c87612d6a5a4c97467;hb=5dc0e29d39f93d609bac1533a78a3cf1e2110347;hp=e796e00f4be66a68341a846fbb77dfa9d469fbcc;hpb=a4d692f24164e5e8271599c2fcfd9cc5acc25c4b;p=pazpar2-moved-to-github.git diff --git a/src/pazpar2_config.c b/src/pazpar2_config.c index e796e00..c937927 100644 --- a/src/pazpar2_config.c +++ b/src/pazpar2_config.c @@ -34,14 +34,39 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include -#define CONFIG_NOEXTERNS +#if HAVE_GLOB_H +#define USE_POSIX_GLOB 1 +#else +#define USE_POSIX_GLOB 0 +#endif + + +#if USE_POSIX_GLOB +#include +#endif +#include +#include +#if HAVE_UNISTD_H +#include +#endif #include "pazpar2_config.h" +#include "settings.h" +#include "eventl.h" +#include "http.h" +struct conf_config +{ + NMEM nmem; /* for conf_config and servers memory */ + struct conf_server *servers; + WRBUF confdir; +}; -static char confdir[256] = "."; -struct conf_config *config = 0; +static char *parse_settings(struct conf_config *config, + NMEM nmem, xmlNode *node); +static struct conf_targetprofiles *parse_targetprofiles(NMEM nmem, + xmlNode *node); static struct conf_metadata * conf_metadata_assign(NMEM nmem, @@ -95,8 +120,9 @@ struct conf_sortkey * conf_sortkey_assign(NMEM nmem, } -struct conf_service * conf_service_create(int num_metadata, int num_sortkeys, - const char *service_id) +struct conf_service * conf_service_create(struct conf_config *config, + int num_metadata, int num_sortkeys, + const char *service_id) { struct conf_service * service = 0; NMEM nmem = nmem_create(); @@ -106,6 +132,10 @@ struct conf_service * conf_service_create(int num_metadata, int num_sortkeys, service = nmem_malloc(nmem, sizeof(struct conf_service)); service->nmem = nmem; service->next = 0; + service->settings = 0; + service->databases = 0; + service->targetprofiles = 0; + service->config = config; service->id = service_id ? nmem_strdup(nmem, service_id) : 0; service->num_metadata = num_metadata; @@ -203,12 +233,30 @@ int conf_service_sortkey_field_id(struct conf_service *service, return -1; } +static void conf_dir_path(struct conf_config *config, WRBUF w, const char *src) +{ + if (config->confdir && wrbuf_len(config->confdir) > 0 && + !yaz_is_abspath(src)) + { + wrbuf_printf(w, "%s/%s", wrbuf_cstr(config->confdir), src); + } + else + wrbuf_puts(w, src); +} +static void service_destroy(struct conf_service *service) +{ + if (service) + { + pp2_charset_destroy(service->relevance_pct); + pp2_charset_destroy(service->sort_pct); + pp2_charset_destroy(service->mergekey_pct); + nmem_destroy(service->nmem); + } +} -/* Code to parse configuration file */ -/* ==================================================== */ - -static struct conf_service *parse_service(xmlNode *node, const char *service_id) +static struct conf_service *service_create(struct conf_config *config, + xmlNode *node, const char *service_id) { xmlNode *n; int md_node = 0; @@ -230,13 +278,36 @@ static struct conf_service *parse_service(xmlNode *node, const char *service_id) xmlFree(sortkey); } - service = conf_service_create(num_metadata, num_sortkeys, service_id); + service = conf_service_create(config, + num_metadata, num_sortkeys, service_id); for (n = node->children; n; n = n->next) { if (n->type != XML_ELEMENT_NODE) continue; - if (!strcmp((const char *) n->name, (const char *) "metadata")) + if (!strcmp((const char *) n->name, "settings")) + { + if (service->settings) + { + yaz_log(YLOG_FATAL, "Can't repeat 'settings'"); + return 0; + } + service->settings = parse_settings(config, service->nmem, n); + if (!service->settings) + return 0; + } + else if (!strcmp((const char *) n->name, (const char *) "targetprofiles")) + { + if (service->targetprofiles) + { + yaz_log(YLOG_FATAL, "Can't repeat targetprofiles"); + return 0; + } + if (!(service->targetprofiles = + parse_targetprofiles(service->nmem, n))) + return 0; + } + else if (!strcmp((const char *) n->name, (const char *) "metadata")) { xmlChar *xml_name = xmlGetProp(n, (xmlChar *) "name"); xmlChar *xml_brief = xmlGetProp(n, (xmlChar *) "brief"); @@ -373,8 +444,7 @@ static struct conf_service *parse_service(xmlNode *node, const char *service_id) } sortkey_offset = sk_node; - conf_service_add_sortkey( -service, sk_node, + conf_service_add_sortkey(service, sk_node, (const char *) xml_name, sk_type); sk_node++; @@ -414,21 +484,18 @@ service, sk_node, return service; } -static char *parse_settings(NMEM nmem, xmlNode *node) +static char *parse_settings(struct conf_config *config, + NMEM nmem, xmlNode *node) { xmlChar *src = xmlGetProp(node, (xmlChar *) "src"); char *r; if (src) { - if (yaz_is_abspath((const char *) src)) - r = nmem_strdup(nmem, (const char *) src); - else - { - r = nmem_malloc(nmem, - strlen(confdir) + strlen((const char *) src) + 2); - sprintf(r, "%s/%s", confdir, src); - } + WRBUF w = wrbuf_alloc(); + conf_dir_path(config, w, (const char *) src); + r = nmem_strdup(nmem, wrbuf_cstr(w)); + wrbuf_destroy(w); } else { @@ -439,7 +506,8 @@ static char *parse_settings(NMEM nmem, xmlNode *node) return r; } -static struct conf_server *parse_server(NMEM nmem, xmlNode *node) +static struct conf_server *parse_server(struct conf_config *config, + NMEM nmem, xmlNode *node) { xmlNode *n; struct conf_server *server = nmem_malloc(nmem, sizeof(struct conf_server)); @@ -449,9 +517,10 @@ static struct conf_server *parse_server(NMEM nmem, xmlNode *node) server->proxy_host = 0; server->proxy_port = 0; server->myurl = 0; + server->proxy_addr = 0; server->service = 0; server->next = 0; - server->settings = 0; + server->server_settings = 0; server->relevance_pct = 0; server->sort_pct = 0; server->mergekey_pct = 0; @@ -488,12 +557,12 @@ static struct conf_server *parse_server(NMEM nmem, xmlNode *node) } else if (!strcmp((const char *) n->name, "settings")) { - if (server->settings) + if (server->server_settings) { yaz_log(YLOG_FATAL, "Can't repeat 'settings'"); return 0; } - if (!(server->settings = parse_settings(nmem, n))) + if (!(server->server_settings = parse_settings(config, nmem, n))) return 0; } else if (!strcmp((const char *) n->name, "relevance")) @@ -516,7 +585,7 @@ static struct conf_server *parse_server(NMEM nmem, xmlNode *node) } else if (!strcmp((const char *) n->name, "service")) { - const char *service_id = (const char *) + char *service_id = (char *) xmlGetProp(n, (xmlChar *) "id"); struct conf_service **sp = &server->service; @@ -537,10 +606,37 @@ static struct conf_server *parse_server(NMEM nmem, xmlNode *node) return 0; else { - struct conf_service *s = parse_service(n, service_id); + struct conf_service *s = service_create(config, n, service_id); if (s) + { + if (server->relevance_pct) + { + s->relevance_pct = server->relevance_pct; + pp2_charset_incref(s->relevance_pct); + } + else + s->relevance_pct = pp2_charset_create(0); + + if (server->sort_pct) + { + + s->sort_pct = server->sort_pct; + pp2_charset_incref(s->sort_pct); + } + else + s->sort_pct = pp2_charset_create(0); + + if (server->mergekey_pct) + { + s->mergekey_pct = server->mergekey_pct; + pp2_charset_incref(s->mergekey_pct); + } + else + s->mergekey_pct = pp2_charset_create(0); *sp = s; + } } + xmlFree(service_id); } else { @@ -548,23 +644,19 @@ static struct conf_server *parse_server(NMEM nmem, xmlNode *node) return 0; } } - if (!server->relevance_pct) - server->relevance_pct = pp2_charset_create(0); - if (!server->sort_pct) - server->sort_pct = pp2_charset_create(0); - if (!server->mergekey_pct) - server->mergekey_pct = pp2_charset_create(0); return server; } -xsltStylesheet *conf_load_stylesheet(const char *fname) +xsltStylesheet *conf_load_stylesheet(struct conf_config *config, + const char *fname) { - char path[256]; - if (yaz_is_abspath(fname)) - yaz_snprintf(path, sizeof(path), fname); - else - yaz_snprintf(path, sizeof(path), "%s/%s", confdir, fname); - return xsltParseStylesheetFile((xmlChar *) path); + WRBUF w = wrbuf_alloc(); + xsltStylesheet *s; + + conf_dir_path(config, w, fname); + s = xsltParseStylesheetFile((xmlChar *) wrbuf_cstr(w)); + wrbuf_destroy(w); + return s; } static struct conf_targetprofiles *parse_targetprofiles(NMEM nmem, @@ -604,9 +696,10 @@ static struct conf_targetprofiles *parse_targetprofiles(NMEM nmem, return r; } -struct conf_service *locate_service(const char *service_id) +struct conf_service *locate_service(struct conf_server *server, + const char *service_id) { - struct conf_service *s = config->servers->service; + struct conf_service *s = server->service; for (; s; s = s->next) if (s->id && service_id && 0 == strcmp(s->id, service_id)) return s; @@ -616,15 +709,9 @@ struct conf_service *locate_service(const char *service_id) } -static struct conf_config *parse_config(xmlNode *root) +static int parse_config(struct conf_config *config, xmlNode *root) { - NMEM nmem = nmem_create(); xmlNode *n; - struct conf_config *r = nmem_malloc(nmem, sizeof(struct conf_config)); - - r->nmem = nmem; - r->servers = 0; - r->targetprofiles = 0; for (n = root->children; n; n = n->next) { @@ -632,44 +719,157 @@ static struct conf_config *parse_config(xmlNode *root) continue; if (!strcmp((const char *) n->name, "server")) { - struct conf_server *tmp = parse_server(nmem, n); + struct conf_server *tmp = parse_server(config, config->nmem, n); if (!tmp) - return 0; - tmp->next = r->servers; - r->servers = tmp; + return -1; + tmp->next = config->servers; + config->servers = tmp; } else if (!strcmp((const char *) n->name, "targetprofiles")) { - // It would be fun to be able to fix this sometime - if (r->targetprofiles) - { - yaz_log(YLOG_FATAL, "Can't repeat targetprofiles"); - return 0; - } - if (!(r->targetprofiles = parse_targetprofiles(nmem, n))) - return 0; + yaz_log(YLOG_FATAL, "targetprofiles unsupported here. Must be part of service"); + return -1; + } else { yaz_log(YLOG_FATAL, "Bad element: %s", n->name); - return 0; + return -1; } } - return r; + return 0; +} + +static int process_config_includes(struct conf_config *config, xmlNode *n); + +static int config_include_one(struct conf_config *config, xmlNode **sib, + const char *path) +{ + struct stat st; + if (stat(path, &st) < 0) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path); + return -1; + } + else + { + if ((st.st_mode & S_IFMT) == S_IFREG) + { + xmlDoc *doc = xmlParseFile(path); + yaz_log(YLOG_LOG, "processing include path=%s", path); + if (doc) + { + xmlNodePtr t = xmlDocGetRootElement(doc); + int ret = process_config_includes(config, t); + *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1)); + xmlFreeDoc(doc); + if (ret) + return -1; + } + else + { + yaz_log(YLOG_FATAL, "Could not parse %s", path); + return -1; + } + } + } + return 0; } -int read_config(const char *fname) +static int config_include_src(struct conf_config *config, xmlNode **np, + const char *src) +{ + int ret = 0; /* return code. OK so far */ + WRBUF w = wrbuf_alloc(); + xmlNodePtr sib; /* our sibling that we append */ + xmlNodePtr c; /* tmp node */ + + wrbuf_printf(w, " begin include src=\"%s\" ", src); + + /* replace include element with a 'begin' comment */ + sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w)); + xmlReplaceNode(*np, sib); + + xmlFreeNode(*np); + + wrbuf_rewind(w); + conf_dir_path(config, w, src); +#if USE_POSIX_GLOB + { + size_t i; + glob_t glob_res; + glob(wrbuf_cstr(w), 0 /* flags */, 0 /* errfunc */, &glob_res); + + for (i = 0; ret == 0 && i < glob_res.gl_pathc; i++) + { + const char *path = glob_res.gl_pathv[i]; + ret = config_include_one(config, &sib, path); + } + globfree(&glob_res); + } +#else + ret = config_include_one(config, &sib, wrbuf_cstr(w)); +#endif + wrbuf_rewind(w); + wrbuf_printf(w, " end include src=\"%s\" ", src); + c = xmlNewComment((const xmlChar *) wrbuf_cstr(w)); + sib = xmlAddNextSibling(sib, c); + + *np = sib; + wrbuf_destroy(w); + return ret; +} + +static int process_config_includes(struct conf_config *config, xmlNode *n) +{ + for (; n; n = n->next) + { + if (n->type == XML_ELEMENT_NODE) + { + if (!strcmp((const char *) n->name, "include")) + { + xmlChar *src = xmlGetProp(n, (xmlChar *) "src"); + if (src) + { + int ret = config_include_src(config, &n, + (const char *) src); + xmlFree(src); + if (ret) + return ret; + + } + } + else + { + if (process_config_includes(config, n->children)) + return -1; + } + } + } + return 0; +} + +struct conf_config *config_create(const char *fname, int verbose) { xmlDoc *doc = xmlParseFile(fname); + xmlNode *n; const char *p; + int r; + NMEM nmem = nmem_create(); + struct conf_config *config = nmem_malloc(nmem, sizeof(struct conf_config)); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; if (!doc) { yaz_log(YLOG_FATAL, "Failed to read %s", fname); - exit(1); + return 0; } + + config->nmem = nmem; + config->servers = 0; + + config->confdir = wrbuf_alloc(); if ((p = strrchr(fname, #ifdef WIN32 '\\' @@ -679,20 +879,131 @@ int read_config(const char *fname) ))) { int len = p - fname; - if (len >= sizeof(confdir)) - len = sizeof(confdir)-1; - strncpy(confdir, fname, len); - confdir[len] = '\0'; + wrbuf_write(config->confdir, fname, len); + } + wrbuf_puts(config->confdir, ""); + + n = xmlDocGetRootElement(doc); + r = process_config_includes(config, n); + if (r == 0) /* OK */ + { + if (verbose) + { + yaz_log(YLOG_LOG, "Configuration %s after include processing", + fname); + xmlDocFormatDump(yaz_log_file(), doc, 0); + } + r = parse_config(config, n); } - config = parse_config(xmlDocGetRootElement(doc)); xmlFreeDoc(doc); - if (config) - return 1; - else + if (r) + { + config_destroy(config); return 0; + } + return config; +} + +void server_destroy(struct conf_server *server) +{ + struct conf_service *s = server->service; + while (s) + { + struct conf_service *s_next = s->next; + service_destroy(s); + s = s_next; + } + pp2_charset_destroy(server->relevance_pct); + pp2_charset_destroy(server->sort_pct); + pp2_charset_destroy(server->mergekey_pct); +} + +void config_destroy(struct conf_config *config) +{ + if (config) + { + struct conf_server *server = config->servers; + while (server) + { + struct conf_server *s_next = server->next; + server_destroy(server); + server = s_next; + } + wrbuf_destroy(config->confdir); + nmem_destroy(config->nmem); + } +} + +void config_read_settings(struct conf_config *config) +{ + struct conf_service *s = config->servers->service; + for (;s ; s = s->next) + { + init_settings(s); + if (s->settings) + settings_read(s, s->settings); + else if (config->servers->server_settings) + settings_read(s, config->servers->server_settings); + else + yaz_log(YLOG_WARN, "No settings for service"); + } +} + +void config_stop_listeners(struct conf_config *conf) +{ + struct conf_server *ser; + for (ser = conf->servers; ser; ser = ser->next) + http_close_server(ser); } +int config_start_listeners(struct conf_config *conf, + const char *listener_override) +{ + struct conf_server *ser; + for (ser = conf->servers; ser; ser = ser->next) + { + WRBUF w = wrbuf_alloc(); + int r; + if (listener_override) + { + wrbuf_puts(w, listener_override); + listener_override = 0; /* only first server is overriden */ + } + else + { + if (ser->host) + wrbuf_puts(w, ser->host); + if (ser->port) + { + if (wrbuf_len(w)) + wrbuf_puts(w, ":"); + wrbuf_printf(w, "%d", ser->port); + } + } + r = http_init(wrbuf_cstr(w), ser); + wrbuf_destroy(w); + if (r) + return -1; + + w = wrbuf_alloc(); + if (ser->proxy_host || ser->proxy_port) + { + if (ser->proxy_host) + wrbuf_puts(w, ser->proxy_host); + if (ser->proxy_port) + { + if (wrbuf_len(w)) + wrbuf_puts(w, ":"); + wrbuf_printf(w, "%d", ser->proxy_port); + } + } + if (wrbuf_len(w)) + http_set_proxyaddr(wrbuf_cstr(w), ser); + wrbuf_destroy(w); + } + return 0; +} /* * Local variables: