2 * Copyright (C) 1994-1999, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.19 2000-07-07 12:49:20 adam
8 * Optimized resultSetInsert{Rank,Sort}.
10 * Revision 1.18 2000/03/20 19:08:36 adam
11 * Added remote record import using Z39.50 extended services and Segment
14 * Revision 1.17 1999/07/14 10:53:51 adam
15 * Updated various routines to handle missing explain schema.
17 * Revision 1.16 1999/05/26 07:49:13 adam
20 * Revision 1.15 1999/01/25 13:47:54 adam
23 * Revision 1.14 1998/11/04 16:31:32 adam
24 * Fixed bug regarding recordBytes in databaseInfo.
26 * Revision 1.13 1998/11/03 10:17:09 adam
27 * Fixed bug regarding creation of some data1 nodes for Explain records.
29 * Revision 1.12 1998/10/13 20:37:11 adam
30 * Changed the way attribute sets are saved in Explain database to
31 * reflect "dynamic" OIDs.
33 * Revision 1.11 1998/06/09 12:16:48 adam
34 * Implemented auto-generation of CategoryList records.
36 * Revision 1.10 1998/06/08 14:43:15 adam
37 * Added suport for EXPLAIN Proxy servers - added settings databasePath
38 * and explainDatabase to facilitate this. Increased maximum number
39 * of databases and attributes in one register.
41 * Revision 1.9 1998/06/02 12:10:27 adam
42 * Fixed bug related to attributeDetails.
44 * Revision 1.8 1998/05/20 10:12:20 adam
45 * Implemented automatic EXPLAIN database maintenance.
46 * Modified Zebra to work with ASN.1 compiled version of YAZ.
48 * Revision 1.7 1998/03/05 08:45:13 adam
49 * New result set model and modular ranking system. Moved towards
50 * descent server API. System information stored as "SGML" records.
52 * Revision 1.6 1998/02/17 10:29:27 adam
53 * Moved towards 'automatic' EXPLAIN database.
55 * Revision 1.5 1997/10/27 14:33:05 adam
56 * Moved towards generic character mapping depending on "structure"
57 * field in abstract syntax file. Fixed a few memory leaks. Fixed
58 * bug with negative integers when doing searches with relational
61 * Revision 1.4 1997/09/25 14:57:08 adam
64 * Revision 1.3 1996/05/22 08:21:59 adam
65 * Added public ZebDatabaseInfo structure.
67 * Revision 1.2 1996/05/14 06:16:41 adam
68 * Compact use/set bytes used in search service.
70 * Revision 1.1 1996/05/13 14:23:07 adam
71 * Work on compaction of set/use bytes in dictionary.
92 struct zebSUInfo info;
93 struct zebSUInfoB *next;
96 typedef struct zebAccessObjectB *zebAccessObject;
97 struct zebAccessObjectB {
101 zebAccessObject next;
104 typedef struct zebAccessInfoB *zebAccessInfo;
105 struct zebAccessInfoB {
106 zebAccessObject attributeSetIds;
107 zebAccessObject schemas;
111 struct zebSUInfoB *SUInfo;
115 data1_node *data1_tree;
116 } *zebAttributeDetails;
118 struct zebDatabaseInfoB {
119 zebAttributeDetails attributeDetails;
121 data1_node *data1_database;
122 int recordCount; /* records in db */
123 int recordBytes; /* size of records */
124 int sysno; /* sysno of database info */
125 int readFlag; /* 1: read is needed when referenced; 0 if not */
126 int dirty; /* 1: database is dirty: write is needed */
127 struct zebDatabaseInfoB *next;
128 zebAccessInfo accessInfo;
131 struct zebraExplainAttset {
134 struct zebraExplainAttset *next;
137 struct zebraCategoryListInfo {
140 data1_node *data1_categoryList;
143 struct zebraExplainInfo {
150 struct zebraExplainAttset *attsets;
152 data1_node *data1_target;
153 struct zebraCategoryListInfo *categoryList;
154 struct zebDatabaseInfoB *databaseInfo;
155 struct zebDatabaseInfoB *curDatabaseInfo;
156 zebAccessInfo accessInfo;
157 char date[15]; /* YYYY MMDD HH MM SS */
158 int (*updateFunc)(void *handle, Record drec, data1_node *n);
162 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
163 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
165 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
167 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
170 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
173 logf (LOG_DEBUG, "data1_search_tag %s", tag);
174 for (; n; n = n->next)
175 if (n->which == DATA1N_tag && n->u.tag.tag &&
176 !yaz_matchstr (tag, n->u.tag.tag))
178 logf (LOG_DEBUG, " found");
181 logf (LOG_DEBUG, " not found");
185 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
186 const char *tag, NMEM nmem)
188 data1_node *partag = get_parent_tag(dh, at);
189 data1_node *res = data1_mk_node (dh, nmem);
190 data1_element *e = NULL;
193 res->which = DATA1N_tag;
194 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
195 res->u.tag.node_selected = 0;
196 res->u.tag.make_variantlist = 0;
197 res->u.tag.no_data_requested = 0;
198 res->u.tag.get_bytes = -1;
201 e = partag->u.tag.element;
203 data1_getelementbytagname (dh, at->root->u.root.absyn,
205 res->root = at->root;
210 assert (at->last_child);
211 at->last_child->next = res;
213 at->last_child = res;
217 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
218 const char *tag, NMEM nmem)
220 data1_node *node = data1_search_tag (dh, at->child, tag);
222 node = data1_add_tag (dh, at, tag, nmem);
224 node->child = node->last_child = NULL;
228 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
229 const char *tag, int num,
232 data1_node *node_data;
234 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
237 node_data->u.data.what = DATA1I_num;
238 node_data->u.data.data = node_data->lbuf;
239 sprintf (node_data->u.data.data, "%d", num);
240 node_data->u.data.len = strlen (node_data->u.data.data);
244 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
245 const char *tag, Odr_oid *oid,
248 data1_node *node_data;
249 char str[128], *p = str;
252 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
256 for (ii = oid; *ii >= 0; ii++)
260 sprintf (p, "%d", *ii);
263 node_data->u.data.what = DATA1I_oid;
264 node_data->u.data.len = strlen (str);
265 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
270 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
271 const char *tag, const char *str,
274 data1_node *node_data;
276 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
279 node_data->u.data.what = DATA1I_text;
280 node_data->u.data.len = strlen (str);
281 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
285 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
286 const char *tag, const char *str,
289 data1_node *node = data1_search_tag (dh, at->child, tag);
291 return data1_add_tagdata_text (dh, at, tag, str, nmem);
294 data1_node *node_data = node->child;
295 node_data->u.data.what = DATA1I_text;
296 node_data->u.data.len = strlen (str);
297 node_data->u.data.data = data1_insert_string (dh, node_data,
303 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
304 struct zebDatabaseInfoB *zdi,
306 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
307 zebAttributeDetails zad,
308 const char *databaseName,
310 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
311 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
314 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
315 struct zebraCategoryListInfo *zcl,
319 static Record createRecord (Records records, int *sysno)
324 rec = rec_get (records, *sysno);
325 xfree (rec->info[recInfo_storeData]);
329 rec = rec_new (records);
332 rec->info[recInfo_fileType] =
333 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
334 rec->info[recInfo_databaseName] =
335 rec_strdup ("IR-Explain-1",
336 &rec->size[recInfo_databaseName]);
341 void zebraExplain_flush (ZebraExplainInfo zei, int writeFlag, void *handle)
343 zei->updateHandle = handle;
346 struct zebDatabaseInfoB *zdi;
349 /* write each database info record */
350 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
352 zebraExplain_writeDatabase (zei, zdi, 1);
353 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
354 zdi->databaseName, 1);
356 zebraExplain_writeTarget (zei, 1);
357 zebraExplain_writeCategoryList (zei,
360 assert (zei->accessInfo);
361 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
363 zebraExplain_writeAttributeSet (zei, o, 1);
364 for (o = zei->accessInfo->schemas; o; o = o->next)
367 /* zebraExplain_writeSchema (zei, o, 1); */
370 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
372 zebraExplain_writeDatabase (zei, zdi, 0);
373 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
374 zdi->databaseName, 0);
376 zebraExplain_writeTarget (zei, 0);
380 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag)
383 logf (LOG_LOG, "zebraExplain_close wr=%d", writeFlag);
387 zebraExplain_flush (zei, writeFlag, zei->updateHandle);
388 nmem_destroy (zei->nmem);
391 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
396 for (np = n->child; np; np = np->next)
403 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
405 len = np->child->u.data.len;
408 memcpy (str, np->child->u.data.data, len);
411 oid = odr_getoidbystr_nmem (zei->nmem, str);
413 for (ao = *op; ao; ao = ao->next)
414 if (!oid_oidcmp (oid, ao->oid))
421 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
431 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
432 zebAccessInfo *accessInfo)
438 *accessInfo = (zebAccessInfo)
439 nmem_malloc (zei->nmem, sizeof(**accessInfo));
440 (*accessInfo)->attributeSetIds = NULL;
441 (*accessInfo)->schemas = NULL;
445 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
447 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
448 zebraExplain_mergeOids (zei, np,
449 &(*accessInfo)->attributeSetIds);
450 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
451 zebraExplain_mergeOids (zei, np,
452 &(*accessInfo)->schemas);
456 ZebraExplainInfo zebraExplain_open (
457 Records records, data1_handle dh,
461 int (*updateFunc)(void *handle, Record drec, data1_node *n))
464 ZebraExplainInfo zei;
465 struct zebDatabaseInfoB **zdip;
468 NMEM nmem = nmem_create ();
471 logf (LOG_LOG, "zebraExplain_open wr=%d", writeFlag);
473 zei = (ZebraExplainInfo) nmem_malloc (nmem, sizeof(*zei));
474 zei->updateHandle = updateHandle;
475 zei->updateFunc = updateFunc;
477 zei->curDatabaseInfo = NULL;
478 zei->records = records;
483 zei->categoryList = (struct zebraCategoryListInfo *)
484 nmem_malloc (zei->nmem, sizeof(*zei->categoryList));
485 zei->categoryList->sysno = 0;
486 zei->categoryList->dirty = 0;
487 zei->categoryList->data1_categoryList = NULL;
490 tm = localtime (&our_time);
491 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
492 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
493 tm->tm_hour, tm->tm_min, tm->tm_sec);
495 zdip = &zei->databaseInfo;
496 trec = rec_get (records, 1); /* get "root" record */
501 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
502 if (trec) /* targetInfo already exists ... */
504 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
506 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
507 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
509 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
510 nmem_destroy (zei->nmem);
514 data1_pr_tree (zei->dh, zei->data1_target, stderr);
516 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
518 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
521 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
526 node_list = data1_search_tag (zei->dh, node_zebra->child,
529 np = node_list->child;
531 for (; np; np = np->next)
533 data1_node *node_name = NULL;
534 data1_node *node_id = NULL;
535 data1_node *node_aid = NULL;
537 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
539 for (np2 = np->child; np2; np2 = np2->next)
541 if (np2->which != DATA1N_tag)
543 if (!strcmp (np2->u.tag.tag, "name"))
544 node_name = np2->child;
545 else if (!strcmp (np2->u.tag.tag, "id"))
546 node_id = np2->child;
547 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
548 node_aid = np2->child;
550 assert (node_id && node_name && node_aid);
552 *zdip = (struct zebDatabaseInfoB *)
553 nmem_malloc (zei->nmem, sizeof(**zdip));
554 (*zdip)->readFlag = 1;
556 (*zdip)->data1_database = NULL;
557 (*zdip)->recordCount = 0;
558 (*zdip)->recordBytes = 0;
559 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
561 (*zdip)->databaseName = (char *)
562 nmem_malloc (zei->nmem, 1+node_name->u.data.len);
563 memcpy ((*zdip)->databaseName, node_name->u.data.data,
564 node_name->u.data.len);
565 (*zdip)->databaseName[node_name->u.data.len] = '\0';
566 (*zdip)->sysno = atoi_n (node_id->u.data.data,
567 node_id->u.data.len);
568 (*zdip)->attributeDetails = (zebAttributeDetails)
569 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
570 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
571 node_aid->u.data.len);
572 (*zdip)->attributeDetails->readFlag = 1;
573 (*zdip)->attributeDetails->dirty = 0;
574 (*zdip)->attributeDetails->SUInfo = NULL;
576 zdip = &(*zdip)->next;
580 np = data1_search_tag (zei->dh, node_zebra->child,
583 assert (np && np->which == DATA1N_data);
584 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
586 np = data1_search_tag (zei->dh, node_zebra->child,
589 assert (np && np->which == DATA1N_data);
590 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
595 else /* create initial targetInfo */
597 data1_node *node_tgtinfo;
606 data1_read_sgml (zei->dh, zei->nmem,
607 "<explain><targetInfo>TargetInfo\n"
609 "<namedResultSets>1</>\n"
610 "<multipleDBSearch>1</>\n"
611 "<nicknames><name>Zebra</></>\n"
613 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
615 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
616 nmem_destroy (zei->nmem);
619 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
621 assert (node_tgtinfo);
623 zebraExplain_initCommonInfo (zei, node_tgtinfo);
624 zebraExplain_initAccessInfo (zei, node_tgtinfo);
626 /* write now because we want to be sure about the sysno */
627 trec = rec_new (records);
628 trec->info[recInfo_fileType] =
629 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
630 trec->info[recInfo_databaseName] =
631 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
633 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
634 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
635 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
636 trec->size[recInfo_storeData] = sgml_len;
638 rec_put (records, &trec);
642 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
644 if (!zei->categoryList->dirty)
646 struct zebraCategoryListInfo *zcl = zei->categoryList;
650 zcl->data1_categoryList =
651 data1_read_sgml (zei->dh, zei->nmem,
652 "<explain><categoryList>CategoryList\n"
655 if (zcl->data1_categoryList)
657 assert (zcl->data1_categoryList->child);
658 node_cl = data1_search_tag (zei->dh,
659 zcl->data1_categoryList->child,
662 zebraExplain_initCommonInfo (zei, node_cl);
669 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
670 zebAttributeDetails zad)
673 struct zebSUInfoB **zsuip = &zad->SUInfo;
674 data1_node *node_adinfo, *node_zebra, *node_list, *np;
677 rec = rec_get (zei->records, zad->sysno);
679 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
681 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
683 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
685 node_list = data1_search_tag (zei->dh, node_zebra->child,
687 for (np = node_list->child; np; np = np->next)
689 data1_node *node_set = NULL;
690 data1_node *node_use = NULL;
691 data1_node *node_ordinal = NULL;
696 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
698 for (np2 = np->child; np2; np2 = np2->next)
700 if (np2->which != DATA1N_tag || !np2->child ||
701 np2->child->which != DATA1N_data)
703 if (!strcmp (np2->u.tag.tag, "set"))
704 node_set = np2->child;
705 else if (!strcmp (np2->u.tag.tag, "use"))
706 node_use = np2->child;
707 else if (!strcmp (np2->u.tag.tag, "ordinal"))
708 node_ordinal = np2->child;
710 assert (node_set && node_use && node_ordinal);
712 oid_str_len = node_set->u.data.len;
713 if (oid_str_len >= (int) sizeof(oid_str))
714 oid_str_len = sizeof(oid_str)-1;
715 memcpy (oid_str, node_set->u.data.data, oid_str_len);
716 oid_str[oid_str_len] = '\0';
718 *zsuip = (struct zebSUInfoB *)
719 nmem_malloc (zei->nmem, sizeof(**zsuip));
720 (*zsuip)->info.set = oid_getvalbyname (oid_str);
722 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
723 node_use->u.data.len);
724 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
725 node_ordinal->u.data.len);
726 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
727 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
728 zsuip = &(*zsuip)->next;
735 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
736 struct zebDatabaseInfoB *zdi)
739 data1_node *node_dbinfo, *node_zebra, *np;
742 rec = rec_get (zei->records, zdi->sysno);
744 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
746 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
748 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
750 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
753 && (np = data1_search_tag (zei->dh, node_zebra->child,
755 && np->child && np->child->which == DATA1N_data)
756 zdi->recordBytes = atoi_n (np->child->u.data.data,
757 np->child->u.data.len);
758 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
760 (np = data1_search_tag (zei->dh, np->child,
761 "recordCountActual")) &&
762 np->child->which == DATA1N_data)
764 zdi->recordCount = atoi_n (np->child->u.data.data,
765 np->child->u.data.len);
771 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
773 struct zebDatabaseInfoB *zdi;
776 if (zei->curDatabaseInfo &&
777 !strcmp (zei->curDatabaseInfo->databaseName, database))
779 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
781 if (!strcmp (zdi->databaseName, database))
787 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
792 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
794 zebraExplain_readDatabase (zei, zdi);
796 if (zdi->attributeDetails->readFlag)
799 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
801 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
803 zei->curDatabaseInfo = zdi;
807 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
809 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
811 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
812 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
813 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
816 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
818 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
820 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
823 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
825 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
826 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
827 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
830 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
831 zebAccessInfo accessInfo)
833 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
839 if ((p = accessInfo->attributeSetIds))
841 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
842 for (; p; p = p->next)
843 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
845 if ((p = accessInfo->schemas))
847 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
848 for (; p; p = p->next)
849 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
853 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
854 int explain_database)
856 struct zebDatabaseInfoB *zdi;
857 data1_node *node_dbinfo, *node_adinfo;
860 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
863 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
865 if (!strcmp (zdi->databaseName, database))
870 /* it's new really. make it */
871 zdi = (struct zebDatabaseInfoB *) nmem_malloc (zei->nmem, sizeof(*zdi));
872 zdi->next = zei->databaseInfo;
873 zei->databaseInfo = zdi;
875 zdi->recordCount = 0;
876 zdi->recordBytes = 0;
878 zdi->databaseName = nmem_strdup (zei->nmem, database);
880 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
885 zdi->data1_database =
886 data1_read_sgml (zei->dh, zei->nmem,
887 "<explain><databaseInfo>DatabaseInfo\n"
889 if (!zdi->data1_database)
892 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
894 assert (node_dbinfo);
896 zebraExplain_initCommonInfo (zei, node_dbinfo);
897 zebraExplain_initAccessInfo (zei, node_dbinfo);
899 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
900 database, zei->nmem);
902 if (explain_database)
903 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
906 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
909 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
913 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
917 zei->curDatabaseInfo = zdi;
919 zdi->attributeDetails = (zebAttributeDetails)
920 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
921 zdi->attributeDetails->readFlag = 0;
922 zdi->attributeDetails->sysno = 0;
923 zdi->attributeDetails->dirty = 1;
924 zdi->attributeDetails->SUInfo = NULL;
925 zdi->attributeDetails->data1_tree =
926 data1_read_sgml (zei->dh, zei->nmem,
927 "<explain><attributeDetails>AttributeDetails\n"
931 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
933 assert (node_adinfo);
935 zebraExplain_initCommonInfo (zei, node_adinfo);
940 static void writeAttributeValueDetails (ZebraExplainInfo zei,
941 zebAttributeDetails zad,
942 data1_node *node_atvs, data1_attset *attset)
945 struct zebSUInfoB *zsui;
946 int set_ordinal = attset->reference;
947 data1_attset_child *c;
949 for (c = attset->children; c; c = c->next)
950 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
951 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
953 data1_node *node_attvalue, *node_value;
954 if (set_ordinal != zsui->info.set)
956 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
958 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
960 data1_add_tagdata_int (zei->dh, node_value, "numeric",
961 zsui->info.use, zei->nmem);
965 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
966 struct zebraCategoryListInfo *zcl,
973 data1_node *node_ci, *node_categoryList;
975 static char *category[] = {
987 node_categoryList = zcl->data1_categoryList;
990 logf (LOG_LOG, "zebraExplain_writeCategoryList");
993 drec = createRecord (zei->records, &sysno);
995 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
998 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
1001 for (i = 0; category[i]; i++)
1003 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
1004 "category", zei->nmem);
1006 data1_add_tagdata_text (zei->dh, node_cat, "name",
1007 category[i], zei->nmem);
1009 /* extract *searchable* keys from it. We do this here, because
1010 record count, etc. is affected */
1012 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1014 /* convert to "SGML" and write it */
1016 data1_pr_tree (zei->dh, node_categoryList, stderr);
1018 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1019 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1020 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1021 drec->size[recInfo_storeData] = sgml_len;
1023 rec_put (zei->records, &drec);
1026 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
1027 zebAttributeDetails zad,
1028 const char *databaseName,
1034 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
1035 struct zebSUInfoB *zsui;
1043 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
1046 drec = createRecord (zei->records, &zad->sysno);
1047 assert (zad->data1_tree);
1048 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
1049 "attributeDetails");
1050 zebraExplain_updateCommonInfo (zei, node_adinfo);
1052 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1053 databaseName, zei->nmem);
1055 /* extract *searchable* keys from it. We do this here, because
1056 record count, etc. is affected */
1058 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1060 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1061 "attributesBySet", zei->nmem);
1065 data1_node *node_asd;
1066 data1_attset *attset;
1067 int set_ordinal = -1;
1068 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1070 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1071 && zsui->info.set > set_min)
1072 set_ordinal = zsui->info.set;
1074 if (set_ordinal < 0)
1076 set_min = set_ordinal;
1077 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1078 "attributeSetDetails", zei->nmem);
1080 attset = data1_attset_search_id (zei->dh, set_ordinal);
1083 zebraExplain_loadAttsets (zei->dh, zei->res);
1084 attset = data1_attset_search_id (zei->dh, set_ordinal);
1091 oe.proto = PROTO_Z3950;
1092 oe.oclass = CLASS_ATTSET;
1093 oe.value = (enum oid_value) set_ordinal;
1095 if (oid_ent_to_oid (&oe, oid))
1097 data1_node *node_abt, *node_atd, *node_atvs;
1098 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1101 node_abt = data1_add_tag (zei->dh, node_asd,
1102 "attributesByType", zei->nmem);
1103 node_atd = data1_add_tag (zei->dh, node_abt,
1104 "attributeTypeDetails", zei->nmem);
1105 data1_add_tagdata_int (zei->dh, node_atd,
1106 "type", 1, zei->nmem);
1107 node_atvs = data1_add_tag (zei->dh, node_atd,
1108 "attributeValues", zei->nmem);
1109 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1113 /* zebra info (private) */
1114 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1115 "zebraInfo", zei->nmem);
1116 node_list = data1_make_tag (zei->dh, node_zebra,
1117 "attrlist", zei->nmem);
1118 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1120 struct oident oident;
1122 data1_node *node_attr;
1124 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1126 oident.proto = PROTO_Z3950;
1127 oident.oclass = CLASS_ATTSET;
1128 oident.value = (enum oid_value) zsui->info.set;
1129 oid_ent_to_oid (&oident, oid);
1131 data1_add_tagdata_text (zei->dh, node_attr, "set",
1132 oident.desc, zei->nmem);
1133 data1_add_tagdata_int (zei->dh, node_attr, "use",
1134 zsui->info.use, zei->nmem);
1135 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1136 zsui->info.ordinal, zei->nmem);
1138 /* convert to "SGML" and write it */
1140 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1142 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1144 drec->info[recInfo_storeData] = (char *) 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 zebraExplain_writeDatabase (ZebraExplainInfo zei,
1152 struct zebDatabaseInfoB *zdi,
1158 data1_node *node_dbinfo, *node_count, *node_zebra;
1165 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1167 drec = createRecord (zei->records, &zdi->sysno);
1168 assert (zdi->data1_database);
1169 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1172 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1173 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1175 /* extract *searchable* keys from it. We do this here, because
1176 record count, etc. is affected */
1178 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1180 node_count = data1_make_tag (zei->dh, node_dbinfo,
1181 "recordCount", zei->nmem);
1182 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1183 zdi->recordCount, zei->nmem);
1185 /* zebra info (private) */
1186 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1187 "zebraInfo", zei->nmem);
1188 data1_add_tagdata_int (zei->dh, node_zebra,
1189 "recordBytes", zdi->recordBytes, zei->nmem);
1190 /* convert to "SGML" and write it */
1192 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1194 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1196 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1197 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1198 drec->size[recInfo_storeData] = sgml_len;
1200 rec_put (zei->records, &drec);
1203 static void writeAttributeValues (ZebraExplainInfo zei,
1204 data1_node *node_values,
1205 data1_attset *attset)
1208 data1_attset_child *c;
1213 for (c = attset->children; c; c = c->next)
1214 writeAttributeValues (zei, node_values, c->child);
1215 for (atts = attset->atts; atts; atts = atts->next)
1217 data1_node *node_value;
1219 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1221 data1_add_tagdata_text (zei->dh, node_value, "name",
1222 atts->name, zei->nmem);
1223 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1224 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1225 atts->value, zei->nmem);
1230 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1237 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1238 data1_node *node_values;
1239 struct oident *entp;
1240 struct data1_attset *attset = NULL;
1242 if ((entp = oid_getentbyoid (o->oid)))
1243 attset = data1_attset_search_id (zei->dh, entp->value);
1246 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1247 attset ? attset->name : "<unknown>");
1250 drec = createRecord (zei->records, &o->sysno);
1252 data1_read_sgml (zei->dh, zei->nmem,
1253 "<explain><attributeSetInfo>AttributeSetInfo\n"
1256 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1257 "attributeSetInfo");
1259 zebraExplain_initCommonInfo (zei, node_attinfo);
1260 zebraExplain_updateCommonInfo (zei, node_attinfo);
1262 data1_add_tagdata_oid (zei->dh, node_attinfo,
1263 "oid", o->oid, zei->nmem);
1264 if (attset && attset->name)
1265 data1_add_tagdata_text (zei->dh, node_attinfo,
1266 "name", attset->name, zei->nmem);
1268 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1269 "attributes", zei->nmem);
1270 node_atttype = data1_make_tag (zei->dh, node_attributes,
1271 "attributeType", zei->nmem);
1272 data1_add_tagdata_text (zei->dh, node_atttype,
1273 "name", "Use", zei->nmem);
1274 data1_add_tagdata_text (zei->dh, node_atttype,
1275 "description", "Use Attribute", zei->nmem);
1276 data1_add_tagdata_int (zei->dh, node_atttype,
1277 "type", 1, zei->nmem);
1278 node_values = data1_add_tag (zei->dh, node_atttype,
1279 "attributeValues", zei->nmem);
1281 writeAttributeValues (zei, node_values, attset);
1283 /* extract *searchable* keys from it. We do this here, because
1284 record count, etc. is affected */
1286 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1287 /* convert to "SGML" and write it */
1289 data1_pr_tree (zei->dh, node_root, stderr);
1291 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1292 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1293 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1294 drec->size[recInfo_storeData] = sgml_len;
1296 rec_put (zei->records, &drec);
1299 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1301 struct zebDatabaseInfoB *zdi;
1302 data1_node *node_tgtinfo, *node_list, *node_zebra;
1311 trec = rec_get (zei->records, 1);
1312 xfree (trec->info[recInfo_storeData]);
1314 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1316 assert (node_tgtinfo);
1318 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1319 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1321 /* convert to "SGML" and write it */
1323 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1325 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1326 "zebraInfo", zei->nmem);
1327 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1328 ZEBRAVER, zei->nmem);
1329 node_list = data1_add_tag (zei->dh, node_zebra,
1330 "databaseList", zei->nmem);
1331 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1333 data1_node *node_db;
1334 node_db = data1_add_tag (zei->dh, node_list,
1335 "database", zei->nmem);
1336 data1_add_tagdata_text (zei->dh, node_db, "name",
1337 zdi->databaseName, zei->nmem);
1338 data1_add_tagdata_int (zei->dh, node_db, "id",
1339 zdi->sysno, zei->nmem);
1340 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1341 zdi->attributeDetails->sysno, zei->nmem);
1343 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1344 zei->ordinalSU, zei->nmem);
1346 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1347 zei->runNumber, zei->nmem);
1350 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1352 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1354 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1355 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1356 trec->size[recInfo_storeData] = sgml_len;
1358 rec_put (zei->records, &trec);
1361 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1363 struct zebSUInfoB *zsui;
1365 assert (zei->curDatabaseInfo);
1366 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1367 zsui; zsui=zsui->next)
1368 if (zsui->info.use == use && zsui->info.set == set)
1369 return zsui->info.ordinal;
1373 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1374 zebAccessObject *op,
1379 for (ao = *op; ao; ao = ao->next)
1380 if (!oid_oidcmp (oid, ao->oid))
1384 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
1387 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1394 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1399 oe.proto = PROTO_Z3950;
1400 oe.oclass = CLASS_ATTSET;
1401 oe.value = (enum oid_value) set;
1403 if (oid_ent_to_oid (&oe, oid))
1405 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1406 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1407 accessInfo->attributeSetIds, oid);
1411 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1413 struct zebSUInfoB *zsui;
1415 assert (zei->curDatabaseInfo);
1416 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1417 zsui; zsui=zsui->next)
1418 if (zsui->info.use == use && zsui->info.set == set)
1420 zebraExplain_addAttributeSet (zei, set);
1421 zsui = (struct zebSUInfoB *) nmem_malloc (zei->nmem, sizeof(*zsui));
1422 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1423 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1424 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1426 zsui->info.set = set;
1427 zsui->info.use = use;
1428 zsui->info.ordinal = (zei->ordinalSU)++;
1429 return zsui->info.ordinal;
1432 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1434 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1435 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1436 accessInfo->schemas, oid);
1439 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1441 assert (zei->curDatabaseInfo);
1445 zei->curDatabaseInfo->recordBytes += adjust_num;
1446 zei->curDatabaseInfo->dirty = 1;
1450 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1452 assert (zei->curDatabaseInfo);
1456 zei->curDatabaseInfo->recordCount += adjust_num;
1457 zei->curDatabaseInfo->dirty = 1;
1461 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1465 return zei->runNumber += adjust_num;
1468 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1470 RecordAttr *recordAttr;
1472 if (rec->info[recInfo_attr])
1473 return (RecordAttr *) rec->info[recInfo_attr];
1474 recordAttr = (RecordAttr *) xmalloc (sizeof(*recordAttr));
1475 rec->info[recInfo_attr] = (char *) recordAttr;
1476 rec->size[recInfo_attr] = sizeof(*recordAttr);
1478 recordAttr->recordSize = 0;
1479 recordAttr->recordOffset = 0;
1480 recordAttr->runNumber = zei->runNumber;
1484 static void att_loadset(void *p, const char *n, const char *name)
1486 data1_handle dh = (data1_handle) p;
1487 if (!data1_get_attset (dh, name))
1488 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1491 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1493 res_trav(res, "attset", dh, att_loadset);
1497 zebraExplain_addSU adds to AttributeDetails for a database and
1498 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1499 exist for the database.
1501 If the database doesn't exist globally (in TargetInfo) an
1502 AttributeSetInfo must be added (globally).