2 * Copyright (C) 1994-1998, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.14 1998-11-04 16:31:32 adam
8 * Fixed bug regarding recordBytes in databaseInfo.
10 * Revision 1.13 1998/11/03 10:17:09 adam
11 * Fixed bug regarding creation of some data1 nodes for Explain records.
13 * Revision 1.12 1998/10/13 20:37:11 adam
14 * Changed the way attribute sets are saved in Explain database to
15 * reflect "dynamic" OIDs.
17 * Revision 1.11 1998/06/09 12:16:48 adam
18 * Implemented auto-generation of CategoryList records.
20 * Revision 1.10 1998/06/08 14:43:15 adam
21 * Added suport for EXPLAIN Proxy servers - added settings databasePath
22 * and explainDatabase to facilitate this. Increased maximum number
23 * of databases and attributes in one register.
25 * Revision 1.9 1998/06/02 12:10:27 adam
26 * Fixed bug related to attributeDetails.
28 * Revision 1.8 1998/05/20 10:12:20 adam
29 * Implemented automatic EXPLAIN database maintenance.
30 * Modified Zebra to work with ASN.1 compiled version of YAZ.
32 * Revision 1.7 1998/03/05 08:45:13 adam
33 * New result set model and modular ranking system. Moved towards
34 * descent server API. System information stored as "SGML" records.
36 * Revision 1.6 1998/02/17 10:29:27 adam
37 * Moved towards 'automatic' EXPLAIN database.
39 * Revision 1.5 1997/10/27 14:33:05 adam
40 * Moved towards generic character mapping depending on "structure"
41 * field in abstract syntax file. Fixed a few memory leaks. Fixed
42 * bug with negative integers when doing searches with relational
45 * Revision 1.4 1997/09/25 14:57:08 adam
48 * Revision 1.3 1996/05/22 08:21:59 adam
49 * Added public ZebDatabaseInfo structure.
51 * Revision 1.2 1996/05/14 06:16:41 adam
52 * Compact use/set bytes used in search service.
54 * Revision 1.1 1996/05/13 14:23:07 adam
55 * Work on compaction of set/use bytes in dictionary.
76 struct zebSUInfo info;
77 struct zebSUInfoB *next;
80 typedef struct zebAccessObjectB *zebAccessObject;
81 struct zebAccessObjectB {
88 typedef struct zebAccessInfoB *zebAccessInfo;
89 struct zebAccessInfoB {
90 zebAccessObject attributeSetIds;
91 zebAccessObject schemas;
95 struct zebSUInfoB *SUInfo;
99 data1_node *data1_tree;
100 } *zebAttributeDetails;
102 struct zebDatabaseInfoB {
103 zebAttributeDetails attributeDetails;
105 data1_node *data1_database;
106 int recordCount; /* records in db */
107 int recordBytes; /* size of records */
108 int sysno; /* sysno of database info */
109 int readFlag; /* 1: read is needed when referenced; 0 if not */
110 int dirty; /* 1: database is dirty: write is needed */
111 struct zebDatabaseInfoB *next;
112 zebAccessInfo accessInfo;
115 struct zebraExplainAttset {
118 struct zebraExplainAttset *next;
121 struct zebraCategoryListInfo {
124 data1_node *data1_categoryList;
127 struct zebraExplainInfo {
134 struct zebraExplainAttset *attsets;
136 data1_node *data1_target;
137 struct zebraCategoryListInfo *categoryList;
138 struct zebDatabaseInfoB *databaseInfo;
139 struct zebDatabaseInfoB *curDatabaseInfo;
140 zebAccessInfo accessInfo;
141 char date[15]; /* YYYY MMDD HH MM SS */
142 int (*updateFunc)(void *handle, Record drec, data1_node *n);
146 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
147 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
149 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
151 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
154 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
157 logf (LOG_DEBUG, "data1_search_tag %s", tag);
158 for (; n; n = n->next)
159 if (n->which == DATA1N_tag && n->u.tag.tag &&
160 !yaz_matchstr (tag, n->u.tag.tag))
162 logf (LOG_DEBUG, " found");
165 logf (LOG_DEBUG, " not found");
169 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
170 const char *tag, NMEM nmem)
172 data1_node *partag = get_parent_tag(dh, at);
173 data1_node *res = data1_mk_node (dh, nmem);
174 data1_element *e = NULL;
177 res->which = DATA1N_tag;
178 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
179 res->u.tag.node_selected = 0;
180 res->u.tag.make_variantlist = 0;
181 res->u.tag.no_data_requested = 0;
182 res->u.tag.get_bytes = -1;
185 e = partag->u.tag.element;
187 data1_getelementbytagname (dh, at->root->u.root.absyn,
189 res->root = at->root;
194 assert (at->last_child);
195 at->last_child->next = res;
197 at->last_child = res;
201 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
202 const char *tag, NMEM nmem)
204 data1_node *node = data1_search_tag (dh, at->child, tag);
206 node = data1_add_tag (dh, at, tag, nmem);
208 node->child = node->last_child = NULL;
212 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
213 const char *tag, int num,
216 data1_node *node_data;
218 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
221 node_data->u.data.what = DATA1I_num;
222 node_data->u.data.data = node_data->lbuf;
223 sprintf (node_data->u.data.data, "%d", num);
224 node_data->u.data.len = strlen (node_data->u.data.data);
228 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
229 const char *tag, Odr_oid *oid,
232 data1_node *node_data;
233 char str[128], *p = str;
236 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
240 for (ii = oid; *ii >= 0; ii++)
244 sprintf (p, "%d", *ii);
247 node_data->u.data.what = DATA1I_oid;
248 node_data->u.data.len = strlen (str);
249 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
254 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
255 const char *tag, const char *str,
258 data1_node *node_data;
260 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
263 node_data->u.data.what = DATA1I_text;
264 node_data->u.data.len = strlen (str);
265 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
269 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
270 const char *tag, const char *str,
273 data1_node *node = data1_search_tag (dh, at->child, tag);
275 return data1_add_tagdata_text (dh, at, tag, str, nmem);
278 data1_node *node_data = node->child;
279 node_data->u.data.what = DATA1I_text;
280 node_data->u.data.len = strlen (node_data->u.data.data);
281 node_data->u.data.data = data1_insert_string (dh, node_data,
287 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
288 struct zebDatabaseInfoB *zdi,
290 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
291 zebAttributeDetails zad,
292 const char *databaseName,
294 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
295 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
298 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
299 struct zebraCategoryListInfo *zcl,
303 static Record createRecord (Records records, int *sysno)
308 rec = rec_get (records, *sysno);
309 xfree (rec->info[recInfo_storeData]);
313 rec = rec_new (records);
316 rec->info[recInfo_fileType] =
317 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
318 rec->info[recInfo_databaseName] =
319 rec_strdup ("IR-Explain-1",
320 &rec->size[recInfo_databaseName]);
325 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag,
326 int (*updateH)(Record drec, data1_node *n))
328 struct zebDatabaseInfoB *zdi;
330 logf (LOG_DEBUG, "zebraExplain_close wr=%d", writeFlag);
334 /* write each database info record */
335 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
337 zebraExplain_writeDatabase (zei, zdi, 1);
338 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
339 zdi->databaseName, 1);
341 zebraExplain_writeTarget (zei, 1);
342 zebraExplain_writeCategoryList (zei,
345 assert (zei->accessInfo);
346 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
348 zebraExplain_writeAttributeSet (zei, o, 1);
349 for (o = zei->accessInfo->schemas; o; o = o->next)
352 /* zebraExplain_writeSchema (zei, o, 1); */
355 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
357 zebraExplain_writeDatabase (zei, zdi, 0);
358 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
359 zdi->databaseName, 0);
361 zebraExplain_writeTarget (zei, 0);
364 nmem_destroy (zei->nmem);
368 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
373 for (np = n->child; np; np = np->next)
380 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
382 len = np->child->u.data.len;
385 memcpy (str, np->child->u.data.data, len);
388 oid = odr_getoidbystr_nmem (zei->nmem, str);
390 for (ao = *op; ao; ao = ao->next)
391 if (!oid_oidcmp (oid, ao->oid))
398 ao = nmem_malloc (zei->nmem, sizeof(*ao));
408 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
409 zebAccessInfo *accessInfo)
415 *accessInfo = nmem_malloc (zei->nmem, sizeof(**accessInfo));
416 (*accessInfo)->attributeSetIds = NULL;
417 (*accessInfo)->schemas = NULL;
421 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
423 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
424 zebraExplain_mergeOids (zei, np,
425 &(*accessInfo)->attributeSetIds);
426 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
427 zebraExplain_mergeOids (zei, np,
428 &(*accessInfo)->schemas);
432 ZebraExplainInfo zebraExplain_open (
433 Records records, data1_handle dh,
437 int (*updateFunc)(void *handle, Record drec, data1_node *n))
440 ZebraExplainInfo zei;
441 struct zebDatabaseInfoB **zdip;
445 logf (LOG_DEBUG, "zebraExplain_open wr=%d", writeFlag);
446 zei = xmalloc (sizeof(*zei));
447 zei->updateHandle = updateHandle;
448 zei->updateFunc = updateFunc;
450 zei->curDatabaseInfo = NULL;
451 zei->records = records;
452 zei->nmem = nmem_create ();
456 zei->categoryList = nmem_malloc (zei->nmem,
457 sizeof(*zei->categoryList));
458 zei->categoryList->sysno = 0;
459 zei->categoryList->dirty = 0;
460 zei->categoryList->data1_categoryList = NULL;
463 tm = localtime (&our_time);
464 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
465 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
466 tm->tm_hour, tm->tm_min, tm->tm_sec);
468 zdip = &zei->databaseInfo;
469 trec = rec_get (records, 1); /* get "root" record */
471 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
472 if (trec) /* targetInfo already exists ... */
474 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
476 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
479 data1_pr_tree (zei->dh, zei->data1_target, stderr);
481 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
483 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
486 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
488 node_list = data1_search_tag (zei->dh, node_zebra->child,
490 for (np = node_list->child; np; np = np->next)
492 data1_node *node_name = NULL;
493 data1_node *node_id = NULL;
494 data1_node *node_aid = NULL;
496 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
498 for (np2 = np->child; np2; np2 = np2->next)
500 if (np2->which != DATA1N_tag)
502 if (!strcmp (np2->u.tag.tag, "name"))
503 node_name = np2->child;
504 else if (!strcmp (np2->u.tag.tag, "id"))
505 node_id = np2->child;
506 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
507 node_aid = np2->child;
509 assert (node_id && node_name && node_aid);
511 *zdip = nmem_malloc (zei->nmem, sizeof(**zdip));
513 (*zdip)->readFlag = 1;
515 (*zdip)->data1_database = NULL;
516 (*zdip)->recordCount = 0;
517 (*zdip)->recordBytes = 0;
518 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
520 (*zdip)->databaseName = nmem_malloc (zei->nmem,
521 1+node_name->u.data.len);
522 memcpy ((*zdip)->databaseName, node_name->u.data.data,
523 node_name->u.data.len);
524 (*zdip)->databaseName[node_name->u.data.len] = '\0';
525 (*zdip)->sysno = atoi_n (node_id->u.data.data,
526 node_id->u.data.len);
527 (*zdip)->attributeDetails =
528 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
529 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
530 node_aid->u.data.len);
531 (*zdip)->attributeDetails->readFlag = 1;
532 (*zdip)->attributeDetails->dirty = 0;
533 (*zdip)->attributeDetails->SUInfo = NULL;
535 zdip = &(*zdip)->next;
537 np = data1_search_tag (zei->dh, node_zebra->child,
540 assert (np && np->which == DATA1N_data);
541 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
543 np = data1_search_tag (zei->dh, node_zebra->child,
546 assert (np && np->which == DATA1N_data);
547 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
551 else /* create initial targetInfo */
553 data1_node *node_tgtinfo;
563 data1_read_sgml (zei->dh, zei->nmem,
564 "<explain><targetInfo>TargetInfo\n"
566 "<namedResultSets>1</>\n"
567 "<multipleDBSearch>1</>\n"
568 "<nicknames><name>Zebra</></>\n"
571 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
573 assert (node_tgtinfo);
575 zebraExplain_initCommonInfo (zei, node_tgtinfo);
576 zebraExplain_initAccessInfo (zei, node_tgtinfo);
578 /* write now because we want to be sure about the sysno */
579 trec = rec_new (records);
580 trec->info[recInfo_fileType] =
581 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
582 trec->info[recInfo_databaseName] =
583 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
585 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
586 trec->info[recInfo_storeData] = xmalloc (sgml_len);
587 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
588 trec->size[recInfo_storeData] = sgml_len;
590 rec_put (records, &trec);
594 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
596 if (!zei->categoryList->dirty)
598 struct zebraCategoryListInfo *zcl = zei->categoryList;
602 zcl->data1_categoryList =
603 data1_read_sgml (zei->dh, zei->nmem,
604 "<explain><categoryList>CategoryList\n"
606 node_cl = data1_search_tag (zei->dh,
607 zcl->data1_categoryList->child,
610 zebraExplain_initCommonInfo (zei, node_cl);
616 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
617 zebAttributeDetails zad)
620 struct zebSUInfoB **zsuip = &zad->SUInfo;
621 data1_node *node_adinfo, *node_zebra, *node_list, *np;
624 rec = rec_get (zei->records, zad->sysno);
626 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
628 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
630 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
632 node_list = data1_search_tag (zei->dh, node_zebra->child,
634 for (np = node_list->child; np; np = np->next)
636 data1_node *node_set = NULL;
637 data1_node *node_use = NULL;
638 data1_node *node_ordinal = NULL;
643 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
645 for (np2 = np->child; np2; np2 = np2->next)
647 if (np2->which != DATA1N_tag || !np2->child ||
648 np2->child->which != DATA1N_data)
650 if (!strcmp (np2->u.tag.tag, "set"))
651 node_set = np2->child;
652 else if (!strcmp (np2->u.tag.tag, "use"))
653 node_use = np2->child;
654 else if (!strcmp (np2->u.tag.tag, "ordinal"))
655 node_ordinal = np2->child;
657 assert (node_set && node_use && node_ordinal);
659 oid_str_len = node_set->u.data.len;
660 if (oid_str_len >= sizeof(oid_str))
661 oid_str_len = sizeof(oid_str)-1;
662 memcpy (oid_str, node_set->u.data.data, oid_str_len);
663 oid_str[oid_str_len] = '\0';
665 *zsuip = nmem_malloc (zei->nmem, sizeof(**zsuip));
666 (*zsuip)->info.set = oid_getvalbyname (oid_str);
668 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
669 node_use->u.data.len);
670 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
671 node_ordinal->u.data.len);
672 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
673 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
674 zsuip = &(*zsuip)->next;
681 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
682 struct zebDatabaseInfoB *zdi)
685 data1_node *node_dbinfo, *node_zebra, *np;
688 rec = rec_get (zei->records, zdi->sysno);
690 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
692 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
694 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
696 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
699 && (np = data1_search_tag (zei->dh, node_zebra->child,
701 && np->child && np->child->which == DATA1N_data)
702 zdi->recordBytes = atoi_n (np->child->u.data.data,
703 np->child->u.data.len);
704 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
706 (np = data1_search_tag (zei->dh, np->child,
707 "recordCountActual")) &&
708 np->child->which == DATA1N_data)
710 zdi->recordCount = atoi_n (np->child->u.data.data,
711 np->child->u.data.len);
717 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
719 struct zebDatabaseInfoB *zdi;
722 if (zei->curDatabaseInfo &&
723 !strcmp (zei->curDatabaseInfo->databaseName, database))
725 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
727 if (!strcmp (zdi->databaseName, database))
733 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
738 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
740 zebraExplain_readDatabase (zei, zdi);
742 if (zdi->attributeDetails->readFlag)
745 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
747 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
749 zei->curDatabaseInfo = zdi;
753 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
755 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
757 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
758 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
759 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
762 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
764 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
766 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
769 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
771 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
772 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
773 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
776 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
777 zebAccessInfo accessInfo)
779 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
785 if ((p = accessInfo->attributeSetIds))
787 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
788 for (; p; p = p->next)
789 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
791 if ((p = accessInfo->schemas))
793 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
794 for (; p; p = p->next)
795 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
799 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
800 int explain_database)
802 struct zebDatabaseInfoB *zdi;
803 data1_node *node_dbinfo, *node_adinfo;
806 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
809 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
811 if (!strcmp (zdi->databaseName, database))
816 /* it's new really. make it */
817 zdi = nmem_malloc (zei->nmem, sizeof(*zdi));
818 zdi->next = zei->databaseInfo;
819 zei->databaseInfo = zdi;
821 zdi->recordCount = 0;
822 zdi->recordBytes = 0;
824 zdi->databaseName = nmem_strdup (zei->nmem, database);
826 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
831 zdi->data1_database =
832 data1_read_sgml (zei->dh, zei->nmem,
833 "<explain><databaseInfo>DatabaseInfo\n"
836 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
838 assert (node_dbinfo);
840 zebraExplain_initCommonInfo (zei, node_dbinfo);
841 zebraExplain_initAccessInfo (zei, node_dbinfo);
843 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
844 database, zei->nmem);
846 if (explain_database)
847 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
850 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
853 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
857 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
861 zei->curDatabaseInfo = zdi;
863 zdi->attributeDetails =
864 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
865 zdi->attributeDetails->readFlag = 0;
866 zdi->attributeDetails->sysno = 0;
867 zdi->attributeDetails->dirty = 1;
868 zdi->attributeDetails->SUInfo = NULL;
869 zdi->attributeDetails->data1_tree =
870 data1_read_sgml (zei->dh, zei->nmem,
871 "<explain><attributeDetails>AttributeDetails\n"
875 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
877 assert (node_adinfo);
879 zebraExplain_initCommonInfo (zei, node_adinfo);
884 static void writeAttributeValueDetails (ZebraExplainInfo zei,
885 zebAttributeDetails zad,
886 data1_node *node_atvs, data1_attset *attset)
889 struct zebSUInfoB *zsui;
890 int set_ordinal = attset->reference;
891 data1_attset_child *c;
893 for (c = attset->children; c; c = c->next)
894 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
895 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
897 data1_node *node_attvalue, *node_value;
898 if (set_ordinal != zsui->info.set)
900 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
902 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
904 data1_add_tagdata_int (zei->dh, node_value, "numeric",
905 zsui->info.use, zei->nmem);
909 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
910 struct zebraCategoryListInfo *zcl,
917 data1_node *node_ci, *node_categoryList;
919 static char *category[] = {
931 node_categoryList = zcl->data1_categoryList;
934 logf (LOG_LOG, "zebraExplain_writeCategoryList");
937 drec = createRecord (zei->records, &sysno);
939 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
942 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
945 for (i = 0; category[i]; i++)
947 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
948 "category", zei->nmem);
950 data1_add_tagdata_text (zei->dh, node_cat, "name",
951 category[i], zei->nmem);
953 /* extract *searchable* keys from it. We do this here, because
954 record count, etc. is affected */
956 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
958 /* convert to "SGML" and write it */
960 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
962 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList,
964 drec->info[recInfo_storeData] = xmalloc (sgml_len);
965 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
966 drec->size[recInfo_storeData] = sgml_len;
968 rec_put (zei->records, &drec);
971 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
972 zebAttributeDetails zad,
973 const char *databaseName,
979 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
980 struct zebSUInfoB *zsui;
988 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
991 drec = createRecord (zei->records, &zad->sysno);
992 assert (zad->data1_tree);
993 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
995 zebraExplain_updateCommonInfo (zei, node_adinfo);
997 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
998 databaseName, zei->nmem);
1000 /* extract *searchable* keys from it. We do this here, because
1001 record count, etc. is affected */
1003 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1005 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1006 "attributesBySet", zei->nmem);
1010 data1_node *node_asd;
1011 data1_attset *attset;
1012 int set_ordinal = -1;
1013 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1015 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1016 && zsui->info.set > set_min)
1017 set_ordinal = zsui->info.set;
1019 if (set_ordinal < 0)
1021 set_min = set_ordinal;
1022 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1023 "attributeSetDetails", zei->nmem);
1025 attset = data1_attset_search_id (zei->dh, set_ordinal);
1028 zebraExplain_loadAttsets (zei->dh, zei->res);
1029 attset = data1_attset_search_id (zei->dh, set_ordinal);
1036 oe.proto = PROTO_Z3950;
1037 oe.oclass = CLASS_ATTSET;
1038 oe.value = set_ordinal;
1040 if (oid_ent_to_oid (&oe, oid))
1042 data1_node *node_abt, *node_atd, *node_atvs;
1043 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1046 node_abt = data1_add_tag (zei->dh, node_asd,
1047 "attributesByType", zei->nmem);
1048 node_atd = data1_add_tag (zei->dh, node_abt,
1049 "attributeTypeDetails", zei->nmem);
1050 data1_add_tagdata_int (zei->dh, node_atd,
1051 "type", 1, zei->nmem);
1052 node_atvs = data1_add_tag (zei->dh, node_atd,
1053 "attributeValues", zei->nmem);
1054 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1058 /* zebra info (private) */
1059 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1060 "zebraInfo", zei->nmem);
1061 node_list = data1_make_tag (zei->dh, node_zebra,
1062 "attrlist", zei->nmem);
1063 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1065 struct oident oident;
1067 data1_node *node_attr;
1069 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1071 oident.proto = PROTO_Z3950;
1072 oident.oclass = CLASS_ATTSET;
1073 oident.value = zsui->info.set;
1074 oid_ent_to_oid (&oident, oid);
1076 data1_add_tagdata_text (zei->dh, node_attr, "set",
1077 oident.desc, zei->nmem);
1078 data1_add_tagdata_int (zei->dh, node_attr, "use",
1079 zsui->info.use, zei->nmem);
1080 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1081 zsui->info.ordinal, zei->nmem);
1083 /* convert to "SGML" and write it */
1085 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1087 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1089 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1090 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1091 drec->size[recInfo_storeData] = sgml_len;
1093 rec_put (zei->records, &drec);
1096 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1097 struct zebDatabaseInfoB *zdi,
1103 data1_node *node_dbinfo, *node_count, *node_zebra;
1110 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1112 drec = createRecord (zei->records, &zdi->sysno);
1113 assert (zdi->data1_database);
1114 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1117 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1118 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1120 /* extract *searchable* keys from it. We do this here, because
1121 record count, etc. is affected */
1123 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1125 node_count = data1_make_tag (zei->dh, node_dbinfo,
1126 "recordCount", zei->nmem);
1127 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1128 zdi->recordCount, zei->nmem);
1130 /* zebra info (private) */
1131 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1132 "zebraInfo", zei->nmem);
1133 data1_add_tagdata_int (zei->dh, node_zebra,
1134 "recordBytes", zdi->recordBytes, zei->nmem);
1135 /* convert to "SGML" and write it */
1137 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1139 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1141 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1142 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1143 drec->size[recInfo_storeData] = sgml_len;
1145 rec_put (zei->records, &drec);
1148 static void writeAttributeValues (ZebraExplainInfo zei,
1149 data1_node *node_values,
1150 data1_attset *attset)
1153 data1_attset_child *c;
1158 for (c = attset->children; c; c = c->next)
1159 writeAttributeValues (zei, node_values, c->child);
1160 for (atts = attset->atts; atts; atts = atts->next)
1162 data1_node *node_value;
1164 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1166 data1_add_tagdata_text (zei->dh, node_value, "name",
1167 atts->name, zei->nmem);
1168 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1169 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1170 atts->value, zei->nmem);
1175 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1182 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1183 data1_node *node_values;
1184 struct oident *entp;
1185 struct data1_attset *attset = NULL;
1187 if ((entp = oid_getentbyoid (o->oid)))
1188 attset = data1_attset_search_id (zei->dh, entp->value);
1191 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1192 attset ? attset->name : "<unknown>");
1195 drec = createRecord (zei->records, &o->sysno);
1197 data1_read_sgml (zei->dh, zei->nmem,
1198 "<explain><attributeSetInfo>AttributeSetInfo\n"
1201 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1202 "attributeSetInfo");
1204 zebraExplain_initCommonInfo (zei, node_attinfo);
1205 zebraExplain_updateCommonInfo (zei, node_attinfo);
1207 data1_add_tagdata_oid (zei->dh, node_attinfo,
1208 "oid", o->oid, zei->nmem);
1209 if (attset && attset->name)
1210 data1_add_tagdata_text (zei->dh, node_attinfo,
1211 "name", attset->name, zei->nmem);
1213 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1214 "attributes", zei->nmem);
1215 node_atttype = data1_make_tag (zei->dh, node_attributes,
1216 "attributeType", zei->nmem);
1217 data1_add_tagdata_text (zei->dh, node_atttype,
1218 "name", "Use", zei->nmem);
1219 data1_add_tagdata_text (zei->dh, node_atttype,
1220 "description", "Use Attribute", zei->nmem);
1221 data1_add_tagdata_int (zei->dh, node_atttype,
1222 "type", 1, zei->nmem);
1223 node_values = data1_add_tag (zei->dh, node_atttype,
1224 "attributeValues", zei->nmem);
1226 writeAttributeValues (zei, node_values, attset);
1228 /* extract *searchable* keys from it. We do this here, because
1229 record count, etc. is affected */
1231 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1232 /* convert to "SGML" and write it */
1234 data1_pr_tree (zei->dh, node_root, stderr);
1236 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1237 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1238 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1239 drec->size[recInfo_storeData] = sgml_len;
1241 rec_put (zei->records, &drec);
1244 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1246 struct zebDatabaseInfoB *zdi;
1247 data1_node *node_tgtinfo, *node_list, *node_zebra;
1256 trec = rec_get (zei->records, 1);
1257 xfree (trec->info[recInfo_storeData]);
1259 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1261 assert (node_tgtinfo);
1263 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1264 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1266 /* convert to "SGML" and write it */
1268 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1270 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1271 "zebraInfo", zei->nmem);
1272 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1273 ZEBRAVER, zei->nmem);
1274 node_list = data1_add_tag (zei->dh, node_zebra,
1275 "databaseList", zei->nmem);
1276 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1278 data1_node *node_db;
1279 node_db = data1_add_tag (zei->dh, node_list,
1280 "database", zei->nmem);
1281 data1_add_tagdata_text (zei->dh, node_db, "name",
1282 zdi->databaseName, zei->nmem);
1283 data1_add_tagdata_int (zei->dh, node_db, "id",
1284 zdi->sysno, zei->nmem);
1285 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1286 zdi->attributeDetails->sysno, zei->nmem);
1288 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1289 zei->ordinalSU, zei->nmem);
1291 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1292 zei->runNumber, zei->nmem);
1295 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1297 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1299 trec->info[recInfo_storeData] = xmalloc (sgml_len);
1300 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1301 trec->size[recInfo_storeData] = sgml_len;
1303 rec_put (zei->records, &trec);
1306 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1308 struct zebSUInfoB *zsui;
1310 assert (zei->curDatabaseInfo);
1311 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1312 zsui; zsui=zsui->next)
1313 if (zsui->info.use == use && zsui->info.set == set)
1314 return zsui->info.ordinal;
1318 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1319 zebAccessObject *op,
1324 for (ao = *op; ao; ao = ao->next)
1325 if (!oid_oidcmp (oid, ao->oid))
1329 ao = nmem_malloc (zei->nmem, sizeof(*ao));
1332 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1339 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1344 oe.proto = PROTO_Z3950;
1345 oe.oclass = CLASS_ATTSET;
1348 if (oid_ent_to_oid (&oe, oid))
1350 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1351 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1352 accessInfo->attributeSetIds, oid);
1356 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1358 struct zebSUInfoB *zsui;
1360 assert (zei->curDatabaseInfo);
1361 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1362 zsui; zsui=zsui->next)
1363 if (zsui->info.use == use && zsui->info.set == set)
1365 zebraExplain_addAttributeSet (zei, set);
1366 zsui = nmem_malloc (zei->nmem, sizeof(*zsui));
1367 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1368 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1369 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1371 zsui->info.set = set;
1372 zsui->info.use = use;
1373 zsui->info.ordinal = (zei->ordinalSU)++;
1374 return zsui->info.ordinal;
1377 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1379 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1380 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1381 accessInfo->schemas, oid);
1384 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1386 assert (zei->curDatabaseInfo);
1390 zei->curDatabaseInfo->recordBytes += adjust_num;
1391 zei->curDatabaseInfo->dirty = 1;
1395 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1397 assert (zei->curDatabaseInfo);
1401 zei->curDatabaseInfo->recordCount += adjust_num;
1402 zei->curDatabaseInfo->dirty = 1;
1406 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1410 return zei->runNumber += adjust_num;
1413 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1415 RecordAttr *recordAttr;
1417 if (rec->info[recInfo_attr])
1418 return (RecordAttr *) rec->info[recInfo_attr];
1419 recordAttr = xmalloc (sizeof(*recordAttr));
1420 rec->info[recInfo_attr] = (char *) recordAttr;
1421 rec->size[recInfo_attr] = sizeof(*recordAttr);
1423 recordAttr->recordSize = 0;
1424 recordAttr->recordOffset = 0;
1425 recordAttr->runNumber = zei->runNumber;
1429 static void att_loadset(void *p, const char *n, const char *name)
1431 data1_handle dh = p;
1432 if (!data1_get_attset (dh, name))
1433 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1436 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1438 res_trav(res, "attset", dh, att_loadset);
1442 zebraExplain_addSU adds to AttributeDetails for a database and
1443 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1444 exist for the database.
1446 If the database doesn't exist globally (in TargetInfo) an
1447 AttributeSetInfo must be added (globally).