X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Flogic.c;h=2a0e9617a11cb9d1ffd08255ea2ff9b3748fe760;hb=315af5c601a268e2d0da60477c3470a6c12654c9;hp=12500ffe0a30eb6a477a5b99f139371fec6368a1;hpb=dedbc922fbe49e599466f41c618ba9ba8ddb9477;p=pazpar2-moved-to-github.git diff --git a/src/logic.c b/src/logic.c index 12500ff..2a0e961 100644 --- a/src/logic.c +++ b/src/logic.c @@ -1,4 +1,4 @@ -/* $Id: logic.c,v 1.16 2007-04-21 12:00:54 adam Exp $ +/* $Id: logic.c,v 1.19 2007-04-23 08:15:22 marc Exp $ Copyright (c) 2006-2007, Index Data. This file is part of Pazpar2. @@ -509,8 +509,9 @@ static void add_facet(struct session *s, const char *type, const char *value) if (i == SESSION_MAX_TERMLISTS) { yaz_log(YLOG_FATAL, "Too many termlists"); - exit(1); + return; } + s->termlists[i].name = nmem_strdup(s->nmem, type); s->termlists[i].termlist = termlist_create(s->nmem, s->expected_maxrecs, 15); s->num_termlists = i + 1; @@ -562,7 +563,7 @@ static xmlDoc *normalize_record(struct client *cl, Z_External *rec) yaz_log(YLOG_FATAL, "Unknown native_syntax in normalize_record from %s", db->url); - exit(1); + return 0; } if (global_parameters.dump_records){ @@ -1100,8 +1101,12 @@ static void connection_release(struct connection *co) static void connection_destroy(struct connection *co) { struct host *h = co->host; - cs_close(co->link); - iochan_destroy(co->iochan); + + if (co->link) + { + cs_close(co->link); + iochan_destroy(co->iochan); + } yaz_log(YLOG_DEBUG, "Connection destroy %s", co->host->hostport); if (h->connections == co) @@ -1126,62 +1131,103 @@ static void connection_destroy(struct connection *co) connection_freelist = co; } - -// Creates a new connection for client, associated with the host of -// client's database -static struct connection *connection_create(struct client *cl) +static int connection_connect(struct connection *con) { - struct connection *new; - COMSTACK link; - int res; + COMSTACK link = 0; + struct client *cl = con->client; + struct host *host = con->host; void *addr; + int res; + assert(host->ipport); + assert(cl); - if (!cl->database->database->host->ipport) + if (!(link = cs_create(tcpip_type, 0, PROTO_Z3950))) { - yaz_log(YLOG_WARN, "Not yet resolved: %s", - cl->database->database->url); - return 0; + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create comstack"); + return -1; } - - if (!(link = cs_create(tcpip_type, 0, PROTO_Z3950))) - { - 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->database->url); - if (!(addr = cs_straddr(link, cl->database->database->host->ipport))) - { - yaz_log(YLOG_WARN|YLOG_ERRNO, - "Lookup of IP address %s failed", - cl->database->database->host->ipport); - return 0; - } - + if (!(addr = cs_straddr(link, host->ipport))) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, + "Lookup of IP address %s failed", host->ipport); + return -1; + } + } else { /* Z39.50 proxy connect */ yaz_log(YLOG_DEBUG, "Connection create %s proxy %s", cl->database->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; - } + { + yaz_log(YLOG_WARN|YLOG_ERRNO, + "Lookup of IP address %s failed", + global_parameters.zproxy_override); + return -1; + } } - + res = cs_connect(link, addr); if (res < 0) { yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_connect %s", cl->database->database->url); - return 0; + return -1; + } + con->link = link; + con->state = Conn_Connecting; + con->iochan = iochan_create(cs_fileno(link), connection_handler, 0); + iochan_setdata(con->iochan, con); + pazpar2_add_channel(con->iochan); + + /* this fragment is bad DRY: from client_prep_connection */ + cl->state = Client_Connecting; + iochan_setflag(con->iochan, EVENT_OUTPUT); + return 0; +} + +void connect_resolver_host(struct host *host) +{ + struct connection *con = host->connections; + + while (con) + { + if (con->state == Conn_Resolving) + { + if (!host->ipport) /* unresolved */ + { + connection_destroy(con); + /* start all over .. at some point it will be NULL */ + con = host->connections; + } + else if (!con->client) + { + yaz_log(YLOG_WARN, "connect_unresolved_host : ophan client"); + connection_destroy(con); + /* start all over .. at some point it will be NULL */ + con = host->connections; + } + else + { + connection_connect(con); + con = con->next; + } + } } +} + + +// Creates a new connection for client, associated with the host of +// client's database +static struct connection *connection_create(struct client *cl) +{ + struct connection *new; + struct host *host = cl->database->database->host; if ((new = connection_freelist)) connection_freelist = new->next; @@ -1191,17 +1237,15 @@ static struct connection *connection_create(struct client *cl) new->ibuf = 0; new->ibufsize = 0; } - new->state = Conn_Connecting; - new->host = cl->database->database->host; + new->host = host; new->next = new->host->connections; new->host->connections = new; new->client = cl; cl->connection = new; - new->link = link; - - new->iochan = iochan_create(cs_fileno(link), connection_handler, 0); - iochan_setdata(new->iochan, new); - pazpar2_add_channel(new->iochan); + new->link = 0; + new->state = Conn_Resolving; + if (host->ipport) + connection_connect(new); return new; } @@ -1596,58 +1640,8 @@ char *search(struct session *se, char *query, char *filter) return 0; } -// Apply a session override to a database -void session_apply_setting(struct session *se, char *dbname, char *setting, char *value) -{ - struct session_database *sdb; - - for (sdb = se->databases; sdb; sdb = sdb->next) - if (!strcmp(dbname, sdb->database->url)) - { - struct setting *new = nmem_malloc(se->session_nmem, sizeof(*new)); - int offset = settings_offset(setting); - - if (offset < 0) - { - yaz_log(YLOG_WARN, "Unknown setting %s", setting); - return; - } - new->precedence = 0; - new->target = dbname; - new->name = setting; - new->value = value; - new->next = sdb->settings[offset]; - sdb->settings[offset] = new; - - // Force later recompute of settings-driven data structures - // (happens when a search starts and client connections are prepared) - switch (offset) - { - case PZ_NATIVESYNTAX: - if (sdb->yaz_marc) - { - yaz_marc_destroy(sdb->yaz_marc); - sdb->yaz_marc = 0; - } - break; - case PZ_XSLT: - if (sdb->map) - { - struct database_retrievalmap *m; - // We don't worry about the map structure -- it's in nmem - for (m = sdb->map; m; m = m->next) - xsltFreeStylesheet(m->stylesheet); - sdb->map = 0; - } - break; - } - break; - } - if (!sdb) - yaz_log(YLOG_WARN, "Unknown database in setting override: %s", dbname); -} - -void session_init_databases_fun(void *context, struct database *db) +// Creates a new session_database object for a database +static void session_init_databases_fun(void *context, struct database *db) { struct session *se = (struct session *) context; struct session_database *new = nmem_malloc(se->session_nmem, sizeof(*new)); @@ -1658,12 +1652,27 @@ void session_init_databases_fun(void *context, struct database *db) new->yaz_marc = 0; new->map = 0; new->settings = nmem_malloc(se->session_nmem, sizeof(struct settings *) * num); - for (i = 0; i < num; i++) - new->settings[i] = db->settings[i]; + memset(new->settings, 0, sizeof(struct settings*) * num); + if (db->settings) + { + for (i = 0; i < num; i++) + new->settings[i] = db->settings[i]; + } new->next = se->databases; se->databases = new; } +// Doesn't free memory associated with sdb -- nmem takes care of that +static void session_database_destroy(struct session_database *sdb) +{ + struct database_retrievalmap *m; + + for (m = sdb->map; m; m = m->next) + xsltFreeStylesheet(m->stylesheet); + if (sdb->yaz_marc) + yaz_marc_destroy(sdb->yaz_marc); +} + // Initialize session_database list -- this represents this session's view // of the database list -- subject to modification by the settings ws command void session_init_databases(struct session *se) @@ -1672,11 +1681,80 @@ void session_init_databases(struct session *se) grep_databases(se, 0, session_init_databases_fun); } +// Probably session_init_databases_fun should be refactored instead of +// called here. +static struct session_database *load_session_database(struct session *se, char *id) +{ + struct database *db = find_database(id, 0); + + session_init_databases_fun((void*) se, db); + // New sdb is head of se->databases list + return se->databases; +} + +// Find an existing session database. If not found, load it +static struct session_database *find_session_database(struct session *se, char *id) +{ + struct session_database *sdb; + + for (sdb = se->databases; sdb; sdb = sdb->next) + if (!strcmp(sdb->database->url, id)) + return sdb; + return load_session_database(se, id); +} + +// Apply a session override to a database +void session_apply_setting(struct session *se, char *dbname, char *setting, char *value) +{ + struct session_database *sdb = find_session_database(se, dbname); + struct setting *new = nmem_malloc(se->session_nmem, sizeof(*new)); + int offset = settings_offset(setting); + + if (offset < 0) + { + yaz_log(YLOG_WARN, "Unknown setting %s", setting); + return; + } + new->precedence = 0; + new->target = dbname; + new->name = setting; + new->value = value; + new->next = sdb->settings[offset]; + sdb->settings[offset] = new; + + // Force later recompute of settings-driven data structures + // (happens when a search starts and client connections are prepared) + switch (offset) + { + case PZ_NATIVESYNTAX: + if (sdb->yaz_marc) + { + yaz_marc_destroy(sdb->yaz_marc); + sdb->yaz_marc = 0; + } + break; + case PZ_XSLT: + if (sdb->map) + { + struct database_retrievalmap *m; + // We don't worry about the map structure -- it's in nmem + for (m = sdb->map; m; m = m->next) + xsltFreeStylesheet(m->stylesheet); + sdb->map = 0; + } + break; + } +} + void destroy_session(struct session *s) { + struct session_database *sdb; + yaz_log(YLOG_LOG, "Destroying session"); while (s->clients) client_destroy(s->clients); + for (sdb = s->databases; sdb; sdb = sdb->next) + session_database_destroy(sdb); nmem_destroy(s->nmem); wrbuf_destroy(s->wrbuf); }