2 * Copyright (C) 1994-1999, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.18 2000-03-20 19:08:36 adam
8 * Added remote record import using Z39.50 extended services and Segment
11 * Revision 1.17 1999/07/14 10:53:51 adam
12 * Updated various routines to handle missing explain schema.
14 * Revision 1.16 1999/05/26 07:49:13 adam
17 * Revision 1.15 1999/01/25 13:47:54 adam
20 * Revision 1.14 1998/11/04 16:31:32 adam
21 * Fixed bug regarding recordBytes in databaseInfo.
23 * Revision 1.13 1998/11/03 10:17:09 adam
24 * Fixed bug regarding creation of some data1 nodes for Explain records.
26 * Revision 1.12 1998/10/13 20:37:11 adam
27 * Changed the way attribute sets are saved in Explain database to
28 * reflect "dynamic" OIDs.
30 * Revision 1.11 1998/06/09 12:16:48 adam
31 * Implemented auto-generation of CategoryList records.
33 * Revision 1.10 1998/06/08 14:43:15 adam
34 * Added suport for EXPLAIN Proxy servers - added settings databasePath
35 * and explainDatabase to facilitate this. Increased maximum number
36 * of databases and attributes in one register.
38 * Revision 1.9 1998/06/02 12:10:27 adam
39 * Fixed bug related to attributeDetails.
41 * Revision 1.8 1998/05/20 10:12:20 adam
42 * Implemented automatic EXPLAIN database maintenance.
43 * Modified Zebra to work with ASN.1 compiled version of YAZ.
45 * Revision 1.7 1998/03/05 08:45:13 adam
46 * New result set model and modular ranking system. Moved towards
47 * descent server API. System information stored as "SGML" records.
49 * Revision 1.6 1998/02/17 10:29:27 adam
50 * Moved towards 'automatic' EXPLAIN database.
52 * Revision 1.5 1997/10/27 14:33:05 adam
53 * Moved towards generic character mapping depending on "structure"
54 * field in abstract syntax file. Fixed a few memory leaks. Fixed
55 * bug with negative integers when doing searches with relational
58 * Revision 1.4 1997/09/25 14:57:08 adam
61 * Revision 1.3 1996/05/22 08:21:59 adam
62 * Added public ZebDatabaseInfo structure.
64 * Revision 1.2 1996/05/14 06:16:41 adam
65 * Compact use/set bytes used in search service.
67 * Revision 1.1 1996/05/13 14:23:07 adam
68 * Work on compaction of set/use bytes in dictionary.
89 struct zebSUInfo info;
90 struct zebSUInfoB *next;
93 typedef struct zebAccessObjectB *zebAccessObject;
94 struct zebAccessObjectB {
101 typedef struct zebAccessInfoB *zebAccessInfo;
102 struct zebAccessInfoB {
103 zebAccessObject attributeSetIds;
104 zebAccessObject schemas;
108 struct zebSUInfoB *SUInfo;
112 data1_node *data1_tree;
113 } *zebAttributeDetails;
115 struct zebDatabaseInfoB {
116 zebAttributeDetails attributeDetails;
118 data1_node *data1_database;
119 int recordCount; /* records in db */
120 int recordBytes; /* size of records */
121 int sysno; /* sysno of database info */
122 int readFlag; /* 1: read is needed when referenced; 0 if not */
123 int dirty; /* 1: database is dirty: write is needed */
124 struct zebDatabaseInfoB *next;
125 zebAccessInfo accessInfo;
128 struct zebraExplainAttset {
131 struct zebraExplainAttset *next;
134 struct zebraCategoryListInfo {
137 data1_node *data1_categoryList;
140 struct zebraExplainInfo {
147 struct zebraExplainAttset *attsets;
149 data1_node *data1_target;
150 struct zebraCategoryListInfo *categoryList;
151 struct zebDatabaseInfoB *databaseInfo;
152 struct zebDatabaseInfoB *curDatabaseInfo;
153 zebAccessInfo accessInfo;
154 char date[15]; /* YYYY MMDD HH MM SS */
155 int (*updateFunc)(void *handle, Record drec, data1_node *n);
159 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
160 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
162 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
164 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
167 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
170 logf (LOG_DEBUG, "data1_search_tag %s", tag);
171 for (; n; n = n->next)
172 if (n->which == DATA1N_tag && n->u.tag.tag &&
173 !yaz_matchstr (tag, n->u.tag.tag))
175 logf (LOG_DEBUG, " found");
178 logf (LOG_DEBUG, " not found");
182 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
183 const char *tag, NMEM nmem)
185 data1_node *partag = get_parent_tag(dh, at);
186 data1_node *res = data1_mk_node (dh, nmem);
187 data1_element *e = NULL;
190 res->which = DATA1N_tag;
191 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
192 res->u.tag.node_selected = 0;
193 res->u.tag.make_variantlist = 0;
194 res->u.tag.no_data_requested = 0;
195 res->u.tag.get_bytes = -1;
198 e = partag->u.tag.element;
200 data1_getelementbytagname (dh, at->root->u.root.absyn,
202 res->root = at->root;
207 assert (at->last_child);
208 at->last_child->next = res;
210 at->last_child = res;
214 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
215 const char *tag, NMEM nmem)
217 data1_node *node = data1_search_tag (dh, at->child, tag);
219 node = data1_add_tag (dh, at, tag, nmem);
221 node->child = node->last_child = NULL;
225 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
226 const char *tag, int num,
229 data1_node *node_data;
231 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
234 node_data->u.data.what = DATA1I_num;
235 node_data->u.data.data = node_data->lbuf;
236 sprintf (node_data->u.data.data, "%d", num);
237 node_data->u.data.len = strlen (node_data->u.data.data);
241 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
242 const char *tag, Odr_oid *oid,
245 data1_node *node_data;
246 char str[128], *p = str;
249 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
253 for (ii = oid; *ii >= 0; ii++)
257 sprintf (p, "%d", *ii);
260 node_data->u.data.what = DATA1I_oid;
261 node_data->u.data.len = strlen (str);
262 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
267 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
268 const char *tag, const char *str,
271 data1_node *node_data;
273 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
276 node_data->u.data.what = DATA1I_text;
277 node_data->u.data.len = strlen (str);
278 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
282 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
283 const char *tag, const char *str,
286 data1_node *node = data1_search_tag (dh, at->child, tag);
288 return data1_add_tagdata_text (dh, at, tag, str, nmem);
291 data1_node *node_data = node->child;
292 node_data->u.data.what = DATA1I_text;
293 node_data->u.data.len = strlen (str);
294 node_data->u.data.data = data1_insert_string (dh, node_data,
300 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
301 struct zebDatabaseInfoB *zdi,
303 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
304 zebAttributeDetails zad,
305 const char *databaseName,
307 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
308 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
311 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
312 struct zebraCategoryListInfo *zcl,
316 static Record createRecord (Records records, int *sysno)
321 rec = rec_get (records, *sysno);
322 xfree (rec->info[recInfo_storeData]);
326 rec = rec_new (records);
329 rec->info[recInfo_fileType] =
330 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
331 rec->info[recInfo_databaseName] =
332 rec_strdup ("IR-Explain-1",
333 &rec->size[recInfo_databaseName]);
338 void zebraExplain_flush (ZebraExplainInfo zei, int writeFlag, void *handle)
340 zei->updateHandle = handle;
343 struct zebDatabaseInfoB *zdi;
346 /* write each database info record */
347 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
349 zebraExplain_writeDatabase (zei, zdi, 1);
350 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
351 zdi->databaseName, 1);
353 zebraExplain_writeTarget (zei, 1);
354 zebraExplain_writeCategoryList (zei,
357 assert (zei->accessInfo);
358 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
360 zebraExplain_writeAttributeSet (zei, o, 1);
361 for (o = zei->accessInfo->schemas; o; o = o->next)
364 /* zebraExplain_writeSchema (zei, o, 1); */
367 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
369 zebraExplain_writeDatabase (zei, zdi, 0);
370 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
371 zdi->databaseName, 0);
373 zebraExplain_writeTarget (zei, 0);
377 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag)
380 logf (LOG_LOG, "zebraExplain_close wr=%d", writeFlag);
384 zebraExplain_flush (zei, writeFlag, zei->updateHandle);
385 nmem_destroy (zei->nmem);
388 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
393 for (np = n->child; np; np = np->next)
400 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
402 len = np->child->u.data.len;
405 memcpy (str, np->child->u.data.data, len);
408 oid = odr_getoidbystr_nmem (zei->nmem, str);
410 for (ao = *op; ao; ao = ao->next)
411 if (!oid_oidcmp (oid, ao->oid))
418 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
428 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
429 zebAccessInfo *accessInfo)
435 *accessInfo = (zebAccessInfo)
436 nmem_malloc (zei->nmem, sizeof(**accessInfo));
437 (*accessInfo)->attributeSetIds = NULL;
438 (*accessInfo)->schemas = NULL;
442 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
444 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
445 zebraExplain_mergeOids (zei, np,
446 &(*accessInfo)->attributeSetIds);
447 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
448 zebraExplain_mergeOids (zei, np,
449 &(*accessInfo)->schemas);
453 ZebraExplainInfo zebraExplain_open (
454 Records records, data1_handle dh,
458 int (*updateFunc)(void *handle, Record drec, data1_node *n))
461 ZebraExplainInfo zei;
462 struct zebDatabaseInfoB **zdip;
465 NMEM nmem = nmem_create ();
468 logf (LOG_LOG, "zebraExplain_open wr=%d", writeFlag);
470 zei = (ZebraExplainInfo) nmem_malloc (nmem, sizeof(*zei));
471 zei->updateHandle = updateHandle;
472 zei->updateFunc = updateFunc;
474 zei->curDatabaseInfo = NULL;
475 zei->records = records;
480 zei->categoryList = (struct zebraCategoryListInfo *)
481 nmem_malloc (zei->nmem, sizeof(*zei->categoryList));
482 zei->categoryList->sysno = 0;
483 zei->categoryList->dirty = 0;
484 zei->categoryList->data1_categoryList = NULL;
487 tm = localtime (&our_time);
488 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
489 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
490 tm->tm_hour, tm->tm_min, tm->tm_sec);
492 zdip = &zei->databaseInfo;
493 trec = rec_get (records, 1); /* get "root" record */
495 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
496 if (trec) /* targetInfo already exists ... */
498 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
500 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
501 if (!zei->data1_target)
504 nmem_destroy(zei->nmem);
508 data1_pr_tree (zei->dh, zei->data1_target, stderr);
510 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
512 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
515 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
517 node_list = data1_search_tag (zei->dh, node_zebra->child,
519 for (np = node_list->child; np; np = np->next)
521 data1_node *node_name = NULL;
522 data1_node *node_id = NULL;
523 data1_node *node_aid = NULL;
525 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
527 for (np2 = np->child; np2; np2 = np2->next)
529 if (np2->which != DATA1N_tag)
531 if (!strcmp (np2->u.tag.tag, "name"))
532 node_name = np2->child;
533 else if (!strcmp (np2->u.tag.tag, "id"))
534 node_id = np2->child;
535 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
536 node_aid = np2->child;
538 assert (node_id && node_name && node_aid);
540 *zdip = (struct zebDatabaseInfoB *)
541 nmem_malloc (zei->nmem, sizeof(**zdip));
542 (*zdip)->readFlag = 1;
544 (*zdip)->data1_database = NULL;
545 (*zdip)->recordCount = 0;
546 (*zdip)->recordBytes = 0;
547 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
549 (*zdip)->databaseName = (char *)
550 nmem_malloc (zei->nmem, 1+node_name->u.data.len);
551 memcpy ((*zdip)->databaseName, node_name->u.data.data,
552 node_name->u.data.len);
553 (*zdip)->databaseName[node_name->u.data.len] = '\0';
554 (*zdip)->sysno = atoi_n (node_id->u.data.data,
555 node_id->u.data.len);
556 (*zdip)->attributeDetails = (zebAttributeDetails)
557 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
558 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
559 node_aid->u.data.len);
560 (*zdip)->attributeDetails->readFlag = 1;
561 (*zdip)->attributeDetails->dirty = 0;
562 (*zdip)->attributeDetails->SUInfo = NULL;
564 zdip = &(*zdip)->next;
566 np = data1_search_tag (zei->dh, node_zebra->child,
569 assert (np && np->which == DATA1N_data);
570 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
572 np = data1_search_tag (zei->dh, node_zebra->child,
575 assert (np && np->which == DATA1N_data);
576 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
580 else /* create initial targetInfo */
582 data1_node *node_tgtinfo;
593 data1_read_sgml (zei->dh, zei->nmem,
594 "<explain><targetInfo>TargetInfo\n"
596 "<namedResultSets>1</>\n"
597 "<multipleDBSearch>1</>\n"
598 "<nicknames><name>Zebra</></>\n"
601 if (!zei->data1_target)
603 nmem_destroy (zei->nmem);
606 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
608 assert (node_tgtinfo);
610 zebraExplain_initCommonInfo (zei, node_tgtinfo);
611 zebraExplain_initAccessInfo (zei, node_tgtinfo);
613 /* write now because we want to be sure about the sysno */
614 trec = rec_new (records);
615 trec->info[recInfo_fileType] =
616 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
617 trec->info[recInfo_databaseName] =
618 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
620 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
621 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
622 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
623 trec->size[recInfo_storeData] = sgml_len;
625 rec_put (records, &trec);
629 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
631 if (!zei->categoryList->dirty)
633 struct zebraCategoryListInfo *zcl = zei->categoryList;
637 zcl->data1_categoryList =
638 data1_read_sgml (zei->dh, zei->nmem,
639 "<explain><categoryList>CategoryList\n"
642 if (zcl->data1_categoryList)
644 assert (zcl->data1_categoryList->child);
645 node_cl = data1_search_tag (zei->dh,
646 zcl->data1_categoryList->child,
649 zebraExplain_initCommonInfo (zei, node_cl);
656 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
657 zebAttributeDetails zad)
660 struct zebSUInfoB **zsuip = &zad->SUInfo;
661 data1_node *node_adinfo, *node_zebra, *node_list, *np;
664 rec = rec_get (zei->records, zad->sysno);
666 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
668 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
670 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
672 node_list = data1_search_tag (zei->dh, node_zebra->child,
674 for (np = node_list->child; np; np = np->next)
676 data1_node *node_set = NULL;
677 data1_node *node_use = NULL;
678 data1_node *node_ordinal = NULL;
683 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
685 for (np2 = np->child; np2; np2 = np2->next)
687 if (np2->which != DATA1N_tag || !np2->child ||
688 np2->child->which != DATA1N_data)
690 if (!strcmp (np2->u.tag.tag, "set"))
691 node_set = np2->child;
692 else if (!strcmp (np2->u.tag.tag, "use"))
693 node_use = np2->child;
694 else if (!strcmp (np2->u.tag.tag, "ordinal"))
695 node_ordinal = np2->child;
697 assert (node_set && node_use && node_ordinal);
699 oid_str_len = node_set->u.data.len;
700 if (oid_str_len >= (int) sizeof(oid_str))
701 oid_str_len = sizeof(oid_str)-1;
702 memcpy (oid_str, node_set->u.data.data, oid_str_len);
703 oid_str[oid_str_len] = '\0';
705 *zsuip = (struct zebSUInfoB *)
706 nmem_malloc (zei->nmem, sizeof(**zsuip));
707 (*zsuip)->info.set = oid_getvalbyname (oid_str);
709 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
710 node_use->u.data.len);
711 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
712 node_ordinal->u.data.len);
713 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
714 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
715 zsuip = &(*zsuip)->next;
722 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
723 struct zebDatabaseInfoB *zdi)
726 data1_node *node_dbinfo, *node_zebra, *np;
729 rec = rec_get (zei->records, zdi->sysno);
731 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
733 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
735 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
737 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
740 && (np = data1_search_tag (zei->dh, node_zebra->child,
742 && np->child && np->child->which == DATA1N_data)
743 zdi->recordBytes = atoi_n (np->child->u.data.data,
744 np->child->u.data.len);
745 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
747 (np = data1_search_tag (zei->dh, np->child,
748 "recordCountActual")) &&
749 np->child->which == DATA1N_data)
751 zdi->recordCount = atoi_n (np->child->u.data.data,
752 np->child->u.data.len);
758 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
760 struct zebDatabaseInfoB *zdi;
763 if (zei->curDatabaseInfo &&
764 !strcmp (zei->curDatabaseInfo->databaseName, database))
766 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
768 if (!strcmp (zdi->databaseName, database))
774 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
779 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
781 zebraExplain_readDatabase (zei, zdi);
783 if (zdi->attributeDetails->readFlag)
786 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
788 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
790 zei->curDatabaseInfo = zdi;
794 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
796 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
798 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
799 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
800 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
803 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
805 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
807 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
810 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
812 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
813 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
814 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
817 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
818 zebAccessInfo accessInfo)
820 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
826 if ((p = accessInfo->attributeSetIds))
828 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
829 for (; p; p = p->next)
830 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
832 if ((p = accessInfo->schemas))
834 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
835 for (; p; p = p->next)
836 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
840 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
841 int explain_database)
843 struct zebDatabaseInfoB *zdi;
844 data1_node *node_dbinfo, *node_adinfo;
847 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
850 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
852 if (!strcmp (zdi->databaseName, database))
857 /* it's new really. make it */
858 zdi = (struct zebDatabaseInfoB *) nmem_malloc (zei->nmem, sizeof(*zdi));
859 zdi->next = zei->databaseInfo;
860 zei->databaseInfo = zdi;
862 zdi->recordCount = 0;
863 zdi->recordBytes = 0;
865 zdi->databaseName = nmem_strdup (zei->nmem, database);
867 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
872 zdi->data1_database =
873 data1_read_sgml (zei->dh, zei->nmem,
874 "<explain><databaseInfo>DatabaseInfo\n"
876 if (!zdi->data1_database)
879 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
881 assert (node_dbinfo);
883 zebraExplain_initCommonInfo (zei, node_dbinfo);
884 zebraExplain_initAccessInfo (zei, node_dbinfo);
886 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
887 database, zei->nmem);
889 if (explain_database)
890 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
893 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
896 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
900 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
904 zei->curDatabaseInfo = zdi;
906 zdi->attributeDetails = (zebAttributeDetails)
907 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
908 zdi->attributeDetails->readFlag = 0;
909 zdi->attributeDetails->sysno = 0;
910 zdi->attributeDetails->dirty = 1;
911 zdi->attributeDetails->SUInfo = NULL;
912 zdi->attributeDetails->data1_tree =
913 data1_read_sgml (zei->dh, zei->nmem,
914 "<explain><attributeDetails>AttributeDetails\n"
918 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
920 assert (node_adinfo);
922 zebraExplain_initCommonInfo (zei, node_adinfo);
927 static void writeAttributeValueDetails (ZebraExplainInfo zei,
928 zebAttributeDetails zad,
929 data1_node *node_atvs, data1_attset *attset)
932 struct zebSUInfoB *zsui;
933 int set_ordinal = attset->reference;
934 data1_attset_child *c;
936 for (c = attset->children; c; c = c->next)
937 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
938 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
940 data1_node *node_attvalue, *node_value;
941 if (set_ordinal != zsui->info.set)
943 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
945 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
947 data1_add_tagdata_int (zei->dh, node_value, "numeric",
948 zsui->info.use, zei->nmem);
952 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
953 struct zebraCategoryListInfo *zcl,
960 data1_node *node_ci, *node_categoryList;
962 static char *category[] = {
974 node_categoryList = zcl->data1_categoryList;
977 logf (LOG_LOG, "zebraExplain_writeCategoryList");
980 drec = createRecord (zei->records, &sysno);
982 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
985 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
988 for (i = 0; category[i]; i++)
990 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
991 "category", zei->nmem);
993 data1_add_tagdata_text (zei->dh, node_cat, "name",
994 category[i], zei->nmem);
996 /* extract *searchable* keys from it. We do this here, because
997 record count, etc. is affected */
999 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1001 /* convert to "SGML" and write it */
1003 data1_pr_tree (zei->dh, node_categoryList, stderr);
1005 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1006 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1007 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1008 drec->size[recInfo_storeData] = sgml_len;
1010 rec_put (zei->records, &drec);
1013 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
1014 zebAttributeDetails zad,
1015 const char *databaseName,
1021 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
1022 struct zebSUInfoB *zsui;
1030 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
1033 drec = createRecord (zei->records, &zad->sysno);
1034 assert (zad->data1_tree);
1035 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
1036 "attributeDetails");
1037 zebraExplain_updateCommonInfo (zei, node_adinfo);
1039 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1040 databaseName, zei->nmem);
1042 /* extract *searchable* keys from it. We do this here, because
1043 record count, etc. is affected */
1045 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1047 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1048 "attributesBySet", zei->nmem);
1052 data1_node *node_asd;
1053 data1_attset *attset;
1054 int set_ordinal = -1;
1055 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1057 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1058 && zsui->info.set > set_min)
1059 set_ordinal = zsui->info.set;
1061 if (set_ordinal < 0)
1063 set_min = set_ordinal;
1064 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1065 "attributeSetDetails", zei->nmem);
1067 attset = data1_attset_search_id (zei->dh, set_ordinal);
1070 zebraExplain_loadAttsets (zei->dh, zei->res);
1071 attset = data1_attset_search_id (zei->dh, set_ordinal);
1078 oe.proto = PROTO_Z3950;
1079 oe.oclass = CLASS_ATTSET;
1080 oe.value = (enum oid_value) set_ordinal;
1082 if (oid_ent_to_oid (&oe, oid))
1084 data1_node *node_abt, *node_atd, *node_atvs;
1085 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1088 node_abt = data1_add_tag (zei->dh, node_asd,
1089 "attributesByType", zei->nmem);
1090 node_atd = data1_add_tag (zei->dh, node_abt,
1091 "attributeTypeDetails", zei->nmem);
1092 data1_add_tagdata_int (zei->dh, node_atd,
1093 "type", 1, zei->nmem);
1094 node_atvs = data1_add_tag (zei->dh, node_atd,
1095 "attributeValues", zei->nmem);
1096 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1100 /* zebra info (private) */
1101 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1102 "zebraInfo", zei->nmem);
1103 node_list = data1_make_tag (zei->dh, node_zebra,
1104 "attrlist", zei->nmem);
1105 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1107 struct oident oident;
1109 data1_node *node_attr;
1111 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1113 oident.proto = PROTO_Z3950;
1114 oident.oclass = CLASS_ATTSET;
1115 oident.value = (enum oid_value) zsui->info.set;
1116 oid_ent_to_oid (&oident, oid);
1118 data1_add_tagdata_text (zei->dh, node_attr, "set",
1119 oident.desc, zei->nmem);
1120 data1_add_tagdata_int (zei->dh, node_attr, "use",
1121 zsui->info.use, zei->nmem);
1122 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1123 zsui->info.ordinal, zei->nmem);
1125 /* convert to "SGML" and write it */
1127 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1129 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1131 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1132 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1133 drec->size[recInfo_storeData] = sgml_len;
1135 rec_put (zei->records, &drec);
1138 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1139 struct zebDatabaseInfoB *zdi,
1145 data1_node *node_dbinfo, *node_count, *node_zebra;
1152 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1154 drec = createRecord (zei->records, &zdi->sysno);
1155 assert (zdi->data1_database);
1156 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1159 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1160 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1162 /* extract *searchable* keys from it. We do this here, because
1163 record count, etc. is affected */
1165 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1167 node_count = data1_make_tag (zei->dh, node_dbinfo,
1168 "recordCount", zei->nmem);
1169 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1170 zdi->recordCount, zei->nmem);
1172 /* zebra info (private) */
1173 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1174 "zebraInfo", zei->nmem);
1175 data1_add_tagdata_int (zei->dh, node_zebra,
1176 "recordBytes", zdi->recordBytes, zei->nmem);
1177 /* convert to "SGML" and write it */
1179 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1181 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1183 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1184 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1185 drec->size[recInfo_storeData] = sgml_len;
1187 rec_put (zei->records, &drec);
1190 static void writeAttributeValues (ZebraExplainInfo zei,
1191 data1_node *node_values,
1192 data1_attset *attset)
1195 data1_attset_child *c;
1200 for (c = attset->children; c; c = c->next)
1201 writeAttributeValues (zei, node_values, c->child);
1202 for (atts = attset->atts; atts; atts = atts->next)
1204 data1_node *node_value;
1206 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1208 data1_add_tagdata_text (zei->dh, node_value, "name",
1209 atts->name, zei->nmem);
1210 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1211 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1212 atts->value, zei->nmem);
1217 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1224 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1225 data1_node *node_values;
1226 struct oident *entp;
1227 struct data1_attset *attset = NULL;
1229 if ((entp = oid_getentbyoid (o->oid)))
1230 attset = data1_attset_search_id (zei->dh, entp->value);
1233 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1234 attset ? attset->name : "<unknown>");
1237 drec = createRecord (zei->records, &o->sysno);
1239 data1_read_sgml (zei->dh, zei->nmem,
1240 "<explain><attributeSetInfo>AttributeSetInfo\n"
1243 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1244 "attributeSetInfo");
1246 zebraExplain_initCommonInfo (zei, node_attinfo);
1247 zebraExplain_updateCommonInfo (zei, node_attinfo);
1249 data1_add_tagdata_oid (zei->dh, node_attinfo,
1250 "oid", o->oid, zei->nmem);
1251 if (attset && attset->name)
1252 data1_add_tagdata_text (zei->dh, node_attinfo,
1253 "name", attset->name, zei->nmem);
1255 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1256 "attributes", zei->nmem);
1257 node_atttype = data1_make_tag (zei->dh, node_attributes,
1258 "attributeType", zei->nmem);
1259 data1_add_tagdata_text (zei->dh, node_atttype,
1260 "name", "Use", zei->nmem);
1261 data1_add_tagdata_text (zei->dh, node_atttype,
1262 "description", "Use Attribute", zei->nmem);
1263 data1_add_tagdata_int (zei->dh, node_atttype,
1264 "type", 1, zei->nmem);
1265 node_values = data1_add_tag (zei->dh, node_atttype,
1266 "attributeValues", zei->nmem);
1268 writeAttributeValues (zei, node_values, attset);
1270 /* extract *searchable* keys from it. We do this here, because
1271 record count, etc. is affected */
1273 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1274 /* convert to "SGML" and write it */
1276 data1_pr_tree (zei->dh, node_root, stderr);
1278 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1279 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1280 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1281 drec->size[recInfo_storeData] = sgml_len;
1283 rec_put (zei->records, &drec);
1286 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1288 struct zebDatabaseInfoB *zdi;
1289 data1_node *node_tgtinfo, *node_list, *node_zebra;
1298 trec = rec_get (zei->records, 1);
1299 xfree (trec->info[recInfo_storeData]);
1301 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1303 assert (node_tgtinfo);
1305 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1306 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1308 /* convert to "SGML" and write it */
1310 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1312 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1313 "zebraInfo", zei->nmem);
1314 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1315 ZEBRAVER, zei->nmem);
1316 node_list = data1_add_tag (zei->dh, node_zebra,
1317 "databaseList", zei->nmem);
1318 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1320 data1_node *node_db;
1321 node_db = data1_add_tag (zei->dh, node_list,
1322 "database", zei->nmem);
1323 data1_add_tagdata_text (zei->dh, node_db, "name",
1324 zdi->databaseName, zei->nmem);
1325 data1_add_tagdata_int (zei->dh, node_db, "id",
1326 zdi->sysno, zei->nmem);
1327 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1328 zdi->attributeDetails->sysno, zei->nmem);
1330 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1331 zei->ordinalSU, zei->nmem);
1333 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1334 zei->runNumber, zei->nmem);
1337 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1339 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1341 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1342 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1343 trec->size[recInfo_storeData] = sgml_len;
1345 rec_put (zei->records, &trec);
1348 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1350 struct zebSUInfoB *zsui;
1352 assert (zei->curDatabaseInfo);
1353 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1354 zsui; zsui=zsui->next)
1355 if (zsui->info.use == use && zsui->info.set == set)
1356 return zsui->info.ordinal;
1360 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1361 zebAccessObject *op,
1366 for (ao = *op; ao; ao = ao->next)
1367 if (!oid_oidcmp (oid, ao->oid))
1371 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
1374 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1381 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1386 oe.proto = PROTO_Z3950;
1387 oe.oclass = CLASS_ATTSET;
1388 oe.value = (enum oid_value) set;
1390 if (oid_ent_to_oid (&oe, oid))
1392 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1393 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1394 accessInfo->attributeSetIds, oid);
1398 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1400 struct zebSUInfoB *zsui;
1402 assert (zei->curDatabaseInfo);
1403 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1404 zsui; zsui=zsui->next)
1405 if (zsui->info.use == use && zsui->info.set == set)
1407 zebraExplain_addAttributeSet (zei, set);
1408 zsui = (struct zebSUInfoB *) nmem_malloc (zei->nmem, sizeof(*zsui));
1409 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1410 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1411 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1413 zsui->info.set = set;
1414 zsui->info.use = use;
1415 zsui->info.ordinal = (zei->ordinalSU)++;
1416 return zsui->info.ordinal;
1419 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1421 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1422 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1423 accessInfo->schemas, oid);
1426 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1428 assert (zei->curDatabaseInfo);
1432 zei->curDatabaseInfo->recordBytes += adjust_num;
1433 zei->curDatabaseInfo->dirty = 1;
1437 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1439 assert (zei->curDatabaseInfo);
1443 zei->curDatabaseInfo->recordCount += adjust_num;
1444 zei->curDatabaseInfo->dirty = 1;
1448 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1452 return zei->runNumber += adjust_num;
1455 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1457 RecordAttr *recordAttr;
1459 if (rec->info[recInfo_attr])
1460 return (RecordAttr *) rec->info[recInfo_attr];
1461 recordAttr = (RecordAttr *) xmalloc (sizeof(*recordAttr));
1462 rec->info[recInfo_attr] = (char *) recordAttr;
1463 rec->size[recInfo_attr] = sizeof(*recordAttr);
1465 recordAttr->recordSize = 0;
1466 recordAttr->recordOffset = 0;
1467 recordAttr->runNumber = zei->runNumber;
1471 static void att_loadset(void *p, const char *n, const char *name)
1473 data1_handle dh = (data1_handle) p;
1474 if (!data1_get_attset (dh, name))
1475 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1478 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1480 res_trav(res, "attset", dh, att_loadset);
1484 zebraExplain_addSU adds to AttributeDetails for a database and
1485 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1486 exist for the database.
1488 If the database doesn't exist globally (in TargetInfo) an
1489 AttributeSetInfo must be added (globally).