2 * Copyright (C) 1994-1999, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.15 1999-01-25 13:47:54 adam
10 * Revision 1.14 1998/11/04 16:31:32 adam
11 * Fixed bug regarding recordBytes in databaseInfo.
13 * Revision 1.13 1998/11/03 10:17:09 adam
14 * Fixed bug regarding creation of some data1 nodes for Explain records.
16 * Revision 1.12 1998/10/13 20:37:11 adam
17 * Changed the way attribute sets are saved in Explain database to
18 * reflect "dynamic" OIDs.
20 * Revision 1.11 1998/06/09 12:16:48 adam
21 * Implemented auto-generation of CategoryList records.
23 * Revision 1.10 1998/06/08 14:43:15 adam
24 * Added suport for EXPLAIN Proxy servers - added settings databasePath
25 * and explainDatabase to facilitate this. Increased maximum number
26 * of databases and attributes in one register.
28 * Revision 1.9 1998/06/02 12:10:27 adam
29 * Fixed bug related to attributeDetails.
31 * Revision 1.8 1998/05/20 10:12:20 adam
32 * Implemented automatic EXPLAIN database maintenance.
33 * Modified Zebra to work with ASN.1 compiled version of YAZ.
35 * Revision 1.7 1998/03/05 08:45:13 adam
36 * New result set model and modular ranking system. Moved towards
37 * descent server API. System information stored as "SGML" records.
39 * Revision 1.6 1998/02/17 10:29:27 adam
40 * Moved towards 'automatic' EXPLAIN database.
42 * Revision 1.5 1997/10/27 14:33:05 adam
43 * Moved towards generic character mapping depending on "structure"
44 * field in abstract syntax file. Fixed a few memory leaks. Fixed
45 * bug with negative integers when doing searches with relational
48 * Revision 1.4 1997/09/25 14:57:08 adam
51 * Revision 1.3 1996/05/22 08:21:59 adam
52 * Added public ZebDatabaseInfo structure.
54 * Revision 1.2 1996/05/14 06:16:41 adam
55 * Compact use/set bytes used in search service.
57 * Revision 1.1 1996/05/13 14:23:07 adam
58 * Work on compaction of set/use bytes in dictionary.
79 struct zebSUInfo info;
80 struct zebSUInfoB *next;
83 typedef struct zebAccessObjectB *zebAccessObject;
84 struct zebAccessObjectB {
91 typedef struct zebAccessInfoB *zebAccessInfo;
92 struct zebAccessInfoB {
93 zebAccessObject attributeSetIds;
94 zebAccessObject schemas;
98 struct zebSUInfoB *SUInfo;
102 data1_node *data1_tree;
103 } *zebAttributeDetails;
105 struct zebDatabaseInfoB {
106 zebAttributeDetails attributeDetails;
108 data1_node *data1_database;
109 int recordCount; /* records in db */
110 int recordBytes; /* size of records */
111 int sysno; /* sysno of database info */
112 int readFlag; /* 1: read is needed when referenced; 0 if not */
113 int dirty; /* 1: database is dirty: write is needed */
114 struct zebDatabaseInfoB *next;
115 zebAccessInfo accessInfo;
118 struct zebraExplainAttset {
121 struct zebraExplainAttset *next;
124 struct zebraCategoryListInfo {
127 data1_node *data1_categoryList;
130 struct zebraExplainInfo {
137 struct zebraExplainAttset *attsets;
139 data1_node *data1_target;
140 struct zebraCategoryListInfo *categoryList;
141 struct zebDatabaseInfoB *databaseInfo;
142 struct zebDatabaseInfoB *curDatabaseInfo;
143 zebAccessInfo accessInfo;
144 char date[15]; /* YYYY MMDD HH MM SS */
145 int (*updateFunc)(void *handle, Record drec, data1_node *n);
149 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
150 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
152 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
154 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
157 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
160 logf (LOG_DEBUG, "data1_search_tag %s", tag);
161 for (; n; n = n->next)
162 if (n->which == DATA1N_tag && n->u.tag.tag &&
163 !yaz_matchstr (tag, n->u.tag.tag))
165 logf (LOG_DEBUG, " found");
168 logf (LOG_DEBUG, " not found");
172 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
173 const char *tag, NMEM nmem)
175 data1_node *partag = get_parent_tag(dh, at);
176 data1_node *res = data1_mk_node (dh, nmem);
177 data1_element *e = NULL;
180 res->which = DATA1N_tag;
181 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
182 res->u.tag.node_selected = 0;
183 res->u.tag.make_variantlist = 0;
184 res->u.tag.no_data_requested = 0;
185 res->u.tag.get_bytes = -1;
188 e = partag->u.tag.element;
190 data1_getelementbytagname (dh, at->root->u.root.absyn,
192 res->root = at->root;
197 assert (at->last_child);
198 at->last_child->next = res;
200 at->last_child = res;
204 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
205 const char *tag, NMEM nmem)
207 data1_node *node = data1_search_tag (dh, at->child, tag);
209 node = data1_add_tag (dh, at, tag, nmem);
211 node->child = node->last_child = NULL;
215 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
216 const char *tag, int num,
219 data1_node *node_data;
221 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
224 node_data->u.data.what = DATA1I_num;
225 node_data->u.data.data = node_data->lbuf;
226 sprintf (node_data->u.data.data, "%d", num);
227 node_data->u.data.len = strlen (node_data->u.data.data);
231 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
232 const char *tag, Odr_oid *oid,
235 data1_node *node_data;
236 char str[128], *p = str;
239 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
243 for (ii = oid; *ii >= 0; ii++)
247 sprintf (p, "%d", *ii);
250 node_data->u.data.what = DATA1I_oid;
251 node_data->u.data.len = strlen (str);
252 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
257 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
258 const char *tag, const char *str,
261 data1_node *node_data;
263 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
266 node_data->u.data.what = DATA1I_text;
267 node_data->u.data.len = strlen (str);
268 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
272 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
273 const char *tag, const char *str,
276 data1_node *node = data1_search_tag (dh, at->child, tag);
278 return data1_add_tagdata_text (dh, at, tag, str, nmem);
281 data1_node *node_data = node->child;
282 node_data->u.data.what = DATA1I_text;
283 node_data->u.data.len = strlen (str);
284 node_data->u.data.data = data1_insert_string (dh, node_data,
290 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
291 struct zebDatabaseInfoB *zdi,
293 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
294 zebAttributeDetails zad,
295 const char *databaseName,
297 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
298 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
301 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
302 struct zebraCategoryListInfo *zcl,
306 static Record createRecord (Records records, int *sysno)
311 rec = rec_get (records, *sysno);
312 xfree (rec->info[recInfo_storeData]);
316 rec = rec_new (records);
319 rec->info[recInfo_fileType] =
320 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
321 rec->info[recInfo_databaseName] =
322 rec_strdup ("IR-Explain-1",
323 &rec->size[recInfo_databaseName]);
328 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag,
329 int (*updateH)(Record drec, data1_node *n))
331 struct zebDatabaseInfoB *zdi;
333 logf (LOG_DEBUG, "zebraExplain_close wr=%d", writeFlag);
337 /* write each database info record */
338 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
340 zebraExplain_writeDatabase (zei, zdi, 1);
341 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
342 zdi->databaseName, 1);
344 zebraExplain_writeTarget (zei, 1);
345 zebraExplain_writeCategoryList (zei,
348 assert (zei->accessInfo);
349 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
351 zebraExplain_writeAttributeSet (zei, o, 1);
352 for (o = zei->accessInfo->schemas; o; o = o->next)
355 /* zebraExplain_writeSchema (zei, o, 1); */
358 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
360 zebraExplain_writeDatabase (zei, zdi, 0);
361 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
362 zdi->databaseName, 0);
364 zebraExplain_writeTarget (zei, 0);
367 nmem_destroy (zei->nmem);
371 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
376 for (np = n->child; np; np = np->next)
383 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
385 len = np->child->u.data.len;
388 memcpy (str, np->child->u.data.data, len);
391 oid = odr_getoidbystr_nmem (zei->nmem, str);
393 for (ao = *op; ao; ao = ao->next)
394 if (!oid_oidcmp (oid, ao->oid))
401 ao = nmem_malloc (zei->nmem, sizeof(*ao));
411 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
412 zebAccessInfo *accessInfo)
418 *accessInfo = nmem_malloc (zei->nmem, sizeof(**accessInfo));
419 (*accessInfo)->attributeSetIds = NULL;
420 (*accessInfo)->schemas = NULL;
424 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
426 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
427 zebraExplain_mergeOids (zei, np,
428 &(*accessInfo)->attributeSetIds);
429 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
430 zebraExplain_mergeOids (zei, np,
431 &(*accessInfo)->schemas);
435 ZebraExplainInfo zebraExplain_open (
436 Records records, data1_handle dh,
440 int (*updateFunc)(void *handle, Record drec, data1_node *n))
443 ZebraExplainInfo zei;
444 struct zebDatabaseInfoB **zdip;
448 logf (LOG_DEBUG, "zebraExplain_open wr=%d", writeFlag);
449 zei = xmalloc (sizeof(*zei));
450 zei->updateHandle = updateHandle;
451 zei->updateFunc = updateFunc;
453 zei->curDatabaseInfo = NULL;
454 zei->records = records;
455 zei->nmem = nmem_create ();
459 zei->categoryList = nmem_malloc (zei->nmem,
460 sizeof(*zei->categoryList));
461 zei->categoryList->sysno = 0;
462 zei->categoryList->dirty = 0;
463 zei->categoryList->data1_categoryList = NULL;
466 tm = localtime (&our_time);
467 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
468 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
469 tm->tm_hour, tm->tm_min, tm->tm_sec);
471 zdip = &zei->databaseInfo;
472 trec = rec_get (records, 1); /* get "root" record */
474 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
475 if (trec) /* targetInfo already exists ... */
477 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
479 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
482 data1_pr_tree (zei->dh, zei->data1_target, stderr);
484 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
486 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
489 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
491 node_list = data1_search_tag (zei->dh, node_zebra->child,
493 for (np = node_list->child; np; np = np->next)
495 data1_node *node_name = NULL;
496 data1_node *node_id = NULL;
497 data1_node *node_aid = NULL;
499 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
501 for (np2 = np->child; np2; np2 = np2->next)
503 if (np2->which != DATA1N_tag)
505 if (!strcmp (np2->u.tag.tag, "name"))
506 node_name = np2->child;
507 else if (!strcmp (np2->u.tag.tag, "id"))
508 node_id = np2->child;
509 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
510 node_aid = np2->child;
512 assert (node_id && node_name && node_aid);
514 *zdip = nmem_malloc (zei->nmem, sizeof(**zdip));
516 (*zdip)->readFlag = 1;
518 (*zdip)->data1_database = NULL;
519 (*zdip)->recordCount = 0;
520 (*zdip)->recordBytes = 0;
521 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
523 (*zdip)->databaseName = nmem_malloc (zei->nmem,
524 1+node_name->u.data.len);
525 memcpy ((*zdip)->databaseName, node_name->u.data.data,
526 node_name->u.data.len);
527 (*zdip)->databaseName[node_name->u.data.len] = '\0';
528 (*zdip)->sysno = atoi_n (node_id->u.data.data,
529 node_id->u.data.len);
530 (*zdip)->attributeDetails =
531 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
532 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
533 node_aid->u.data.len);
534 (*zdip)->attributeDetails->readFlag = 1;
535 (*zdip)->attributeDetails->dirty = 0;
536 (*zdip)->attributeDetails->SUInfo = NULL;
538 zdip = &(*zdip)->next;
540 np = data1_search_tag (zei->dh, node_zebra->child,
543 assert (np && np->which == DATA1N_data);
544 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
546 np = data1_search_tag (zei->dh, node_zebra->child,
549 assert (np && np->which == DATA1N_data);
550 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
554 else /* create initial targetInfo */
556 data1_node *node_tgtinfo;
566 data1_read_sgml (zei->dh, zei->nmem,
567 "<explain><targetInfo>TargetInfo\n"
569 "<namedResultSets>1</>\n"
570 "<multipleDBSearch>1</>\n"
571 "<nicknames><name>Zebra</></>\n"
574 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
576 assert (node_tgtinfo);
578 zebraExplain_initCommonInfo (zei, node_tgtinfo);
579 zebraExplain_initAccessInfo (zei, node_tgtinfo);
581 /* write now because we want to be sure about the sysno */
582 trec = rec_new (records);
583 trec->info[recInfo_fileType] =
584 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
585 trec->info[recInfo_databaseName] =
586 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
588 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
589 trec->info[recInfo_storeData] = xmalloc (sgml_len);
590 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
591 trec->size[recInfo_storeData] = sgml_len;
593 rec_put (records, &trec);
597 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
599 if (!zei->categoryList->dirty)
601 struct zebraCategoryListInfo *zcl = zei->categoryList;
605 zcl->data1_categoryList =
606 data1_read_sgml (zei->dh, zei->nmem,
607 "<explain><categoryList>CategoryList\n"
609 node_cl = data1_search_tag (zei->dh,
610 zcl->data1_categoryList->child,
613 zebraExplain_initCommonInfo (zei, node_cl);
619 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
620 zebAttributeDetails zad)
623 struct zebSUInfoB **zsuip = &zad->SUInfo;
624 data1_node *node_adinfo, *node_zebra, *node_list, *np;
627 rec = rec_get (zei->records, zad->sysno);
629 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
631 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
633 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
635 node_list = data1_search_tag (zei->dh, node_zebra->child,
637 for (np = node_list->child; np; np = np->next)
639 data1_node *node_set = NULL;
640 data1_node *node_use = NULL;
641 data1_node *node_ordinal = NULL;
646 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
648 for (np2 = np->child; np2; np2 = np2->next)
650 if (np2->which != DATA1N_tag || !np2->child ||
651 np2->child->which != DATA1N_data)
653 if (!strcmp (np2->u.tag.tag, "set"))
654 node_set = np2->child;
655 else if (!strcmp (np2->u.tag.tag, "use"))
656 node_use = np2->child;
657 else if (!strcmp (np2->u.tag.tag, "ordinal"))
658 node_ordinal = np2->child;
660 assert (node_set && node_use && node_ordinal);
662 oid_str_len = node_set->u.data.len;
663 if (oid_str_len >= sizeof(oid_str))
664 oid_str_len = sizeof(oid_str)-1;
665 memcpy (oid_str, node_set->u.data.data, oid_str_len);
666 oid_str[oid_str_len] = '\0';
668 *zsuip = nmem_malloc (zei->nmem, sizeof(**zsuip));
669 (*zsuip)->info.set = oid_getvalbyname (oid_str);
671 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
672 node_use->u.data.len);
673 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
674 node_ordinal->u.data.len);
675 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
676 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
677 zsuip = &(*zsuip)->next;
684 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
685 struct zebDatabaseInfoB *zdi)
688 data1_node *node_dbinfo, *node_zebra, *np;
691 rec = rec_get (zei->records, zdi->sysno);
693 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
695 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
697 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
699 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
702 && (np = data1_search_tag (zei->dh, node_zebra->child,
704 && np->child && np->child->which == DATA1N_data)
705 zdi->recordBytes = atoi_n (np->child->u.data.data,
706 np->child->u.data.len);
707 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
709 (np = data1_search_tag (zei->dh, np->child,
710 "recordCountActual")) &&
711 np->child->which == DATA1N_data)
713 zdi->recordCount = atoi_n (np->child->u.data.data,
714 np->child->u.data.len);
720 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
722 struct zebDatabaseInfoB *zdi;
725 if (zei->curDatabaseInfo &&
726 !strcmp (zei->curDatabaseInfo->databaseName, database))
728 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
730 if (!strcmp (zdi->databaseName, database))
736 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
741 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
743 zebraExplain_readDatabase (zei, zdi);
745 if (zdi->attributeDetails->readFlag)
748 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
750 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
752 zei->curDatabaseInfo = zdi;
756 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
758 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
760 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
761 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
762 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
765 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
767 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
769 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
772 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
774 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
775 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
776 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
779 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
780 zebAccessInfo accessInfo)
782 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
788 if ((p = accessInfo->attributeSetIds))
790 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
791 for (; p; p = p->next)
792 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
794 if ((p = accessInfo->schemas))
796 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
797 for (; p; p = p->next)
798 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
802 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
803 int explain_database)
805 struct zebDatabaseInfoB *zdi;
806 data1_node *node_dbinfo, *node_adinfo;
809 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
812 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
814 if (!strcmp (zdi->databaseName, database))
819 /* it's new really. make it */
820 zdi = nmem_malloc (zei->nmem, sizeof(*zdi));
821 zdi->next = zei->databaseInfo;
822 zei->databaseInfo = zdi;
824 zdi->recordCount = 0;
825 zdi->recordBytes = 0;
827 zdi->databaseName = nmem_strdup (zei->nmem, database);
829 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
834 zdi->data1_database =
835 data1_read_sgml (zei->dh, zei->nmem,
836 "<explain><databaseInfo>DatabaseInfo\n"
839 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
841 assert (node_dbinfo);
843 zebraExplain_initCommonInfo (zei, node_dbinfo);
844 zebraExplain_initAccessInfo (zei, node_dbinfo);
846 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
847 database, zei->nmem);
849 if (explain_database)
850 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
853 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
856 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
860 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
864 zei->curDatabaseInfo = zdi;
866 zdi->attributeDetails =
867 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
868 zdi->attributeDetails->readFlag = 0;
869 zdi->attributeDetails->sysno = 0;
870 zdi->attributeDetails->dirty = 1;
871 zdi->attributeDetails->SUInfo = NULL;
872 zdi->attributeDetails->data1_tree =
873 data1_read_sgml (zei->dh, zei->nmem,
874 "<explain><attributeDetails>AttributeDetails\n"
878 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
880 assert (node_adinfo);
882 zebraExplain_initCommonInfo (zei, node_adinfo);
887 static void writeAttributeValueDetails (ZebraExplainInfo zei,
888 zebAttributeDetails zad,
889 data1_node *node_atvs, data1_attset *attset)
892 struct zebSUInfoB *zsui;
893 int set_ordinal = attset->reference;
894 data1_attset_child *c;
896 for (c = attset->children; c; c = c->next)
897 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
898 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
900 data1_node *node_attvalue, *node_value;
901 if (set_ordinal != zsui->info.set)
903 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
905 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
907 data1_add_tagdata_int (zei->dh, node_value, "numeric",
908 zsui->info.use, zei->nmem);
912 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
913 struct zebraCategoryListInfo *zcl,
920 data1_node *node_ci, *node_categoryList;
922 static char *category[] = {
934 node_categoryList = zcl->data1_categoryList;
937 logf (LOG_LOG, "zebraExplain_writeCategoryList");
940 drec = createRecord (zei->records, &sysno);
942 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
945 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
948 for (i = 0; category[i]; i++)
950 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
951 "category", zei->nmem);
953 data1_add_tagdata_text (zei->dh, node_cat, "name",
954 category[i], zei->nmem);
956 /* extract *searchable* keys from it. We do this here, because
957 record count, etc. is affected */
959 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
961 /* convert to "SGML" and write it */
963 data1_pr_tree (zei->dh, node_categoryList, stderr);
965 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList,
967 drec->info[recInfo_storeData] = xmalloc (sgml_len);
968 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
969 drec->size[recInfo_storeData] = sgml_len;
971 rec_put (zei->records, &drec);
974 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
975 zebAttributeDetails zad,
976 const char *databaseName,
982 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
983 struct zebSUInfoB *zsui;
991 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
994 drec = createRecord (zei->records, &zad->sysno);
995 assert (zad->data1_tree);
996 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
998 zebraExplain_updateCommonInfo (zei, node_adinfo);
1000 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1001 databaseName, zei->nmem);
1003 /* extract *searchable* keys from it. We do this here, because
1004 record count, etc. is affected */
1006 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1008 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1009 "attributesBySet", zei->nmem);
1013 data1_node *node_asd;
1014 data1_attset *attset;
1015 int set_ordinal = -1;
1016 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1018 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1019 && zsui->info.set > set_min)
1020 set_ordinal = zsui->info.set;
1022 if (set_ordinal < 0)
1024 set_min = set_ordinal;
1025 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1026 "attributeSetDetails", zei->nmem);
1028 attset = data1_attset_search_id (zei->dh, set_ordinal);
1031 zebraExplain_loadAttsets (zei->dh, zei->res);
1032 attset = data1_attset_search_id (zei->dh, set_ordinal);
1039 oe.proto = PROTO_Z3950;
1040 oe.oclass = CLASS_ATTSET;
1041 oe.value = set_ordinal;
1043 if (oid_ent_to_oid (&oe, oid))
1045 data1_node *node_abt, *node_atd, *node_atvs;
1046 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1049 node_abt = data1_add_tag (zei->dh, node_asd,
1050 "attributesByType", zei->nmem);
1051 node_atd = data1_add_tag (zei->dh, node_abt,
1052 "attributeTypeDetails", zei->nmem);
1053 data1_add_tagdata_int (zei->dh, node_atd,
1054 "type", 1, zei->nmem);
1055 node_atvs = data1_add_tag (zei->dh, node_atd,
1056 "attributeValues", zei->nmem);
1057 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1061 /* zebra info (private) */
1062 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1063 "zebraInfo", zei->nmem);
1064 node_list = data1_make_tag (zei->dh, node_zebra,
1065 "attrlist", zei->nmem);
1066 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1068 struct oident oident;
1070 data1_node *node_attr;
1072 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1074 oident.proto = PROTO_Z3950;
1075 oident.oclass = CLASS_ATTSET;
1076 oident.value = zsui->info.set;
1077 oid_ent_to_oid (&oident, oid);
1079 data1_add_tagdata_text (zei->dh, node_attr, "set",
1080 oident.desc, zei->nmem);
1081 data1_add_tagdata_int (zei->dh, node_attr, "use",
1082 zsui->info.use, zei->nmem);
1083 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1084 zsui->info.ordinal, zei->nmem);
1086 /* convert to "SGML" and write it */
1088 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1090 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1092 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1093 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1094 drec->size[recInfo_storeData] = sgml_len;
1096 rec_put (zei->records, &drec);
1099 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1100 struct zebDatabaseInfoB *zdi,
1106 data1_node *node_dbinfo, *node_count, *node_zebra;
1113 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1115 drec = createRecord (zei->records, &zdi->sysno);
1116 assert (zdi->data1_database);
1117 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1120 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1121 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1123 /* extract *searchable* keys from it. We do this here, because
1124 record count, etc. is affected */
1126 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1128 node_count = data1_make_tag (zei->dh, node_dbinfo,
1129 "recordCount", zei->nmem);
1130 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1131 zdi->recordCount, zei->nmem);
1133 /* zebra info (private) */
1134 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1135 "zebraInfo", zei->nmem);
1136 data1_add_tagdata_int (zei->dh, node_zebra,
1137 "recordBytes", zdi->recordBytes, zei->nmem);
1138 /* convert to "SGML" and write it */
1140 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1142 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1144 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1145 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1146 drec->size[recInfo_storeData] = sgml_len;
1148 rec_put (zei->records, &drec);
1151 static void writeAttributeValues (ZebraExplainInfo zei,
1152 data1_node *node_values,
1153 data1_attset *attset)
1156 data1_attset_child *c;
1161 for (c = attset->children; c; c = c->next)
1162 writeAttributeValues (zei, node_values, c->child);
1163 for (atts = attset->atts; atts; atts = atts->next)
1165 data1_node *node_value;
1167 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1169 data1_add_tagdata_text (zei->dh, node_value, "name",
1170 atts->name, zei->nmem);
1171 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1172 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1173 atts->value, zei->nmem);
1178 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1185 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1186 data1_node *node_values;
1187 struct oident *entp;
1188 struct data1_attset *attset = NULL;
1190 if ((entp = oid_getentbyoid (o->oid)))
1191 attset = data1_attset_search_id (zei->dh, entp->value);
1194 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1195 attset ? attset->name : "<unknown>");
1198 drec = createRecord (zei->records, &o->sysno);
1200 data1_read_sgml (zei->dh, zei->nmem,
1201 "<explain><attributeSetInfo>AttributeSetInfo\n"
1204 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1205 "attributeSetInfo");
1207 zebraExplain_initCommonInfo (zei, node_attinfo);
1208 zebraExplain_updateCommonInfo (zei, node_attinfo);
1210 data1_add_tagdata_oid (zei->dh, node_attinfo,
1211 "oid", o->oid, zei->nmem);
1212 if (attset && attset->name)
1213 data1_add_tagdata_text (zei->dh, node_attinfo,
1214 "name", attset->name, zei->nmem);
1216 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1217 "attributes", zei->nmem);
1218 node_atttype = data1_make_tag (zei->dh, node_attributes,
1219 "attributeType", zei->nmem);
1220 data1_add_tagdata_text (zei->dh, node_atttype,
1221 "name", "Use", zei->nmem);
1222 data1_add_tagdata_text (zei->dh, node_atttype,
1223 "description", "Use Attribute", zei->nmem);
1224 data1_add_tagdata_int (zei->dh, node_atttype,
1225 "type", 1, zei->nmem);
1226 node_values = data1_add_tag (zei->dh, node_atttype,
1227 "attributeValues", zei->nmem);
1229 writeAttributeValues (zei, node_values, attset);
1231 /* extract *searchable* keys from it. We do this here, because
1232 record count, etc. is affected */
1234 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1235 /* convert to "SGML" and write it */
1237 data1_pr_tree (zei->dh, node_root, stderr);
1239 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1240 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1241 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1242 drec->size[recInfo_storeData] = sgml_len;
1244 rec_put (zei->records, &drec);
1247 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1249 struct zebDatabaseInfoB *zdi;
1250 data1_node *node_tgtinfo, *node_list, *node_zebra;
1259 trec = rec_get (zei->records, 1);
1260 xfree (trec->info[recInfo_storeData]);
1262 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1264 assert (node_tgtinfo);
1266 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1267 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1269 /* convert to "SGML" and write it */
1271 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1273 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1274 "zebraInfo", zei->nmem);
1275 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1276 ZEBRAVER, zei->nmem);
1277 node_list = data1_add_tag (zei->dh, node_zebra,
1278 "databaseList", zei->nmem);
1279 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1281 data1_node *node_db;
1282 node_db = data1_add_tag (zei->dh, node_list,
1283 "database", zei->nmem);
1284 data1_add_tagdata_text (zei->dh, node_db, "name",
1285 zdi->databaseName, zei->nmem);
1286 data1_add_tagdata_int (zei->dh, node_db, "id",
1287 zdi->sysno, zei->nmem);
1288 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1289 zdi->attributeDetails->sysno, zei->nmem);
1291 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1292 zei->ordinalSU, zei->nmem);
1294 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1295 zei->runNumber, zei->nmem);
1298 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1300 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1302 trec->info[recInfo_storeData] = xmalloc (sgml_len);
1303 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1304 trec->size[recInfo_storeData] = sgml_len;
1306 rec_put (zei->records, &trec);
1309 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1311 struct zebSUInfoB *zsui;
1313 assert (zei->curDatabaseInfo);
1314 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1315 zsui; zsui=zsui->next)
1316 if (zsui->info.use == use && zsui->info.set == set)
1317 return zsui->info.ordinal;
1321 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1322 zebAccessObject *op,
1327 for (ao = *op; ao; ao = ao->next)
1328 if (!oid_oidcmp (oid, ao->oid))
1332 ao = nmem_malloc (zei->nmem, sizeof(*ao));
1335 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1342 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1347 oe.proto = PROTO_Z3950;
1348 oe.oclass = CLASS_ATTSET;
1351 if (oid_ent_to_oid (&oe, oid))
1353 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1354 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1355 accessInfo->attributeSetIds, oid);
1359 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1361 struct zebSUInfoB *zsui;
1363 assert (zei->curDatabaseInfo);
1364 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1365 zsui; zsui=zsui->next)
1366 if (zsui->info.use == use && zsui->info.set == set)
1368 zebraExplain_addAttributeSet (zei, set);
1369 zsui = nmem_malloc (zei->nmem, sizeof(*zsui));
1370 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1371 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1372 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1374 zsui->info.set = set;
1375 zsui->info.use = use;
1376 zsui->info.ordinal = (zei->ordinalSU)++;
1377 return zsui->info.ordinal;
1380 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1382 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1383 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1384 accessInfo->schemas, oid);
1387 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1389 assert (zei->curDatabaseInfo);
1393 zei->curDatabaseInfo->recordBytes += adjust_num;
1394 zei->curDatabaseInfo->dirty = 1;
1398 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1400 assert (zei->curDatabaseInfo);
1404 zei->curDatabaseInfo->recordCount += adjust_num;
1405 zei->curDatabaseInfo->dirty = 1;
1409 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1413 return zei->runNumber += adjust_num;
1416 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1418 RecordAttr *recordAttr;
1420 if (rec->info[recInfo_attr])
1421 return (RecordAttr *) rec->info[recInfo_attr];
1422 recordAttr = xmalloc (sizeof(*recordAttr));
1423 rec->info[recInfo_attr] = (char *) recordAttr;
1424 rec->size[recInfo_attr] = sizeof(*recordAttr);
1426 recordAttr->recordSize = 0;
1427 recordAttr->recordOffset = 0;
1428 recordAttr->runNumber = zei->runNumber;
1432 static void att_loadset(void *p, const char *n, const char *name)
1434 data1_handle dh = p;
1435 if (!data1_get_attset (dh, name))
1436 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1439 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1441 res_trav(res, "attset", dh, att_loadset);
1445 zebraExplain_addSU adds to AttributeDetails for a database and
1446 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1447 exist for the database.
1449 If the database doesn't exist globally (in TargetInfo) an
1450 AttributeSetInfo must be added (globally).