Settings, bytarget + db out-of-range check
[pazpar2-moved-to-github.git] / src / logic.c
index 2b9fbd5..5399dd0 100644 (file)
@@ -77,8 +77,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 struct parameters global_parameters = 
 {
     0,   // dump_records
-    0,   // debug_mode
-    100,
+    0    // debug_mode
 };
 
 static void log_xml_doc(xmlDoc *doc)
@@ -146,14 +145,13 @@ static void add_facet(struct session *s, const char *type, const char *value)
 
         s->termlists[i].name = nmem_strdup(s->nmem, type);
         s->termlists[i].termlist 
-            = termlist_create(s->nmem, s->expected_maxrecs,
-                              TERMLIST_HIGH_SCORE);
+            = termlist_create(s->nmem, TERMLIST_HIGH_SCORE);
         s->num_termlists = i + 1;
     }
     termlist_insert(s->termlists[i].termlist, value);
 }
 
-xmlDoc *record_to_xml(struct session_database *sdb, const char *rec)
+static xmlDoc *record_to_xml(struct session_database *sdb, const char *rec)
 {
     struct database *db = sdb->database;
     xmlDoc *rdoc = 0;
@@ -240,8 +238,9 @@ static void insert_settings_values(struct session_database *sdb, xmlDoc *doc,
     }
 }
 
-xmlDoc *normalize_record(struct session_database *sdb, struct session *se,
-                         const char *rec)
+static xmlDoc *normalize_record(struct session_database *sdb,
+                                struct session *se,
+                                const char *rec)
 {
     xmlDoc *rdoc = record_to_xml(sdb, rec);
 
@@ -270,6 +269,29 @@ xmlDoc *normalize_record(struct session_database *sdb, struct session *se,
     return rdoc;
 }
 
+void session_settings_dump(struct session *se,
+                           struct session_database *db,
+                           WRBUF w)
+{
+    if (db->settings)
+    {
+        struct conf_service *service = se->service;
+        int i, num = settings_num(service);
+        for (i = 0; i < num; i++)
+        {
+            struct setting *s = db->settings[i];
+            for (;s; s = s->next)
+            {
+                wrbuf_puts(w, "<set name=\"");
+                wrbuf_xmlputs(w, s->name);
+                wrbuf_puts(w, "\" value=\"");
+                wrbuf_xmlputs(w, s->value);
+                wrbuf_puts(w, "\"/>\n");
+            }
+        }
+    }
+}
+
 // Retrieve first defined value for 'name' for given database.
 // Will be extended to take into account user associated with session
 const char *session_setting_oneval(struct session_database *db, int offset)
@@ -319,7 +341,8 @@ static int prepare_map(struct session *se, struct session_database *sdb)
                 yaz_log(YLOG_WARN, "No pz:requestsyntax for auto stylesheet");
             }
         }
-        sdb->map = normalize_record_create(se->service, s);
+        sdb->map = normalize_cache_get(se->normalize_cache,
+                                       se->service, s);
         if (!sdb->map)
             return -1;
     }
@@ -444,11 +467,11 @@ static struct database_criterion *parse_filter(NMEM m, const char *buf)
         char *eq;
         if ((eq = strchr(values[i], '=')))
             new->type = PAZPAR2_STRING_MATCH;
-        if ((eq = strchr(values[i], '~')))
+        else if ((eq = strchr(values[i], '~')))
             new->type = PAZPAR2_SUBSTRING_MATCH;
-        if (!eq)
+        else
         {
-            yaz_log(YLOG_WARN, "Missing equal-signi/tilde in filter");
+            yaz_log(YLOG_WARN, "Missing equal-sign/tilde in filter");
             return 0;
         }
         *(eq++) = '\0';
