1 /* $Id: database.c,v 1.4 2007-03-23 03:26:22 quinn Exp $ */
3 #include <libxml/parser.h>
4 #include <libxml/tree.h>
5 #include <libxslt/xslt.h>
6 #include <libxslt/transform.h>
7 #include <libxslt/xsltutils.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
18 #include <netinet/in.h>
20 static struct host *hosts = 0; // The hosts we know about
21 static struct database *databases = 0; // The databases we know about
24 // This needs to be extended with selection criteria
25 static struct conf_retrievalprofile *database_retrievalprofile(const char *id)
29 yaz_log(YLOG_FATAL, "Must load configuration (-f)");
32 if (!config->retrievalprofiles)
34 yaz_log(YLOG_FATAL, "No retrieval profiles defined");
36 return config->retrievalprofiles;
39 static struct conf_queryprofile *database_queryprofile(const char *id)
41 return (struct conf_queryprofile*) 1;
44 static xmlDoc *get_explain_xml(const char *id)
49 if (!config || !config->targetprofiles)
51 yaz_log(YLOG_WARN, "Config must be loaded and specify targetprofiles");
54 if (config->targetprofiles->type != Targetprofiles_local)
56 yaz_log(YLOG_FATAL, "Only supports local type");
59 dir = config->targetprofiles->src;
61 sprintf(path, "%s/%s", dir, ide);
62 yaz_log(YLOG_LOG, "Path: %s", path);
63 return xmlParseFile(path);
66 // Create a new host structure for hostport
67 static struct host *create_host(const char *hostport)
69 struct addrinfo *addrinfo, hints;
73 unsigned char addrbuf[4];
76 host = xmalloc(sizeof(struct host));
77 host->hostport = xstrdup(hostport);
78 host->connections = 0;
80 if ((port = strchr(hostport, ':')))
86 hints.ai_family = PF_INET;
87 hints.ai_socktype = SOCK_STREAM;
88 hints.ai_protocol = IPPROTO_TCP;
91 hints.ai_canonname = 0;
93 // This is not robust code. It assumes that getaddrinfo always
94 // returns AF_INET address.
95 if ((res = getaddrinfo(hostport, port, &hints, &addrinfo)))
97 yaz_log(YLOG_WARN, "Failed to resolve %s: %s", hostport, gai_strerror(res));
98 xfree(host->hostport);
102 assert(addrinfo->ai_family == PF_INET);
103 memcpy(addrbuf, &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4);
104 sprintf(ipport, "%u.%u.%u.%u:%s",
105 addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port);
106 host->ipport = xstrdup(ipport);
107 freeaddrinfo(addrinfo);
113 static struct host *find_host(const char *hostport)
116 for (p = hosts; p; p = p->next)
117 if (!strcmp(p->hostport, hostport))
119 return create_host(hostport);
122 static struct database *load_database(const char *id)
124 xmlDoc *doc = get_explain_xml(id);
125 struct zr_explain *explain;
126 struct conf_retrievalprofile *retrieval;
127 struct conf_queryprofile *query;
134 nmem = nmem_create();
137 explain = zr_read_xml(nmem, xmlDocGetRootElement(doc));
141 if (!(retrieval = database_retrievalprofile(id)) ||
142 !(query = database_queryprofile(id)))
147 if (strlen(id) > 255)
149 strcpy(hostport, id);
150 if ((dbname = strchr(hostport, '/')))
154 if (!(host = find_host(hostport)))
156 db = nmem_malloc(nmem, sizeof(*db));
157 memset(db, 0, sizeof(*db));
159 db->url = nmem_strdup(nmem, id);
161 db->databases = xmalloc(2 * sizeof(char *));
162 db->databases[0] = nmem_strdup(nmem, dbname);
163 db->databases[1] = 0;
165 db->explain = explain;
166 db->qprofile = query;
167 db->rprofile = retrieval;
168 db->next = databases;
174 // Return a database structure by ID. Load and add to list if necessary
175 // new==1 just means we know it's not in the list
176 struct database *find_database(const char *id, int new)
181 for (p = databases; p; p = p->next)
182 if (!strcmp(p->url, id))
185 return load_database(id);
188 // This will be generalized at some point
189 static int match_criterion(struct database *db, struct database_criterion *c)
191 if (!strcmp(c->name, "id"))
193 struct database_criterion_value *v;
194 for (v = c->values; v; v = v->next)
195 if (!strcmp(v->value, db->url))
203 int database_match_criteria(struct database *db, struct database_criterion *cl)
205 for (; cl; cl = cl->next)
206 if (!match_criterion(db, cl))
208 if (cl) // one of the criteria failed to match -- skip this db
214 // Cycles through databases, calling a handler function on the ones for
215 // which all criteria matched.
216 int grep_databases(void *context, struct database_criterion *cl,
217 void (*fun)(void *context, struct database *db))
222 for (p = databases; p; p = p->next)
224 if (database_match_criteria(p, cl))
233 // This function will most likely vanish when a proper target profile mechanism is
235 void load_simpletargets(const char *fn)
237 FILE *f = fopen(fn, "r");
242 yaz_log(YLOG_WARN|YLOG_ERRNO, "open %s", fn);
246 while (fgets(line, 255, f))
252 if (strncmp(line, "target ", 7))
254 line[strlen(line) - 1] = '\0';
256 if ((name = strchr(line, ';')))
261 if (!(db = find_database(url, 0)))
262 yaz_log(YLOG_WARN, "Unable to load database %s", url);
264 db->name = nmem_strdup(nmem, name);
273 * indent-tabs-mode: nil
275 * vim: shiftwidth=4 tabstop=8 expandtab