2 * Copyright (C) 1994-1998, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.10 1998-06-08 14:43:15 adam
8 * Added suport for EXPLAIN Proxy servers - added settings databasePath
9 * and explainDatabase to facilitate this. Increased maximum number
10 * of databases and attributes in one register.
12 * Revision 1.9 1998/06/02 12:10:27 adam
13 * Fixed bug related to attributeDetails.
15 * Revision 1.8 1998/05/20 10:12:20 adam
16 * Implemented automatic EXPLAIN database maintenance.
17 * Modified Zebra to work with ASN.1 compiled version of YAZ.
19 * Revision 1.7 1998/03/05 08:45:13 adam
20 * New result set model and modular ranking system. Moved towards
21 * descent server API. System information stored as "SGML" records.
23 * Revision 1.6 1998/02/17 10:29:27 adam
24 * Moved towards 'automatic' EXPLAIN database.
26 * Revision 1.5 1997/10/27 14:33:05 adam
27 * Moved towards generic character mapping depending on "structure"
28 * field in abstract syntax file. Fixed a few memory leaks. Fixed
29 * bug with negative integers when doing searches with relational
32 * Revision 1.4 1997/09/25 14:57:08 adam
35 * Revision 1.3 1996/05/22 08:21:59 adam
36 * Added public ZebDatabaseInfo structure.
38 * Revision 1.2 1996/05/14 06:16:41 adam
39 * Compact use/set bytes used in search service.
41 * Revision 1.1 1996/05/13 14:23:07 adam
42 * Work on compaction of set/use bytes in dictionary.
63 struct zebSUInfo info;
64 struct zebSUInfoB *next;
67 typedef struct zebAccessObjectB *zebAccessObject;
68 struct zebAccessObjectB {
75 typedef struct zebAccessInfoB *zebAccessInfo;
76 struct zebAccessInfoB {
77 zebAccessObject attributeSetIds;
78 zebAccessObject schemas;
82 struct zebSUInfoB *SUInfo;
86 data1_node *data1_tree;
87 } *zebAttributeDetails;
89 struct zebDatabaseInfoB {
90 zebAttributeDetails attributeDetails;
92 data1_node *data1_database;
93 int recordCount; /* records in db */
94 int recordBytes; /* size of records */
95 int sysno; /* sysno of database info */
96 int readFlag; /* 1: read is needed when referenced; 0 if not */
97 int dirty; /* 1: database is dirty: write is needed */
98 struct zebDatabaseInfoB *next;
99 zebAccessInfo accessInfo;
102 struct zebraExplainAttset {
105 struct zebraExplainAttset *next;
108 struct zebraExplainInfo {
115 struct zebraExplainAttset *attsets;
117 data1_node *data1_target;
118 struct zebDatabaseInfoB *databaseInfo;
119 struct zebDatabaseInfoB *curDatabaseInfo;
120 zebAccessInfo accessInfo;
121 char date[15]; /* YYYY MMDD HH MM SS */
122 int (*updateFunc)(void *handle, Record drec, data1_node *n);
126 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
127 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
129 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
131 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
134 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
137 logf (LOG_DEBUG, "data1_search_tag %s", tag);
138 for (; n; n = n->next)
139 if (n->which == DATA1N_tag && n->u.tag.tag &&
140 !yaz_matchstr (tag, n->u.tag.tag))
142 logf (LOG_DEBUG, " found");
145 logf (LOG_DEBUG, " not found");
149 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
150 const char *tag, NMEM nmem)
152 data1_node *partag = get_parent_tag(dh, at);
153 data1_node *res = data1_mk_node (dh, nmem);
154 data1_element *e = NULL;
157 res->which = DATA1N_tag;
158 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
159 res->u.tag.node_selected = 0;
160 res->u.tag.make_variantlist = 0;
161 res->u.tag.no_data_requested = 0;
162 res->u.tag.get_bytes = -1;
165 e = partag->u.tag.element;
167 data1_getelementbytagname (dh, at->root->u.root.absyn,
169 res->root = at->root;
174 assert (at->last_child);
175 at->last_child->next = res;
177 at->last_child = res;
181 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
182 const char *tag, NMEM nmem)
184 data1_node *node = data1_search_tag (dh, at->child, tag);
186 node = data1_add_tag (dh, at, tag, nmem);
188 node->child = node->last_child = NULL;
192 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
193 const char *tag, int num,
196 data1_node *node_data;
198 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
201 node_data->u.data.what = DATA1I_num;
202 node_data->u.data.data = node_data->lbuf;
203 sprintf (node_data->u.data.data, "%d", num);
204 node_data->u.data.len = strlen (node_data->u.data.data);
208 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
209 const char *tag, Odr_oid *oid,
212 data1_node *node_data;
213 char str[128], *p = str;
216 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
220 for (ii = oid; *ii >= 0; ii++)
224 sprintf (p, "%d", *ii);
227 node_data->u.data.what = DATA1I_oid;
228 node_data->u.data.len = strlen (str);
229 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
234 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
235 const char *tag, const char *str,
238 data1_node *node_data;
240 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
243 node_data->u.data.what = DATA1I_text;
244 node_data->u.data.len = strlen (str);
245 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
249 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
250 const char *tag, const char *str,
253 data1_node *node = data1_search_tag (dh, at->child, tag);
255 return data1_add_tagdata_text (dh, at, tag, str, nmem);
258 data1_node *node_data = node->child;
259 node_data->u.data.what = DATA1I_text;
260 node_data->u.data.data = node_data->lbuf;
261 strcpy (node_data->u.data.data, str);
262 node_data->u.data.len = strlen (node_data->u.data.data);
267 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
268 struct zebDatabaseInfoB *zdi,
270 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
271 zebAttributeDetails zad,
272 const char *databaseName,
274 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
275 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
279 static Record createRecord (Records records, int *sysno)
284 rec = rec_get (records, *sysno);
285 xfree (rec->info[recInfo_storeData]);
289 rec = rec_new (records);
292 rec->info[recInfo_fileType] =
293 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
294 rec->info[recInfo_databaseName] =
295 rec_strdup ("IR-Explain-1",
296 &rec->size[recInfo_databaseName]);
301 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag,
302 int (*updateH)(Record drec, data1_node *n))
304 struct zebDatabaseInfoB *zdi;
306 logf (LOG_DEBUG, "zebraExplain_close wr=%d", writeFlag);
310 /* write each database info record */
311 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
313 zebraExplain_writeDatabase (zei, zdi, 1);
314 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
315 zdi->databaseName, 1);
317 zebraExplain_writeTarget (zei, 1);
319 assert (zei->accessInfo);
320 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
322 zebraExplain_writeAttributeSet (zei, o, 1);
323 for (o = zei->accessInfo->schemas; o; o = o->next)
326 /* zebraExplain_writeSchema (zei, o, 1); */
329 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
331 zebraExplain_writeDatabase (zei, zdi, 0);
332 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
333 zdi->databaseName, 0);
335 zebraExplain_writeTarget (zei, 0);
338 nmem_destroy (zei->nmem);
342 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
347 for (np = n->child; np; np = np->next)
354 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
356 len = np->child->u.data.len;
359 memcpy (str, np->child->u.data.data, len);
362 oid = odr_getoidbystr_nmem (zei->nmem, str);
364 for (ao = *op; ao; ao = ao->next)
365 if (!oid_oidcmp (oid, ao->oid))
372 ao = nmem_malloc (zei->nmem, sizeof(*ao));
382 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
383 zebAccessInfo *accessInfo)
389 *accessInfo = nmem_malloc (zei->nmem, sizeof(**accessInfo));
390 (*accessInfo)->attributeSetIds = NULL;
391 (*accessInfo)->schemas = NULL;
395 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
397 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
398 zebraExplain_mergeOids (zei, np,
399 &(*accessInfo)->attributeSetIds);
400 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
401 zebraExplain_mergeOids (zei, np,
402 &(*accessInfo)->schemas);
406 ZebraExplainInfo zebraExplain_open (
407 Records records, data1_handle dh,
411 int (*updateFunc)(void *handle, Record drec, data1_node *n))
414 ZebraExplainInfo zei;
415 struct zebDatabaseInfoB **zdip;
419 logf (LOG_DEBUG, "zebraExplain_open wr=%d", writeFlag);
420 zei = xmalloc (sizeof(*zei));
421 zei->updateHandle = updateHandle;
422 zei->updateFunc = updateFunc;
424 zei->curDatabaseInfo = NULL;
425 zei->records = records;
426 zei->nmem = nmem_create ();
432 tm = localtime (&our_time);
433 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
434 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
435 tm->tm_hour, tm->tm_min, tm->tm_sec);
437 zdip = &zei->databaseInfo;
438 trec = rec_get (records, 1); /* get "root" record */
440 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
441 if (trec) /* targetInfo already exists ... */
443 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
445 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
448 data1_pr_tree (zei->dh, zei->data1_target, stderr);
450 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
452 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
455 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
457 node_list = data1_search_tag (zei->dh, node_zebra->child,
459 for (np = node_list->child; np; np = np->next)
461 data1_node *node_name = NULL;
462 data1_node *node_id = NULL;
463 data1_node *node_aid = NULL;
465 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
467 for (np2 = np->child; np2; np2 = np2->next)
469 if (np2->which != DATA1N_tag)
471 if (!strcmp (np2->u.tag.tag, "name"))
472 node_name = np2->child;
473 else if (!strcmp (np2->u.tag.tag, "id"))
474 node_id = np2->child;
475 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
476 node_aid = np2->child;
478 assert (node_id && node_name && node_aid);
480 *zdip = nmem_malloc (zei->nmem, sizeof(**zdip));
482 (*zdip)->readFlag = 1;
484 (*zdip)->data1_database = NULL;
485 (*zdip)->recordCount = 0;
486 (*zdip)->recordBytes = 0;
487 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
489 (*zdip)->databaseName = nmem_malloc (zei->nmem,
490 1+node_name->u.data.len);
491 memcpy ((*zdip)->databaseName, node_name->u.data.data,
492 node_name->u.data.len);
493 (*zdip)->databaseName[node_name->u.data.len] = '\0';
494 (*zdip)->sysno = atoi_n (node_id->u.data.data,
495 node_id->u.data.len);
496 (*zdip)->attributeDetails =
497 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
498 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
499 node_aid->u.data.len);
500 (*zdip)->attributeDetails->readFlag = 1;
501 (*zdip)->attributeDetails->dirty = 0;
502 (*zdip)->attributeDetails->SUInfo = NULL;
504 zdip = &(*zdip)->next;
506 np = data1_search_tag (zei->dh, node_zebra->child,
509 assert (np && np->which == DATA1N_data);
510 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
512 np = data1_search_tag (zei->dh, node_zebra->child,
515 assert (np && np->which == DATA1N_data);
516 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
520 else /* create initial targetInfo */
522 data1_node *node_tgtinfo;
532 data1_read_sgml (zei->dh, zei->nmem,
533 "<explain><targetInfo>TargetInfo\n"
535 "<namedResultSets>1</>\n"
536 "<multipleDBSearch>1</>\n"
537 "<nicknames><name>Zebra</></>\n"
540 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
542 assert (node_tgtinfo);
545 zebraExplain_initCommonInfo (zei, node_tgtinfo);
546 zebraExplain_initAccessInfo (zei, node_tgtinfo);
548 /* write now because we want to be sure about the sysno */
549 trec = rec_new (records);
550 trec->info[recInfo_fileType] =
551 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
552 trec->info[recInfo_databaseName] =
553 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
555 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
556 trec->info[recInfo_storeData] = xmalloc (sgml_len);
557 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
558 trec->size[recInfo_storeData] = sgml_len;
560 rec_put (records, &trec);
564 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
569 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
570 zebAttributeDetails zad)
573 struct zebSUInfoB **zsuip = &zad->SUInfo;
574 data1_node *node_adinfo, *node_zebra, *node_list, *np;
577 rec = rec_get (zei->records, zad->sysno);
579 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
581 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
583 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
585 node_list = data1_search_tag (zei->dh, node_zebra->child,
587 for (np = node_list->child; np; np = np->next)
589 data1_node *node_set = NULL;
590 data1_node *node_use = NULL;
591 data1_node *node_ordinal = NULL;
593 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
595 for (np2 = np->child; np2; np2 = np2->next)
597 if (np2->which != DATA1N_tag || !np2->child ||
598 np2->child->which != DATA1N_data)
600 if (!strcmp (np2->u.tag.tag, "set"))
601 node_set = np2->child;
602 else if (!strcmp (np2->u.tag.tag, "use"))
603 node_use = np2->child;
604 else if (!strcmp (np2->u.tag.tag, "ordinal"))
605 node_ordinal = np2->child;
607 assert (node_set && node_use && node_ordinal);
609 *zsuip = nmem_malloc (zei->nmem, sizeof(**zsuip));
610 (*zsuip)->info.set = atoi_n (node_set->u.data.data,
611 node_set->u.data.len);
612 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
613 node_use->u.data.len);
614 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
615 node_ordinal->u.data.len);
616 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
617 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
618 zsuip = &(*zsuip)->next;
625 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
626 struct zebDatabaseInfoB *zdi)
629 data1_node *node_dbinfo, *node_zebra, *np;
632 rec = rec_get (zei->records, zdi->sysno);
634 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
636 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
638 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
640 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
642 np = data1_search_tag (zei->dh, node_dbinfo->child,
644 if (np && np->child && np->child->which == DATA1N_data)
645 zdi->recordBytes = atoi_n (np->child->u.data.data,
646 np->child->u.data.len);
647 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
649 (np = data1_search_tag (zei->dh, np->child,
650 "recordCountActual")) &&
651 np->child->which == DATA1N_data)
653 zdi->recordCount = atoi_n (np->child->u.data.data,
654 np->child->u.data.len);
660 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
662 struct zebDatabaseInfoB *zdi;
665 if (zei->curDatabaseInfo &&
666 !strcmp (zei->curDatabaseInfo->databaseName, database))
668 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
670 if (!strcmp (zdi->databaseName, database))
676 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
681 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
683 zebraExplain_readDatabase (zei, zdi);
685 if (zdi->attributeDetails->readFlag)
688 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
690 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
692 zei->curDatabaseInfo = zdi;
696 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
698 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
700 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
701 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
702 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
705 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
707 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
709 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
712 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
714 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
715 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
716 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
719 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
720 zebAccessInfo accessInfo)
722 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
728 if ((p = accessInfo->attributeSetIds))
730 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
731 for (; p; p = p->next)
732 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
734 if ((p = accessInfo->schemas))
736 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
737 for (; p; p = p->next)
738 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
742 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
743 int explain_database)
745 struct zebDatabaseInfoB *zdi;
746 data1_node *node_dbinfo, *node_adinfo;
749 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
752 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
754 if (!strcmp (zdi->databaseName, database))
759 /* it's new really. make it */
760 zdi = nmem_malloc (zei->nmem, sizeof(*zdi));
761 zdi->next = zei->databaseInfo;
762 zei->databaseInfo = zdi;
764 zdi->recordCount = 0;
765 zdi->recordBytes = 0;
767 zdi->databaseName = nmem_strdup (zei->nmem, database);
769 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
774 zdi->data1_database =
775 data1_read_sgml (zei->dh, zei->nmem,
776 "<explain><databaseInfo>DatabaseInfo\n"
779 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
781 assert (node_dbinfo);
783 zebraExplain_initCommonInfo (zei, node_dbinfo);
784 zebraExplain_initAccessInfo (zei, node_dbinfo);
786 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
787 database, zei->nmem);
789 if (explain_database)
790 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
793 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
796 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
800 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
804 zei->curDatabaseInfo = zdi;
806 zdi->attributeDetails =
807 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
808 zdi->attributeDetails->readFlag = 0;
809 zdi->attributeDetails->sysno = 0;
810 zdi->attributeDetails->dirty = 1;
811 zdi->attributeDetails->SUInfo = NULL;
812 zdi->attributeDetails->data1_tree =
813 data1_read_sgml (zei->dh, zei->nmem,
814 "<explain><attributeDetails>AttributeDetails\n"
818 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
820 assert (node_adinfo);
822 zebraExplain_initCommonInfo (zei, node_adinfo);
827 static void writeAttributeValueDetails (ZebraExplainInfo zei,
828 zebAttributeDetails zad,
829 data1_node *node_atvs, data1_attset *attset)
832 struct zebSUInfoB *zsui;
833 int set_ordinal = attset->reference;
834 data1_attset_child *c;
836 for (c = attset->children; c; c = c->next)
837 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
838 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
840 data1_node *node_attvalue, *node_value;
841 if (set_ordinal != zsui->info.set)
843 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
845 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
847 data1_add_tagdata_int (zei->dh, node_value, "numeric",
848 zsui->info.use, zei->nmem);
852 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
853 zebAttributeDetails zad,
854 const char *databaseName,
860 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
861 struct zebSUInfoB *zsui;
869 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
872 drec = createRecord (zei->records, &zad->sysno);
873 assert (zad->data1_tree);
874 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
876 zebraExplain_updateCommonInfo (zei, node_adinfo);
878 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
879 databaseName, zei->nmem);
881 /* extract *searchable* keys from it. We do this here, because
882 record count, etc. is affected */
884 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
886 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
887 "attributesBySet", zei->nmem);
891 data1_node *node_asd;
892 data1_attset *attset;
893 int set_ordinal = -1;
894 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
896 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
897 && zsui->info.set > set_min)
898 set_ordinal = zsui->info.set;
902 set_min = set_ordinal;
903 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
904 "attributeSetDetails", zei->nmem);
906 attset = data1_attset_search_id (zei->dh, set_ordinal);
909 zebraExplain_loadAttsets (zei->dh, zei->res);
910 attset = data1_attset_search_id (zei->dh, set_ordinal);
917 oe.proto = PROTO_Z3950;
918 oe.oclass = CLASS_ATTSET;
919 oe.value = set_ordinal;
921 if (oid_ent_to_oid (&oe, oid))
923 data1_node *node_abt, *node_atd, *node_atvs;
924 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
927 node_abt = data1_add_tag (zei->dh, node_asd,
928 "attributesByType", zei->nmem);
929 node_atd = data1_add_tag (zei->dh, node_abt,
930 "attributeTypeDetails", zei->nmem);
931 data1_add_tagdata_int (zei->dh, node_atd,
932 "type", 1, zei->nmem);
933 node_atvs = data1_add_tag (zei->dh, node_atd,
934 "attributeValues", zei->nmem);
935 writeAttributeValueDetails (zei, zad, node_atvs, attset);
939 /* zebra info (private) */
940 node_zebra = data1_make_tag (zei->dh, node_adinfo,
941 "zebraInfo", zei->nmem);
942 node_list = data1_make_tag (zei->dh, node_zebra,
943 "attrlist", zei->nmem);
944 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
946 data1_node *node_attr;
947 node_attr = data1_add_tag (zei->dh, node_list,
949 data1_add_tagdata_int (zei->dh, node_attr, "set",
950 zsui->info.set, zei->nmem);
951 data1_add_tagdata_int (zei->dh, node_attr, "use",
952 zsui->info.use, zei->nmem);
953 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
954 zsui->info.ordinal, zei->nmem);
956 /* convert to "SGML" and write it */
958 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
960 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
962 drec->info[recInfo_storeData] = xmalloc (sgml_len);
963 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
964 drec->size[recInfo_storeData] = sgml_len;
966 rec_put (zei->records, &drec);
969 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
970 struct zebDatabaseInfoB *zdi,
976 data1_node *node_dbinfo, *node_count, *node_zebra;
983 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
985 drec = createRecord (zei->records, &zdi->sysno);
986 assert (zdi->data1_database);
987 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
990 zebraExplain_updateCommonInfo (zei, node_dbinfo);
991 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
993 /* extract *searchable* keys from it. We do this here, because
994 record count, etc. is affected */
996 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
998 node_count = data1_make_tag (zei->dh, node_dbinfo,
999 "recordCount", zei->nmem);
1000 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1001 zdi->recordCount, zei->nmem);
1003 /* zebra info (private) */
1004 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1005 "zebraInfo", zei->nmem);
1006 data1_add_tagdata_int (zei->dh, node_zebra,
1007 "recordBytes", zdi->recordBytes, zei->nmem);
1008 /* convert to "SGML" and write it */
1010 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1012 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1014 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1015 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1016 drec->size[recInfo_storeData] = sgml_len;
1018 rec_put (zei->records, &drec);
1021 static void writeAttributeValues (ZebraExplainInfo zei,
1022 data1_node *node_values,
1023 data1_attset *attset)
1026 data1_attset_child *c;
1031 for (c = attset->children; c; c = c->next)
1032 writeAttributeValues (zei, node_values, c->child);
1033 for (atts = attset->atts; atts; atts = atts->next)
1035 data1_node *node_value;
1037 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1039 data1_add_tagdata_text (zei->dh, node_value, "name",
1040 atts->name, zei->nmem);
1041 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1042 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1043 atts->value, zei->nmem);
1048 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1055 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1056 data1_node *node_values;
1057 struct oident *entp;
1058 struct data1_attset *attset = NULL;
1060 if ((entp = oid_getentbyoid (o->oid)))
1061 attset = data1_attset_search_id (zei->dh, entp->value);
1064 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1065 attset ? attset->name : "<unknown>");
1068 drec = createRecord (zei->records, &o->sysno);
1070 data1_read_sgml (zei->dh, zei->nmem,
1071 "<explain><attributeSetInfo>AttributeSetInfo\n"
1074 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1075 "attributeSetInfo");
1077 zebraExplain_initCommonInfo (zei, node_attinfo);
1078 zebraExplain_updateCommonInfo (zei, node_attinfo);
1080 data1_add_tagdata_oid (zei->dh, node_attinfo,
1081 "oid", o->oid, zei->nmem);
1082 if (attset && attset->name)
1083 data1_add_tagdata_text (zei->dh, node_attinfo,
1084 "name", attset->name, zei->nmem);
1086 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1087 "attributes", zei->nmem);
1088 node_atttype = data1_make_tag (zei->dh, node_attributes,
1089 "attributeType", zei->nmem);
1090 data1_add_tagdata_text (zei->dh, node_atttype,
1091 "name", "Use", zei->nmem);
1092 data1_add_tagdata_text (zei->dh, node_atttype,
1093 "description", "Use Attribute", zei->nmem);
1094 data1_add_tagdata_int (zei->dh, node_atttype,
1095 "type", 1, zei->nmem);
1096 node_values = data1_add_tag (zei->dh, node_atttype,
1097 "attributeValues", zei->nmem);
1099 writeAttributeValues (zei, node_values, attset);
1101 /* extract *searchable* keys from it. We do this here, because
1102 record count, etc. is affected */
1104 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1105 /* convert to "SGML" and write it */
1107 data1_pr_tree (zei->dh, node_root, stderr);
1109 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1110 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1111 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1112 drec->size[recInfo_storeData] = sgml_len;
1114 rec_put (zei->records, &drec);
1117 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1119 struct zebDatabaseInfoB *zdi;
1120 data1_node *node_tgtinfo, *node_list, *node_zebra;
1129 trec = rec_get (zei->records, 1);
1130 xfree (trec->info[recInfo_storeData]);
1132 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1134 assert (node_tgtinfo);
1136 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1137 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1139 /* convert to "SGML" and write it */
1141 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1143 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1144 "zebraInfo", zei->nmem);
1145 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1146 ZEBRAVER, zei->nmem);
1147 node_list = data1_add_tag (zei->dh, node_zebra,
1148 "databaseList", zei->nmem);
1149 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1151 data1_node *node_db;
1152 node_db = data1_add_tag (zei->dh, node_list,
1153 "database", zei->nmem);
1154 data1_add_tagdata_text (zei->dh, node_db, "name",
1155 zdi->databaseName, zei->nmem);
1156 data1_add_tagdata_int (zei->dh, node_db, "id",
1157 zdi->sysno, zei->nmem);
1158 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1159 zdi->attributeDetails->sysno, zei->nmem);
1161 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1162 zei->ordinalSU, zei->nmem);
1164 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1165 zei->runNumber, zei->nmem);
1168 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1170 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1172 trec->info[recInfo_storeData] = xmalloc (sgml_len);
1173 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1174 trec->size[recInfo_storeData] = sgml_len;
1176 rec_put (zei->records, &trec);
1179 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1181 struct zebSUInfoB *zsui;
1183 assert (zei->curDatabaseInfo);
1184 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1185 zsui; zsui=zsui->next)
1186 if (zsui->info.use == use && zsui->info.set == set)
1187 return zsui->info.ordinal;
1191 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1192 zebAccessObject *op,
1197 for (ao = *op; ao; ao = ao->next)
1198 if (!oid_oidcmp (oid, ao->oid))
1202 ao = nmem_malloc (zei->nmem, sizeof(*ao));
1205 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1212 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1217 oe.proto = PROTO_Z3950;
1218 oe.oclass = CLASS_ATTSET;
1221 if (oid_ent_to_oid (&oe, oid))
1223 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1224 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1225 accessInfo->attributeSetIds, oid);
1229 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1231 struct zebSUInfoB *zsui;
1233 assert (zei->curDatabaseInfo);
1234 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1235 zsui; zsui=zsui->next)
1236 if (zsui->info.use == use && zsui->info.set == set)
1238 zebraExplain_addAttributeSet (zei, set);
1239 zsui = nmem_malloc (zei->nmem, sizeof(*zsui));
1240 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1241 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1242 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1244 zsui->info.set = set;
1245 zsui->info.use = use;
1246 zsui->info.ordinal = (zei->ordinalSU)++;
1247 return zsui->info.ordinal;
1250 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1252 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1253 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1254 accessInfo->schemas, oid);
1257 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1259 assert (zei->curDatabaseInfo);
1263 zei->curDatabaseInfo->recordBytes += adjust_num;
1264 zei->curDatabaseInfo->dirty = 1;
1268 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1270 assert (zei->curDatabaseInfo);
1274 zei->curDatabaseInfo->recordCount += adjust_num;
1275 zei->curDatabaseInfo->dirty = 1;
1279 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1283 return zei->runNumber += adjust_num;
1286 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1288 RecordAttr *recordAttr;
1290 if (rec->info[recInfo_attr])
1291 return (RecordAttr *) rec->info[recInfo_attr];
1292 recordAttr = xmalloc (sizeof(*recordAttr));
1293 rec->info[recInfo_attr] = (char *) recordAttr;
1294 rec->size[recInfo_attr] = sizeof(*recordAttr);
1296 recordAttr->recordSize = 0;
1297 recordAttr->recordOffset = 0;
1298 recordAttr->runNumber = zei->runNumber;
1302 static void att_loadset(void *p, const char *n, const char *name)
1304 data1_handle dh = p;
1305 if (!data1_get_attset (dh, name))
1306 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1309 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1311 res_trav(res, "attset", dh, att_loadset);
1315 zebraExplain_addSU adds to AttributeDetails for a database and
1316 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1317 exist for the database.
1319 If the database doesn't exist globally (in TargetInfo) an
1320 AttributeSetInfo must be added (globally).