@@ -470,7 +493,9 @@ static struct database_criterion *parse_filter(NMEM m, const char *buf)
 }
 
 enum pazpar2_error_code search(struct session *se,
-                               const char *query, const char *filter,
+                               const char *query,
+                               const char *startrecs, const char *maxrecs,
+                               const char *filter,
                                const char **addinfo)
 {
     int live_channels = 0;
@@ -491,15 +516,17 @@ enum pazpar2_error_code search(struct session *se,
     live_channels = select_targets(se, criteria);
     if (live_channels)
     {
-        int maxrecs = live_channels * global_parameters.toget; // This is buggy!!!
-        se->reclist = reclist_create(se->nmem, maxrecs);
-        se->expected_maxrecs = maxrecs;
+        se->reclist = reclist_create(se->nmem);
     }
     else
         return PAZPAR2_NO_TARGETS;
 
     for (cl = se->clients; cl; cl = client_next_in_session(cl))
     {
+        if (maxrecs)
+            client_set_maxrecs(cl, atoi(maxrecs));
+        if (startrecs)
+            client_set_startrecs(cl, atoi(startrecs));
         if (prepare_session_database(se, client_get_database(cl)) < 0)
             continue;
         // Parse query for target
@@ -554,7 +581,6 @@ static void session_init_databases_fun(void *context, struct database *db)
 // Doesn't free memory associated with sdb -- nmem takes care of that
 static void session_database_destroy(struct session_database *sdb)
 {
-    normalize_record_destroy(sdb->map);
     sdb->map = 0;
 }
 
@@ -626,7 +652,6 @@ void session_apply_setting(struct session *se, char *dbname, char *setting,
     case PZ_XSLT:
         if (sdb->map)
         {
-            normalize_record_destroy(sdb->map);
             sdb->map = 0;
         }
         break;
@@ -641,6 +666,7 @@ void destroy_session(struct session *s)
         client_destroy(s->clients);
     for (sdb = s->databases; sdb; sdb = sdb->next)
         session_database_destroy(sdb);
+    normalize_cache_destroy(s->normalize_cache);
     nmem_destroy(s->nmem);
     service_destroy(s->service);
     wrbuf_destroy(s->wrbuf);
@@ -662,7 +688,6 @@ struct session *new_session(NMEM nmem, struct conf_service *service)
     session->num_termlists = 0;
     session->reclist = 0;
     session->clients = 0;
-    session->expected_maxrecs = 0;
     session->session_nmem = nmem;
     session->nmem = nmem_create();
     session->wrbuf = wrbuf_alloc();
@@ -672,6 +697,8 @@ struct session *new_session(NMEM nmem, struct conf_service *service)
         session->watchlist[i].data = 0;
         session->watchlist[i].fun = 0;
     }
+    session->normalize_cache = normalize_cache_create();
+
     return session;
 }
 
@@ -688,6 +715,7 @@ struct hitsbytarget *hitsbytarget(struct session *se, int *count, NMEM nmem)
     *count = 0;
     for (cl = se->clients; cl; cl = client_next_in_session(cl))
     {
+        WRBUF w = wrbuf_alloc();
         const char *name = session_setting_oneval(client_get_database(cl),
                                                   PZ_NAME);
 
@@ -698,6 +726,8 @@ struct hitsbytarget *hitsbytarget(struct session *se, int *count, NMEM nmem)
         res[*count].diagnostic = client_get_diagnostic(cl);
         res[*count].state = client_get_state_str(cl);
         res[*count].connected  = client_get_connection(cl) ? 1 : 0;
+        session_settings_dump(se, client_get_database(cl), w);
+        res[*count].settings_xml = w;
         (*count)++;
     }
     return res;
@@ -776,7 +806,7 @@ struct record_cluster **show(struct session *s, struct reclist_sortparms *sp,
             }
         reclist_sort(s->reclist, sp);
         
-        *total = s->reclist->num_records;
+        *total = reclist_get_num_records(s->reclist);
         *sumhits = s->total_hits;
         
         for (i = 0; i < start; i++)
@@ -1019,7 +1049,7 @@ static int check_record_filter(xmlNode *root, struct session_database *sdb)
             if (type)
             {
                 size_t len;
-                const char *eq = strchr(s, '=');
+                const char *eq = strchr(s, '~');
                 if (eq)
                     len = eq - s;
                 else
@@ -1091,15 +1121,15 @@ struct record *ingest_record(struct client *cl, const char *rec,
                              service, 
                              record, (char *) mergekey_norm, 
                              &se->total_merged);
-    if (global_parameters.dump_records)
-        yaz_log(YLOG_LOG, "Cluster id %s from %s (#%d)", cluster->recid,
-                sdb->database->url, record_no);
     if (!cluster)
     {
         /* no room for record */
         xmlFreeDoc(xdoc);
         return 0;
     }
+    if (global_parameters.dump_records)
+        yaz_log(YLOG_LOG, "Cluster id %s from %s (#%d)", cluster->recid,
+                sdb->database->url, record_no);
     relevance_newrec(se->relevance, cluster);
     
     // now parsing XML record and adding data to cluster or record metadata