2 * Copyright (C) 1994-2000, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.21 2000-12-05 10:01:44 adam
8 * Fixed bug regarding user-defined attribute sets.
10 * Revision 1.20 2000/11/29 14:24:01 adam
11 * Script configure uses yaz pthreads options. Added locking for
12 * zebra_register_{lock,unlock}.
14 * Revision 1.19 2000/07/07 12:49:20 adam
15 * Optimized resultSetInsert{Rank,Sort}.
17 * Revision 1.18 2000/03/20 19:08:36 adam
18 * Added remote record import using Z39.50 extended services and Segment
21 * Revision 1.17 1999/07/14 10:53:51 adam
22 * Updated various routines to handle missing explain schema.
24 * Revision 1.16 1999/05/26 07:49:13 adam
27 * Revision 1.15 1999/01/25 13:47:54 adam
30 * Revision 1.14 1998/11/04 16:31:32 adam
31 * Fixed bug regarding recordBytes in databaseInfo.
33 * Revision 1.13 1998/11/03 10:17:09 adam
34 * Fixed bug regarding creation of some data1 nodes for Explain records.
36 * Revision 1.12 1998/10/13 20:37:11 adam
37 * Changed the way attribute sets are saved in Explain database to
38 * reflect "dynamic" OIDs.
40 * Revision 1.11 1998/06/09 12:16:48 adam
41 * Implemented auto-generation of CategoryList records.
43 * Revision 1.10 1998/06/08 14:43:15 adam
44 * Added suport for EXPLAIN Proxy servers - added settings databasePath
45 * and explainDatabase to facilitate this. Increased maximum number
46 * of databases and attributes in one register.
48 * Revision 1.9 1998/06/02 12:10:27 adam
49 * Fixed bug related to attributeDetails.
51 * Revision 1.8 1998/05/20 10:12:20 adam
52 * Implemented automatic EXPLAIN database maintenance.
53 * Modified Zebra to work with ASN.1 compiled version of YAZ.
55 * Revision 1.7 1998/03/05 08:45:13 adam
56 * New result set model and modular ranking system. Moved towards
57 * descent server API. System information stored as "SGML" records.
59 * Revision 1.6 1998/02/17 10:29:27 adam
60 * Moved towards 'automatic' EXPLAIN database.
62 * Revision 1.5 1997/10/27 14:33:05 adam
63 * Moved towards generic character mapping depending on "structure"
64 * field in abstract syntax file. Fixed a few memory leaks. Fixed
65 * bug with negative integers when doing searches with relational
68 * Revision 1.4 1997/09/25 14:57:08 adam
71 * Revision 1.3 1996/05/22 08:21:59 adam
72 * Added public ZebDatabaseInfo structure.
74 * Revision 1.2 1996/05/14 06:16:41 adam
75 * Compact use/set bytes used in search service.
77 * Revision 1.1 1996/05/13 14:23:07 adam
78 * Work on compaction of set/use bytes in dictionary.
99 struct zebSUInfo info;
100 struct zebSUInfoB *next;
103 typedef struct zebAccessObjectB *zebAccessObject;
104 struct zebAccessObjectB {
108 zebAccessObject next;
111 typedef struct zebAccessInfoB *zebAccessInfo;
112 struct zebAccessInfoB {
113 zebAccessObject attributeSetIds;
114 zebAccessObject schemas;
118 struct zebSUInfoB *SUInfo;
122 data1_node *data1_tree;
123 } *zebAttributeDetails;
125 struct zebDatabaseInfoB {
126 zebAttributeDetails attributeDetails;
128 data1_node *data1_database;
129 int recordCount; /* records in db */
130 int recordBytes; /* size of records */
131 int sysno; /* sysno of database info */
132 int readFlag; /* 1: read is needed when referenced; 0 if not */
133 int dirty; /* 1: database is dirty: write is needed */
134 struct zebDatabaseInfoB *next;
135 zebAccessInfo accessInfo;
138 struct zebraExplainAttset {
141 struct zebraExplainAttset *next;
144 struct zebraCategoryListInfo {
147 data1_node *data1_categoryList;
150 struct zebraExplainInfo {
157 struct zebraExplainAttset *attsets;
159 data1_node *data1_target;
160 struct zebraCategoryListInfo *categoryList;
161 struct zebDatabaseInfoB *databaseInfo;
162 struct zebDatabaseInfoB *curDatabaseInfo;
163 zebAccessInfo accessInfo;
164 char date[15]; /* YYYY MMDD HH MM SS */
165 int (*updateFunc)(void *handle, Record drec, data1_node *n);
169 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
170 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
172 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
174 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
177 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
180 logf (LOG_DEBUG, "data1_search_tag %s", tag);
181 for (; n; n = n->next)
182 if (n->which == DATA1N_tag && n->u.tag.tag &&
183 !yaz_matchstr (tag, n->u.tag.tag))
185 logf (LOG_DEBUG, " found");
188 logf (LOG_DEBUG, " not found");
192 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
193 const char *tag, NMEM nmem)
195 data1_node *partag = get_parent_tag(dh, at);
196 data1_node *res = data1_mk_node_type (dh, nmem, DATA1N_tag);
197 data1_element *e = NULL;
200 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
203 e = partag->u.tag.element;
205 data1_getelementbytagname (dh, at->root->u.root.absyn,
207 res->root = at->root;
212 assert (at->last_child);
213 at->last_child->next = res;
215 at->last_child = res;
219 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
220 const char *tag, NMEM nmem)
222 data1_node *node = data1_search_tag (dh, at->child, tag);
224 node = data1_add_tag (dh, at, tag, nmem);
226 node->child = node->last_child = NULL;
230 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
231 const char *tag, int num,
234 data1_node *node_data;
236 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
239 node_data->u.data.what = DATA1I_num;
240 node_data->u.data.data = node_data->lbuf;
241 sprintf (node_data->u.data.data, "%d", num);
242 node_data->u.data.len = strlen (node_data->u.data.data);
246 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
247 const char *tag, Odr_oid *oid,
250 data1_node *node_data;
251 char str[128], *p = str;
254 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
258 for (ii = oid; *ii >= 0; ii++)
262 sprintf (p, "%d", *ii);
265 node_data->u.data.what = DATA1I_oid;
266 node_data->u.data.len = strlen (str);
267 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
272 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
273 const char *tag, const char *str,
276 data1_node *node_data;
278 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
281 node_data->u.data.what = DATA1I_text;
282 node_data->u.data.len = strlen (str);
283 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
287 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
288 const char *tag, const char *str,
291 data1_node *node = data1_search_tag (dh, at->child, tag);
293 return data1_add_tagdata_text (dh, at, tag, str, nmem);
296 data1_node *node_data = node->child;
297 node_data->u.data.what = DATA1I_text;
298 node_data->u.data.len = strlen (str);
299 node_data->u.data.data = data1_insert_string (dh, node_data,
305 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
306 struct zebDatabaseInfoB *zdi,
308 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
309 zebAttributeDetails zad,
310 const char *databaseName,
312 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
313 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
316 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
317 struct zebraCategoryListInfo *zcl,
321 static Record createRecord (Records records, int *sysno)
326 rec = rec_get (records, *sysno);
327 xfree (rec->info[recInfo_storeData]);
331 rec = rec_new (records);
334 rec->info[recInfo_fileType] =
335 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
336 rec->info[recInfo_databaseName] =
337 rec_strdup ("IR-Explain-1",
338 &rec->size[recInfo_databaseName]);
343 void zebraExplain_flush (ZebraExplainInfo zei, int writeFlag, void *handle)
345 zei->updateHandle = handle;
348 struct zebDatabaseInfoB *zdi;
351 /* write each database info record */
352 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
354 zebraExplain_writeDatabase (zei, zdi, 1);
355 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
356 zdi->databaseName, 1);
358 zebraExplain_writeTarget (zei, 1);
359 zebraExplain_writeCategoryList (zei,
362 assert (zei->accessInfo);
363 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
365 zebraExplain_writeAttributeSet (zei, o, 1);
366 for (o = zei->accessInfo->schemas; o; o = o->next)
369 /* zebraExplain_writeSchema (zei, o, 1); */
372 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
374 zebraExplain_writeDatabase (zei, zdi, 0);
375 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
376 zdi->databaseName, 0);
378 zebraExplain_writeTarget (zei, 0);
382 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag)
385 logf (LOG_LOG, "zebraExplain_close wr=%d", writeFlag);
389 zebraExplain_flush (zei, writeFlag, zei->updateHandle);
390 nmem_destroy (zei->nmem);
393 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
398 for (np = n->child; np; np = np->next)
405 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
407 len = np->child->u.data.len;
410 memcpy (str, np->child->u.data.data, len);
413 oid = odr_getoidbystr_nmem (zei->nmem, str);
415 for (ao = *op; ao; ao = ao->next)
416 if (!oid_oidcmp (oid, ao->oid))
423 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
433 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
434 zebAccessInfo *accessInfo)
440 *accessInfo = (zebAccessInfo)
441 nmem_malloc (zei->nmem, sizeof(**accessInfo));
442 (*accessInfo)->attributeSetIds = NULL;
443 (*accessInfo)->schemas = NULL;
447 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
449 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
450 zebraExplain_mergeOids (zei, np,
451 &(*accessInfo)->attributeSetIds);
452 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
453 zebraExplain_mergeOids (zei, np,
454 &(*accessInfo)->schemas);
458 ZebraExplainInfo zebraExplain_open (
459 Records records, data1_handle dh,
463 int (*updateFunc)(void *handle, Record drec, data1_node *n))
466 ZebraExplainInfo zei;
467 struct zebDatabaseInfoB **zdip;
470 NMEM nmem = nmem_create ();
473 logf (LOG_LOG, "zebraExplain_open wr=%d", writeFlag);
475 zei = (ZebraExplainInfo) nmem_malloc (nmem, sizeof(*zei));
476 zei->updateHandle = updateHandle;
477 zei->updateFunc = updateFunc;
479 zei->curDatabaseInfo = NULL;
480 zei->records = records;
485 zei->categoryList = (struct zebraCategoryListInfo *)
486 nmem_malloc (zei->nmem, sizeof(*zei->categoryList));
487 zei->categoryList->sysno = 0;
488 zei->categoryList->dirty = 0;
489 zei->categoryList->data1_categoryList = NULL;
492 tm = localtime (&our_time);
493 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
494 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
495 tm->tm_hour, tm->tm_min, tm->tm_sec);
497 zdip = &zei->databaseInfo;
498 trec = rec_get (records, 1); /* get "root" record */
503 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
504 if (trec) /* targetInfo already exists ... */
506 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
508 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
509 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
511 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
512 nmem_destroy (zei->nmem);
516 data1_pr_tree (zei->dh, zei->data1_target, stderr);
518 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
520 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
523 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
528 node_list = data1_search_tag (zei->dh, node_zebra->child,
531 np = node_list->child;
533 for (; np; np = np->next)
535 data1_node *node_name = NULL;
536 data1_node *node_id = NULL;
537 data1_node *node_aid = NULL;
539 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
541 for (np2 = np->child; np2; np2 = np2->next)
543 if (np2->which != DATA1N_tag)
545 if (!strcmp (np2->u.tag.tag, "name"))
546 node_name = np2->child;
547 else if (!strcmp (np2->u.tag.tag, "id"))
548 node_id = np2->child;
549 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
550 node_aid = np2->child;
552 assert (node_id && node_name && node_aid);
554 *zdip = (struct zebDatabaseInfoB *)
555 nmem_malloc (zei->nmem, sizeof(**zdip));
556 (*zdip)->readFlag = 1;
558 (*zdip)->data1_database = NULL;
559 (*zdip)->recordCount = 0;
560 (*zdip)->recordBytes = 0;
561 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
563 (*zdip)->databaseName = (char *)
564 nmem_malloc (zei->nmem, 1+node_name->u.data.len);
565 memcpy ((*zdip)->databaseName, node_name->u.data.data,
566 node_name->u.data.len);
567 (*zdip)->databaseName[node_name->u.data.len] = '\0';
568 (*zdip)->sysno = atoi_n (node_id->u.data.data,
569 node_id->u.data.len);
570 (*zdip)->attributeDetails = (zebAttributeDetails)
571 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
572 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
573 node_aid->u.data.len);
574 (*zdip)->attributeDetails->readFlag = 1;
575 (*zdip)->attributeDetails->dirty = 0;
576 (*zdip)->attributeDetails->SUInfo = NULL;
578 zdip = &(*zdip)->next;
582 np = data1_search_tag (zei->dh, node_zebra->child,
585 assert (np && np->which == DATA1N_data);
586 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
588 np = data1_search_tag (zei->dh, node_zebra->child,
591 assert (np && np->which == DATA1N_data);
592 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
597 else /* create initial targetInfo */
599 data1_node *node_tgtinfo;
608 data1_read_sgml (zei->dh, zei->nmem,
609 "<explain><targetInfo>TargetInfo\n"
611 "<namedResultSets>1</>\n"
612 "<multipleDBSearch>1</>\n"
613 "<nicknames><name>Zebra</></>\n"
615 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
617 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
618 nmem_destroy (zei->nmem);
621 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
623 assert (node_tgtinfo);
625 zebraExplain_initCommonInfo (zei, node_tgtinfo);
626 zebraExplain_initAccessInfo (zei, node_tgtinfo);
628 /* write now because we want to be sure about the sysno */
629 trec = rec_new (records);
630 trec->info[recInfo_fileType] =
631 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
632 trec->info[recInfo_databaseName] =
633 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
635 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
636 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
637 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
638 trec->size[recInfo_storeData] = sgml_len;
640 rec_put (records, &trec);
644 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
646 if (!zei->categoryList->dirty)
648 struct zebraCategoryListInfo *zcl = zei->categoryList;
652 zcl->data1_categoryList =
653 data1_read_sgml (zei->dh, zei->nmem,
654 "<explain><categoryList>CategoryList\n"
657 if (zcl->data1_categoryList)
659 assert (zcl->data1_categoryList->child);
660 node_cl = data1_search_tag (zei->dh,
661 zcl->data1_categoryList->child,
664 zebraExplain_initCommonInfo (zei, node_cl);
671 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
672 zebAttributeDetails zad)
675 struct zebSUInfoB **zsuip = &zad->SUInfo;
676 data1_node *node_adinfo, *node_zebra, *node_list, *np;
679 rec = rec_get (zei->records, zad->sysno);
681 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
683 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
685 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
687 node_list = data1_search_tag (zei->dh, node_zebra->child,
689 for (np = node_list->child; np; np = np->next)
691 data1_node *node_set = NULL;
692 data1_node *node_use = NULL;
693 data1_node *node_ordinal = NULL;
698 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
700 for (np2 = np->child; np2; np2 = np2->next)
702 if (np2->which != DATA1N_tag || !np2->child ||
703 np2->child->which != DATA1N_data)
705 if (!strcmp (np2->u.tag.tag, "set"))
706 node_set = np2->child;
707 else if (!strcmp (np2->u.tag.tag, "use"))
708 node_use = np2->child;
709 else if (!strcmp (np2->u.tag.tag, "ordinal"))
710 node_ordinal = np2->child;
712 assert (node_set && node_use && node_ordinal);
714 oid_str_len = node_set->u.data.len;
715 if (oid_str_len >= (int) sizeof(oid_str))
716 oid_str_len = sizeof(oid_str)-1;
717 memcpy (oid_str, node_set->u.data.data, oid_str_len);
718 oid_str[oid_str_len] = '\0';
720 *zsuip = (struct zebSUInfoB *)
721 nmem_malloc (zei->nmem, sizeof(**zsuip));
722 (*zsuip)->info.set = oid_getvalbyname (oid_str);
724 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
725 node_use->u.data.len);
726 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
727 node_ordinal->u.data.len);
728 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
729 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
730 zsuip = &(*zsuip)->next;
737 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
738 struct zebDatabaseInfoB *zdi)
741 data1_node *node_dbinfo, *node_zebra, *np;
744 rec = rec_get (zei->records, zdi->sysno);
746 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
748 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
750 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
752 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
755 && (np = data1_search_tag (zei->dh, node_zebra->child,
757 && np->child && np->child->which == DATA1N_data)
758 zdi->recordBytes = atoi_n (np->child->u.data.data,
759 np->child->u.data.len);
760 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
762 (np = data1_search_tag (zei->dh, np->child,
763 "recordCountActual")) &&
764 np->child->which == DATA1N_data)
766 zdi->recordCount = atoi_n (np->child->u.data.data,
767 np->child->u.data.len);
773 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
775 struct zebDatabaseInfoB *zdi;
778 if (zei->curDatabaseInfo &&
779 !strcmp (zei->curDatabaseInfo->databaseName, database))
781 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
783 if (!strcmp (zdi->databaseName, database))
789 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
794 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
796 zebraExplain_readDatabase (zei, zdi);
798 if (zdi->attributeDetails->readFlag)
801 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
803 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
805 zei->curDatabaseInfo = zdi;
809 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
811 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
813 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
814 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
815 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
818 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
820 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
822 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
825 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
827 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
828 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
829 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
832 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
833 zebAccessInfo accessInfo)
835 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
841 if ((p = accessInfo->attributeSetIds))
843 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
844 for (; p; p = p->next)
845 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
847 if ((p = accessInfo->schemas))
849 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
850 for (; p; p = p->next)
851 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
855 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
856 int explain_database)
858 struct zebDatabaseInfoB *zdi;
859 data1_node *node_dbinfo, *node_adinfo;
862 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
865 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
867 if (!strcmp (zdi->databaseName, database))
872 /* it's new really. make it */
873 zdi = (struct zebDatabaseInfoB *) nmem_malloc (zei->nmem, sizeof(*zdi));
874 zdi->next = zei->databaseInfo;
875 zei->databaseInfo = zdi;
877 zdi->recordCount = 0;
878 zdi->recordBytes = 0;
880 zdi->databaseName = nmem_strdup (zei->nmem, database);
882 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
887 zdi->data1_database =
888 data1_read_sgml (zei->dh, zei->nmem,
889 "<explain><databaseInfo>DatabaseInfo\n"
891 if (!zdi->data1_database)
894 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
896 assert (node_dbinfo);
898 zebraExplain_initCommonInfo (zei, node_dbinfo);
899 zebraExplain_initAccessInfo (zei, node_dbinfo);
901 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
902 database, zei->nmem);
904 if (explain_database)
905 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
908 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
911 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
915 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
919 zei->curDatabaseInfo = zdi;
921 zdi->attributeDetails = (zebAttributeDetails)
922 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
923 zdi->attributeDetails->readFlag = 0;
924 zdi->attributeDetails->sysno = 0;
925 zdi->attributeDetails->dirty = 1;
926 zdi->attributeDetails->SUInfo = NULL;
927 zdi->attributeDetails->data1_tree =
928 data1_read_sgml (zei->dh, zei->nmem,
929 "<explain><attributeDetails>AttributeDetails\n"
933 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
935 assert (node_adinfo);
937 zebraExplain_initCommonInfo (zei, node_adinfo);
942 static void writeAttributeValueDetails (ZebraExplainInfo zei,
943 zebAttributeDetails zad,
944 data1_node *node_atvs, data1_attset *attset)
947 struct zebSUInfoB *zsui;
948 int set_ordinal = attset->reference;
949 data1_attset_child *c;
951 for (c = attset->children; c; c = c->next)
952 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
953 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
955 data1_node *node_attvalue, *node_value;
956 if (set_ordinal != zsui->info.set)
958 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
960 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
962 data1_add_tagdata_int (zei->dh, node_value, "numeric",
963 zsui->info.use, zei->nmem);
967 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
968 struct zebraCategoryListInfo *zcl,
975 data1_node *node_ci, *node_categoryList;
977 static char *category[] = {
989 node_categoryList = zcl->data1_categoryList;
992 logf (LOG_LOG, "zebraExplain_writeCategoryList");
995 drec = createRecord (zei->records, &sysno);
997 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
1000 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
1003 for (i = 0; category[i]; i++)
1005 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
1006 "category", zei->nmem);
1008 data1_add_tagdata_text (zei->dh, node_cat, "name",
1009 category[i], zei->nmem);
1011 /* extract *searchable* keys from it. We do this here, because
1012 record count, etc. is affected */
1014 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1016 /* convert to "SGML" and write it */
1018 data1_pr_tree (zei->dh, node_categoryList, stderr);
1020 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1021 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1022 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1023 drec->size[recInfo_storeData] = sgml_len;
1025 rec_put (zei->records, &drec);
1028 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
1029 zebAttributeDetails zad,
1030 const char *databaseName,
1036 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
1037 struct zebSUInfoB *zsui;
1045 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
1048 drec = createRecord (zei->records, &zad->sysno);
1049 assert (zad->data1_tree);
1050 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
1051 "attributeDetails");
1052 zebraExplain_updateCommonInfo (zei, node_adinfo);
1054 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1055 databaseName, zei->nmem);
1057 /* extract *searchable* keys from it. We do this here, because
1058 record count, etc. is affected */
1060 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1062 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1063 "attributesBySet", zei->nmem);
1067 data1_node *node_asd;
1068 data1_attset *attset;
1069 int set_ordinal = -1;
1070 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1072 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1073 && zsui->info.set > set_min)
1074 set_ordinal = zsui->info.set;
1076 if (set_ordinal < 0)
1078 set_min = set_ordinal;
1079 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1080 "attributeSetDetails", zei->nmem);
1082 attset = data1_attset_search_id (zei->dh, set_ordinal);
1085 zebraExplain_loadAttsets (zei->dh, zei->res);
1086 attset = data1_attset_search_id (zei->dh, set_ordinal);
1093 oe.proto = PROTO_Z3950;
1094 oe.oclass = CLASS_ATTSET;
1095 oe.value = (enum oid_value) set_ordinal;
1097 if (oid_ent_to_oid (&oe, oid))
1099 data1_node *node_abt, *node_atd, *node_atvs;
1100 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1103 node_abt = data1_add_tag (zei->dh, node_asd,
1104 "attributesByType", zei->nmem);
1105 node_atd = data1_add_tag (zei->dh, node_abt,
1106 "attributeTypeDetails", zei->nmem);
1107 data1_add_tagdata_int (zei->dh, node_atd,
1108 "type", 1, zei->nmem);
1109 node_atvs = data1_add_tag (zei->dh, node_atd,
1110 "attributeValues", zei->nmem);
1111 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1115 /* zebra info (private) */
1116 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1117 "zebraInfo", zei->nmem);
1118 node_list = data1_make_tag (zei->dh, node_zebra,
1119 "attrlist", zei->nmem);
1120 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1122 struct oident oident;
1124 data1_node *node_attr;
1126 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1128 oident.proto = PROTO_Z3950;
1129 oident.oclass = CLASS_ATTSET;
1130 oident.value = (enum oid_value) zsui->info.set;
1131 oid_ent_to_oid (&oident, oid);
1133 data1_add_tagdata_text (zei->dh, node_attr, "set",
1134 oident.desc, zei->nmem);
1135 data1_add_tagdata_int (zei->dh, node_attr, "use",
1136 zsui->info.use, zei->nmem);
1137 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1138 zsui->info.ordinal, zei->nmem);
1140 /* convert to "SGML" and write it */
1142 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1144 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1146 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1147 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1148 drec->size[recInfo_storeData] = sgml_len;
1150 rec_put (zei->records, &drec);
1153 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1154 struct zebDatabaseInfoB *zdi,
1160 data1_node *node_dbinfo, *node_count, *node_zebra;
1167 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1169 drec = createRecord (zei->records, &zdi->sysno);
1170 assert (zdi->data1_database);
1171 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1174 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1175 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1177 /* extract *searchable* keys from it. We do this here, because
1178 record count, etc. is affected */
1180 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1182 node_count = data1_make_tag (zei->dh, node_dbinfo,
1183 "recordCount", zei->nmem);
1184 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1185 zdi->recordCount, zei->nmem);
1187 /* zebra info (private) */
1188 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1189 "zebraInfo", zei->nmem);
1190 data1_add_tagdata_int (zei->dh, node_zebra,
1191 "recordBytes", zdi->recordBytes, zei->nmem);
1192 /* convert to "SGML" and write it */
1194 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1196 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1198 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1199 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1200 drec->size[recInfo_storeData] = sgml_len;
1202 rec_put (zei->records, &drec);
1205 static void writeAttributeValues (ZebraExplainInfo zei,
1206 data1_node *node_values,
1207 data1_attset *attset)
1210 data1_attset_child *c;
1215 for (c = attset->children; c; c = c->next)
1216 writeAttributeValues (zei, node_values, c->child);
1217 for (atts = attset->atts; atts; atts = atts->next)
1219 data1_node *node_value;
1221 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1223 data1_add_tagdata_text (zei->dh, node_value, "name",
1224 atts->name, zei->nmem);
1225 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1226 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1227 atts->value, zei->nmem);
1232 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1239 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1240 data1_node *node_values;
1241 struct oident *entp;
1242 struct data1_attset *attset = NULL;
1244 if ((entp = oid_getentbyoid (o->oid)))
1245 attset = data1_attset_search_id (zei->dh, entp->value);
1248 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1249 attset ? attset->name : "<unknown>");
1252 drec = createRecord (zei->records, &o->sysno);
1254 data1_read_sgml (zei->dh, zei->nmem,
1255 "<explain><attributeSetInfo>AttributeSetInfo\n"
1258 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1259 "attributeSetInfo");
1261 zebraExplain_initCommonInfo (zei, node_attinfo);
1262 zebraExplain_updateCommonInfo (zei, node_attinfo);
1264 data1_add_tagdata_oid (zei->dh, node_attinfo,
1265 "oid", o->oid, zei->nmem);
1266 if (attset && attset->name)
1267 data1_add_tagdata_text (zei->dh, node_attinfo,
1268 "name", attset->name, zei->nmem);
1270 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1271 "attributes", zei->nmem);
1272 node_atttype = data1_make_tag (zei->dh, node_attributes,
1273 "attributeType", zei->nmem);
1274 data1_add_tagdata_text (zei->dh, node_atttype,
1275 "name", "Use", zei->nmem);
1276 data1_add_tagdata_text (zei->dh, node_atttype,
1277 "description", "Use Attribute", zei->nmem);
1278 data1_add_tagdata_int (zei->dh, node_atttype,
1279 "type", 1, zei->nmem);
1280 node_values = data1_add_tag (zei->dh, node_atttype,
1281 "attributeValues", zei->nmem);
1283 writeAttributeValues (zei, node_values, attset);
1285 /* extract *searchable* keys from it. We do this here, because
1286 record count, etc. is affected */
1288 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1289 /* convert to "SGML" and write it */
1291 data1_pr_tree (zei->dh, node_root, stderr);
1293 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1294 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1295 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1296 drec->size[recInfo_storeData] = sgml_len;
1298 rec_put (zei->records, &drec);
1301 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1303 struct zebDatabaseInfoB *zdi;
1304 data1_node *node_tgtinfo, *node_list, *node_zebra;
1313 trec = rec_get (zei->records, 1);
1314 xfree (trec->info[recInfo_storeData]);
1316 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1318 assert (node_tgtinfo);
1320 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1321 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1323 /* convert to "SGML" and write it */
1325 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1327 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1328 "zebraInfo", zei->nmem);
1329 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1330 ZEBRAVER, zei->nmem);
1331 node_list = data1_add_tag (zei->dh, node_zebra,
1332 "databaseList", zei->nmem);
1333 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1335 data1_node *node_db;
1336 node_db = data1_add_tag (zei->dh, node_list,
1337 "database", zei->nmem);
1338 data1_add_tagdata_text (zei->dh, node_db, "name",
1339 zdi->databaseName, zei->nmem);
1340 data1_add_tagdata_int (zei->dh, node_db, "id",
1341 zdi->sysno, zei->nmem);
1342 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1343 zdi->attributeDetails->sysno, zei->nmem);
1345 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1346 zei->ordinalSU, zei->nmem);
1348 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1349 zei->runNumber, zei->nmem);
1352 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1354 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1356 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1357 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1358 trec->size[recInfo_storeData] = sgml_len;
1360 rec_put (zei->records, &trec);
1363 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1365 struct zebSUInfoB *zsui;
1367 assert (zei->curDatabaseInfo);
1368 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1369 zsui; zsui=zsui->next)
1370 if (zsui->info.use == use && zsui->info.set == set)
1371 return zsui->info.ordinal;
1375 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1376 zebAccessObject *op,
1381 for (ao = *op; ao; ao = ao->next)
1382 if (!oid_oidcmp (oid, ao->oid))
1386 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
1389 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1396 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1401 oe.proto = PROTO_Z3950;
1402 oe.oclass = CLASS_ATTSET;
1403 oe.value = (enum oid_value) set;
1405 if (oid_ent_to_oid (&oe, oid))
1407 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1408 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1409 accessInfo->attributeSetIds, oid);
1413 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1415 struct zebSUInfoB *zsui;
1417 assert (zei->curDatabaseInfo);
1418 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1419 zsui; zsui=zsui->next)
1420 if (zsui->info.use == use && zsui->info.set == set)
1422 zebraExplain_addAttributeSet (zei, set);
1423 zsui = (struct zebSUInfoB *) nmem_malloc (zei->nmem, sizeof(*zsui));
1424 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1425 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1426 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1428 zsui->info.set = set;
1429 zsui->info.use = use;
1430 zsui->info.ordinal = (zei->ordinalSU)++;
1431 return zsui->info.ordinal;
1434 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1436 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1437 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1438 accessInfo->schemas, oid);
1441 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1443 assert (zei->curDatabaseInfo);
1447 zei->curDatabaseInfo->recordBytes += adjust_num;
1448 zei->curDatabaseInfo->dirty = 1;
1452 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1454 assert (zei->curDatabaseInfo);
1458 zei->curDatabaseInfo->recordCount += adjust_num;
1459 zei->curDatabaseInfo->dirty = 1;
1463 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1467 return zei->runNumber += adjust_num;
1470 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1472 RecordAttr *recordAttr;
1474 if (rec->info[recInfo_attr])
1475 return (RecordAttr *) rec->info[recInfo_attr];
1476 recordAttr = (RecordAttr *) xmalloc (sizeof(*recordAttr));
1477 rec->info[recInfo_attr] = (char *) recordAttr;
1478 rec->size[recInfo_attr] = sizeof(*recordAttr);
1480 recordAttr->recordSize = 0;
1481 recordAttr->recordOffset = 0;
1482 recordAttr->runNumber = zei->runNumber;
1486 static void att_loadset(void *p, const char *n, const char *name)
1488 data1_handle dh = (data1_handle) p;
1489 if (!data1_get_attset (dh, name))
1490 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1493 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1495 res_trav(res, "attset", dh, att_loadset);
1499 zebraExplain_addSU adds to AttributeDetails for a database and
1500 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1501 exist for the database.
1503 If the database doesn't exist globally (in TargetInfo) an
1504 AttributeSetInfo must be added (globally).