From fdf549621a2712e2e7fafd5966bbbf9a5c891adf Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 23 Sep 2009 16:16:06 +0200 Subject: [PATCH] Service may be POSTed for command=init. A service may be posted for command=init. This service will be used during the session. The service may have its own target settings, ICU config, timeout, etc. In order to be recognized, the POST request must use Content-Type=text/xml. --- NEWS | 5 ++ src/http_command.c | 45 +++++++++++----- src/logic.c | 1 + src/pazpar2_config.c | 140 ++++++++++++++++++++++++++++++-------------------- src/pazpar2_config.h | 7 ++- test/Makefile.am | 6 ++- test/run_pazpar2.sh | 22 ++++++-- 7 files changed, 150 insertions(+), 76 deletions(-) diff --git a/NEWS b/NEWS index 4ec5f16..a0b84fd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +A service may be posted for command=init. This service will be used +during the session. The service may have its own target settings, +ICU config, timeout, etc. In order to be recognized, the POST request +must use Content-Type=text/xml. + Timeout values may be given per-service. That's element 'timeout' which takes three attribute values (a subset may be given): 'session', 'z3950_connect', 'z3950_session'. Option -T is no longer supported diff --git a/src/http_command.c b/src/http_command.c index 0cb7442..616a48c 100644 --- a/src/http_command.c +++ b/src/http_command.c @@ -207,7 +207,7 @@ static struct http_session *locate_session(struct http_request *rq, struct http_ // Decode settings parameters and apply to session // Syntax: setting[target]=value static int process_settings(struct session *se, struct http_request *rq, - struct http_response *rs) + struct http_response *rs) { struct http_argument *a; @@ -242,26 +242,47 @@ static void cmd_exit(struct http_channel *c) static void cmd_init(struct http_channel *c) { - unsigned int sesid; char buf[1024]; - const char *clear = http_argbyname(c->request, "clear"); - const char *service_name = http_argbyname(c->request, "service"); - struct conf_service *service = locate_service(c->server, - service_name); - struct http_session *s = http_session_create(service); + struct http_request *r = c->request; + const char *clear = http_argbyname(r, "clear"); + const char *content_type = http_lookup_header(r->headers, "Content-Type"); + unsigned int sesid; + struct http_session *s; struct http_response *rs = c->response; - - if (!service) + struct conf_service *service; + + if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) { - error(rs, PAZPAR2_MALFORMED_PARAMETER_VALUE, "service"); - return; + xmlDoc *doc = xmlParseMemory(r->content_buf, r->content_len); + xmlNode *root_n; + if (!doc) + { + error(rs, PAZPAR2_MALFORMED_SETTING, 0); + return; + } + root_n = xmlDocGetRootElement(doc); + service = service_create(c->server, root_n); + xmlFreeDoc(doc); } - + else + { + const char *service_name = http_argbyname(c->request, "service"); + service = locate_service(c->server, service_name); + if (!service) + { + error(rs, PAZPAR2_MALFORMED_PARAMETER_VALUE, "service"); + return; + } + service_incref(service); + } + s = http_session_create(service); + yaz_log(YLOG_DEBUG, "HTTP Session init"); if (!clear || *clear == '0') session_init_databases(s->psession); else yaz_log(YLOG_LOG, "No databases preloaded"); + sesid = make_sessionid(); s->session_id = sesid; if (process_settings(s->psession, c->request, c->response) < 0) diff --git a/src/logic.c b/src/logic.c index cfefc67..d559670 100644 --- a/src/logic.c +++ b/src/logic.c @@ -702,6 +702,7 @@ void destroy_session(struct session *s) for (sdb = s->databases; sdb; sdb = sdb->next) session_database_destroy(sdb); nmem_destroy(s->nmem); + service_destroy(s->service); wrbuf_destroy(s->wrbuf); } diff --git a/src/pazpar2_config.c b/src/pazpar2_config.c index 818eff4..959bfcb 100644 --- a/src/pazpar2_config.c +++ b/src/pazpar2_config.c @@ -122,6 +122,7 @@ static struct conf_service *service_init(struct conf_server *server, NMEM nmem = nmem_create(); service = nmem_malloc(nmem, sizeof(struct conf_service)); + service->ref_count = 1; service->nmem = nmem; service->next = 0; service->settings = 0; @@ -244,17 +245,27 @@ static void conf_dir_path(struct conf_config *config, WRBUF w, const char *src) wrbuf_puts(w, src); } -static void service_destroy(struct conf_service *service) +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); + assert(service->ref_count > 0); + service->ref_count--; + if (service->ref_count == 0) + { + pp2_charset_destroy(service->relevance_pct); + pp2_charset_destroy(service->sort_pct); + pp2_charset_destroy(service->mergekey_pct); + nmem_destroy(service->nmem); + } } } +void service_incref(struct conf_service *service) +{ + service->ref_count++; +} + static int parse_metadata(struct conf_service *service, xmlNode *n, int *md_node, int *sk_node) { @@ -426,9 +437,9 @@ static int parse_metadata(struct conf_service *service, xmlNode *n, return 0; } -static struct conf_service *service_create(struct conf_server *server, - xmlNode *node, - const char *service_id) +static struct conf_service *service_create_static(struct conf_server *server, + xmlNode *node, + const char *service_id) { xmlNode *n; int md_node = 0; @@ -614,65 +625,75 @@ static char *parse_settings(struct conf_config *config, return r; } -static void inherit_server_settings(struct conf_server *server) +static void inherit_server_settings(struct conf_service *s) { - struct conf_service *s; - for (s = server->service; s; s = s->next) + struct conf_server *server = s->server; + if (!s->dictionary) /* service has no config settings ? */ { - if (!s->dictionary) /* service has no config settings ? */ + if (server->server_settings) { - if (server->server_settings) - { - /* inherit settings from server */ - init_settings(s); - settings_read_file(s, server->server_settings, 1); - settings_read_file(s, server->server_settings, 2); - } - else - { - yaz_log(YLOG_WARN, "service '%s' has no settings", - s->id ? s->id : "unnamed"); - init_settings(s); - } + /* inherit settings from server */ + init_settings(s); + settings_read_file(s, server->server_settings, 1); + settings_read_file(s, server->server_settings, 2); } - - /* use relevance/sort/mergekey from server if not defined - for this service.. */ - if (!s->relevance_pct) + else { - if (server->relevance_pct) - { - s->relevance_pct = server->relevance_pct; - pp2_charset_incref(s->relevance_pct); - } - else - s->relevance_pct = pp2_charset_create(0); + yaz_log(YLOG_WARN, "service '%s' has no settings", + s->id ? s->id : "unnamed"); + init_settings(s); } - - if (!s->sort_pct) + } + + /* use relevance/sort/mergekey from server if not defined + for this service.. */ + if (!s->relevance_pct) + { + if (server->relevance_pct) { - if (server->sort_pct) - { - s->sort_pct = server->sort_pct; - pp2_charset_incref(s->sort_pct); - } - else - s->sort_pct = pp2_charset_create(0); + s->relevance_pct = server->relevance_pct; + pp2_charset_incref(s->relevance_pct); } - - if (!s->mergekey_pct) + else + s->relevance_pct = pp2_charset_create(0); + } + + if (!s->sort_pct) + { + if (server->sort_pct) { - if (server->mergekey_pct) - { - s->mergekey_pct = server->mergekey_pct; - pp2_charset_incref(s->mergekey_pct); - } - else - s->mergekey_pct = pp2_charset_create(0); + s->sort_pct = server->sort_pct; + pp2_charset_incref(s->sort_pct); } + else + s->sort_pct = pp2_charset_create(0); + } + + if (!s->mergekey_pct) + { + if (server->mergekey_pct) + { + s->mergekey_pct = server->mergekey_pct; + pp2_charset_incref(s->mergekey_pct); + } + else + s->mergekey_pct = pp2_charset_create(0); } } +struct conf_service *service_create(struct conf_server *server, + xmlNode *node) +{ + struct conf_service *service = service_create_static(server, + node, 0); + if (service) + { + inherit_server_settings(service); + resolve_databases(service); + } + return service; +} + static struct conf_server *server_create(struct conf_config *config, NMEM nmem, xmlNode *node) { @@ -778,8 +799,8 @@ static struct conf_server *server_create(struct conf_config *config, } else { - struct conf_service *s = service_create(server, n, - service_id); + struct conf_service *s = service_create_static(server, n, + service_id); xmlFree(service_id); if (!s) return 0; @@ -792,7 +813,12 @@ static struct conf_server *server_create(struct conf_config *config, return 0; } } - inherit_server_settings(server); + if (server->service) + { + struct conf_service *s; + for (s = server->service; s; s = s->next) + inherit_server_settings(s); + } return server; } diff --git a/src/pazpar2_config.h b/src/pazpar2_config.h index f56ea7f..ddd987b 100644 --- a/src/pazpar2_config.h +++ b/src/pazpar2_config.h @@ -110,7 +110,8 @@ struct conf_service int session_timeout; int z3950_session_timeout; int z3950_connect_timeout; - + + int ref_count; /* duplicated from conf_server */ pp2_charset_t relevance_pct; pp2_charset_t sort_pct; @@ -162,6 +163,10 @@ void config_start_databases(struct conf_config *config); struct conf_service *locate_service(struct conf_server *server, const char *service_id); +struct conf_service *service_create(struct conf_server *server, + xmlNode *node); +void service_incref(struct conf_service *service); +void service_destroy(struct conf_service *service); int config_start_listeners(struct conf_config *conf, const char *listener_override); diff --git a/test/Makefile.am b/test/Makefile.am index f87c6e5..25a5a40 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,11 @@ # This file is part of Pazpar2. -check_SCRIPTS = test_http.sh test_icu.sh +check_SCRIPTS = test_http.sh test_icu.sh test_post.sh EXTRA_DIST = run_pazpar2.sh marc21.xsl z3950_indexdata_com_marc.xml \ z3950_indexdata_com_gils.xml test_http.cfg \ gils_service.xml marc_service.xml marc21.mmap \ - test_http_urls test_icu.cfg test_icu_urls $(check_SCRIPTS) + test_http_urls test_icu.cfg test_icu_urls \ + test_post.cfg test_post_urls $(check_SCRIPTS) TESTS = $(check_SCRIPTS) @@ -15,4 +16,5 @@ CONFIG_CLEAN_FILES=*.log *.dif dist-hook: cp ${srcdir}/test_http_*.res $(distdir) cp ${srcdir}/test_icu_*.res $(distdir) + cp ${srcdir}/test_post_*.res $(distdir) diff --git a/test/run_pazpar2.sh b/test/run_pazpar2.sh index 5b0c9b0..b4b9f86 100755 --- a/test/run_pazpar2.sh +++ b/test/run_pazpar2.sh @@ -31,8 +31,9 @@ fi CFG=${PREFIX}.cfg URLS=${PREFIX}_urls +usevalgrind=false if test "$usevalgrind"; then - valgrind --log-file=valgrind ../src/pazpar2 -X -l pazpar2.log -f ${CFG} >extra_pazpar2.log 2>&1 & + valgrind --leak-check=full --log-file=valgrind ../src/pazpar2 -X -l pazpar2.log -f ${CFG} >extra_pazpar2.log 2>&1 & else YAZ_LOG=zoom,zoomdetails,debug,log,fatal ../src/pazpar2 -d -X -l pazpar2.log -f ${srcdir}/${CFG} >extra_pazpar2.log 2>&1 & fi @@ -69,7 +70,11 @@ for f in `cat ${srcdir}/${URLS}`; do if test -f $OUT1; then rm -f $OUT2 if test -n "${wget}"; then - ${wget} -q -O $OUT2 $f + if test -n "${postfile}"; then + ${wget} -q -O $OUT2 --header="Content-Type: text/xml" --post-file=$postfile $f + else + ${wget} -q -O $OUT2 $f + fi elif test -n "${lynx}"; then ${lynx} -dump $f >$OUT2 else @@ -88,13 +93,22 @@ for f in `cat ${srcdir}/${URLS}`; do code=1 fi testno=`expr $testno + 1` - else + postfile= + elif echo $f | grep '^[0-9]' >/dev/null; then sleep $f + else + if test -f $f; then + postfile=$f + else + echo "File $f does not exist" + code=1 + fi fi if ps -p $PP2PID >/dev/null 2>&1; then : else - echo "pazpar2 died" + echo "Test $testno: pazpar2 died" + exit 1 fi done IFS="$oIFS" -- 1.7.10.4