X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fpazpar2_config.c;h=5c808b8a612a34388d7770a4a9150a4973935a6b;hb=5b4ea0cf66dd82c871ed7d69a5801d78789087b2;hp=174fe8358f47b24ada9e95744a5f0fdb9d59508c;hpb=602c355d05619c98b4103dd93794be8f89625a7a;p=pazpar2-moved-to-github.git diff --git a/src/pazpar2_config.c b/src/pazpar2_config.c index 174fe83..5c808b8 100644 --- a/src/pazpar2_config.c +++ b/src/pazpar2_config.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2008 Index Data + Copyright (C) 2006-2009 Index Data Pazpar2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -32,17 +32,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include -#define CONFIG_NOEXTERNS #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 NMEM nmem = 0; -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, struct conf_metadata * metadata, const char *name, @@ -52,7 +63,8 @@ struct conf_metadata * conf_metadata_assign(NMEM nmem, int brief, int termlist, int rank, - int sortkey_offset) + int sortkey_offset, + enum conf_metadata_mergekey mt) { if (!nmem || !metadata || !name) return 0; @@ -72,10 +84,12 @@ struct conf_metadata * conf_metadata_assign(NMEM nmem, metadata->termlist = termlist; metadata->rank = rank; metadata->sortkey_offset = sortkey_offset; + metadata->mergekey = mt; return metadata; } +static struct conf_sortkey * conf_sortkey_assign(NMEM nmem, struct conf_sortkey * sortkey, const char *name, @@ -91,15 +105,24 @@ struct conf_sortkey * conf_sortkey_assign(NMEM nmem, } -struct conf_service * conf_service_create(NMEM nmem, - int num_metadata, int num_sortkeys) +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(); //assert(nmem); 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; service->metadata = 0; if (service->num_metadata) @@ -112,12 +135,11 @@ struct conf_service * conf_service_create(NMEM nmem, service->sortkeys = nmem_malloc(nmem, sizeof(struct conf_sortkey) * service->num_sortkeys); - + service->dictionary = 0; return service; } -struct conf_metadata* conf_service_add_metadata(NMEM nmem, - struct conf_service *service, +struct conf_metadata* conf_service_add_metadata(struct conf_service *service, int field_id, const char *name, enum conf_metadata_type type, @@ -126,7 +148,8 @@ struct conf_metadata* conf_service_add_metadata(NMEM nmem, int brief, int termlist, int rank, - int sortkey_offset) + int sortkey_offset, + enum conf_metadata_mergekey mt) { struct conf_metadata * md = 0; @@ -136,14 +159,14 @@ struct conf_metadata* conf_service_add_metadata(NMEM nmem, //md = &((service->metadata)[field_id]); md = service->metadata + field_id; - md = conf_metadata_assign(nmem, md, name, type, merge, setting, - brief, termlist, rank, sortkey_offset); + md = conf_metadata_assign(service->nmem, md, name, type, merge, setting, + brief, termlist, rank, sortkey_offset, + mt); return md; } -struct conf_sortkey * conf_service_add_sortkey(NMEM nmem, - struct conf_service *service, +struct conf_sortkey * conf_service_add_sortkey(struct conf_service *service, int field_id, const char *name, enum conf_sortkey_type type) @@ -156,7 +179,7 @@ struct conf_sortkey * conf_service_add_sortkey(NMEM nmem, //sk = &((service->sortkeys)[field_id]); sk = service->sortkeys + field_id; - sk = conf_sortkey_assign(nmem, sk, name, type); + sk = conf_sortkey_assign(service->nmem, sk, name, type); return sk; } @@ -200,7 +223,8 @@ int conf_service_sortkey_field_id(struct conf_service *service, /* Code to parse configuration file */ /* ==================================================== */ -static struct conf_service *parse_service(xmlNode *node) +static struct conf_service *parse_service(struct conf_config *config, + xmlNode *node, const char *service_id) { xmlNode *n; int md_node = 0; @@ -222,13 +246,36 @@ static struct conf_service *parse_service(xmlNode *node) xmlFree(sortkey); } - service = conf_service_create(nmem, num_metadata, num_sortkeys); + 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"); @@ -238,11 +285,13 @@ static struct conf_service *parse_service(xmlNode *node) xmlChar *xml_termlist = xmlGetProp(n, (xmlChar *) "termlist"); xmlChar *xml_rank = xmlGetProp(n, (xmlChar *) "rank"); xmlChar *xml_setting = xmlGetProp(n, (xmlChar *) "setting"); + xmlChar *xml_mergekey = xmlGetProp(n, (xmlChar *) "mergekey"); enum conf_metadata_type type = Metadata_type_generic; enum conf_metadata_merge merge = Metadata_merge_no; enum conf_setting_type setting = Metadata_setting_no; enum conf_sortkey_type sk_type = Metadata_sortkey_relevance; + enum conf_metadata_mergekey mergekey_type = Metadata_mergekey_no; int brief = 0; int termlist = 0; int rank = 0; @@ -363,7 +412,7 @@ static struct conf_service *parse_service(xmlNode *node) } sortkey_offset = sk_node; - conf_service_add_sortkey(nmem, service, sk_node, + conf_service_add_sortkey(service, sk_node, (const char *) xml_name, sk_type); sk_node++; @@ -371,11 +420,18 @@ static struct conf_service *parse_service(xmlNode *node) else sortkey_offset = -1; + if (xml_mergekey && strcmp((const char *) xml_mergekey, "no")) + { + mergekey_type = Metadata_mergekey_yes; + } + + // metadata known, assign values - conf_service_add_metadata(nmem, service, md_node, + conf_service_add_metadata(service, md_node, (const char *) xml_name, type, merge, setting, - brief, termlist, rank, sortkey_offset); + brief, termlist, rank, sortkey_offset, + mergekey_type); xmlFree(xml_name); xmlFree(xml_brief); @@ -396,13 +452,24 @@ static struct conf_service *parse_service(xmlNode *node) return service; } -static char *parse_settings(xmlNode *node) +static char *parse_settings(struct conf_config *config, + NMEM nmem, xmlNode *node) { xmlChar *src = xmlGetProp(node, (xmlChar *) "src"); char *r; if (src) - r = nmem_strdup(nmem, (const char *) src); + { + if (yaz_is_abspath((const char *) src) || !wrbuf_len(config->confdir)) + r = nmem_strdup(nmem, (const char *) src); + else + { + r = nmem_malloc(nmem, + wrbuf_len(config->confdir) + + strlen((const char *) src) + 2); + sprintf(r, "%s/%s", wrbuf_cstr(config->confdir), src); + } + } else { yaz_log(YLOG_FATAL, "Must specify src in targetprofile"); @@ -412,7 +479,8 @@ static char *parse_settings(xmlNode *node) return r; } -static struct conf_server *parse_server(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)); @@ -422,9 +490,10 @@ static struct conf_server *parse_server(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; @@ -461,32 +530,68 @@ static struct conf_server *parse_server(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(n))) + if (!(server->server_settings = parse_settings(config, nmem, n))) return 0; } else if (!strcmp((const char *) n->name, "relevance")) { - server->relevance_pct = pp2_charset_create_xml(n->children); + server->relevance_pct = pp2_charset_create_xml(n); + if (!server->relevance_pct) + return 0; } else if (!strcmp((const char *) n->name, "sort")) { - server->sort_pct = pp2_charset_create_xml(n->children); + server->sort_pct = pp2_charset_create_xml(n); + if (!server->sort_pct) + return 0; } else if (!strcmp((const char *) n->name, "mergekey")) { - server->mergekey_pct = pp2_charset_create_xml(n->children); + server->mergekey_pct = pp2_charset_create_xml(n); + if (!server->mergekey_pct) + return 0; } else if (!strcmp((const char *) n->name, "service")) { - struct conf_service *s = parse_service(n); - if (!s) + char *service_id = (char *) + xmlGetProp(n, (xmlChar *) "id"); + + struct conf_service **sp = &server->service; + for (; *sp; sp = &(*sp)->next) + if ((*sp)->id && service_id && + 0 == strcmp((*sp)->id, service_id)) + { + yaz_log(YLOG_FATAL, "Duplicate service: %s", service_id); + break; + } + else if (!(*sp)->id && !service_id) + { + yaz_log(YLOG_FATAL, "Duplicate unnamed service"); + break; + } + + if (*sp) /* service already exist */ return 0; - server->service = s; + else + { + struct conf_service *s = parse_service(config, n, service_id); + if (s) + { + s->relevance_pct = server->relevance_pct ? + server->relevance_pct : pp2_charset_create(0); + s->sort_pct = server->sort_pct ? + server->sort_pct : pp2_charset_create(0); + s->mergekey_pct = server->mergekey_pct ? + server->mergekey_pct : pp2_charset_create(0); + *sp = s; + } + } + xmlFree(service_id); } else { @@ -494,26 +599,23 @@ static struct conf_server *parse_server(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 (*fname == '/') + if (yaz_is_abspath(fname) || !config || !wrbuf_len(config->confdir)) yaz_snprintf(path, sizeof(path), fname); else - yaz_snprintf(path, sizeof(path), "%s/%s", confdir, fname); + yaz_snprintf(path, sizeof(path), "%s/%s", + wrbuf_cstr(config->confdir), fname); return xsltParseStylesheetFile((xmlChar *) path); } -static struct conf_targetprofiles *parse_targetprofiles(xmlNode *node) +static struct conf_targetprofiles *parse_targetprofiles(NMEM nmem, + xmlNode *node) { struct conf_targetprofiles *r = nmem_malloc(nmem, sizeof(*r)); xmlChar *type = xmlGetProp(node, (xmlChar *) "type"); @@ -549,13 +651,22 @@ static struct conf_targetprofiles *parse_targetprofiles(xmlNode *node) return r; } -static struct conf_config *parse_config(xmlNode *root) +struct conf_service *locate_service(struct conf_server *server, + const char *service_id) { - xmlNode *n; - struct conf_config *r = nmem_malloc(nmem, sizeof(struct conf_config)); + struct conf_service *s = server->service; + for (; s; s = s->next) + if (s->id && service_id && 0 == strcmp(s->id, service_id)) + return s; + else if (!s->id && !service_id) + return s; + return 0; +} - r->servers = 0; - r->targetprofiles = 0; + +static int parse_config(struct conf_config *config, xmlNode *root) +{ + xmlNode *n; for (n = root->children; n; n = n->next) { @@ -563,70 +674,187 @@ static struct conf_config *parse_config(xmlNode *root) continue; if (!strcmp((const char *) n->name, "server")) { - struct conf_server *tmp = parse_server(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(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; } -int read_config(const char *fname) +static void config_include_src(struct conf_config *config, xmlNode *n, + const char *src) { - xmlDoc *doc = xmlParseFile(fname); - const char *p; + xmlDoc *doc = xmlParseFile(src); + yaz_log(YLOG_LOG, "processing incldue src=%s", src); + if (doc) + { + xmlNodePtr t = xmlDocGetRootElement(doc); + xmlReplaceNode(n, xmlCopyNode(t, 1)); + xmlFreeDoc(doc); + } +} - if (!nmem) // Initialize +static void process_config_includes(struct conf_config *config, xmlNode *n) +{ + for (; n; n = n->next) { - nmem = nmem_create(); - xmlSubstituteEntitiesDefault(1); - xmlLoadExtDtdDefaultValue = 1; + if (n->type == XML_ELEMENT_NODE) + { + if (!strcmp((const char *) n->name, "include")) + { + xmlChar *src = xmlGetProp(n, (xmlChar *) "src"); + if (src) + { + config_include_src(config, n, (const char *) src); + xmlFree(src); + } + } + } + process_config_includes(config, n->children); } +} + +struct conf_config *read_config(const char *fname) +{ + 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); } - if ((p = strrchr(fname, '/'))) + + config->nmem = nmem; + config->servers = 0; + + config->confdir = wrbuf_alloc(); + if ((p = strrchr(fname, +#ifdef WIN32 + '\\' +#else + '/' +#endif + ))) { 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); } - config = parse_config(xmlDocGetRootElement(doc)); + wrbuf_puts(config->confdir, ""); + + n = xmlDocGetRootElement(doc); + process_config_includes(config, n); + xmlDocFormatDump(stdout, doc, 0); + r = parse_config(config, n); xmlFreeDoc(doc); - if (config) - return 1; - else + if (r) return 0; + return config; } +void config_read_settings(struct conf_config *config, + const char *path_override) +{ + struct conf_service *s = config->servers->service; + for (;s ; s = s->next) + { + init_settings(s); + if (path_override) + settings_read(s, path_override); + else 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, + const char *proxy_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 (proxy_override) + wrbuf_puts(w, proxy_override); + else 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: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab */ +