Functional settings system. At this point, they control the CCL map only
authorSebastian Hammer <quinn@indexdata.com>
Fri, 30 Mar 2007 02:45:07 +0000 (02:45 +0000)
committerSebastian Hammer <quinn@indexdata.com>
Fri, 30 Mar 2007 02:45:07 +0000 (02:45 +0000)
etc/settings/defaults-query.xml [new file with mode: 0644]
src/config.c
src/config.h
src/database.c
src/http.c
src/pazpar2.c
src/pazpar2.h
src/settings.c
src/settings.h

diff --git a/etc/settings/defaults-query.xml b/etc/settings/defaults-query.xml
new file mode 100644 (file)
index 0000000..a2f0be3
--- /dev/null
@@ -0,0 +1,15 @@
+<settings target="*">
+
+  <!-- Default query mapping -->
+  <!-- Note, individual fields can be overriden per-database and/or per-user -->
+
+  <!-- mapping for unqualified search -->
+  <set name="pz:cclmap:term" value="u=1016 t=l,r s=al"/>
+
+  <set name="pz:cclmap:ti" value="u=4 s=al"/>
+  <set name="pz:cclmap:su" value="u=21 s=al"/>
+  <set name="pz:cclmap:isbn" value="u=7"/>
+  <set name="pz:cclmap:issn" value="u=8"/>
+  <set name="pz:cclmap:date" value="u=30 r=r"/>
+
+</settings>
index 780894e..cbdbd97 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 1.18 2007-03-27 11:25:57 marc Exp $ */
+/* $Id: config.c,v 1.19 2007-03-30 02:45:07 quinn Exp $ */
 
 #include <string.h>
 
@@ -183,6 +183,22 @@ static struct conf_service *parse_service(xmlNode *node)
     return r;
 }
 
+static char *parse_settings(xmlNode *node)
+{
+    xmlChar *src = xmlGetProp(node, (xmlChar *) "src");
+    char *r;
+
+    if (src)
+        r = nmem_strdup(nmem, (const char *) src);
+    else
+    {
+        yaz_log(YLOG_FATAL, "Must specify src in targetprofile");
+        return 0;
+    }
+    xmlFree(src);
+    return r;
+}
+
 static struct conf_server *parse_server(xmlNode *node)
 {
     xmlNode *n;
@@ -197,6 +213,7 @@ static struct conf_server *parse_server(xmlNode *node)
     r->zproxy_port = 0;
     r->service = 0;
     r->next = 0;
+    r->settings = 0;
 
     for (n = node->children; n; n = n->next)
     {
@@ -224,11 +241,13 @@ static struct conf_server *parse_server(xmlNode *node)
                 r->proxy_host = nmem_strdup(nmem, (const char *) host);
             if (myurl)
                 r->myurl = nmem_strdup(nmem, (const char *) myurl);
+#ifdef GAGA
             else
             {
                 yaz_log(YLOG_FATAL, "Must specify @myurl for proxy");
                 return 0;
             }
+#endif
             xmlFree(port);
             xmlFree(host);
             xmlFree(myurl);
@@ -249,6 +268,16 @@ static struct conf_server *parse_server(xmlNode *node)
             xmlFree(port);
             xmlFree(host);
         }
+        else if (!strcmp((const char *) n->name, "settings"))
+        {
+            if (r->settings)
+            {
+                yaz_log(YLOG_FATAL, "Can't repeat 'settings'");
+                return 0;
+            }
+            if (!(r->settings = parse_settings(n)))
+                return 0;
+        }
         else if (!strcmp((const char *) n->name, "service"))
         {
             struct conf_service *s = parse_service(n);
@@ -454,7 +483,6 @@ static struct conf_config *parse_config(xmlNode *root)
     struct conf_retrievalprofile **rp = &r->retrievalprofiles;
 
     r->servers = 0;
-    r->queryprofiles = 0;
     r->retrievalprofiles = 0;
     r->targetprofiles = 0;
 
@@ -470,9 +498,6 @@ static struct conf_config *parse_config(xmlNode *root)
             tmp->next = r->servers;
             r->servers = tmp;
         }
-        else if (!strcmp((const char *) n->name, "queryprofile"))
-        {
-        }
         else if (!strcmp((const char *) n->name, "retrievalprofile"))
         {
             if (!(*rp = parse_retrievalprofile(n)))
index 5c2c8b1..3a79498 100644 (file)
@@ -69,15 +69,11 @@ struct conf_server
     char *myurl;
     char *zproxy_host;
     int zproxy_port;
+    char *settings;
     struct conf_service *service;
     struct conf_server *next;
 };
 
-struct conf_queryprofile
-{
-    int dummy;
-};
-
 struct conf_retrievalmap
 {
     enum {
@@ -122,7 +118,6 @@ struct conf_targetprofiles
 struct conf_config
 {
     struct conf_server *servers;
-    struct conf_queryprofile *queryprofiles;
     struct conf_targetprofiles *targetprofiles;
     struct conf_retrievalprofile *retrievalprofiles;
 };
index dea337b..95703e0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: database.c,v 1.5 2007-03-29 13:44:38 quinn Exp $ */
+/* $Id: database.c,v 1.6 2007-03-30 02:45:07 quinn Exp $ */
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -127,9 +127,8 @@ static struct host *find_host(const char *hostport)
 static struct database *load_database(const char *id)
 {
     xmlDoc *doc = get_explain_xml(id);
-    struct zr_explain *explain;
+    struct zr_explain *explain = 0;
     struct conf_retrievalprofile *retrieval;
-    struct conf_queryprofile *query;
     struct database *db;
     struct host *host;
     char hostport[256];
@@ -143,8 +142,7 @@ static struct database *load_database(const char *id)
         if (!explain)
             return 0;
     }
-    if (!(retrieval = database_retrievalprofile(id)) ||
-            !(query = database_queryprofile(id)))
+    if (!(retrieval = database_retrievalprofile(id)))
     {
         xmlFree(doc);
         return 0;
@@ -168,10 +166,10 @@ static struct database *load_database(const char *id)
     db->databases[1] = 0;
     db->errors = 0;
     db->explain = explain;
-    db->qprofile = query;
     db->rprofile = retrieval;
     db->settings = 0;
     db->next = databases;
+    db->ccl_map = 0;
     databases = db;
 
     return db;
index 021d730..e4655e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: http.c,v 1.16 2007-03-29 15:23:17 quinn Exp $
+ * $Id: http.c,v 1.17 2007-03-30 02:45:07 quinn Exp $
  */
 
 #include <stdio.h>
@@ -760,6 +760,7 @@ static void http_io(IOCHAN i, int event)
     }
 }
 
+#ifdef GAGA
 // If this hostname contains our proxy host as a prefix, replace with myurl
 static char *sub_hostname(struct http_channel *c, char *buf)
 {
@@ -776,6 +777,7 @@ static char *sub_hostname(struct http_channel *c, char *buf)
     }
     return buf;
 }
+#endif
 
 // Handles I/O on a client connection to a backend web server (proxy mode)
 static void proxy_io(IOCHAN pi, int event)
index 31cf431..c151cae 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pazpar2.c,v 1.56 2007-03-28 12:05:18 marc Exp $ */
+/* $Id: pazpar2.c,v 1.57 2007-03-30 02:45:07 quinn Exp $ */
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -88,7 +88,6 @@ struct parameters global_parameters =
     MAX_CHUNK,
     0,
     0,
-    0,
     0
 };
 
@@ -161,6 +160,34 @@ static void send_init(IOCHAN i)
     odr_reset(global_parameters.odr_out);
 }
 
