2 * Copyright (C) 1994-1999, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.20 2000-11-29 14:24:01 adam
8 * Script configure uses yaz pthreads options. Added locking for
9 * zebra_register_{lock,unlock}.
11 * Revision 1.19 2000/07/07 12:49:20 adam
12 * Optimized resultSetInsert{Rank,Sort}.
14 * Revision 1.18 2000/03/20 19:08:36 adam
15 * Added remote record import using Z39.50 extended services and Segment
18 * Revision 1.17 1999/07/14 10:53:51 adam
19 * Updated various routines to handle missing explain schema.
21 * Revision 1.16 1999/05/26 07:49:13 adam
24 * Revision 1.15 1999/01/25 13:47:54 adam
27 * Revision 1.14 1998/11/04 16:31:32 adam
28 * Fixed bug regarding recordBytes in databaseInfo.
30 * Revision 1.13 1998/11/03 10:17:09 adam
31 * Fixed bug regarding creation of some data1 nodes for Explain records.
33 * Revision 1.12 1998/10/13 20:37:11 adam
34 * Changed the way attribute sets are saved in Explain database to
35 * reflect "dynamic" OIDs.
37 * Revision 1.11 1998/06/09 12:16:48 adam
38 * Implemented auto-generation of CategoryList records.
40 * Revision 1.10 1998/06/08 14:43:15 adam
41 * Added suport for EXPLAIN Proxy servers - added settings databasePath
42 * and explainDatabase to facilitate this. Increased maximum number
43 * of databases and attributes in one register.
45 * Revision 1.9 1998/06/02 12:10:27 adam
46 * Fixed bug related to attributeDetails.
48 * Revision 1.8 1998/05/20 10:12:20 adam
49 * Implemented automatic EXPLAIN database maintenance.
50 * Modified Zebra to work with ASN.1 compiled version of YAZ.
52 * Revision 1.7 1998/03/05 08:45:13 adam
53 * New result set model and modular ranking system. Moved towards
54 * descent server API. System information stored as "SGML" records.
56 * Revision 1.6 1998/02/17 10:29:27 adam
57 * Moved towards 'automatic' EXPLAIN database.
59 * Revision 1.5 1997/10/27 14:33:05 adam
60 * Moved towards generic character mapping depending on "structure"
61 * field in abstract syntax file. Fixed a few memory leaks. Fixed
62 * bug with negative integers when doing searches with relational
65 * Revision 1.4 1997/09/25 14:57:08 adam
68 * Revision 1.3 1996/05/22 08:21:59 adam
69 * Added public ZebDatabaseInfo structure.
71 * Revision 1.2 1996/05/14 06:16:41 adam
72 * Compact use/set bytes used in search service.
74 * Revision 1.1 1996/05/13 14:23:07 adam
75 * Work on compaction of set/use bytes in dictionary.
96 struct zebSUInfo info;
97 struct zebSUInfoB *next;
100 typedef struct zebAccessObjectB *zebAccessObject;
101 struct zebAccessObjectB {
105 zebAccessObject next;
108 typedef struct zebAccessInfoB *zebAccessInfo;
109 struct zebAccessInfoB {
110 zebAccessObject attributeSetIds;
111 zebAccessObject schemas;
115 struct zebSUInfoB *SUInfo;
119 data1_node *data1_tree;
120 } *zebAttributeDetails;
122 struct zebDatabaseInfoB {
123 zebAttributeDetails attributeDetails;
125 data1_node *data1_database;
126 int recordCount; /* records in db */
127 int recordBytes; /* size of records */
128 int sysno; /* sysno of database info */
129 int readFlag; /* 1: read is needed when referenced; 0 if not */
130 int dirty; /* 1: database is dirty: write is needed */
131 struct zebDatabaseInfoB *next;
132 zebAccessInfo accessInfo;
135 struct zebraExplainAttset {
138 struct zebraExplainAttset *next;
141 struct zebraCategoryListInfo {
144 data1_node *data1_categoryList;
147 struct zebraExplainInfo {
154 struct zebraExplainAttset *attsets;
156 data1_node *data1_target;
157 struct zebraCategoryListInfo *categoryList;
158 struct zebDatabaseInfoB *databaseInfo;
159 struct zebDatabaseInfoB *curDatabaseInfo;
160 zebAccessInfo accessInfo;
161 char date[15]; /* YYYY MMDD HH MM SS */
162 int (*updateFunc)(void *handle, Record drec, data1_node *n);
166 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
167 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
169 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
171 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
174 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
177 logf (LOG_DEBUG, "data1_search_tag %s", tag);
178 for (; n; n = n->next)
179 if (n->which == DATA1N_tag && n->u.tag.tag &&
180 !yaz_matchstr (tag, n->u.tag.tag))
182 logf (LOG_DEBUG, " found");
185 logf (LOG_DEBUG, " not found");
189 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
190 const char *tag, NMEM nmem)
192 data1_node *partag = get_parent_tag(dh, at);
193 data1_node *res = data1_mk_node_type (dh, nmem, DATA1N_tag);
194 data1_element *e = NULL;
197 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
200 e = partag->u.tag.element;
202 data1_getelementbytagname (dh, at->root->u.root.absyn,
204 res->root = at->root;
209 assert (at->last_child);
210 at->last_child->next = res;
212 at->last_child = res;
216 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
217 const char *tag, NMEM nmem)
219 data1_node *node = data1_search_tag (dh, at->child, tag);
221 node = data1_add_tag (dh, at, tag, nmem);
223 node->child = node->last_child = NULL;
227 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
228 const char *tag, int num,
231 data1_node *node_data;
233 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
236 node_data->u.data.what = DATA1I_num;
237 node_data->u.data.data = node_data->lbuf;
238 sprintf (node_data->u.data.data, "%d", num);
239 node_data->u.data.len = strlen (node_data->u.data.data);
243 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
244 const char *tag, Odr_oid *oid,
247 data1_node *node_data;
248 char str[128], *p = str;
251 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
255 for (ii = oid; *ii >= 0; ii++)
259 sprintf (p, "%d", *ii);
262 node_data->u.data.what = DATA1I_oid;
263 node_data->u.data.len = strlen (str);
264 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
269 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
270 const char *tag, const char *str,
273 data1_node *node_data;
275 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
278 node_data->u.data.what = DATA1I_text;
279 node_data->u.data.len = strlen (str);
280 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
284 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
285 const char *tag, const char *str,
288 data1_node *node = data1_search_tag (dh, at->child, tag);
290 return data1_add_tagdata_text (dh, at, tag, str, nmem);
293 data1_node *node_data = node->child;
294 node_data->u.data.what = DATA1I_text;
295 node_data->u.data.len = strlen (str);
296 node_data->u.data.data = data1_insert_string (dh, node_data,
302 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
303 struct zebDatabaseInfoB *zdi,
305 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
306 zebAttributeDetails zad,
307 const char *databaseName,
309 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
310 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
313 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
314 struct zebraCategoryListInfo *zcl,
318 static Record createRecord (Records records, int *sysno)
323 rec = rec_get (records, *sysno);
324 xfree (rec->info[recInfo_storeData]);
328 rec = rec_new (records);
331 rec->info[recInfo_fileType] =
332 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
333 rec->info[recInfo_databaseName] =
334 rec_strdup ("IR-Explain-1",
335 &rec->size[recInfo_databaseName]);
340 void zebraExplain_flush (ZebraExplainInfo zei, int writeFlag, void *handle)
342 zei->updateHandle = handle;
345 struct zebDatabaseInfoB *zdi;
348 /* write each database info record */
349 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
351 zebraExplain_writeDatabase (zei, zdi, 1);
352 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
353 zdi->databaseName, 1);
355 zebraExplain_writeTarget (zei, 1);
356 zebraExplain_writeCategoryList (zei,
359 assert (zei->accessInfo);
360 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
362 zebraExplain_writeAttributeSet (zei, o, 1);
363 for (o = zei->accessInfo->schemas; o; o = o->next)
366 /* zebraExplain_writeSchema (zei, o, 1); */
369 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
371 zebraExplain_writeDatabase (zei, zdi, 0);
372 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
373 zdi->databaseName, 0);
375 zebraExplain_writeTarget (zei, 0);
379 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag)
382 logf (LOG_LOG, "zebraExplain_close wr=%d", writeFlag);
386 zebraExplain_flush (zei, writeFlag, zei->updateHandle);
387 nmem_destroy (zei->nmem);
390 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
395 for (np = n->child; np; np = np->next)
402 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
404 len = np->child->u.data.len;
407 memcpy (str, np->child->u.data.data, len);
410 oid = odr_getoidbystr_nmem (zei->nmem, str);
412 for (ao = *op; ao; ao = ao->next)
413 if (!oid_oidcmp (oid, ao->oid))
420 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
430 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
431 zebAccessInfo *accessInfo)
437 *accessInfo = (zebAccessInfo)
438 nmem_malloc (zei->nmem, sizeof(**accessInfo));
439 (*accessInfo)->attributeSetIds = NULL;
440 (*accessInfo)->schemas = NULL;
444 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
446 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
447 zebraExplain_mergeOids (zei, np,
448 &(*accessInfo)->attributeSetIds);
449 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
450 zebraExplain_mergeOids (zei, np,
451 &(*accessInfo)->schemas);
455 ZebraExplainInfo zebraExplain_open (
456 Records records, data1_handle dh,
460 int (*updateFunc)(void *handle, Record drec, data1_node *n))
463 ZebraExplainInfo zei;
464 struct zebDatabaseInfoB **zdip;
467 NMEM nmem = nmem_create ();
470 logf (LOG_LOG, "zebraExplain_open wr=%d", writeFlag);
472 zei = (ZebraExplainInfo) nmem_malloc (nmem, sizeof(*zei));
473 zei->updateHandle = updateHandle;
474 zei->updateFunc = updateFunc;
476 zei->curDatabaseInfo = NULL;
477 zei->records = records;
482 zei->categoryList = (struct zebraCategoryListInfo *)
483 nmem_malloc (zei->nmem, sizeof(*zei->categoryList));
484 zei->categoryList->sysno = 0;
485 zei->categoryList->dirty = 0;
486 zei->categoryList->data1_categoryList = NULL;
489 tm = localtime (&our_time);
490 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
491 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
492 tm->tm_hour, tm->tm_min, tm->tm_sec);
494 zdip = &zei->databaseInfo;
495 trec = rec_get (records, 1); /* get "root" record */
500 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
501 if (trec) /* targetInfo already exists ... */
503 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
505 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
506 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
508 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
509 nmem_destroy (zei->nmem);
513 data1_pr_tree (zei->dh, zei->data1_target, stderr);
515 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
517 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
520 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
525 node_list = data1_search_tag (zei->dh, node_zebra->child,
528 np = node_list->child;
530 for (; np; np = np->next)
532 data1_node *node_name = NULL;
533 data1_node *node_id = NULL;
534 data1_node *node_aid = NULL;
536 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
538 for (np2 = np->child; np2; np2 = np2->next)
540 if (np2->which != DATA1N_tag)
542 if (!strcmp (np2->u.tag.tag, "name"))
543 node_name = np2->child;
544 else if (!strcmp (np2->u.tag.tag, "id"))
545 node_id = np2->child;
546 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
547 node_aid = np2->child;
549 assert (node_id && node_name && node_aid);
551 *zdip = (struct zebDatabaseInfoB *)
552 nmem_malloc (zei->nmem, sizeof(**zdip));
553 (*zdip)->readFlag = 1;
555 (*zdip)->data1_database = NULL;
556 (*zdip)->recordCount = 0;
557 (*zdip)->recordBytes = 0;
558 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
560 (*zdip)->databaseName = (char *)
561 nmem_malloc (zei->nmem, 1+node_name->u.data.len);
562 memcpy ((*zdip)->databaseName, node_name->u.data.data,
563 node_name->u.data.len);
564 (*zdip)->databaseName[node_name->u.data.len] = '\0';
565 (*zdip)->sysno = atoi_n (node_id->u.data.data,
566 node_id->u.data.len);
567 (*zdip)->attributeDetails = (zebAttributeDetails)
568 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
569 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
570 node_aid->u.data.len);
571 (*zdip)->attributeDetails->readFlag = 1;
572 (*zdip)->attributeDetails->dirty = 0;
573 (*zdip)->attributeDetails->SUInfo = NULL;
575 zdip = &(*zdip)->next;
579 np = data1_search_tag (zei->dh, node_zebra->child,
582 assert (np && np->which == DATA1N_data);
583 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
585 np = data1_search_tag (zei->dh, node_zebra->child,
588 assert (np && np->which == DATA1N_data);
589 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
594 else /* create initial targetInfo */
596 data1_node *node_tgtinfo;
605 data1_read_sgml (zei->dh, zei->nmem,
606 "<explain><targetInfo>TargetInfo\n"
608 "<namedResultSets>1</>\n"
609 "<multipleDBSearch>1</>\n"
610 "<nicknames><name>Zebra</></>\n"
612 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
614 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
615 nmem_destroy (zei->nmem);
618 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
620 assert (node_tgtinfo);
622 zebraExplain_initCommonInfo (zei, node_tgtinfo);
623 zebraExplain_initAccessInfo (zei, node_tgtinfo);
625 /* write now because we want to be sure about the sysno */
626 trec = rec_new (records);
627 trec->info[recInfo_fileType] =
628 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
629 trec->info[recInfo_databaseName] =
630 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
632 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
633 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
634 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
635 trec->size[recInfo_storeData] = sgml_len;
637 rec_put (records, &trec);
641 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
643 if (!zei->categoryList->dirty)
645 struct zebraCategoryListInfo *zcl = zei->categoryList;
649 zcl->data1_categoryList =
650 data1_read_sgml (zei->dh, zei->nmem,
651 "<explain><categoryList>CategoryList\n"
654 if (zcl->data1_categoryList)
656 assert (zcl->data1_categoryList->child);
657 node_cl = data1_search_tag (zei->dh,
658 zcl->data1_categoryList->child,
661 zebraExplain_initCommonInfo (zei, node_cl);
668 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
669 zebAttributeDetails zad)
672 struct zebSUInfoB **zsuip = &zad->SUInfo;
673 data1_node *node_adinfo, *node_zebra, *node_list, *np;
676 rec = rec_get (zei->records, zad->sysno);
678 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
680 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
682 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
684 node_list = data1_search_tag (zei->dh, node_zebra->child,
686 for (np = node_list->child; np; np = np->next)
688 data1_node *node_set = NULL;
689 data1_node *node_use = NULL;
690 data1_node *node_ordinal = NULL;
695 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
697 for (np2 = np->child; np2; np2 = np2->next)
699 if (np2->which != DATA1N_tag || !np2->child ||
700 np2->child->which != DATA1N_data)
702 if (!strcmp (np2->u.tag.tag, "set"))
703 node_set = np2->child;
704 else if (!strcmp (np2->u.tag.tag, "use"))
705 node_use = np2->child;
706 else if (!strcmp (np2->u.tag.tag, "ordinal"))
707 node_ordinal = np2->child;
709 assert (node_set && node_use && node_ordinal);
711 oid_str_len = node_set->u.data.len;
712 if (oid_str_len >= (int) sizeof(oid_str))
713 oid_str_len = sizeof(oid_str)-1;
714 memcpy (oid_str, node_set->u.data.data, oid_str_len);
715 oid_str[oid_str_len] = '\0';
717 *zsuip = (struct zebSUInfoB *)
718 nmem_malloc (zei->nmem, sizeof(**zsuip));
719 (*zsuip)->info.set = oid_getvalbyname (oid_str);
721 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
722 node_use->u.data.len);
723 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
724 node_ordinal->u.data.len);
725 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
726 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
727 zsuip = &(*zsuip)->next;
734 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
735 struct zebDatabaseInfoB *zdi)
738 data1_node *node_dbinfo, *node_zebra, *np;
741 rec = rec_get (zei->records, zdi->sysno);
743 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
745 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
747 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
749 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
752 && (np = data1_search_tag (zei->dh, node_zebra->child,
754 && np->child && np->child->which == DATA1N_data)
755 zdi->recordBytes = atoi_n (np->child->u.data.data,
756 np->child->u.data.len);
757 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
759 (np = data1_search_tag (zei->dh, np->child,
760 "recordCountActual")) &&
761 np->child->which == DATA1N_data)
763 zdi->recordCount = atoi_n (np->child->u.data.data,
764 np->child->u.data.len);
770 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
772 struct zebDatabaseInfoB *zdi;
775 if (zei->curDatabaseInfo &&
776 !strcmp (zei->curDatabaseInfo->databaseName, database))
778 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
780 if (!strcmp (zdi->databaseName, database))
786 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
791 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
793 zebraExplain_readDatabase (zei, zdi);
795 if (zdi->attributeDetails->readFlag)
798 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
800 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
802 zei->curDatabaseInfo = zdi;
806 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
808 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
810 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
811 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
812 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
815 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
817 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
819 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
822 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
824 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
825 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
826 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
829 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
830 zebAccessInfo accessInfo)
832 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
838 if ((p = accessInfo->attributeSetIds))
840 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
841 for (; p; p = p->next)
842 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
844 if ((p = accessInfo->schemas))
846 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
847 for (; p; p = p->next)
848 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
852 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
853 int explain_database)
855 struct zebDatabaseInfoB *zdi;
856 data1_node *node_dbinfo, *node_adinfo;
859 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
862 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
864 if (!strcmp (zdi->databaseName, database))
869 /* it's new really. make it */
870 zdi = (struct zebDatabaseInfoB *) nmem_malloc (zei->nmem, sizeof(*zdi));
871 zdi->next = zei->databaseInfo;
872 zei->databaseInfo = zdi;
874 zdi->recordCount = 0;
875 zdi->recordBytes = 0;
877 zdi->databaseName = nmem_strdup (zei->nmem, database);
879 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
884 zdi->data1_database =
885 data1_read_sgml (zei->dh, zei->nmem,
886 "<explain><databaseInfo>DatabaseInfo\n"
888 if (!zdi->data1_database)
891 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
893 assert (node_dbinfo);
895 zebraExplain_initCommonInfo (zei, node_dbinfo);
896 zebraExplain_initAccessInfo (zei, node_dbinfo);
898 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
899 database, zei->nmem);
901 if (explain_database)
902 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
905 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
908 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
912 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
916 zei->curDatabaseInfo = zdi;
918 zdi->attributeDetails = (zebAttributeDetails)
919 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
920 zdi->attributeDetails->readFlag = 0;
921 zdi->attributeDetails->sysno = 0;
922 zdi->attributeDetails->dirty = 1;
923 zdi->attributeDetails->SUInfo = NULL;
924 zdi->attributeDetails->data1_tree =
925 data1_read_sgml (zei->dh, zei->nmem,
926 "<explain><attributeDetails>AttributeDetails\n"
930 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
932 assert (node_adinfo);
934 zebraExplain_initCommonInfo (zei, node_adinfo);
939 static void writeAttributeValueDetails (ZebraExplainInfo zei,
940 zebAttributeDetails zad,
941 data1_node *node_atvs, data1_attset *attset)
944 struct zebSUInfoB *zsui;
945 int set_ordinal = attset->reference;
946 data1_attset_child *c;
948 for (c = attset->children; c; c = c->next)
949 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
950 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
952 data1_node *node_attvalue, *node_value;
953 if (set_ordinal != zsui->info.set)
955 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
957 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
959 data1_add_tagdata_int (zei->dh, node_value, "numeric",
960 zsui->info.use, zei->nmem);
964 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
965 struct zebraCategoryListInfo *zcl,
972 data1_node *node_ci, *node_categoryList;
974 static char *category[] = {
986 node_categoryList = zcl->data1_categoryList;
989 logf (LOG_LOG, "zebraExplain_writeCategoryList");
992 drec = createRecord (zei->records, &sysno);
994 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
997 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
1000 for (i = 0; category[i]; i++)
1002 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
1003 "category", zei->nmem);
1005 data1_add_tagdata_text (zei->dh, node_cat, "name",
1006 category[i], zei->nmem);
1008 /* extract *searchable* keys from it. We do this here, because
1009 record count, etc. is affected */
1011 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1013 /* convert to "SGML" and write it */
1015 data1_pr_tree (zei->dh, node_categoryList, stderr);
1017 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1018 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1019 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1020 drec->size[recInfo_storeData] = sgml_len;
1022 rec_put (zei->records, &drec);
1025 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
1026 zebAttributeDetails zad,
1027 const char *databaseName,
1033 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
1034 struct zebSUInfoB *zsui;
1042 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
1045 drec = createRecord (zei->records, &zad->sysno);
1046 assert (zad->data1_tree);
1047 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
1048 "attributeDetails");
1049 zebraExplain_updateCommonInfo (zei, node_adinfo);
1051 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1052 databaseName, zei->nmem);
1054 /* extract *searchable* keys from it. We do this here, because
1055 record count, etc. is affected */
1057 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1059 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1060 "attributesBySet", zei->nmem);
1064 data1_node *node_asd;
1065 data1_attset *attset;
1066 int set_ordinal = -1;
1067 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1069 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1070 && zsui->info.set > set_min)
1071 set_ordinal = zsui->info.set;
1073 if (set_ordinal < 0)
1075 set_min = set_ordinal;
1076 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1077 "attributeSetDetails", zei->nmem);
1079 attset = data1_attset_search_id (zei->dh, set_ordinal);
1082 zebraExplain_loadAttsets (zei->dh, zei->res);
1083 attset = data1_attset_search_id (zei->dh, set_ordinal);
1090 oe.proto = PROTO_Z3950;
1091 oe.oclass = CLASS_ATTSET;
1092 oe.value = (enum oid_value) set_ordinal;
1094 if (oid_ent_to_oid (&oe, oid))
1096 data1_node *node_abt, *node_atd, *node_atvs;
1097 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1100 node_abt = data1_add_tag (zei->dh, node_asd,
1101 "attributesByType", zei->nmem);
1102 node_atd = data1_add_tag (zei->dh, node_abt,
1103 "attributeTypeDetails", zei->nmem);
1104 data1_add_tagdata_int (zei->dh, node_atd,
1105 "type", 1, zei->nmem);
1106 node_atvs = data1_add_tag (zei->dh, node_atd,
1107 "attributeValues", zei->nmem);
1108 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1112 /* zebra info (private) */
1113 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1114 "zebraInfo", zei->nmem);
1115 node_list = data1_make_tag (zei->dh, node_zebra,
1116 "attrlist", zei->nmem);
1117 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1119 struct oident oident;
1121 data1_node *node_attr;
1123 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1125 oident.proto = PROTO_Z3950;
1126 oident.oclass = CLASS_ATTSET;
1127 oident.value = (enum oid_value) zsui->info.set;
1128 oid_ent_to_oid (&oident, oid);
1130 data1_add_tagdata_text (zei->dh, node_attr, "set",
1131 oident.desc, zei->nmem);
1132 data1_add_tagdata_int (zei->dh, node_attr, "use",
1133 zsui->info.use, zei->nmem);
1134 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1135 zsui->info.ordinal, zei->nmem);
1137 /* convert to "SGML" and write it */
1139 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1141 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1143 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1144 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1145 drec->size[recInfo_storeData] = sgml_len;
1147 rec_put (zei->records, &drec);
1150 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1151 struct zebDatabaseInfoB *zdi,
1157 data1_node *node_dbinfo, *node_count, *node_zebra;
1164 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1166 drec = createRecord (zei->records, &zdi->sysno);
1167 assert (zdi->data1_database);
1168 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1171 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1172 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1174 /* extract *searchable* keys from it. We do this here, because
1175 record count, etc. is affected */
1177 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1179 node_count = data1_make_tag (zei->dh, node_dbinfo,
1180 "recordCount", zei->nmem);
1181 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1182 zdi->recordCount, zei->nmem);
1184 /* zebra info (private) */
1185 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1186 "zebraInfo", zei->nmem);
1187 data1_add_tagdata_int (zei->dh, node_zebra,
1188 "recordBytes", zdi->recordBytes, zei->nmem);
1189 /* convert to "SGML" and write it */
1191 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1193 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1195 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1196 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1197 drec->size[recInfo_storeData] = sgml_len;
1199 rec_put (zei->records, &drec);
1202 static void writeAttributeValues (ZebraExplainInfo zei,
1203 data1_node *node_values,
1204 data1_attset *attset)
1207 data1_attset_child *c;
1212 for (c = attset->children; c; c = c->next)
1213 writeAttributeValues (zei, node_values, c->child);
1214 for (atts = attset->atts; atts; atts = atts->next)
1216 data1_node *node_value;
1218 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1220 data1_add_tagdata_text (zei->dh, node_value, "name",
1221 atts->name, zei->nmem);
1222 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1223 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1224 atts->value, zei->nmem);
1229 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1236 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1237 data1_node *node_values;
1238 struct oident *entp;
1239 struct data1_attset *attset = NULL;
1241 if ((entp = oid_getentbyoid (o->oid)))
1242 attset = data1_attset_search_id (zei->dh, entp->value);
1245 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1246 attset ? attset->name : "<unknown>");
1249 drec = createRecord (zei->records, &o->sysno);
1251 data1_read_sgml (zei->dh, zei->nmem,
1252 "<explain><attributeSetInfo>AttributeSetInfo\n"
1255 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1256 "attributeSetInfo");
1258 zebraExplain_initCommonInfo (zei, node_attinfo);
1259 zebraExplain_updateCommonInfo (zei, node_attinfo);
1261 data1_add_tagdata_oid (zei->dh, node_attinfo,
1262 "oid", o->oid, zei->nmem);
1263 if (attset && attset->name)
1264 data1_add_tagdata_text (zei->dh, node_attinfo,
1265 "name", attset->name, zei->nmem);
1267 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1268 "attributes", zei->nmem);
1269 node_atttype = data1_make_tag (zei->dh, node_attributes,
1270 "attributeType", zei->nmem);
1271 data1_add_tagdata_text (zei->dh, node_atttype,
1272 "name", "Use", zei->nmem);
1273 data1_add_tagdata_text (zei->dh, node_atttype,
1274 "description", "Use Attribute", zei->nmem);
1275 data1_add_tagdata_int (zei->dh, node_atttype,
1276 "type", 1, zei->nmem);
1277 node_values = data1_add_tag (zei->dh, node_atttype,
1278 "attributeValues", zei->nmem);
1280 writeAttributeValues (zei, node_values, attset);
1282 /* extract *searchable* keys from it. We do this here, because
1283 record count, etc. is affected */
1285 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1286 /* convert to "SGML" and write it */
1288 data1_pr_tree (zei->dh, node_root, stderr);
1290 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1291 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1292 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1293 drec->size[recInfo_storeData] = sgml_len;
1295 rec_put (zei->records, &drec);
1298 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1300 struct zebDatabaseInfoB *zdi;
1301 data1_node *node_tgtinfo, *node_list, *node_zebra;
1310 trec = rec_get (zei->records, 1);
1311 xfree (trec->info[recInfo_storeData]);
1313 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1315 assert (node_tgtinfo);
1317 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1318 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1320 /* convert to "SGML" and write it */
1322 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1324 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1325 "zebraInfo", zei->nmem);
1326 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1327 ZEBRAVER, zei->nmem);
1328 node_list = data1_add_tag (zei->dh, node_zebra,
1329 "databaseList", zei->nmem);
1330 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1332 data1_node *node_db;
1333 node_db = data1_add_tag (zei->dh, node_list,
1334 "database", zei->nmem);
1335 data1_add_tagdata_text (zei->dh, node_db, "name",
1336 zdi->databaseName, zei->nmem);
1337 data1_add_tagdata_int (zei->dh, node_db, "id",
1338 zdi->sysno, zei->nmem);
1339 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1340 zdi->attributeDetails->sysno, zei->nmem);
1342 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1343 zei->ordinalSU, zei->nmem);
1345 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1346 zei->runNumber, zei->nmem);
1349 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1351 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1353 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1354 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1355 trec->size[recInfo_storeData] = sgml_len;
1357 rec_put (zei->records, &trec);
1360 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1362 struct zebSUInfoB *zsui;
1364 assert (zei->curDatabaseInfo);
1365 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1366 zsui; zsui=zsui->next)
1367 if (zsui->info.use == use && zsui->info.set == set)
1368 return zsui->info.ordinal;
1372 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1373 zebAccessObject *op,
1378 for (ao = *op; ao; ao = ao->next)
1379 if (!oid_oidcmp (oid, ao->oid))
1383 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
1386 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1393 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1398 oe.proto = PROTO_Z3950;
1399 oe.oclass = CLASS_ATTSET;
1400 oe.value = (enum oid_value) set;
1402 if (oid_ent_to_oid (&oe, oid))
1404 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1405 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1406 accessInfo->attributeSetIds, oid);
1410 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1412 struct zebSUInfoB *zsui;
1414 assert (zei->curDatabaseInfo);
1415 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1416 zsui; zsui=zsui->next)
1417 if (zsui->info.use == use && zsui->info.set == set)
1419 zebraExplain_addAttributeSet (zei, set);
1420 zsui = (struct zebSUInfoB *) nmem_malloc (zei->nmem, sizeof(*zsui));
1421 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1422 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1423 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1425 zsui->info.set = set;
1426 zsui->info.use = use;
1427 zsui->info.ordinal = (zei->ordinalSU)++;
1428 return zsui->info.ordinal;
1431 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1433 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1434 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1435 accessInfo->schemas, oid);
1438 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1440 assert (zei->curDatabaseInfo);
1444 zei->curDatabaseInfo->recordBytes += adjust_num;
1445 zei->curDatabaseInfo->dirty = 1;
1449 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1451 assert (zei->curDatabaseInfo);
1455 zei->curDatabaseInfo->recordCount += adjust_num;
1456 zei->curDatabaseInfo->dirty = 1;
1460 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1464 return zei->runNumber += adjust_num;
1467 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1469 RecordAttr *recordAttr;
1471 if (rec->info[recInfo_attr])
1472 return (RecordAttr *) rec->info[recInfo_attr];
1473 recordAttr = (RecordAttr *) xmalloc (sizeof(*recordAttr));
1474 rec->info[recInfo_attr] = (char *) recordAttr;
1475 rec->size[recInfo_attr] = sizeof(*recordAttr);
1477 recordAttr->recordSize = 0;
1478 recordAttr->recordOffset = 0;
1479 recordAttr->runNumber = zei->runNumber;
1483 static void att_loadset(void *p, const char *n, const char *name)
1485 data1_handle dh = (data1_handle) p;
1486 if (!data1_get_attset (dh, name))
1487 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1490 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1492 res_trav(res, "attset", dh, att_loadset);
1496 zebraExplain_addSU adds to AttributeDetails for a database and
1497 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1498 exist for the database.
1500 If the database doesn't exist globally (in TargetInfo) an
1501 AttributeSetInfo must be added (globally).