#include "settings.h"
#include "http.h"
#include "zeerex.h"
+#include "database.h"
#include <sys/types.h>
#if HAVE_SYS_SOCKET_H
return create_host(hostport);
}
-static struct database *load_database(const char *id)
+static struct database *load_database(const char *id,
+ struct conf_service *service)
{
xmlDoc *doc = 0;
struct zr_explain *explain = 0;
db->settings = 0;
- db->settings = nmem_malloc(nmem, sizeof(struct settings*) * settings_num());
- memset(db->settings, 0, sizeof(struct settings*) * settings_num());
+ db->settings = nmem_malloc(nmem, sizeof(struct settings*) *
+ settings_num(service));
+ memset(db->settings, 0, sizeof(struct settings*) * settings_num(service));
idset = nmem_malloc(nmem, sizeof(*idset));
idset->precedence = 0;
idset->name = "pz:id";
// Return a database structure by ID. Load and add to list if necessary
// new==1 just means we know it's not in the list
-struct database *find_database(const char *id, int new)
+struct database *find_database(const char *id, int new,
+ struct conf_service *service)
{
struct database *p;
if (!new)
if (!strcmp(p->url, id))
return p;
}
- return load_database(id);
+ return load_database(id, service);
}
// This whole session_grep database thing should be moved elsewhere
}
// This will be generalized at some point
-static int match_criterion(struct setting **settings, struct database_criterion *c)
+static int match_criterion(struct setting **settings,
+ struct conf_service *service,
+ struct database_criterion *c)
{
- int offset = settings_offset(c->name);
+ int offset = settings_offset(service, c->name);
struct database_criterion_value *v;
if (offset < 0)
return 0;
}
-int database_match_criteria(struct setting **settings, struct database_criterion *cl)
+int database_match_criteria(struct setting **settings,
+ struct conf_service *service,
+ struct database_criterion *cl)
{
for (; cl; cl = cl->next)
- if (!match_criterion(settings, cl))
+ if (!match_criterion(settings, service, cl))
break;
if (cl) // one of the criteria failed to match -- skip this db
return 0;
continue;
if (!p->settings[PZ_NAME])
continue;
- if (database_match_criteria(p->settings, cl))
+ if (database_match_criteria(p->settings, se->service, cl))
{
(*fun)(se, p);
i++;
return i;
}
-int predef_grep_databases(void *context, struct database_criterion *cl,
+int predef_grep_databases(void *context, struct conf_service *service,
+ struct database_criterion *cl,
void (*fun)(void *context, struct database *db))
{
struct database *p;
int i = 0;
for (p = databases; p; p = p->next)
- if (database_match_criteria(p->settings, cl))
+ if (database_match_criteria(p->settings, service, cl))
{
(*fun)(context, p);
i++;
#define DATABASE_H
void prepare_databases(void);
-struct database *find_database(const char *id, int new);
-int database_match_criteria(struct session_database *db, struct database_criterion *cl);
+struct database *find_database(const char *id, int new, struct conf_service *service);
int session_grep_databases(struct session *se, struct database_criterion *cl,
void (*fun)(void *context, struct session_database *db));
-int predef_grep_databases(void *context, struct database_criterion *cl,
+int predef_grep_databases(void *context, struct conf_service *service,
+ struct database_criterion *cl,
void (*fun)(void *context, struct database *db));
int match_zurl(const char *zurl, const char *pattern);
http_session_destroy(s);
}
-struct http_session *http_session_create(void)
+struct http_session *http_session_create(struct conf_service *service)
{
NMEM nmem = nmem_create();
struct http_session *r = nmem_malloc(nmem, sizeof(*r));
- r->psession = new_session(nmem);
+ r->psession = new_session(nmem, service);
r->session_id = 0;
r->timestamp = 0;
r->nmem = nmem;
http_close_server();
}
+static struct conf_service *locate_service(const char *service_name)
+{
+ return global_parameters.server->service;
+}
+
static void cmd_init(struct http_channel *c)
{
unsigned int sesid;
char buf[1024];
const char *clear = http_argbyname(c->request, "clear");
- struct http_session *s = http_session_create();
+ const char *service_name = http_argbyname(c->request, "service");
+ struct http_session *s = http_session_create(locate_service(service_name));
struct http_response *rs = c->response;
yaz_log(YLOG_DEBUG, "HTTP Session init");
struct http_session *s = locate_session(rq, rs);
struct record_cluster *rec, *prev_r, *next_r;
struct record *r;
- struct conf_service *service = global_parameters.server->service;
+ struct conf_service *service = s->psession->service;
const char *idstr = http_argbyname(rq, "id");
const char *offsetstr = http_argbyname(rq, "offset");
const char *binarystr = http_argbyname(rq, "binary");
numn = atoi(num);
if (!sort)
sort = "relevance";
- if (!(sp = reclist_parse_sortparms(c->nmem, sort)))
+ if (!(sp = reclist_parse_sortparms(c->nmem, sort, s->psession->service)))
{
error(rs, PAZPAR2_MALFORMED_PARAMETER_VALUE, "sort");
return;
int ccount;
struct record *p;
struct record_cluster *rec = rl[i];
- struct conf_service *service = global_parameters.server->service;
+ struct conf_service *service = s->psession->service;
wrbuf_puts(c->wrbuf, "<hit>\n");
write_metadata(c->wrbuf, service, rec->metadata, 0);
static void insert_settings_parameters(struct session_database *sdb,
struct session *se, char **parms)
{
- struct conf_service *service = global_parameters.server->service;
+ struct conf_service *service = se->service;
int i;
int nparms = 0;
int offset = 0;
int setting;
if (md->setting == Metadata_setting_parameter &&
- (setting = settings_offset(md->name)) > 0)
+ (setting = settings_offset(service, md->name)) > 0)
{
const char *val = session_setting_oneval(sdb, setting);
if (val && nparms < MAX_XSLT_ARGS)
}
// Add static values from session database settings if applicable
-static void insert_settings_values(struct session_database *sdb, xmlDoc *doc)
+static void insert_settings_values(struct session_database *sdb, xmlDoc *doc,
+ struct conf_service *service)
{
- struct conf_service *service = global_parameters.server->service;
int i;
for (i = 0; i < service->num_metadata; i++)
int offset;
if (md->setting == Metadata_setting_postproc &&
- (offset = settings_offset(md->name)) > 0)
+ (offset = settings_offset(service, md->name)) > 0)
{
const char *val = session_setting_oneval(sdb, offset);
if (val)
rdoc = new;
}
- insert_settings_values(sdb, rdoc);
+ insert_settings_values(sdb, rdoc, se->service);
if (global_parameters.dump_records)
{
static void session_init_databases_fun(void *context, struct database *db)
{
struct session *se = (struct session *) context;
+ struct conf_service *service = se->service;
struct session_database *new = nmem_malloc(se->session_nmem, sizeof(*new));
- int num = settings_num();
+ int num = settings_num(service);
int i;
new->database = db;
void session_init_databases(struct session *se)
{
se->databases = 0;
- predef_grep_databases(se, 0, session_init_databases_fun);
+ predef_grep_databases(se, se->service, 0, session_init_databases_fun);
}
// Probably session_init_databases_fun should be refactored instead of
static struct session_database *load_session_database(struct session *se,
char *id)
{
- struct database *db = find_database(id, 0);
+ struct database *db = find_database(id, 0, se->service);
session_init_databases_fun((void*) se, db);
// New sdb is head of se->databases list
char *value)
{
struct session_database *sdb = find_session_database(se, dbname);
+ struct conf_service *service = se->service;
struct setting *new = nmem_malloc(se->session_nmem, sizeof(*new));
- int offset = settings_offset_cprefix(setting);
+ int offset = settings_offset_cprefix(service, setting);
if (offset < 0)
{
wrbuf_destroy(s->wrbuf);
}
-struct session *new_session(NMEM nmem)
+struct session *new_session(NMEM nmem, struct conf_service *service)
{
int i;
struct session *session = nmem_malloc(nmem, sizeof(*session));
yaz_log(YLOG_DEBUG, "New Pazpar2 session");
-
+
+ session->service = service;
session->relevance = 0;
session->total_hits = 0;
session->total_records = 0;
const char *mergekey_norm;
xmlChar *type = 0;
xmlChar *value = 0;
- struct conf_service *service = global_parameters.server->service;
+ struct conf_service *service = se->service;
if (!xdoc)
return 0;
record_no);
cluster = reclist_insert(se->reclist,
- global_parameters.server->service,
+ service,
record, (char *) mergekey_norm,
&se->total_merged);
if (global_parameters.dump_records)
void child_handler(void *data)
{
+ struct conf_service *service = global_parameters.server->service;
start_proxy();
- init_settings();
+
+ init_settings(service);
if (*global_parameters.settings_path_override)
- settings_read(global_parameters.settings_path_override);
+ settings_read(service, global_parameters.settings_path_override);
else if (global_parameters.server->settings)
- settings_read(global_parameters.server->settings);
+ settings_read(service, global_parameters.server->settings);
else
yaz_log(YLOG_WARN, "No settings-directory specified");
global_parameters.odr_in = odr_createmem(ODR_DECODE);
pazpar2_event_loop();
-
}
static void show_version(void)
// End-user session
struct session {
+ struct conf_service *service; /* service in use for this session */
struct session_database *databases; // All databases, settings overriden
struct client *clients; // Clients connected for current search
NMEM session_nmem; // Nmem for session-permanent storage
struct hitsbytarget *hitsbytarget(struct session *s, int *count, NMEM nmem);
int select_targets(struct session *se, struct database_criterion *crit);
-struct session *new_session(NMEM nmem);
+struct session *new_session(NMEM nmem, struct conf_service *service);
void destroy_session(struct session *s);
void session_init_databases(struct session *s);
int load_targets(struct session *s, const char *fn);
= nmem_malloc(nmem,
sizeof(struct conf_sortkey) * service->num_sortkeys);
+ service->nmem = 0;
+ service->dictionary = 0;
return service;
}
struct conf_metadata *metadata;
int num_sortkeys;
struct conf_sortkey *sortkeys;
-
+ struct setting_dictionary *dictionary;
+ NMEM nmem;
};
struct conf_service * conf_service_create(NMEM nmem,
#endif
-struct reclist_sortparms *reclist_parse_sortparms(NMEM nmem, const char *parms)
+struct reclist_sortparms *reclist_parse_sortparms(NMEM nmem, const char *parms,
+ struct conf_service *service)
{
struct reclist_sortparms *res = 0;
struct reclist_sortparms **rp = &res;
- struct conf_service *service = config->servers->service;
if (strlen(parms) > 256)
return 0;
void reclist_sort(struct reclist *l, struct reclist_sortparms *parms);
struct record_cluster *reclist_read_record(struct reclist *l);
void reclist_rewind(struct reclist *l);
-struct reclist_sortparms *reclist_parse_sortparms(NMEM nmem, const char *parms);
+struct reclist_sortparms *reclist_parse_sortparms(NMEM nmem, const char *parms,
+ struct conf_service *service);
#endif
#include "database.h"
#include "settings.h"
-static NMEM nmem = 0;
-
// Used for initializing setting_dictionary with pazpar2-specific settings
static char *hard_settings[] = {
"pz:piggyback",
int num;
};
-static struct setting_dictionary *dictionary = 0;
-
// This establishes the precedence of wildcard expressions
#define SETTING_WILDCARD_NO 0 // No wildcard
#define SETTING_WILDCARD_DB 1 // Database wildcard 'host:port/*'
#define SETTING_WILDCARD_YES 2 // Complete wildcard '*'
// Returns size of settings directory
-int settings_num(void)
+int settings_num(struct conf_service *service)
{
- return dictionary->num;
+ return service->dictionary->num;
}
-int settings_offset(const char *name)
+int settings_offset(struct conf_service *service, const char *name)
{
int i;
if (!name)
name = "";
- for (i = 0; i < dictionary->num; i++)
- if (!strcmp(name, dictionary->dict[i]))
+ for (i = 0; i < service->dictionary->num; i++)
+ if (!strcmp(name, service->dictionary->dict[i]))
return i;
return -1;
}
// Ignores everything after second colon, if present
// A bit of a hack to support the pz:cclmap: scheme (and more to come?)
-int settings_offset_cprefix(const char *name)
+int settings_offset_cprefix(struct conf_service *service, const char *name)
{
const char *p;
int maxlen = 100;
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))
+ for (i = 0; i < service->dictionary->num; i++)
+ if (!strncmp(name, service->dictionary->dict[i], maxlen))
return i;
return -1;
}
-char *settings_name(int offset)
+char *settings_name(struct conf_service *service, int offset)
{
- return dictionary->dict[offset];
+ return service->dictionary->dict[offset];
}
static int isdir(const char *path)
// Read settings from an XML file, calling handler function for each setting
static void read_settings_file(const char *path,
- void (*fun)(struct setting *set))
+ struct conf_service *service,
+ void (*fun)(struct conf_service *service,
+ struct setting *set))
{
xmlDoc *doc = xmlParseFile(path);
xmlNode *n;
strcpy(valueb, (const char *) valuea);
set.value = valueb;
set.next = 0;
- (*fun)(&set);
+ (*fun)(service, &set);
}
xmlFree(name);
xmlFree(precedence);
// Recursively read files or directories, invoking a
// callback for each one
static void read_settings(const char *path,
- void (*fun)(struct setting *set))
+ struct conf_service *service,
+ void (*fun)(struct conf_service *service,
+ struct setting *set))
{
DIR *d;
struct dirent *de;
if (*de->d_name == '.' || !strcmp(de->d_name, "CVS"))
continue;
sprintf(tmp, "%s/%s", path, de->d_name);
- read_settings(tmp, fun);
+ read_settings(tmp, service, fun);
}
closedir(d);
}
else if ((dot = strrchr(path, '.')) && !strcmp(dot + 1, "xml"))
- read_settings_file(path, fun);
+ read_settings_file(path, service, fun);
}
// Determines if a ZURL is a wildcard, and what kind
// Callback. Adds a new entry to the dictionary if necessary
// This is used in pass 1 to determine layout of dictionary
// and to load any databases mentioned
-static void prepare_dictionary(struct setting *set)
+static void prepare_dictionary(struct conf_service *service,
+ struct setting *set)
{
+ struct setting_dictionary *dictionary = service->dictionary;
+
int i;
char *p;
// If target address is not wildcard, add the database
if (*set->target && !zurl_wildcard(set->target))
- find_database(set->target, 0);
+ find_database(set->target, 0, service);
// Determine if we already have a dictionary entry
if (!strncmp(set->name, "pz:", 3) && (p = strchr(set->name + 3, ':')))
// Create a new dictionary entry
// Grow dictionary if necessary
if (!dictionary->size)
- dictionary->dict = nmem_malloc(nmem, (dictionary->size = 50) * sizeof(char*));
+ dictionary->dict =
+ nmem_malloc(service->nmem, (dictionary->size = 50) * sizeof(char*));
else if (dictionary->num + 1 > dictionary->size)
{
- char **tmp = nmem_malloc(nmem, dictionary->size * 2 * sizeof(char*));
+ char **tmp =
+ nmem_malloc(service->nmem, dictionary->size * 2 * sizeof(char*));
memcpy(tmp, dictionary->dict, dictionary->size * sizeof(char*));
dictionary->dict = tmp;
dictionary->size *= 2;
}
- dictionary->dict[dictionary->num++] = nmem_strdup(nmem, set->name);
+ dictionary->dict[dictionary->num++] = nmem_strdup(service->nmem, set->name);
}
+struct update_database_context {
+ struct setting *set;
+ struct conf_service *service;
+};
+
// This is called from grep_databases -- adds/overrides setting for a target
// This is also where the rules for precedence of settings are implemented
static void update_database(void *context, struct database *db)
{
- struct setting *set = (struct setting *) context;
+ struct setting *set = ((struct update_database_context *)
+ context)->set;
+ struct conf_service *service = ((struct update_database_context *)
+ context)->service;
struct setting *s, **sp;
int offset;
if (!match_zurl(db->url, set->target))
return;
- if ((offset = settings_offset_cprefix(set->name)) < 0)
+ if ((offset = settings_offset_cprefix(service, set->name)) < 0)
abort(); // Should never get here
// First we determine if this setting is overriding any existing settings
}
if (!s) // s will be null when there are no higher-priority settings -- we add one
{
- struct setting *new = nmem_malloc(nmem, sizeof(*new));
+ struct setting *new = nmem_malloc(service->nmem, sizeof(*new));
memset(new, 0, sizeof(*new));
new->precedence = set->precedence;
- new->target = nmem_strdup(nmem, set->target);
- new->name = nmem_strdup(nmem, set->name);
- new->value = nmem_strdup(nmem, set->value);
+ new->target = nmem_strdup(service->nmem, set->target);
+ new->name = nmem_strdup(service->nmem, set->name);
+ new->value = nmem_strdup(service->nmem, set->value);
new->next = db->settings[offset];
db->settings[offset] = new;
}
// Callback -- updates database records with dictionary entries as appropriate
// This is used in pass 2 to assign name/value pairs to databases
-static void update_databases(struct setting *set)
+static void update_databases(struct conf_service *service,
+ struct setting *set)
{
- predef_grep_databases(set, 0, update_database);
+ struct update_database_context context;
+ context.set = set;
+ context.service = service;
+ predef_grep_databases(&context, service, 0, update_database);
}
// This simply copies the 'hard' (application-specific) settings
// to the settings dictionary.
-static void initialize_hard_settings(struct setting_dictionary *dict)
+static void initialize_hard_settings(struct conf_service *service)
{
- dict->dict = nmem_malloc(nmem, sizeof(hard_settings) - sizeof(char*));
+ struct setting_dictionary *dict = service->dictionary;
+ dict->dict = nmem_malloc(service->nmem, sizeof(hard_settings) - sizeof(char*));
dict->size = (sizeof(hard_settings) - sizeof(char*)) / sizeof(char*);
memcpy(dict->dict, hard_settings, dict->size * sizeof(char*));
dict->num = dict->size;
// Read any settings names introduced in service definition (config) and add to dictionary
// This is done now to avoid errors if user settings are declared in session overrides
-static void initialize_soft_settings(void)
+static void initialize_soft_settings(struct conf_service *service)
{
- struct conf_service *service = config->servers->service;
int i;
for (i = 0; i < service->num_metadata; i++)
set.name = md->name;
set.value = "";
set.next = 0;
- prepare_dictionary(&set);
+ prepare_dictionary(service, &set);
}
}
// If we ever decide we need to be able to specify multiple settings directories,
// the two calls to read_settings must be split -- so the dictionary is prepared
// for the contents of every directory before the databases are updated.
-void settings_read(const char *path)
+void settings_read(struct conf_service *service, const char *path)
{
- read_settings(path, prepare_dictionary);
- read_settings(path, update_databases);
+ read_settings(path, service, prepare_dictionary);
+ read_settings(path, service, update_databases);
}
-void init_settings(void)
+void init_settings(struct conf_service *service)
{
struct setting_dictionary *new;
- if (!nmem)
- nmem = nmem_create();
- else
- nmem_reset(nmem);
- new = nmem_malloc(nmem, sizeof(*new));
+
+ service->nmem = nmem_create();
+
+ new = nmem_malloc(service->nmem, sizeof(*new));
memset(new, 0, sizeof(*new));
- initialize_hard_settings(new);
- dictionary = new;
- initialize_soft_settings();
+ service->dictionary = new;
+ initialize_hard_settings(service);
+ initialize_soft_settings(service);
}
/*
struct setting *next;
};
-int settings_num(void);
-void settings_read(const char *path);
-int settings_offset(const char *name);
-int settings_offset_cprefix(const char *name);
-void init_settings(void);
+int settings_num(struct conf_service *service);
+void settings_read(struct conf_service *service, const char *path);
+int settings_offset(struct conf_service *service, const char *name);
+int settings_offset_cprefix(struct conf_service *service, const char *name);
+void init_settings(struct conf_service *service);
#endif