+static void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num)
+{
+    switch (n->kind)
+    {
+        case CCL_RPN_AND:
+        case CCL_RPN_OR:
+        case CCL_RPN_NOT:
+        case CCL_RPN_PROX:
+            pull_terms(nmem, n->u.p[0], termlist, num);
+            pull_terms(nmem, n->u.p[1], termlist, num);
+            break;
+        case CCL_RPN_TERM:
+            termlist[(*num)++] = nmem_strdup(nmem, n->u.t.term);
+            break;
+        default: // NOOP
+            break;
+    }
+}
+
+// Extract terms from query into null-terminated termlist
+static void extract_terms(NMEM nmem, struct ccl_rpn_node *query, char **termlist)
+{
+    int num = 0;
+
+    pull_terms(nmem, query, termlist, &num);
+    termlist[num] = 0;
+}
+
 static void send_search(IOCHAN i)
 {
     struct connection *co = iochan_getdata(i);
@@ -176,9 +203,19 @@ static void send_search(IOCHAN i)
 
     yaz_log(YLOG_DEBUG, "Sending search");
 
-    cn = ccl_find_str(global_parameters.ccl_filter, se->query, &cerror, &cpos);
+    cn = ccl_find_str(db->ccl_map, se->query, &cerror, &cpos);
     if (!cn)
         return;
+
+    if (!se->relevance)
+    {
+        // Initialize relevance structure with query terms
+        char *p[512];
+        extract_terms(se->nmem, cn, p);
+        se->relevance = relevance_create(se->nmem, (const char **) p,
+                se->expected_maxrecs);
+    }
+
     a->u.searchRequest->query = zquery = odr_malloc(global_parameters.odr_out,
             sizeof(Z_Query));
     zquery->which = Z_Query_type_1;
@@ -1189,41 +1226,6 @@ void load_simpletargets(const char *fn)
 
 #endif
 
-static void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num)
-{
-    switch (n->kind)
-    {
-        case CCL_RPN_AND:
-        case CCL_RPN_OR:
-        case CCL_RPN_NOT:
-        case CCL_RPN_PROX:
-            pull_terms(nmem, n->u.p[0], termlist, num);
-            pull_terms(nmem, n->u.p[1], termlist, num);
-            break;
-        case CCL_RPN_TERM:
-            termlist[(*num)++] = nmem_strdup(nmem, n->u.t.term);
-            break;
-        default: // NOOP
-            break;
-    }
-}
-
-// Extract terms from query into null-terminated termlist
-static int extract_terms(NMEM nmem, char *query, char **termlist)
-{
-    int error, pos;
-    struct ccl_rpn_node *n;
-    int num = 0;
-
-    n = ccl_find_str(global_parameters.ccl_filter, query, &error, &pos);
-    if (!n)
-        return -1;
-    pull_terms(nmem, n, termlist, &num);
-    termlist[num] = 0;
-    ccl_rpn_delete(n);
-    return 0;
-}
-
 static struct client *client_create(void)
 {
     struct client *r;
@@ -1378,12 +1380,11 @@ char *search(struct session *se, char *query, char *filter)
     }
     if (live_channels)
     {
-        char *p[512];
         int maxrecs = live_channels * global_parameters.toget;
         se->num_termlists = 0;
         se->reclist = reclist_create(se->nmem, maxrecs);
-        extract_terms(se->nmem, query, p);
-        se->relevance = relevance_create(se->nmem, (const char **) p, maxrecs);
+        // This will be initialized in send_search()
+        se->relevance = 0;
         se->total_records = se->total_hits = se->total_merged = 0;
         se->expected_maxrecs = maxrecs;
     }
@@ -1562,17 +1563,6 @@ void statistics(struct session *se, struct statistics *stat)
     stat->num_clients = count;
 }
 
-static CCL_bibset load_cclfile(const char *fn)
-{
-    CCL_bibset res = ccl_qual_mk();
-    if (ccl_qual_fname(res, fn) < 0)
-    {
-        yaz_log(YLOG_FATAL|YLOG_ERRNO, "%s", fn);
-        exit(1);
-    }
-    return res;
-}
-
 static void start_http_listener(void)
 {
     char hp[128] = "";
@@ -1593,6 +1583,36 @@ static void start_http_listener(void)
     http_init(hp);
 }
 
