2 * Copyright (C) 1994-1998, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.11 1998-06-09 12:16:48 adam
8 * Implemented auto-generation of CategoryList records.
10 * Revision 1.10 1998/06/08 14:43:15 adam
11 * Added suport for EXPLAIN Proxy servers - added settings databasePath
12 * and explainDatabase to facilitate this. Increased maximum number
13 * of databases and attributes in one register.
15 * Revision 1.9 1998/06/02 12:10:27 adam
16 * Fixed bug related to attributeDetails.
18 * Revision 1.8 1998/05/20 10:12:20 adam
19 * Implemented automatic EXPLAIN database maintenance.
20 * Modified Zebra to work with ASN.1 compiled version of YAZ.
22 * Revision 1.7 1998/03/05 08:45:13 adam
23 * New result set model and modular ranking system. Moved towards
24 * descent server API. System information stored as "SGML" records.
26 * Revision 1.6 1998/02/17 10:29:27 adam
27 * Moved towards 'automatic' EXPLAIN database.
29 * Revision 1.5 1997/10/27 14:33:05 adam
30 * Moved towards generic character mapping depending on "structure"
31 * field in abstract syntax file. Fixed a few memory leaks. Fixed
32 * bug with negative integers when doing searches with relational
35 * Revision 1.4 1997/09/25 14:57:08 adam
38 * Revision 1.3 1996/05/22 08:21:59 adam
39 * Added public ZebDatabaseInfo structure.
41 * Revision 1.2 1996/05/14 06:16:41 adam
42 * Compact use/set bytes used in search service.
44 * Revision 1.1 1996/05/13 14:23:07 adam
45 * Work on compaction of set/use bytes in dictionary.
66 struct zebSUInfo info;
67 struct zebSUInfoB *next;
70 typedef struct zebAccessObjectB *zebAccessObject;
71 struct zebAccessObjectB {
78 typedef struct zebAccessInfoB *zebAccessInfo;
79 struct zebAccessInfoB {
80 zebAccessObject attributeSetIds;
81 zebAccessObject schemas;
85 struct zebSUInfoB *SUInfo;
89 data1_node *data1_tree;
90 } *zebAttributeDetails;
92 struct zebDatabaseInfoB {
93 zebAttributeDetails attributeDetails;
95 data1_node *data1_database;
96 int recordCount; /* records in db */
97 int recordBytes; /* size of records */
98 int sysno; /* sysno of database info */
99 int readFlag; /* 1: read is needed when referenced; 0 if not */
100 int dirty; /* 1: database is dirty: write is needed */
101 struct zebDatabaseInfoB *next;
102 zebAccessInfo accessInfo;
105 struct zebraExplainAttset {
108 struct zebraExplainAttset *next;
111 struct zebraCategoryListInfo {
114 data1_node *data1_categoryList;
117 struct zebraExplainInfo {
124 struct zebraExplainAttset *attsets;
126 data1_node *data1_target;
127 struct zebraCategoryListInfo *categoryList;
128 struct zebDatabaseInfoB *databaseInfo;
129 struct zebDatabaseInfoB *curDatabaseInfo;
130 zebAccessInfo accessInfo;
131 char date[15]; /* YYYY MMDD HH MM SS */
132 int (*updateFunc)(void *handle, Record drec, data1_node *n);
136 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
137 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
139 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
141 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
144 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
147 logf (LOG_DEBUG, "data1_search_tag %s", tag);
148 for (; n; n = n->next)
149 if (n->which == DATA1N_tag && n->u.tag.tag &&
150 !yaz_matchstr (tag, n->u.tag.tag))
152 logf (LOG_DEBUG, " found");
155 logf (LOG_DEBUG, " not found");
159 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
160 const char *tag, NMEM nmem)
162 data1_node *partag = get_parent_tag(dh, at);
163 data1_node *res = data1_mk_node (dh, nmem);
164 data1_element *e = NULL;
167 res->which = DATA1N_tag;
168 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
169 res->u.tag.node_selected = 0;
170 res->u.tag.make_variantlist = 0;
171 res->u.tag.no_data_requested = 0;
172 res->u.tag.get_bytes = -1;
175 e = partag->u.tag.element;
177 data1_getelementbytagname (dh, at->root->u.root.absyn,
179 res->root = at->root;
184 assert (at->last_child);
185 at->last_child->next = res;
187 at->last_child = res;
191 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
192 const char *tag, NMEM nmem)
194 data1_node *node = data1_search_tag (dh, at->child, tag);
196 node = data1_add_tag (dh, at, tag, nmem);
198 node->child = node->last_child = NULL;
202 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
203 const char *tag, int num,
206 data1_node *node_data;
208 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
211 node_data->u.data.what = DATA1I_num;
212 node_data->u.data.data = node_data->lbuf;
213 sprintf (node_data->u.data.data, "%d", num);
214 node_data->u.data.len = strlen (node_data->u.data.data);
218 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
219 const char *tag, Odr_oid *oid,
222 data1_node *node_data;
223 char str[128], *p = str;
226 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
230 for (ii = oid; *ii >= 0; ii++)
234 sprintf (p, "%d", *ii);
237 node_data->u.data.what = DATA1I_oid;
238 node_data->u.data.len = strlen (str);
239 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
244 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
245 const char *tag, const char *str,
248 data1_node *node_data;
250 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
253 node_data->u.data.what = DATA1I_text;
254 node_data->u.data.len = strlen (str);
255 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
259 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
260 const char *tag, const char *str,
263 data1_node *node = data1_search_tag (dh, at->child, tag);
265 return data1_add_tagdata_text (dh, at, tag, str, nmem);
268 data1_node *node_data = node->child;
269 node_data->u.data.what = DATA1I_text;
270 node_data->u.data.data = node_data->lbuf;
271 strcpy (node_data->u.data.data, str);
272 node_data->u.data.len = strlen (node_data->u.data.data);
277 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
278 struct zebDatabaseInfoB *zdi,
280 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
281 zebAttributeDetails zad,
282 const char *databaseName,
284 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
285 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
288 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
289 struct zebraCategoryListInfo *zcl,
293 static Record createRecord (Records records, int *sysno)
298 rec = rec_get (records, *sysno);
299 xfree (rec->info[recInfo_storeData]);
303 rec = rec_new (records);
306 rec->info[recInfo_fileType] =
307 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
308 rec->info[recInfo_databaseName] =
309 rec_strdup ("IR-Explain-1",
310 &rec->size[recInfo_databaseName]);
315 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag,
316 int (*updateH)(Record drec, data1_node *n))
318 struct zebDatabaseInfoB *zdi;
320 logf (LOG_DEBUG, "zebraExplain_close wr=%d", writeFlag);
324 /* write each database info record */
325 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
327 zebraExplain_writeDatabase (zei, zdi, 1);
328 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
329 zdi->databaseName, 1);
331 zebraExplain_writeTarget (zei, 1);
332 zebraExplain_writeCategoryList (zei,
335 assert (zei->accessInfo);
336 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
338 zebraExplain_writeAttributeSet (zei, o, 1);
339 for (o = zei->accessInfo->schemas; o; o = o->next)
342 /* zebraExplain_writeSchema (zei, o, 1); */
345 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
347 zebraExplain_writeDatabase (zei, zdi, 0);
348 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
349 zdi->databaseName, 0);
351 zebraExplain_writeTarget (zei, 0);
354 nmem_destroy (zei->nmem);
358 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
363 for (np = n->child; np; np = np->next)
370 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
372 len = np->child->u.data.len;
375 memcpy (str, np->child->u.data.data, len);
378 oid = odr_getoidbystr_nmem (zei->nmem, str);
380 for (ao = *op; ao; ao = ao->next)
381 if (!oid_oidcmp (oid, ao->oid))
388 ao = nmem_malloc (zei->nmem, sizeof(*ao));
398 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
399 zebAccessInfo *accessInfo)
405 *accessInfo = nmem_malloc (zei->nmem, sizeof(**accessInfo));
406 (*accessInfo)->attributeSetIds = NULL;
407 (*accessInfo)->schemas = NULL;
411 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
413 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
414 zebraExplain_mergeOids (zei, np,
415 &(*accessInfo)->attributeSetIds);
416 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
417 zebraExplain_mergeOids (zei, np,
418 &(*accessInfo)->schemas);
422 ZebraExplainInfo zebraExplain_open (
423 Records records, data1_handle dh,
427 int (*updateFunc)(void *handle, Record drec, data1_node *n))
430 ZebraExplainInfo zei;
431 struct zebDatabaseInfoB **zdip;
435 logf (LOG_DEBUG, "zebraExplain_open wr=%d", writeFlag);
436 zei = xmalloc (sizeof(*zei));
437 zei->updateHandle = updateHandle;
438 zei->updateFunc = updateFunc;
440 zei->curDatabaseInfo = NULL;
441 zei->records = records;
442 zei->nmem = nmem_create ();
446 zei->categoryList = nmem_malloc (zei->nmem,
447 sizeof(*zei->categoryList));
448 zei->categoryList->sysno = 0;
449 zei->categoryList->dirty = 0;
450 zei->categoryList->data1_categoryList = NULL;
453 tm = localtime (&our_time);
454 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
455 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
456 tm->tm_hour, tm->tm_min, tm->tm_sec);
458 zdip = &zei->databaseInfo;
459 trec = rec_get (records, 1); /* get "root" record */
461 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
462 if (trec) /* targetInfo already exists ... */
464 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
466 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
469 data1_pr_tree (zei->dh, zei->data1_target, stderr);
471 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
473 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
476 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
478 node_list = data1_search_tag (zei->dh, node_zebra->child,
480 for (np = node_list->child; np; np = np->next)
482 data1_node *node_name = NULL;
483 data1_node *node_id = NULL;
484 data1_node *node_aid = NULL;
486 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
488 for (np2 = np->child; np2; np2 = np2->next)
490 if (np2->which != DATA1N_tag)
492 if (!strcmp (np2->u.tag.tag, "name"))
493 node_name = np2->child;
494 else if (!strcmp (np2->u.tag.tag, "id"))
495 node_id = np2->child;
496 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
497 node_aid = np2->child;
499 assert (node_id && node_name && node_aid);
501 *zdip = nmem_malloc (zei->nmem, sizeof(**zdip));
503 (*zdip)->readFlag = 1;
505 (*zdip)->data1_database = NULL;
506 (*zdip)->recordCount = 0;
507 (*zdip)->recordBytes = 0;
508 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
510 (*zdip)->databaseName = nmem_malloc (zei->nmem,
511 1+node_name->u.data.len);
512 memcpy ((*zdip)->databaseName, node_name->u.data.data,
513 node_name->u.data.len);
514 (*zdip)->databaseName[node_name->u.data.len] = '\0';
515 (*zdip)->sysno = atoi_n (node_id->u.data.data,
516 node_id->u.data.len);
517 (*zdip)->attributeDetails =
518 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
519 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
520 node_aid->u.data.len);
521 (*zdip)->attributeDetails->readFlag = 1;
522 (*zdip)->attributeDetails->dirty = 0;
523 (*zdip)->attributeDetails->SUInfo = NULL;
525 zdip = &(*zdip)->next;
527 np = data1_search_tag (zei->dh, node_zebra->child,
530 assert (np && np->which == DATA1N_data);
531 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
533 np = data1_search_tag (zei->dh, node_zebra->child,
536 assert (np && np->which == DATA1N_data);
537 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
541 else /* create initial targetInfo */
543 data1_node *node_tgtinfo;
553 data1_read_sgml (zei->dh, zei->nmem,
554 "<explain><targetInfo>TargetInfo\n"
556 "<namedResultSets>1</>\n"
557 "<multipleDBSearch>1</>\n"
558 "<nicknames><name>Zebra</></>\n"
561 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
563 assert (node_tgtinfo);
565 zebraExplain_initCommonInfo (zei, node_tgtinfo);
566 zebraExplain_initAccessInfo (zei, node_tgtinfo);
568 /* write now because we want to be sure about the sysno */
569 trec = rec_new (records);
570 trec->info[recInfo_fileType] =
571 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
572 trec->info[recInfo_databaseName] =
573 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
575 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
576 trec->info[recInfo_storeData] = xmalloc (sgml_len);
577 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
578 trec->size[recInfo_storeData] = sgml_len;
580 rec_put (records, &trec);
584 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
586 if (!zei->categoryList->dirty)
588 struct zebraCategoryListInfo *zcl = zei->categoryList;
592 zcl->data1_categoryList =
593 data1_read_sgml (zei->dh, zei->nmem,
594 "<explain><categoryList>CategoryList\n"
596 node_cl = data1_search_tag (zei->dh,
597 zcl->data1_categoryList->child,
600 zebraExplain_initCommonInfo (zei, node_cl);
606 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
607 zebAttributeDetails zad)
610 struct zebSUInfoB **zsuip = &zad->SUInfo;
611 data1_node *node_adinfo, *node_zebra, *node_list, *np;
614 rec = rec_get (zei->records, zad->sysno);
616 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
618 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
620 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
622 node_list = data1_search_tag (zei->dh, node_zebra->child,
624 for (np = node_list->child; np; np = np->next)
626 data1_node *node_set = NULL;
627 data1_node *node_use = NULL;
628 data1_node *node_ordinal = NULL;
630 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
632 for (np2 = np->child; np2; np2 = np2->next)
634 if (np2->which != DATA1N_tag || !np2->child ||
635 np2->child->which != DATA1N_data)
637 if (!strcmp (np2->u.tag.tag, "set"))
638 node_set = np2->child;
639 else if (!strcmp (np2->u.tag.tag, "use"))
640 node_use = np2->child;
641 else if (!strcmp (np2->u.tag.tag, "ordinal"))
642 node_ordinal = np2->child;
644 assert (node_set && node_use && node_ordinal);
646 *zsuip = nmem_malloc (zei->nmem, sizeof(**zsuip));
647 (*zsuip)->info.set = atoi_n (node_set->u.data.data,
648 node_set->u.data.len);
649 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
650 node_use->u.data.len);
651 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
652 node_ordinal->u.data.len);
653 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
654 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
655 zsuip = &(*zsuip)->next;
662 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
663 struct zebDatabaseInfoB *zdi)
666 data1_node *node_dbinfo, *node_zebra, *np;
669 rec = rec_get (zei->records, zdi->sysno);
671 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
673 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
675 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
677 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
679 np = data1_search_tag (zei->dh, node_dbinfo->child,
681 if (np && np->child && np->child->which == DATA1N_data)
682 zdi->recordBytes = atoi_n (np->child->u.data.data,
683 np->child->u.data.len);
684 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
686 (np = data1_search_tag (zei->dh, np->child,
687 "recordCountActual")) &&
688 np->child->which == DATA1N_data)
690 zdi->recordCount = atoi_n (np->child->u.data.data,
691 np->child->u.data.len);
697 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
699 struct zebDatabaseInfoB *zdi;
702 if (zei->curDatabaseInfo &&
703 !strcmp (zei->curDatabaseInfo->databaseName, database))
705 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
707 if (!strcmp (zdi->databaseName, database))
713 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
718 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
720 zebraExplain_readDatabase (zei, zdi);
722 if (zdi->attributeDetails->readFlag)
725 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
727 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
729 zei->curDatabaseInfo = zdi;
733 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
735 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
737 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
738 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
739 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
742 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
744 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
746 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
749 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
751 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
752 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
753 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
756 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
757 zebAccessInfo accessInfo)
759 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
765 if ((p = accessInfo->attributeSetIds))
767 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
768 for (; p; p = p->next)
769 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
771 if ((p = accessInfo->schemas))
773 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
774 for (; p; p = p->next)
775 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
779 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
780 int explain_database)
782 struct zebDatabaseInfoB *zdi;
783 data1_node *node_dbinfo, *node_adinfo;
786 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
789 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
791 if (!strcmp (zdi->databaseName, database))
796 /* it's new really. make it */
797 zdi = nmem_malloc (zei->nmem, sizeof(*zdi));
798 zdi->next = zei->databaseInfo;
799 zei->databaseInfo = zdi;
801 zdi->recordCount = 0;
802 zdi->recordBytes = 0;
804 zdi->databaseName = nmem_strdup (zei->nmem, database);
806 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
811 zdi->data1_database =
812 data1_read_sgml (zei->dh, zei->nmem,
813 "<explain><databaseInfo>DatabaseInfo\n"
816 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
818 assert (node_dbinfo);
820 zebraExplain_initCommonInfo (zei, node_dbinfo);
821 zebraExplain_initAccessInfo (zei, node_dbinfo);
823 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
824 database, zei->nmem);
826 if (explain_database)
827 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
830 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
833 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
837 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
841 zei->curDatabaseInfo = zdi;
843 zdi->attributeDetails =
844 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
845 zdi->attributeDetails->readFlag = 0;
846 zdi->attributeDetails->sysno = 0;
847 zdi->attributeDetails->dirty = 1;
848 zdi->attributeDetails->SUInfo = NULL;
849 zdi->attributeDetails->data1_tree =
850 data1_read_sgml (zei->dh, zei->nmem,
851 "<explain><attributeDetails>AttributeDetails\n"
855 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
857 assert (node_adinfo);
859 zebraExplain_initCommonInfo (zei, node_adinfo);
864 static void writeAttributeValueDetails (ZebraExplainInfo zei,
865 zebAttributeDetails zad,
866 data1_node *node_atvs, data1_attset *attset)
869 struct zebSUInfoB *zsui;
870 int set_ordinal = attset->reference;
871 data1_attset_child *c;
873 for (c = attset->children; c; c = c->next)
874 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
875 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
877 data1_node *node_attvalue, *node_value;
878 if (set_ordinal != zsui->info.set)
880 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
882 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
884 data1_add_tagdata_int (zei->dh, node_value, "numeric",
885 zsui->info.use, zei->nmem);
889 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
890 struct zebraCategoryListInfo *zcl,
897 data1_node *node_ci, *node_categoryList;
899 static char *category[] = {
911 node_categoryList = zcl->data1_categoryList;
914 logf (LOG_LOG, "zebraExplain_writeCategoryList");
917 drec = createRecord (zei->records, &sysno);
919 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
922 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
925 for (i = 0; category[i]; i++)
927 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
928 "category", zei->nmem);
930 data1_add_tagdata_text (zei->dh, node_cat, "name",
931 category[i], zei->nmem);
933 /* extract *searchable* keys from it. We do this here, because
934 record count, etc. is affected */
936 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
938 /* convert to "SGML" and write it */
940 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
942 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList,
944 drec->info[recInfo_storeData] = xmalloc (sgml_len);
945 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
946 drec->size[recInfo_storeData] = sgml_len;
948 rec_put (zei->records, &drec);
951 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
952 zebAttributeDetails zad,
953 const char *databaseName,
959 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
960 struct zebSUInfoB *zsui;
968 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
971 drec = createRecord (zei->records, &zad->sysno);
972 assert (zad->data1_tree);
973 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
975 zebraExplain_updateCommonInfo (zei, node_adinfo);
977 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
978 databaseName, zei->nmem);
980 /* extract *searchable* keys from it. We do this here, because
981 record count, etc. is affected */
983 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
985 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
986 "attributesBySet", zei->nmem);
990 data1_node *node_asd;
991 data1_attset *attset;
992 int set_ordinal = -1;
993 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
995 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
996 && zsui->info.set > set_min)
997 set_ordinal = zsui->info.set;
1001 set_min = set_ordinal;
1002 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1003 "attributeSetDetails", zei->nmem);
1005 attset = data1_attset_search_id (zei->dh, set_ordinal);
1008 zebraExplain_loadAttsets (zei->dh, zei->res);
1009 attset = data1_attset_search_id (zei->dh, set_ordinal);
1016 oe.proto = PROTO_Z3950;
1017 oe.oclass = CLASS_ATTSET;
1018 oe.value = set_ordinal;
1020 if (oid_ent_to_oid (&oe, oid))
1022 data1_node *node_abt, *node_atd, *node_atvs;
1023 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1026 node_abt = data1_add_tag (zei->dh, node_asd,
1027 "attributesByType", zei->nmem);
1028 node_atd = data1_add_tag (zei->dh, node_abt,
1029 "attributeTypeDetails", zei->nmem);
1030 data1_add_tagdata_int (zei->dh, node_atd,
1031 "type", 1, zei->nmem);
1032 node_atvs = data1_add_tag (zei->dh, node_atd,
1033 "attributeValues", zei->nmem);
1034 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1038 /* zebra info (private) */
1039 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1040 "zebraInfo", zei->nmem);
1041 node_list = data1_make_tag (zei->dh, node_zebra,
1042 "attrlist", zei->nmem);
1043 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1045 data1_node *node_attr;
1046 node_attr = data1_add_tag (zei->dh, node_list,
1048 data1_add_tagdata_int (zei->dh, node_attr, "set",
1049 zsui->info.set, zei->nmem);
1050 data1_add_tagdata_int (zei->dh, node_attr, "use",
1051 zsui->info.use, zei->nmem);
1052 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1053 zsui->info.ordinal, zei->nmem);
1055 /* convert to "SGML" and write it */
1057 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1059 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1061 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1062 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1063 drec->size[recInfo_storeData] = sgml_len;
1065 rec_put (zei->records, &drec);
1068 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1069 struct zebDatabaseInfoB *zdi,
1075 data1_node *node_dbinfo, *node_count, *node_zebra;
1082 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1084 drec = createRecord (zei->records, &zdi->sysno);
1085 assert (zdi->data1_database);
1086 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1089 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1090 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1092 /* extract *searchable* keys from it. We do this here, because
1093 record count, etc. is affected */
1095 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1097 node_count = data1_make_tag (zei->dh, node_dbinfo,
1098 "recordCount", zei->nmem);
1099 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1100 zdi->recordCount, zei->nmem);
1102 /* zebra info (private) */
1103 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1104 "zebraInfo", zei->nmem);
1105 data1_add_tagdata_int (zei->dh, node_zebra,
1106 "recordBytes", zdi->recordBytes, zei->nmem);
1107 /* convert to "SGML" and write it */
1109 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1111 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1113 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1114 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1115 drec->size[recInfo_storeData] = sgml_len;
1117 rec_put (zei->records, &drec);
1120 static void writeAttributeValues (ZebraExplainInfo zei,
1121 data1_node *node_values,
1122 data1_attset *attset)
1125 data1_attset_child *c;
1130 for (c = attset->children; c; c = c->next)
1131 writeAttributeValues (zei, node_values, c->child);
1132 for (atts = attset->atts; atts; atts = atts->next)
1134 data1_node *node_value;
1136 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1138 data1_add_tagdata_text (zei->dh, node_value, "name",
1139 atts->name, zei->nmem);
1140 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1141 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1142 atts->value, zei->nmem);
1147 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1154 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1155 data1_node *node_values;
1156 struct oident *entp;
1157 struct data1_attset *attset = NULL;
1159 if ((entp = oid_getentbyoid (o->oid)))
1160 attset = data1_attset_search_id (zei->dh, entp->value);
1163 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1164 attset ? attset->name : "<unknown>");
1167 drec = createRecord (zei->records, &o->sysno);
1169 data1_read_sgml (zei->dh, zei->nmem,
1170 "<explain><attributeSetInfo>AttributeSetInfo\n"
1173 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1174 "attributeSetInfo");
1176 zebraExplain_initCommonInfo (zei, node_attinfo);
1177 zebraExplain_updateCommonInfo (zei, node_attinfo);
1179 data1_add_tagdata_oid (zei->dh, node_attinfo,
1180 "oid", o->oid, zei->nmem);
1181 if (attset && attset->name)
1182 data1_add_tagdata_text (zei->dh, node_attinfo,
1183 "name", attset->name, zei->nmem);
1185 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1186 "attributes", zei->nmem);
1187 node_atttype = data1_make_tag (zei->dh, node_attributes,
1188 "attributeType", zei->nmem);
1189 data1_add_tagdata_text (zei->dh, node_atttype,
1190 "name", "Use", zei->nmem);
1191 data1_add_tagdata_text (zei->dh, node_atttype,
1192 "description", "Use Attribute", zei->nmem);
1193 data1_add_tagdata_int (zei->dh, node_atttype,
1194 "type", 1, zei->nmem);
1195 node_values = data1_add_tag (zei->dh, node_atttype,
1196 "attributeValues", zei->nmem);
1198 writeAttributeValues (zei, node_values, attset);
1200 /* extract *searchable* keys from it. We do this here, because
1201 record count, etc. is affected */
1203 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1204 /* convert to "SGML" and write it */
1206 data1_pr_tree (zei->dh, node_root, stderr);
1208 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1209 drec->info[recInfo_storeData] = xmalloc (sgml_len);
1210 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1211 drec->size[recInfo_storeData] = sgml_len;
1213 rec_put (zei->records, &drec);
1216 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1218 struct zebDatabaseInfoB *zdi;
1219 data1_node *node_tgtinfo, *node_list, *node_zebra;
1228 trec = rec_get (zei->records, 1);
1229 xfree (trec->info[recInfo_storeData]);
1231 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1233 assert (node_tgtinfo);
1235 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1236 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1238 /* convert to "SGML" and write it */
1240 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1242 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1243 "zebraInfo", zei->nmem);
1244 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1245 ZEBRAVER, zei->nmem);
1246 node_list = data1_add_tag (zei->dh, node_zebra,
1247 "databaseList", zei->nmem);
1248 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1250 data1_node *node_db;
1251 node_db = data1_add_tag (zei->dh, node_list,
1252 "database", zei->nmem);
1253 data1_add_tagdata_text (zei->dh, node_db, "name",
1254 zdi->databaseName, zei->nmem);
1255 data1_add_tagdata_int (zei->dh, node_db, "id",
1256 zdi->sysno, zei->nmem);
1257 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1258 zdi->attributeDetails->sysno, zei->nmem);
1260 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1261 zei->ordinalSU, zei->nmem);
1263 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1264 zei->runNumber, zei->nmem);
1267 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1269 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1271 trec->info[recInfo_storeData] = xmalloc (sgml_len);
1272 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1273 trec->size[recInfo_storeData] = sgml_len;
1275 rec_put (zei->records, &trec);
1278 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1280 struct zebSUInfoB *zsui;
1282 assert (zei->curDatabaseInfo);
1283 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1284 zsui; zsui=zsui->next)
1285 if (zsui->info.use == use && zsui->info.set == set)
1286 return zsui->info.ordinal;
1290 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1291 zebAccessObject *op,
1296 for (ao = *op; ao; ao = ao->next)
1297 if (!oid_oidcmp (oid, ao->oid))
1301 ao = nmem_malloc (zei->nmem, sizeof(*ao));
1304 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1311 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1316 oe.proto = PROTO_Z3950;
1317 oe.oclass = CLASS_ATTSET;
1320 if (oid_ent_to_oid (&oe, oid))
1322 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1323 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1324 accessInfo->attributeSetIds, oid);
1328 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1330 struct zebSUInfoB *zsui;
1332 assert (zei->curDatabaseInfo);
1333 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1334 zsui; zsui=zsui->next)
1335 if (zsui->info.use == use && zsui->info.set == set)
1337 zebraExplain_addAttributeSet (zei, set);
1338 zsui = nmem_malloc (zei->nmem, sizeof(*zsui));
1339 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1340 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1341 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1343 zsui->info.set = set;
1344 zsui->info.use = use;
1345 zsui->info.ordinal = (zei->ordinalSU)++;
1346 return zsui->info.ordinal;
1349 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1351 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1352 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1353 accessInfo->schemas, oid);
1356 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1358 assert (zei->curDatabaseInfo);
1362 zei->curDatabaseInfo->recordBytes += adjust_num;
1363 zei->curDatabaseInfo->dirty = 1;
1367 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1369 assert (zei->curDatabaseInfo);
1373 zei->curDatabaseInfo->recordCount += adjust_num;
1374 zei->curDatabaseInfo->dirty = 1;
1378 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1382 return zei->runNumber += adjust_num;
1385 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1387 RecordAttr *recordAttr;
1389 if (rec->info[recInfo_attr])
1390 return (RecordAttr *) rec->info[recInfo_attr];
1391 recordAttr = xmalloc (sizeof(*recordAttr));
1392 rec->info[recInfo_attr] = (char *) recordAttr;
1393 rec->size[recInfo_attr] = sizeof(*recordAttr);
1395 recordAttr->recordSize = 0;
1396 recordAttr->recordOffset = 0;
1397 recordAttr->runNumber = zei->runNumber;
1401 static void att_loadset(void *p, const char *n, const char *name)
1403 data1_handle dh = p;
1404 if (!data1_get_attset (dh, name))
1405 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1408 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1410 res_trav(res, "attset", dh, att_loadset);
1414 zebraExplain_addSU adds to AttributeDetails for a database and
1415 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1416 exist for the database.
1418 If the database doesn't exist globally (in TargetInfo) an
1419 AttributeSetInfo must be added (globally).