-/* $Id: pazpar2.c,v 1.17 2007-01-06 04:54:58 quinn Exp $ */;
+/* $Id: pazpar2.c,v 1.53 2007-03-26 14:00:21 marc Exp $ */
#include <stdlib.h>
#include <stdio.h>
#include <yaz/yaz-util.h>
#include <yaz/nmem.h>
+#if HAVE_CONFIG_H
+#include "cconfig.h"
+#endif
+
#define USE_TIMING 0
#if USE_TIMING
#include <yaz/timing.h>
#endif
+#include <netinet/in.h>
+
#include "pazpar2.h"
#include "eventl.h"
#include "http.h"
#include "reclists.h"
#include "relevance.h"
#include "config.h"
+#include "database.h"
-#define PAZPAR2_VERSION "0.1"
#define MAX_CHUNK 15
static void client_fatal(struct client *cl);
static void connection_destroy(struct connection *co);
static int client_prep_connection(struct client *cl);
static void ingest_records(struct client *cl, Z_Records *r);
-static struct conf_retrievalprofile *database_retrieval_profile(struct database *db);
+//static struct conf_retrievalprofile *database_retrieval_profile(struct database *db);
void session_alert_watch(struct session *s, int what);
IOCHAN channel_list = 0; // Master list of connections we're handling events to
static struct connection *connection_freelist = 0;
static struct client *client_freelist = 0;
-static struct host *hosts = 0; // The hosts we know about
-static struct database *databases = 0; // The databases we know about
-
static char *client_states[] = {
"Client_Connecting",
"Client_Connected",
"Client_Stopped"
};
+// Note: Some things in this structure will eventually move to configuration
struct parameters global_parameters =
{
+ "",
+ "",
+ "",
+ 0,
0,
30,
"81",
"Index Data PazPar2 (MasterKey)",
- PAZPAR2_VERSION,
+ VERSION,
600, // 10 minutes
60,
100,
static void send_init(IOCHAN i)
{
+
struct connection *co = iochan_getdata(i);
struct client *cl = co->client;
Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_initRequest);
ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_1);
ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_2);
ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_3);
+
+
+ /* add virtual host if tunneling through Z39.50 proxy */
+
+ if (0 < strlen(global_parameters.zproxy_override)
+ && 0 < strlen(cl->database->url))
+ yaz_oi_set_string_oidval(&a->u.initRequest->otherInfo,
+ global_parameters.odr_out, VAL_PROXY,
+ 1, cl->database->url);
+
+
+
if (send_apdu(cl, a) >= 0)
{
iochan_setflags(i, EVENT_INPUT);
for (ndb = 0; db->databases[ndb]; ndb++)
databaselist[ndb] = db->databases[ndb];
- a->u.presentRequest->preferredRecordSyntax =
+ a->u.searchRequest->preferredRecordSyntax =
yaz_oidval_to_z3950oid(global_parameters.odr_out,
CLASS_RECSYN, VAL_USMARC);
a->u.searchRequest->smallSetUpperBound = &ssub;
if (r->presentStatus && !*r->presentStatus && r->records)
{
yaz_log(YLOG_DEBUG, "Records in search response");
- cl->records += *r->numberOfRecordsReturned;
ingest_records(cl, r->records);
}
cl->state = Client_Idle;
}
}
-char *normalize_mergekey(char *buf)
+char *normalize_mergekey(char *buf, int skiparticle)
{
char *p = buf, *pout = buf;
+ if (skiparticle)
+ {
+ char firstword[64];
+ char articles[] = "the den der die des an a "; // must end in space
+
+ while (*p && !isalnum(*p))
+ p++;
+ pout = firstword;
+ while (*p && *p != ' ' && pout - firstword < 62)
+ *(pout++) = tolower(*(p++));
+ *(pout++) = ' ';
+ *(pout++) = '\0';
+ if (!strstr(articles, firstword))
+ p = buf;
+ pout = buf;
+ }
+
while (*p)
{
while (*p && !isalnum(*p))
p++;
}
if (buf != pout)
- *pout = '\0';
+ do {
+ *(pout--) = '\0';
+ }
+ while (pout > buf && *pout == ' ');
return buf;
}
{
int i;
+ if (!*value)
+ return;
for (i = 0; i < s->num_termlists; i++)
if (!strcmp(s->termlists[i].name, type))
break;
yaz_log(YLOG_FATAL, "Unknown native_syntax in normalize_record");
exit(1);
}
+
+ if (global_parameters.dump_records)
+ {
+ fprintf(stderr, "Input Record (normalized):\n----------------\n");
+#if LIBXML_VERSION >= 20600
+ xmlDocFormatDump(stderr, rdoc, 1);
+#else
+ xmlDocDump(stderr, rdoc);
+#endif
+ }
+
for (m = rprofile->maplist; m; m = m->next)
{
xmlDoc *new;
if (global_parameters.dump_records)
{
fprintf(stderr, "Record:\n----------------\n");
+#if LIBXML_VERSION >= 20600
xmlDocFormatDump(stderr, rdoc, 1);
+#else
+ xmlDocDump(stderr, rdoc);
+#endif
}
return rdoc;
}
+// Extract what appears to be years from buf, storing highest and
+// lowest values.
+static int extract_years(const char *buf, int *first, int *last)
+{
+ *first = -1;
+ *last = -1;
+ while (*buf)
+ {
+ const char *e;
+ int len;
+
+ while (*buf && !isdigit(*buf))
+ buf++;
+ len = 0;
+ for (e = buf; *e && isdigit(*e); e++)
+ len++;
+ if (len == 4)
+ {
+ int value = atoi(buf);
+ if (*first < 0 || value < *first)
+ *first = value;
+ if (*last < 0 || value > *last)
+ *last = value;
+ }
+ buf = e;
+ }
+ return *first;
+}
+
static struct record *ingest_record(struct client *cl, Z_External *rec)
{
xmlDoc *xdoc = normalize_record(cl, rec);
xmlNode *root, *n;
- struct record *res, *head;
+ struct record *res;
+ struct record_cluster *cluster;
struct session *se = cl->session;
xmlChar *mergekey, *mergekey_norm;
+ xmlChar *type = 0;
+ xmlChar *value = 0;
+ struct conf_service *service = global_parameters.server->service;
if (!xdoc)
return 0;
}
res = nmem_malloc(se->nmem, sizeof(struct record));
- res->next_cluster = 0;
- res->target_offset = -1;
- res->term_frequency_vec = 0;
- res->title = "Unknown";
- res->relevance = 0;
+ res->next = 0;
+ res->client = cl;
+ res->metadata = nmem_malloc(se->nmem,
+ sizeof(struct record_metadata*) * service->num_metadata);
+ memset(res->metadata, 0, sizeof(struct record_metadata*) * service->num_metadata);
mergekey_norm = nmem_strdup(se->nmem, (char*) mergekey);
xmlFree(mergekey);
- res->merge_key = normalize_mergekey(mergekey_norm);
+ normalize_mergekey(mergekey_norm, 0);
- head = reclist_insert(se->reclist, res);
- if (!head)
+ cluster = reclist_insert(se->reclist, res, mergekey_norm, &se->total_merged);
+ if (global_parameters.dump_records)
+ yaz_log(YLOG_LOG, "Cluster id %d from %s (#%d)", cluster->recid,
+ cl->database->url, cl->records);
+ if (!cluster)
{
/* no room for record */
xmlFreeDoc(xdoc);
return 0;
}
- relevance_newrec(se->relevance, head);
+ relevance_newrec(se->relevance, cluster);
for (n = root->children; n; n = n->next)
{
+ if (type)
+ xmlFree(type);
+ if (value)
+ xmlFree(value);
+ type = value = 0;
+
if (n->type != XML_ELEMENT_NODE)
continue;
- if (!strcmp(n->name, "facet"))
+ if (!strcmp(n->name, "metadata"))
{
- xmlChar *type = xmlGetProp(n, "type");
- xmlChar *value = xmlNodeListGetString(xdoc, n->children, 0);
- if (type && value)
+ struct conf_metadata *md = 0;
+ struct conf_sortkey *sk = 0;
+ struct record_metadata **wheretoput, *newm;
+ int imeta;
+ int first, last;
+
+ type = xmlGetProp(n, "type");
+ value = xmlNodeListGetString(xdoc, n->children, 0);
+
+ if (!type || !value)
+ continue;
+
+ // First, find out what field we're looking at
+ for (imeta = 0; imeta < service->num_metadata; imeta++)
+ if (!strcmp(type, service->metadata[imeta].name))
+ {
+ md = &service->metadata[imeta];
+ if (md->sortkey_offset >= 0)
+ sk = &service->sortkeys[md->sortkey_offset];
+ break;
+ }
+ if (!md)
{
- add_facet(se, type, value);
- relevance_countwords(se->relevance, head, value, 1);
+ yaz_log(YLOG_WARN, "Ignoring unknown metadata element: %s", type);
+ continue;
}
- xmlFree(type);
- xmlFree(value);
- }
- else if (!strcmp(n->name, "metadata"))
- {
- xmlChar *type = xmlGetProp(n, "type");
- if (type && !strcmp(type, "title"))
+
+ // Find out where we are putting it
+ if (md->merge == Metadata_merge_no)
+ wheretoput = &res->metadata[imeta];
+ else
+ wheretoput = &cluster->metadata[imeta];
+
+ // Put it there
+ newm = nmem_malloc(se->nmem, sizeof(struct record_metadata));
+ newm->next = 0;
+ if (md->type == Metadata_type_generic)
+ {
+ char *p, *pe;
+ for (p = value; *p && isspace(*p); p++)
+ ;
+ for (pe = p + strlen(p) - 1;
+ pe > p && strchr(" ,/.:([", *pe); pe--)
+ *pe = '\0';
+ newm->data.text = nmem_strdup(se->nmem, p);
+
+ }
+ else if (md->type == Metadata_type_year)
+ {
+ if (extract_years(value, &first, &last) < 0)
+ continue;
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Unknown type in metadata element %s", type);
+ continue;
+ }
+ if (md->type == Metadata_type_year && md->merge != Metadata_merge_range)
+ {
+ yaz_log(YLOG_WARN, "Only range merging supported for years");
+ continue;
+ }
+ if (md->merge == Metadata_merge_unique)
+ {
+ struct record_metadata *mnode;
+ for (mnode = *wheretoput; mnode; mnode = mnode->next)
+ if (!strcmp(mnode->data.text, newm->data.text))
+ break;
+ if (!mnode)
+ {
+ newm->next = *wheretoput;
+ *wheretoput = newm;
+ }
+ }
+ else if (md->merge == Metadata_merge_longest)
+ {
+ if (!*wheretoput ||
+ strlen(newm->data.text) > strlen((*wheretoput)->data.text))
+ {
+ *wheretoput = newm;
+ if (sk)
+ {
+ char *s = nmem_strdup(se->nmem, newm->data.text);
+ if (!cluster->sortkeys[md->sortkey_offset])
+ cluster->sortkeys[md->sortkey_offset] =
+ nmem_malloc(se->nmem, sizeof(union data_types));
+ normalize_mergekey(s,
+ (sk->type == Metadata_sortkey_skiparticle));
+ cluster->sortkeys[md->sortkey_offset]->text = s;
+ }
+ }
+ }
+ else if (md->merge == Metadata_merge_all || md->merge == Metadata_merge_no)
+ {
+ newm->next = *wheretoput;
+ *wheretoput = newm;
+ }
+ else if (md->merge == Metadata_merge_range)
+ {
+ assert(md->type == Metadata_type_year);
+ if (!*wheretoput)
+ {
+ *wheretoput = newm;
+ (*wheretoput)->data.number.min = first;
+ (*wheretoput)->data.number.max = last;
+ if (sk)
+ cluster->sortkeys[md->sortkey_offset] = &newm->data;
+ }
+ else
+ {
+ if (first < (*wheretoput)->data.number.min)
+ (*wheretoput)->data.number.min = first;
+ if (last > (*wheretoput)->data.number.max)
+ (*wheretoput)->data.number.max = last;
+ }
+#ifdef GAGA
+ if (sk)
+ {
+ union data_types *sdata = cluster->sortkeys[md->sortkey_offset];
+ yaz_log(YLOG_LOG, "SK range: %d-%d", sdata->number.min, sdata->number.max);
+ }
+#endif
+ }
+ else
+ yaz_log(YLOG_WARN, "Don't know how to merge on element name %s", md->name);
+
+ if (md->rank)
+ relevance_countwords(se->relevance, cluster, value, md->rank);
+ if (md->termlist)
{
- xmlChar *value = xmlNodeListGetString(xdoc, n->children, 0);
- if (value)
+ if (md->type == Metadata_type_year)
{
- res->title = nmem_strdup(se->nmem, value);
- relevance_countwords(se->relevance, head, value, 4);
- xmlFree(value);
+ char year[64];
+ sprintf(year, "%d", last);
+ add_facet(se, type, year);
+ if (first != last)
+ {
+ sprintf(year, "%d", first);
+ add_facet(se, type, year);
+ }
}
+ else
+ add_facet(se, type, value);
}
xmlFree(type);
+ xmlFree(value);
+ type = value = 0;
}
else
yaz_log(YLOG_WARN, "Unexpected element %s in internal record", n->name);
}
+ if (type)
+ xmlFree(type);
+ if (value)
+ xmlFree(value);
xmlFreeDoc(xdoc);
- relevance_donerecord(se->relevance, head);
+ relevance_donerecord(se->relevance, cluster);
se->total_records++;
return res;
{
Z_NamePlusRecord *npr = rlist->records[i];
+ cl->records++;
if (npr->which != Z_NamePlusRecord_databaseRecord)
{
yaz_log(YLOG_WARN, "Unexpected record type, probably diagnostic");
if (!*r->presentStatus && cl->state != Client_Error)
{
yaz_log(YLOG_DEBUG, "Good Present response");
- cl->records += *r->numberOfRecordsReturned;
ingest_records(cl, r->records);
cl->state = Client_Idle;
}
int res;
void *addr;
- yaz_log(YLOG_DEBUG, "Connection create %s", cl->database->url);
+
if (!(link = cs_create(tcpip_type, 0, PROTO_Z3950)))
- {
- yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create comstack");
- exit(1);
- }
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create comstack");
+ exit(1);
+ }
+
+ if (0 == strlen(global_parameters.zproxy_override)){
+ /* no Z39.50 proxy needed - direct connect */
+ yaz_log(YLOG_DEBUG, "Connection create %s", cl->database->url);
+
+ if (!(addr = cs_straddr(link, cl->database->host->ipport)))
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO,
+ "Lookup of IP address %s failed",
+ cl->database->host->ipport);
+ return 0;
+ }
+
+ } else {
+ /* Z39.50 proxy connect */
+ yaz_log(YLOG_DEBUG, "Connection create %s proxy %s",
+ cl->database->url, global_parameters.zproxy_override);
- if (!(addr = cs_straddr(link, cl->database->host->ipport)))
- {
- yaz_log(YLOG_WARN|YLOG_ERRNO, "Lookup of IP address failed?");
- return 0;
+ yaz_log(YLOG_LOG, "Connection cs_create_host %s proxy %s",
+ cl->database->url, global_parameters.zproxy_override);
+
+ if (!(addr = cs_straddr(link, global_parameters.zproxy_override)))
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO,
+ "Lookup of IP address %s failed",
+ global_parameters.zproxy_override);
+ return 0;
+ }
}
res = cs_connect(link, addr);
return 0;
}
+#ifdef GAGA // Moved to database.c
+
// This function will most likely vanish when a proper target profile mechanism is
// introduced.
void load_simpletargets(const char *fn)
while (fgets(line, 255, f))
{
char *url, *db;
+ char *name;
struct host *host;
struct database *database;
if (strncmp(line, "target ", 7))
continue;
+ line[strlen(line) - 1] = '\0';
+
+ if ((name = strchr(line, ';')))
+ *(name++) = '\0';
+
url = line + 7;
- url[strlen(url) - 1] = '\0';
- yaz_log(YLOG_DEBUG, "Target: %s", url);
if ((db = strchr(url, '/')))
*(db++) = '\0';
else
db = "Default";
+ yaz_log(YLOG_LOG, "Target: %s, '%s'", url, db);
for (host = hosts; host; host = host->next)
if (!strcmp(url, host->hostport))
break;
}
assert(addrinfo->ai_family == PF_INET);
memcpy(addrbuf, &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4);
- sprintf(ipport, "%hhd.%hhd.%hhd.%hhd:%s",
+ sprintf(ipport, "%u.%u.%u.%u:%s",
addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port);
host->ipport = xstrdup(ipport);
freeaddrinfo(addrinfo);
strcpy(database->url, url);
strcat(database->url, "/");
strcat(database->url, db);
+ if (name)
+ database->name = xstrdup(name);
+ else
+ database->name = 0;
database->databases = xmalloc(2 * sizeof(char *));
database->databases[0] = xstrdup(db);
fclose(f);
}
+#endif
+
static void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num)
{
switch (n->kind)
s->watchlist[what].data = 0;
}
-// This needs to be extended with selection criteria
-static struct conf_retrievalprofile *database_retrieval_profile(struct database *db)
+//callback for grep_databases
+static void select_targets_callback(void *context, struct database *db)
{
- if (!config)
- {
- yaz_log(YLOG_FATAL, "Must load configuration (-f)");
- exit(1);
- }
- if (!config->retrievalprofiles)
- {
- yaz_log(YLOG_FATAL, "No retrieval profiles defined");
- }
- return config->retrievalprofiles;
+ struct session *se = (struct session*) context;
+ struct client *cl = client_create();
+ cl->database = db;
+ cl->session = se;
+ cl->next = se->clients;
+ se->clients = cl;
}
// This should be extended with parameters to control selection criteria
// Associates a set of clients with a session;
-int select_targets(struct session *se)
+int select_targets(struct session *se, struct database_criterion *crit)
{
- struct database *db;
- int c = 0;
-
while (se->clients)
client_destroy(se->clients);
- for (db = databases; db; db = db->next)
- {
- struct client *cl = client_create();
- cl->database = db;
- cl->session = se;
- cl->next = se->clients;
- se->clients = cl;
- c++;
- }
- return c;
+
+ return grep_databases(se, crit, select_targets_callback);
}
int session_active_clients(struct session *s)
return res;
}
-char *search(struct session *se, char *query)
+// parses crit1=val1,crit2=val2|val3,...
+static struct database_criterion *parse_filter(NMEM m, const char *buf)
+{
+ struct database_criterion *res = 0;
+ char **values;
+ int num;
+ int i;
+
+ if (!buf || !*buf)
+ return 0;
+ nmem_strsplit(m, ",", buf, &values, &num);
+ for (i = 0; i < num; i++)
+ {
+ char **subvalues;
+ int subnum;
+ int subi;
+ struct database_criterion *new = nmem_malloc(m, sizeof(*new));
+ char *eq = strchr(values[i], '=');
+ if (!eq)
+ {
+ yaz_log(YLOG_WARN, "Missing equal-sign in filter");
+ return 0;
+ }
+ *(eq++) = '\0';
+ new->name = values[i];
+ nmem_strsplit(m, "|", eq, &subvalues, &subnum);
+ new->values = 0;
+ for (subi = 0; subi < subnum; subi++)
+ {
+ struct database_criterion_value *newv = nmem_malloc(m, sizeof(*newv));
+ newv->value = subvalues[subi];
+ newv->next = new->values;
+ new->values = newv;
+ }
+ new->next = res;
+ res = new;
+ }
+ return res;
+}
+
+char *search(struct session *se, char *query, char *filter)
{
int live_channels = 0;
struct client *cl;
+ struct database_criterion *criteria;
yaz_log(YLOG_DEBUG, "Search");
+ nmem_reset(se->nmem);
+ criteria = parse_filter(se->nmem, filter);
strcpy(se->query, query);
se->requestid++;
- nmem_reset(se->nmem);
+ // Release any existing clients
+ select_targets(se, criteria);
for (cl = se->clients; cl; cl = cl->next)
{
- cl->hits = -1;
- cl->records = 0;
- cl->diagnostic = 0;
-
if (client_prep_connection(cl))
live_channels++;
}
se->reclist = reclist_create(se->nmem, maxrecs);
extract_terms(se->nmem, query, p);
se->relevance = relevance_create(se->nmem, (const char **) p, maxrecs);
- se->total_records = se->total_hits = 0;
+ se->total_records = se->total_hits = se->total_merged = 0;
se->expected_maxrecs = maxrecs;
}
else
while (s->clients)
client_destroy(s->clients);
nmem_destroy(s->nmem);
- wrbuf_free(s->wrbuf, 1);
+ wrbuf_destroy(s->wrbuf);
}
struct session *new_session()
session->watchlist[i].fun = 0;
}
- select_targets(session);
-
return session;
}
*count = 0;
for (cl = se->clients; cl; cl = cl->next)
{
- strcpy(res[*count].id, cl->database->host->hostport);
+ res[*count].id = cl->database->url;
+ res[*count].name = cl->database->name;
res[*count].hits = cl->hits;
res[*count].records = cl->records;
res[*count].diagnostic = cl->diagnostic;
}
#endif
-struct record **show(struct session *s, int start, int *num, int *total,
- int *sumhits, NMEM nmem_show)
+struct record_cluster *show_single(struct session *s, int id)
+{
+ struct record_cluster *r;
+
+ reclist_rewind(s->reclist);
+ while ((r = reclist_read_record(s->reclist)))
+ if (r->recid == id)
+ return r;
+ return 0;
+}
+
+struct record_cluster **show(struct session *s, struct reclist_sortparms *sp, int start,
+ int *num, int *total, int *sumhits, NMEM nmem_show)
{
- struct record **recs = nmem_malloc(nmem_show, *num
- * sizeof(struct record *));
+ struct record_cluster **recs = nmem_malloc(nmem_show, *num
+ * sizeof(struct record_cluster *));
+ struct reclist_sortparms *spp;
int i;
#if USE_TIMING
yaz_timing_t t = yaz_timing_create();
#endif
- relevance_prepare_read(s->relevance, s->reclist);
+
+ for (spp = sp; spp; spp = spp->next)
+ if (spp->type == Metadata_sortkey_relevance)
+ {
+ relevance_prepare_read(s->relevance, s->reclist);
+ break;
+ }
+ reclist_sort(s->reclist, sp);
*total = s->reclist->num_records;
*sumhits = s->total_hits;
for (i = 0; i < *num; i++)
{
- struct record *r = reclist_read_record(s->reclist);
+ struct record_cluster *r = reclist_read_record(s->reclist);
if (!r)
{
*num = i;
struct client *cl;
int count = 0;
- bzero(stat, sizeof(*stat));
+ memset(stat, 0, sizeof(*stat));
for (cl = se->clients; cl; cl = cl->next)
{
if (!cl->connection)
return res;
}
+static void start_http_listener(void)
+{
+ char hp[128] = "";
+ struct conf_server *ser = global_parameters.server;
+
+ if (*global_parameters.listener_override)
+ strcpy(hp, global_parameters.listener_override);
+ else
+ {
+ strcpy(hp, ser->host ? ser->host : "");
+ if (ser->port)
+ {
+ if (*hp)
+ strcat(hp, ":");
+ sprintf(hp + strlen(hp), "%d", ser->port);
+ }
+ }
+ http_init(hp);
+}
+
+static void start_proxy(void)
+{
+ char hp[128] = "";
+ struct conf_server *ser = global_parameters.server;
+
+ if (*global_parameters.proxy_override)
+ strcpy(hp, global_parameters.proxy_override);
+ else if (ser->proxy_host || ser->proxy_port)
+ {
+ strcpy(hp, ser->proxy_host ? ser->proxy_host : "");
+ if (ser->proxy_port)
+ {
+ if (*hp)
+ strcat(hp, ":");
+ sprintf(hp + strlen(hp), "%d", ser->proxy_port);
+ }
+ }
+ else
+ return;
+
+ http_set_proxyaddr(hp, ser->myurl ? ser->myurl : "");
+}
+
int main(int argc, char **argv)
{
int ret;
char *arg;
- int setport = 0;
- if (signal(SIGPIPE, SIG_IGN) < 0)
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
yaz_log(YLOG_WARN|YLOG_ERRNO, "signal");
yaz_log_init(YLOG_DEFAULT_LEVEL, "pazpar2", 0);
- while ((ret = options("f:x:h:p:C:s:d", argv, argc, &arg)) != -2)
+ while ((ret = options("f:x:h:p:z:C:s:d", argv, argc, &arg)) != -2)
{
switch (ret) {
case 'f':
exit(1);
break;
case 'h':
- http_init(arg);
- setport++;
+ strcpy(global_parameters.listener_override, arg);
break;
case 'C':
global_parameters.ccl_filter = load_cclfile(arg);
break;
case 'p':
- http_set_proxyaddr(arg);
+ strcpy(global_parameters.proxy_override, arg);
+ break;
+ case 'z':
+ strcpy(global_parameters.zproxy_override, arg);
break;
case 's':
load_simpletargets(arg);
" -h [host:]port (REST protocol listener)\n"
" -C cclconfig\n"
" -s simpletargetfile\n"
- " -p hostname[:portno] (HTTP proxy)\n");
+ " -p hostname[:portno] (HTTP proxy)\n"
+ " -z hostname[:portno] (Z39.50 proxy)\n"
+ " -d (show internal records)\n");
exit(1);
}
}
- if (!setport)
+ if (!config)
{
- fprintf(stderr, "Set command port with -h\n");
+ yaz_log(YLOG_FATAL, "Load config with -f");
exit(1);
}
+ global_parameters.server = config->servers;
- global_parameters.ccl_filter = load_cclfile("../etc/default.bib");
+ start_http_listener();
+ start_proxy();
+ if (!global_parameters.ccl_filter)
+ global_parameters.ccl_filter = load_cclfile("../etc/default.bib");
global_parameters.yaz_marc = yaz_marc_create();
yaz_marc_subfield_str(global_parameters.yaz_marc, "\t");
global_parameters.odr_in = odr_createmem(ODR_DECODE);