+// Initialize CCL map for a target
+// Note: This approach ignores user-specific CCL maps, for which I
+// don't presently see any application.
+static void prepare_cclmap(void *context, struct database *db)
+{
+    struct setting *s;
+
+    if (!db->settings)
+        return;
+    db->ccl_map = ccl_qual_mk();
+    for (s = db->settings[PZ_CCLMAP]; s; s = s->next)
+        if (!*s->user)
+        {
+            char *p = strchr(s->name + 3, ':');
+            if (!p)
+            {
+                yaz_log(YLOG_FATAL, "Malformed cclmap name: %s", s->name);
+                exit(1);
+            }
+            p++;
+            ccl_qual_fitem(db->ccl_map, s->value, p);
+        }
+}
+
+// Read settings for each database, and prepare a CCL map for that database
+static void prepare_cclmaps(void)
+{
+    grep_databases(0, 0, prepare_cclmap);
+}
+
 static void start_proxy(void)
 {
     char hp[128] = "";
@@ -1661,7 +1681,7 @@ int main(int argc, char **argv)
 
     yaz_log_init(YLOG_DEFAULT_LEVEL, "pazpar2", 0);
 
-    while ((ret = options("t:f:x:h:p:z:C:s:d", argv, argc, &arg)) != -2)
+    while ((ret = options("t:f:x:h:p:z:s:d", argv, argc, &arg)) != -2)
     {
        switch (ret) {
             case 'f':
@@ -1671,9 +1691,6 @@ int main(int argc, char **argv)
             case 'h':
                 strcpy(global_parameters.listener_override, arg);
                 break;
-            case 'C':
-                global_parameters.ccl_filter = load_cclfile(arg);
-                break;
             case 'p':
                 strcpy(global_parameters.proxy_override, arg);
                 break;
@@ -1681,7 +1698,7 @@ int main(int argc, char **argv)
                 strcpy(global_parameters.zproxy_override, arg);
                 break;
             case 't':
-                strcpy(global_parameters.settings_path, arg);
+                strcpy(global_parameters.settings_path_override, arg);
                 break;
             case 's':
                 load_simpletargets(arg);
@@ -1713,10 +1730,13 @@ int main(int argc, char **argv)
     start_proxy();
     start_zproxy();
 
-    if (*global_parameters.settings_path)
-        settings_read(global_parameters.settings_path);
-    if (!global_parameters.ccl_filter)
-        global_parameters.ccl_filter = load_cclfile("../etc/default.bib");
+    if (*global_parameters.settings_path_override)
+        settings_read(global_parameters.settings_path_override);
+    else if (global_parameters.server->settings)
+        settings_read(global_parameters.server->settings);
+    else
+        yaz_log(YLOG_WARN, "No settings-directory specified. Problems may ensue!");
+    prepare_cclmaps();
     global_parameters.yaz_marc = yaz_marc_create();
     yaz_marc_subfield_str(global_parameters.yaz_marc, "\t");
     global_parameters.odr_in = odr_createmem(ODR_DECODE);
index ec9e95a..846750b 100644 (file)
@@ -70,10 +70,10 @@ struct database {
     char **databases;
     int errors;
     struct zr_explain *explain;
-    struct conf_queryprofile *qprofile;
     struct conf_retrievalprofile *rprofile;
     struct setting **settings;
     struct database *next;
+    CCL_bibset ccl_map;
 };
 
 struct database_criterion_value {
@@ -191,7 +191,7 @@ struct parameters {
     char proxy_override[128];
     char listener_override[128];
     char zproxy_override[128];
-    char settings_path[128];
+    char settings_path_override[128];
     struct conf_server *server;
     int dump_records;
     int timeout;               /* operations timeout, in seconds */
@@ -202,7 +202,6 @@ struct parameters {
     int session_timeout;
     int toget;
     int chunk;
-    CCL_bibset ccl_filter;
     yaz_marc_t yaz_marc;
     ODR odr_out;
     ODR odr_in;
index 11215c9..391a32b 100644 (file)
@@ -1,8 +1,7 @@
-// $Id: settings.c,v 1.3 2007-03-29 13:44:19 quinn Exp $
+// $Id: settings.c,v 1.4 2007-03-30 02:45:07 quinn Exp $
 // This module implements a generic system of settings (attribute-value) that can 
 // be associated with search targets. The system supports both default values,
 // per-target overrides, and per-user settings.
-//
 
 #include <string.h>
 #include <stdio.h>
@@ -27,7 +26,8 @@ static NMEM nmem = 0;
 static char *hard_settings[] = {
     "pz:piggyback",
     "pz:elements",
-    "pz::syntax",
+    "pz:syntax",
+    "pz:cclmap:",
     0
 };
 
@@ -50,6 +50,22 @@ int settings_offset(const char *name)
     return -1;
 }
 
+// Ignores everything after second colon, if present
+// A bit of a hack to support the pz:cclmap: scheme (and more to come?)
+static int settings_offset_cprefix(const char *name)
+{
+    const char *p;
+    int maxlen = 100;
+    int i;
+
+    if (!strncmp("pz:", name, 3) && (p = strchr(name + 3, ':')))
+        maxlen = (p - name) + 1;
+    for (i = 0; i < dictionary->num; i++)
+        if (!strncmp(name, dictionary->dict[i], maxlen))
+            return i;
+    return -1;
+}
+
 char *settings_name(int offset)
 {
     return dictionary->dict[offset];
@@ -201,7 +217,10 @@ static void read_settings(const char *path,
 static void prepare_dictionary(struct setting *set)
 {
     int i;
+    char *p;
 
+    if (!strncmp(set->name, "pz:", 3) && (p = strchr(set->name + 3, ':')))
+        *(p + 1) = '\0';
     for (i = 0; i < dictionary->num; i++)
         if (!strcmp(dictionary->dict[i], set->name))
             return;
@@ -230,16 +249,16 @@ static void update_database(void *context, struct database *db)
     if (!db->settings)
     {
         db->settings = nmem_malloc(nmem, sizeof(struct settings*) * dictionary->num);
-        memset(db->settings, sizeof(struct settings*) * dictionary->num, 0);
+        memset(db->settings, 0, sizeof(struct settings*) * dictionary->num);
     }
-    if ((offset = settings_offset(set->name)) < 0)
+    if ((offset = settings_offset_cprefix(set->name)) < 0)
         abort(); // Should never get here
 
     // First we determine if this setting is overriding  any existing settings
     // with the same name.
     for (s = db->settings[offset], sp = &db->settings[offset]; s;
             sp = &s->next, s = s->next)
-        if (!strcmp(s->user, set->user))
+        if (!strcmp(s->user, set->user) && !strcmp(s->name, set->name))
         {
             if (s->precedence < set->precedence)
                 // We discard the value (nmem keeps track of the space)
@@ -258,7 +277,7 @@ static void update_database(void *context, struct database *db)
     {
         struct setting *new = nmem_malloc(nmem, sizeof(*new));
 
-        memset(new, sizeof(*new), 0);
+        memset(new, 0, sizeof(*new));
         new->precedence = set->precedence;
         new->target = nmem_strdup(nmem, set->target);
         new->name = nmem_strdup(nmem, set->name);
@@ -306,8 +325,8 @@ void settings_read(const char *path)
     else
         nmem_reset(nmem);
     new = nmem_malloc(nmem, sizeof(*new));
+    memset(new, 0, sizeof(*new));
     initialize_hard_settings(new);
-    memset(new, sizeof(*new), 0);
     dictionary = new;
     read_settings(path, prepare_dictionary);
     read_settings(path, update_databases);
index e381ff9..abb8942 100644 (file)
@@ -4,6 +4,7 @@
 #define PZ_PIGGYBACK    0 
 #define PZ_ELEMENTS     1
 #define PZ_SYNTAX       2
+#define PZ_CCLMAP       3
 
 struct setting
 {