2 * Copyright (C) 1994-2000, Index Data
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.22 2001-10-15 19:53:43 adam
8 * POSIX thread updates. First work on term sets.
10 * Revision 1.21 2000/12/05 10:01:44 adam
11 * Fixed bug regarding user-defined attribute sets.
13 * Revision 1.20 2000/11/29 14:24:01 adam
14 * Script configure uses yaz pthreads options. Added locking for
15 * zebra_register_{lock,unlock}.
17 * Revision 1.19 2000/07/07 12:49:20 adam
18 * Optimized resultSetInsert{Rank,Sort}.
20 * Revision 1.18 2000/03/20 19:08:36 adam
21 * Added remote record import using Z39.50 extended services and Segment
24 * Revision 1.17 1999/07/14 10:53:51 adam
25 * Updated various routines to handle missing explain schema.
27 * Revision 1.16 1999/05/26 07:49:13 adam
30 * Revision 1.15 1999/01/25 13:47:54 adam
33 * Revision 1.14 1998/11/04 16:31:32 adam
34 * Fixed bug regarding recordBytes in databaseInfo.
36 * Revision 1.13 1998/11/03 10:17:09 adam
37 * Fixed bug regarding creation of some data1 nodes for Explain records.
39 * Revision 1.12 1998/10/13 20:37:11 adam
40 * Changed the way attribute sets are saved in Explain database to
41 * reflect "dynamic" OIDs.
43 * Revision 1.11 1998/06/09 12:16:48 adam
44 * Implemented auto-generation of CategoryList records.
46 * Revision 1.10 1998/06/08 14:43:15 adam
47 * Added suport for EXPLAIN Proxy servers - added settings databasePath
48 * and explainDatabase to facilitate this. Increased maximum number
49 * of databases and attributes in one register.
51 * Revision 1.9 1998/06/02 12:10:27 adam
52 * Fixed bug related to attributeDetails.
54 * Revision 1.8 1998/05/20 10:12:20 adam
55 * Implemented automatic EXPLAIN database maintenance.
56 * Modified Zebra to work with ASN.1 compiled version of YAZ.
58 * Revision 1.7 1998/03/05 08:45:13 adam
59 * New result set model and modular ranking system. Moved towards
60 * descent server API. System information stored as "SGML" records.
62 * Revision 1.6 1998/02/17 10:29:27 adam
63 * Moved towards 'automatic' EXPLAIN database.
65 * Revision 1.5 1997/10/27 14:33:05 adam
66 * Moved towards generic character mapping depending on "structure"
67 * field in abstract syntax file. Fixed a few memory leaks. Fixed
68 * bug with negative integers when doing searches with relational
71 * Revision 1.4 1997/09/25 14:57:08 adam
74 * Revision 1.3 1996/05/22 08:21:59 adam
75 * Added public ZebDatabaseInfo structure.
77 * Revision 1.2 1996/05/14 06:16:41 adam
78 * Compact use/set bytes used in search service.
80 * Revision 1.1 1996/05/13 14:23:07 adam
81 * Work on compaction of set/use bytes in dictionary.
102 struct zebSUInfo info;
103 struct zebSUInfoB *next;
106 typedef struct zebAccessObjectB *zebAccessObject;
107 struct zebAccessObjectB {
111 zebAccessObject next;
114 typedef struct zebAccessInfoB *zebAccessInfo;
115 struct zebAccessInfoB {
116 zebAccessObject attributeSetIds;
117 zebAccessObject schemas;
121 struct zebSUInfoB *SUInfo;
125 data1_node *data1_tree;
126 } *zebAttributeDetails;
128 struct zebDatabaseInfoB {
129 zebAttributeDetails attributeDetails;
131 data1_node *data1_database;
132 int recordCount; /* records in db */
133 int recordBytes; /* size of records */
134 int sysno; /* sysno of database info */
135 int readFlag; /* 1: read is needed when referenced; 0 if not */
136 int dirty; /* 1: database is dirty: write is needed */
137 struct zebDatabaseInfoB *next;
138 zebAccessInfo accessInfo;
141 struct zebraExplainAttset {
144 struct zebraExplainAttset *next;
147 struct zebraCategoryListInfo {
150 data1_node *data1_categoryList;
153 struct zebraExplainInfo {
160 struct zebraExplainAttset *attsets;
162 data1_node *data1_target;
163 struct zebraCategoryListInfo *categoryList;
164 struct zebDatabaseInfoB *databaseInfo;
165 struct zebDatabaseInfoB *curDatabaseInfo;
166 zebAccessInfo accessInfo;
167 char date[15]; /* YYYY MMDD HH MM SS */
168 int (*updateFunc)(void *handle, Record drec, data1_node *n);
172 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n);
173 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n);
175 static data1_node *read_sgml_rec (data1_handle dh, NMEM nmem, Record rec)
177 return data1_read_sgml (dh, nmem, rec->info[recInfo_storeData]);
180 static data1_node *data1_search_tag (data1_handle dh, data1_node *n,
183 logf (LOG_DEBUG, "data1_search_tag %s", tag);
184 for (; n; n = n->next)
185 if (n->which == DATA1N_tag && n->u.tag.tag &&
186 !yaz_matchstr (tag, n->u.tag.tag))
188 logf (LOG_DEBUG, " found");
191 logf (LOG_DEBUG, " not found");
195 static data1_node *data1_add_tag (data1_handle dh, data1_node *at,
196 const char *tag, NMEM nmem)
198 data1_node *partag = get_parent_tag(dh, at);
199 data1_node *res = data1_mk_node_type (dh, nmem, DATA1N_tag);
200 data1_element *e = NULL;
203 res->u.tag.tag = data1_insert_string (dh, res, nmem, tag);
206 e = partag->u.tag.element;
208 data1_getelementbytagname (dh, at->root->u.root.absyn,
210 res->root = at->root;
215 assert (at->last_child);
216 at->last_child->next = res;
218 at->last_child = res;
222 static data1_node *data1_make_tag (data1_handle dh, data1_node *at,
223 const char *tag, NMEM nmem)
225 data1_node *node = data1_search_tag (dh, at->child, tag);
227 node = data1_add_tag (dh, at, tag, nmem);
229 node->child = node->last_child = NULL;
233 static data1_node *data1_add_tagdata_int (data1_handle dh, data1_node *at,
234 const char *tag, int num,
237 data1_node *node_data;
239 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
242 node_data->u.data.what = DATA1I_num;
243 node_data->u.data.data = node_data->lbuf;
244 sprintf (node_data->u.data.data, "%d", num);
245 node_data->u.data.len = strlen (node_data->u.data.data);
249 static data1_node *data1_add_tagdata_oid (data1_handle dh, data1_node *at,
250 const char *tag, Odr_oid *oid,
253 data1_node *node_data;
254 char str[128], *p = str;
257 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
261 for (ii = oid; *ii >= 0; ii++)
265 sprintf (p, "%d", *ii);
268 node_data->u.data.what = DATA1I_oid;
269 node_data->u.data.len = strlen (str);
270 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
275 static data1_node *data1_add_tagdata_text (data1_handle dh, data1_node *at,
276 const char *tag, const char *str,
279 data1_node *node_data;
281 node_data = data1_add_taggeddata (dh, at->root, at, tag, nmem);
284 node_data->u.data.what = DATA1I_text;
285 node_data->u.data.len = strlen (str);
286 node_data->u.data.data = data1_insert_string (dh, node_data, nmem, str);
290 static data1_node *data1_make_tagdata_text (data1_handle dh, data1_node *at,
291 const char *tag, const char *str,
294 data1_node *node = data1_search_tag (dh, at->child, tag);
296 return data1_add_tagdata_text (dh, at, tag, str, nmem);
299 data1_node *node_data = node->child;
300 node_data->u.data.what = DATA1I_text;
301 node_data->u.data.len = strlen (str);
302 node_data->u.data.data = data1_insert_string (dh, node_data,
308 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
309 struct zebDatabaseInfoB *zdi,
311 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
312 zebAttributeDetails zad,
313 const char *databaseName,
315 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush);
316 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
319 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
320 struct zebraCategoryListInfo *zcl,
324 static Record createRecord (Records records, int *sysno)
329 rec = rec_get (records, *sysno);
330 xfree (rec->info[recInfo_storeData]);
334 rec = rec_new (records);
337 rec->info[recInfo_fileType] =
338 rec_strdup ("grs.sgml", &rec->size[recInfo_fileType]);
339 rec->info[recInfo_databaseName] =
340 rec_strdup ("IR-Explain-1",
341 &rec->size[recInfo_databaseName]);
346 void zebraExplain_flush (ZebraExplainInfo zei, int writeFlag, void *handle)
348 zei->updateHandle = handle;
351 struct zebDatabaseInfoB *zdi;
354 /* write each database info record */
355 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
357 zebraExplain_writeDatabase (zei, zdi, 1);
358 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
359 zdi->databaseName, 1);
361 zebraExplain_writeTarget (zei, 1);
362 zebraExplain_writeCategoryList (zei,
365 assert (zei->accessInfo);
366 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
368 zebraExplain_writeAttributeSet (zei, o, 1);
369 for (o = zei->accessInfo->schemas; o; o = o->next)
372 /* zebraExplain_writeSchema (zei, o, 1); */
375 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
377 zebraExplain_writeDatabase (zei, zdi, 0);
378 zebraExplain_writeAttributeDetails (zei, zdi->attributeDetails,
379 zdi->databaseName, 0);
381 zebraExplain_writeTarget (zei, 0);
385 void zebraExplain_close (ZebraExplainInfo zei, int writeFlag)
388 logf (LOG_LOG, "zebraExplain_close wr=%d", writeFlag);
392 zebraExplain_flush (zei, writeFlag, zei->updateHandle);
393 nmem_destroy (zei->nmem);
396 void zebraExplain_mergeOids (ZebraExplainInfo zei, data1_node *n,
401 for (np = n->child; np; np = np->next)
408 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "oid"))
410 len = np->child->u.data.len;
413 memcpy (str, np->child->u.data.data, len);
416 oid = odr_getoidbystr_nmem (zei->nmem, str);
418 for (ao = *op; ao; ao = ao->next)
419 if (!oid_oidcmp (oid, ao->oid))
426 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
436 void zebraExplain_mergeAccessInfo (ZebraExplainInfo zei, data1_node *n,
437 zebAccessInfo *accessInfo)
443 *accessInfo = (zebAccessInfo)
444 nmem_malloc (zei->nmem, sizeof(**accessInfo));
445 (*accessInfo)->attributeSetIds = NULL;
446 (*accessInfo)->schemas = NULL;
450 if (!(n = data1_search_tag (zei->dh, n->child, "accessInfo")))
452 if ((np = data1_search_tag (zei->dh, n->child, "attributeSetIds")))
453 zebraExplain_mergeOids (zei, np,
454 &(*accessInfo)->attributeSetIds);
455 if ((np = data1_search_tag (zei->dh, n->child, "schemas")))
456 zebraExplain_mergeOids (zei, np,
457 &(*accessInfo)->schemas);
461 ZebraExplainInfo zebraExplain_open (
462 Records records, data1_handle dh,
466 int (*updateFunc)(void *handle, Record drec, data1_node *n))
469 ZebraExplainInfo zei;
470 struct zebDatabaseInfoB **zdip;
473 NMEM nmem = nmem_create ();
476 logf (LOG_LOG, "zebraExplain_open wr=%d", writeFlag);
478 zei = (ZebraExplainInfo) nmem_malloc (nmem, sizeof(*zei));
479 zei->updateHandle = updateHandle;
480 zei->updateFunc = updateFunc;
482 zei->curDatabaseInfo = NULL;
483 zei->records = records;
488 zei->categoryList = (struct zebraCategoryListInfo *)
489 nmem_malloc (zei->nmem, sizeof(*zei->categoryList));
490 zei->categoryList->sysno = 0;
491 zei->categoryList->dirty = 0;
492 zei->categoryList->data1_categoryList = NULL;
495 tm = localtime (&our_time);
496 sprintf (zei->date, "%04d%02d%02d%02d%02d%02d",
497 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
498 tm->tm_hour, tm->tm_min, tm->tm_sec);
500 zdip = &zei->databaseInfo;
501 trec = rec_get (records, 1); /* get "root" record */
506 zebraExplain_mergeAccessInfo (zei, 0, &zei->accessInfo);
507 if (trec) /* targetInfo already exists ... */
509 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
511 zei->data1_target = read_sgml_rec (zei->dh, zei->nmem, trec);
512 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
514 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
515 nmem_destroy (zei->nmem);
519 data1_pr_tree (zei->dh, zei->data1_target, stderr);
521 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
523 zebraExplain_mergeAccessInfo (zei, node_tgtinfo,
526 node_zebra = data1_search_tag (zei->dh, node_tgtinfo->child,
531 node_list = data1_search_tag (zei->dh, node_zebra->child,
534 np = node_list->child;
536 for (; np; np = np->next)
538 data1_node *node_name = NULL;
539 data1_node *node_id = NULL;
540 data1_node *node_aid = NULL;
542 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "database"))
544 for (np2 = np->child; np2; np2 = np2->next)
546 if (np2->which != DATA1N_tag)
548 if (!strcmp (np2->u.tag.tag, "name"))
549 node_name = np2->child;
550 else if (!strcmp (np2->u.tag.tag, "id"))
551 node_id = np2->child;
552 else if (!strcmp (np2->u.tag.tag, "attributeDetailsId"))
553 node_aid = np2->child;
555 assert (node_id && node_name && node_aid);
557 *zdip = (struct zebDatabaseInfoB *)
558 nmem_malloc (zei->nmem, sizeof(**zdip));
559 (*zdip)->readFlag = 1;
561 (*zdip)->data1_database = NULL;
562 (*zdip)->recordCount = 0;
563 (*zdip)->recordBytes = 0;
564 zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
566 (*zdip)->databaseName = (char *)
567 nmem_malloc (zei->nmem, 1+node_name->u.data.len);
568 memcpy ((*zdip)->databaseName, node_name->u.data.data,
569 node_name->u.data.len);
570 (*zdip)->databaseName[node_name->u.data.len] = '\0';
571 (*zdip)->sysno = atoi_n (node_id->u.data.data,
572 node_id->u.data.len);
573 (*zdip)->attributeDetails = (zebAttributeDetails)
574 nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
575 (*zdip)->attributeDetails->sysno = atoi_n (node_aid->u.data.data,
576 node_aid->u.data.len);
577 (*zdip)->attributeDetails->readFlag = 1;
578 (*zdip)->attributeDetails->dirty = 0;
579 (*zdip)->attributeDetails->SUInfo = NULL;
581 zdip = &(*zdip)->next;
585 np = data1_search_tag (zei->dh, node_zebra->child,
588 assert (np && np->which == DATA1N_data);
589 zei->ordinalSU = atoi_n (np->u.data.data, np->u.data.len);
591 np = data1_search_tag (zei->dh, node_zebra->child,
594 assert (np && np->which == DATA1N_data);
595 zei->runNumber = atoi_n (np->u.data.data, np->u.data.len);
600 else /* create initial targetInfo */
602 data1_node *node_tgtinfo;
611 data1_read_sgml (zei->dh, zei->nmem,
612 "<explain><targetInfo>TargetInfo\n"
614 "<namedResultSets>1</>\n"
615 "<multipleDBSearch>1</>\n"
616 "<nicknames><name>Zebra</></>\n"
618 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
620 logf (LOG_FATAL, "Explain schema missing. Check profilePath");
621 nmem_destroy (zei->nmem);
624 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
626 assert (node_tgtinfo);
628 zebraExplain_initCommonInfo (zei, node_tgtinfo);
629 zebraExplain_initAccessInfo (zei, node_tgtinfo);
631 /* write now because we want to be sure about the sysno */
632 trec = rec_new (records);
633 trec->info[recInfo_fileType] =
634 rec_strdup ("grs.sgml", &trec->size[recInfo_fileType]);
635 trec->info[recInfo_databaseName] =
636 rec_strdup ("IR-Explain-1", &trec->size[recInfo_databaseName]);
638 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
639 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
640 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
641 trec->size[recInfo_storeData] = sgml_len;
643 rec_put (records, &trec);
647 zebraExplain_newDatabase (zei, "IR-Explain-1", 0);
649 if (!zei->categoryList->dirty)
651 struct zebraCategoryListInfo *zcl = zei->categoryList;
655 zcl->data1_categoryList =
656 data1_read_sgml (zei->dh, zei->nmem,
657 "<explain><categoryList>CategoryList\n"
660 if (zcl->data1_categoryList)
662 assert (zcl->data1_categoryList->child);
663 node_cl = data1_search_tag (zei->dh,
664 zcl->data1_categoryList->child,
667 zebraExplain_initCommonInfo (zei, node_cl);
674 static void zebraExplain_readAttributeDetails (ZebraExplainInfo zei,
675 zebAttributeDetails zad)
678 struct zebSUInfoB **zsuip = &zad->SUInfo;
679 data1_node *node_adinfo, *node_zebra, *node_list, *np;
682 rec = rec_get (zei->records, zad->sysno);
684 zad->data1_tree = read_sgml_rec (zei->dh, zei->nmem, rec);
686 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
688 node_zebra = data1_search_tag (zei->dh, node_adinfo->child,
690 node_list = data1_search_tag (zei->dh, node_zebra->child,
692 for (np = node_list->child; np; np = np->next)
694 data1_node *node_set = NULL;
695 data1_node *node_use = NULL;
696 data1_node *node_ordinal = NULL;
701 if (np->which != DATA1N_tag || strcmp (np->u.tag.tag, "attr"))
703 for (np2 = np->child; np2; np2 = np2->next)
705 if (np2->which != DATA1N_tag || !np2->child ||
706 np2->child->which != DATA1N_data)
708 if (!strcmp (np2->u.tag.tag, "set"))
709 node_set = np2->child;
710 else if (!strcmp (np2->u.tag.tag, "use"))
711 node_use = np2->child;
712 else if (!strcmp (np2->u.tag.tag, "ordinal"))
713 node_ordinal = np2->child;
715 assert (node_set && node_use && node_ordinal);
717 oid_str_len = node_set->u.data.len;
718 if (oid_str_len >= (int) sizeof(oid_str))
719 oid_str_len = sizeof(oid_str)-1;
720 memcpy (oid_str, node_set->u.data.data, oid_str_len);
721 oid_str[oid_str_len] = '\0';
723 *zsuip = (struct zebSUInfoB *)
724 nmem_malloc (zei->nmem, sizeof(**zsuip));
725 (*zsuip)->info.set = oid_getvalbyname (oid_str);
727 (*zsuip)->info.use = atoi_n (node_use->u.data.data,
728 node_use->u.data.len);
729 (*zsuip)->info.ordinal = atoi_n (node_ordinal->u.data.data,
730 node_ordinal->u.data.len);
731 logf (LOG_DEBUG, "set=%d use=%d ordinal=%d",
732 (*zsuip)->info.set, (*zsuip)->info.use, (*zsuip)->info.ordinal);
733 zsuip = &(*zsuip)->next;
740 static void zebraExplain_readDatabase (ZebraExplainInfo zei,
741 struct zebDatabaseInfoB *zdi)
744 data1_node *node_dbinfo, *node_zebra, *np;
747 rec = rec_get (zei->records, zdi->sysno);
749 zdi->data1_database = read_sgml_rec (zei->dh, zei->nmem, rec);
751 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
753 zebraExplain_mergeAccessInfo (zei, node_dbinfo, &zdi->accessInfo);
755 node_zebra = data1_search_tag (zei->dh, node_dbinfo->child,
758 && (np = data1_search_tag (zei->dh, node_zebra->child,
760 && np->child && np->child->which == DATA1N_data)
761 zdi->recordBytes = atoi_n (np->child->u.data.data,
762 np->child->u.data.len);
763 if ((np = data1_search_tag (zei->dh, node_dbinfo->child,
765 (np = data1_search_tag (zei->dh, np->child,
766 "recordCountActual")) &&
767 np->child->which == DATA1N_data)
769 zdi->recordCount = atoi_n (np->child->u.data.data,
770 np->child->u.data.len);
776 int zebraExplain_curDatabase (ZebraExplainInfo zei, const char *database)
778 struct zebDatabaseInfoB *zdi;
781 if (zei->curDatabaseInfo &&
782 !strcmp (zei->curDatabaseInfo->databaseName, database))
784 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
786 if (!strcmp (zdi->databaseName, database))
792 logf (LOG_LOG, "zebraExplain_curDatabase: %s", database);
797 logf (LOG_LOG, "zebraExplain_readDatabase: %s", database);
799 zebraExplain_readDatabase (zei, zdi);
801 if (zdi->attributeDetails->readFlag)
804 logf (LOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
806 zebraExplain_readAttributeDetails (zei, zdi->attributeDetails);
808 zei->curDatabaseInfo = zdi;
812 static void zebraExplain_initCommonInfo (ZebraExplainInfo zei, data1_node *n)
814 data1_node *c = data1_add_tag (zei->dh, n, "commonInfo", zei->nmem);
816 data1_add_tagdata_text (zei->dh, c, "dateAdded", zei->date, zei->nmem);
817 data1_add_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
818 data1_add_tagdata_text (zei->dh, c, "languageCode", "EN", zei->nmem);
821 static void zebraExplain_updateCommonInfo (ZebraExplainInfo zei, data1_node *n)
823 data1_node *c = data1_search_tag (zei->dh, n->child, "commonInfo");
825 data1_make_tagdata_text (zei->dh, c, "dateChanged", zei->date, zei->nmem);
828 static void zebraExplain_initAccessInfo (ZebraExplainInfo zei, data1_node *n)
830 data1_node *c = data1_add_tag (zei->dh, n, "accessInfo", zei->nmem);
831 data1_node *d = data1_add_tag (zei->dh, c, "unitSystems", zei->nmem);
832 data1_add_tagdata_text (zei->dh, d, "string", "ISO", zei->nmem);
835 static void zebraExplain_updateAccessInfo (ZebraExplainInfo zei, data1_node *n,
836 zebAccessInfo accessInfo)
838 data1_node *c = data1_search_tag (zei->dh, n->child, "accessInfo");
844 if ((p = accessInfo->attributeSetIds))
846 d = data1_make_tag (zei->dh, c, "attributeSetIds", zei->nmem);
847 for (; p; p = p->next)
848 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
850 if ((p = accessInfo->schemas))
852 d = data1_make_tag (zei->dh, c, "schemas", zei->nmem);
853 for (; p; p = p->next)
854 data1_add_tagdata_oid (zei->dh, d, "oid", p->oid, zei->nmem);
858 int zebraExplain_newDatabase (ZebraExplainInfo zei, const char *database,
859 int explain_database)
861 struct zebDatabaseInfoB *zdi;
862 data1_node *node_dbinfo, *node_adinfo;
865 logf (LOG_LOG, "zebraExplain_newDatabase: %s", database);
868 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
870 if (!strcmp (zdi->databaseName, database))
875 /* it's new really. make it */
876 zdi = (struct zebDatabaseInfoB *) nmem_malloc (zei->nmem, sizeof(*zdi));
877 zdi->next = zei->databaseInfo;
878 zei->databaseInfo = zdi;
880 zdi->recordCount = 0;
881 zdi->recordBytes = 0;
883 zdi->databaseName = nmem_strdup (zei->nmem, database);
885 zebraExplain_mergeAccessInfo (zei, 0, &zdi->accessInfo);
890 zdi->data1_database =
891 data1_read_sgml (zei->dh, zei->nmem,
892 "<explain><databaseInfo>DatabaseInfo\n"
894 if (!zdi->data1_database)
897 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
899 assert (node_dbinfo);
901 zebraExplain_initCommonInfo (zei, node_dbinfo);
902 zebraExplain_initAccessInfo (zei, node_dbinfo);
904 data1_add_tagdata_text (zei->dh, node_dbinfo, "name",
905 database, zei->nmem);
907 if (explain_database)
908 data1_add_tagdata_text (zei->dh, node_dbinfo, "explainDatabase",
911 data1_add_tagdata_text (zei->dh, node_dbinfo, "userFee",
914 data1_add_tagdata_text (zei->dh, node_dbinfo, "available",
918 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
922 zei->curDatabaseInfo = zdi;
924 zdi->attributeDetails = (zebAttributeDetails)
925 nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
926 zdi->attributeDetails->readFlag = 0;
927 zdi->attributeDetails->sysno = 0;
928 zdi->attributeDetails->dirty = 1;
929 zdi->attributeDetails->SUInfo = NULL;
930 zdi->attributeDetails->data1_tree =
931 data1_read_sgml (zei->dh, zei->nmem,
932 "<explain><attributeDetails>AttributeDetails\n"
936 data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree->child,
938 assert (node_adinfo);
940 zebraExplain_initCommonInfo (zei, node_adinfo);
945 static void writeAttributeValueDetails (ZebraExplainInfo zei,
946 zebAttributeDetails zad,
947 data1_node *node_atvs, data1_attset *attset)
950 struct zebSUInfoB *zsui;
951 int set_ordinal = attset->reference;
952 data1_attset_child *c;
954 for (c = attset->children; c; c = c->next)
955 writeAttributeValueDetails (zei, zad, node_atvs, c->child);
956 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
958 data1_node *node_attvalue, *node_value;
959 if (set_ordinal != zsui->info.set)
961 node_attvalue = data1_add_tag (zei->dh, node_atvs, "attributeValue",
963 node_value = data1_add_tag (zei->dh, node_attvalue, "value",
965 data1_add_tagdata_int (zei->dh, node_value, "numeric",
966 zsui->info.use, zei->nmem);
970 static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
971 struct zebraCategoryListInfo *zcl,
978 data1_node *node_ci, *node_categoryList;
980 static char *category[] = {
992 node_categoryList = zcl->data1_categoryList;
995 logf (LOG_LOG, "zebraExplain_writeCategoryList");
998 drec = createRecord (zei->records, &sysno);
1000 node_ci = data1_search_tag (zei->dh, node_categoryList->child,
1003 node_ci = data1_add_tag (zei->dh, node_ci, "categories", zei->nmem);
1006 for (i = 0; category[i]; i++)
1008 data1_node *node_cat = data1_add_tag (zei->dh, node_ci,
1009 "category", zei->nmem);
1011 data1_add_tagdata_text (zei->dh, node_cat, "name",
1012 category[i], zei->nmem);
1014 /* extract *searchable* keys from it. We do this here, because
1015 record count, etc. is affected */
1017 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1019 /* convert to "SGML" and write it */
1021 data1_pr_tree (zei->dh, node_categoryList, stderr);
1023 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1024 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1025 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1026 drec->size[recInfo_storeData] = sgml_len;
1028 rec_put (zei->records, &drec);
1031 static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
1032 zebAttributeDetails zad,
1033 const char *databaseName,
1039 data1_node *node_adinfo, *node_list, *node_zebra, *node_attributesBySet;
1040 struct zebSUInfoB *zsui;
1048 logf (LOG_LOG, "zebraExplain_writeAttributeDetails");
1051 drec = createRecord (zei->records, &zad->sysno);
1052 assert (zad->data1_tree);
1053 node_adinfo = data1_search_tag (zei->dh, zad->data1_tree->child,
1054 "attributeDetails");
1055 zebraExplain_updateCommonInfo (zei, node_adinfo);
1057 data1_add_tagdata_text (zei->dh, node_adinfo, "name",
1058 databaseName, zei->nmem);
1060 /* extract *searchable* keys from it. We do this here, because
1061 record count, etc. is affected */
1063 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1065 node_attributesBySet = data1_make_tag (zei->dh, node_adinfo,
1066 "attributesBySet", zei->nmem);
1070 data1_node *node_asd;
1071 data1_attset *attset;
1072 int set_ordinal = -1;
1073 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1075 if ((set_ordinal < 0 || set_ordinal > zsui->info.set)
1076 && zsui->info.set > set_min)
1077 set_ordinal = zsui->info.set;
1079 if (set_ordinal < 0)
1081 set_min = set_ordinal;
1082 node_asd = data1_add_tag (zei->dh, node_attributesBySet,
1083 "attributeSetDetails", zei->nmem);
1085 attset = data1_attset_search_id (zei->dh, set_ordinal);
1088 zebraExplain_loadAttsets (zei->dh, zei->res);
1089 attset = data1_attset_search_id (zei->dh, set_ordinal);
1096 oe.proto = PROTO_Z3950;
1097 oe.oclass = CLASS_ATTSET;
1098 oe.value = (enum oid_value) set_ordinal;
1100 if (oid_ent_to_oid (&oe, oid))
1102 data1_node *node_abt, *node_atd, *node_atvs;
1103 data1_add_tagdata_oid (zei->dh, node_asd, "oid",
1106 node_abt = data1_add_tag (zei->dh, node_asd,
1107 "attributesByType", zei->nmem);
1108 node_atd = data1_add_tag (zei->dh, node_abt,
1109 "attributeTypeDetails", zei->nmem);
1110 data1_add_tagdata_int (zei->dh, node_atd,
1111 "type", 1, zei->nmem);
1112 node_atvs = data1_add_tag (zei->dh, node_atd,
1113 "attributeValues", zei->nmem);
1114 writeAttributeValueDetails (zei, zad, node_atvs, attset);
1118 /* zebra info (private) */
1119 node_zebra = data1_make_tag (zei->dh, node_adinfo,
1120 "zebraInfo", zei->nmem);
1121 node_list = data1_make_tag (zei->dh, node_zebra,
1122 "attrlist", zei->nmem);
1123 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1125 struct oident oident;
1127 data1_node *node_attr;
1129 node_attr = data1_add_tag (zei->dh, node_list, "attr", zei->nmem);
1131 oident.proto = PROTO_Z3950;
1132 oident.oclass = CLASS_ATTSET;
1133 oident.value = (enum oid_value) zsui->info.set;
1134 oid_ent_to_oid (&oident, oid);
1136 data1_add_tagdata_text (zei->dh, node_attr, "set",
1137 oident.desc, zei->nmem);
1138 data1_add_tagdata_int (zei->dh, node_attr, "use",
1139 zsui->info.use, zei->nmem);
1140 data1_add_tagdata_int (zei->dh, node_attr, "ordinal",
1141 zsui->info.ordinal, zei->nmem);
1143 /* convert to "SGML" and write it */
1145 data1_pr_tree (zei->dh, zad->data1_tree, stderr);
1147 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1149 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1150 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1151 drec->size[recInfo_storeData] = sgml_len;
1153 rec_put (zei->records, &drec);
1156 static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
1157 struct zebDatabaseInfoB *zdi,
1163 data1_node *node_dbinfo, *node_count, *node_zebra;
1170 logf (LOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1172 drec = createRecord (zei->records, &zdi->sysno);
1173 assert (zdi->data1_database);
1174 node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database->child,
1177 zebraExplain_updateCommonInfo (zei, node_dbinfo);
1178 zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
1180 /* extract *searchable* keys from it. We do this here, because
1181 record count, etc. is affected */
1183 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1185 node_count = data1_make_tag (zei->dh, node_dbinfo,
1186 "recordCount", zei->nmem);
1187 data1_add_tagdata_int (zei->dh, node_count, "recordCountActual",
1188 zdi->recordCount, zei->nmem);
1190 /* zebra info (private) */
1191 node_zebra = data1_make_tag (zei->dh, node_dbinfo,
1192 "zebraInfo", zei->nmem);
1193 data1_add_tagdata_int (zei->dh, node_zebra,
1194 "recordBytes", zdi->recordBytes, zei->nmem);
1195 /* convert to "SGML" and write it */
1197 data1_pr_tree (zei->dh, zdi->data1_database, stderr);
1199 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1201 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1202 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1203 drec->size[recInfo_storeData] = sgml_len;
1205 rec_put (zei->records, &drec);
1208 static void writeAttributeValues (ZebraExplainInfo zei,
1209 data1_node *node_values,
1210 data1_attset *attset)
1213 data1_attset_child *c;
1218 for (c = attset->children; c; c = c->next)
1219 writeAttributeValues (zei, node_values, c->child);
1220 for (atts = attset->atts; atts; atts = atts->next)
1222 data1_node *node_value;
1224 node_value = data1_add_tag (zei->dh, node_values, "attributeValue",
1226 data1_add_tagdata_text (zei->dh, node_value, "name",
1227 atts->name, zei->nmem);
1228 node_value = data1_add_tag (zei->dh, node_value, "value", zei->nmem);
1229 data1_add_tagdata_int (zei->dh, node_value, "numeric",
1230 atts->value, zei->nmem);
1235 static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
1242 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1243 data1_node *node_values;
1244 struct oident *entp;
1245 struct data1_attset *attset = NULL;
1247 if ((entp = oid_getentbyoid (o->oid)))
1248 attset = data1_attset_search_id (zei->dh, entp->value);
1251 logf (LOG_LOG, "zebraExplain_writeAttributeSet %s",
1252 attset ? attset->name : "<unknown>");
1255 drec = createRecord (zei->records, &o->sysno);
1257 data1_read_sgml (zei->dh, zei->nmem,
1258 "<explain><attributeSetInfo>AttributeSetInfo\n"
1261 node_attinfo = data1_search_tag (zei->dh, node_root->child,
1262 "attributeSetInfo");
1264 zebraExplain_initCommonInfo (zei, node_attinfo);
1265 zebraExplain_updateCommonInfo (zei, node_attinfo);
1267 data1_add_tagdata_oid (zei->dh, node_attinfo,
1268 "oid", o->oid, zei->nmem);
1269 if (attset && attset->name)
1270 data1_add_tagdata_text (zei->dh, node_attinfo,
1271 "name", attset->name, zei->nmem);
1273 node_attributes = data1_make_tag (zei->dh, node_attinfo,
1274 "attributes", zei->nmem);
1275 node_atttype = data1_make_tag (zei->dh, node_attributes,
1276 "attributeType", zei->nmem);
1277 data1_add_tagdata_text (zei->dh, node_atttype,
1278 "name", "Use", zei->nmem);
1279 data1_add_tagdata_text (zei->dh, node_atttype,
1280 "description", "Use Attribute", zei->nmem);
1281 data1_add_tagdata_int (zei->dh, node_atttype,
1282 "type", 1, zei->nmem);
1283 node_values = data1_add_tag (zei->dh, node_atttype,
1284 "attributeValues", zei->nmem);
1286 writeAttributeValues (zei, node_values, attset);
1288 /* extract *searchable* keys from it. We do this here, because
1289 record count, etc. is affected */
1291 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1292 /* convert to "SGML" and write it */
1294 data1_pr_tree (zei->dh, node_root, stderr);
1296 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1297 drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1298 memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
1299 drec->size[recInfo_storeData] = sgml_len;
1301 rec_put (zei->records, &drec);
1304 static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
1306 struct zebDatabaseInfoB *zdi;
1307 data1_node *node_tgtinfo, *node_list, *node_zebra;
1316 trec = rec_get (zei->records, 1);
1317 xfree (trec->info[recInfo_storeData]);
1319 node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target->child,
1321 assert (node_tgtinfo);
1323 zebraExplain_updateCommonInfo (zei, node_tgtinfo);
1324 zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
1326 /* convert to "SGML" and write it */
1328 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1330 node_zebra = data1_make_tag (zei->dh, node_tgtinfo,
1331 "zebraInfo", zei->nmem);
1332 data1_add_tagdata_text (zei->dh, node_zebra, "version",
1333 ZEBRAVER, zei->nmem);
1334 node_list = data1_add_tag (zei->dh, node_zebra,
1335 "databaseList", zei->nmem);
1336 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1338 data1_node *node_db;
1339 node_db = data1_add_tag (zei->dh, node_list,
1340 "database", zei->nmem);
1341 data1_add_tagdata_text (zei->dh, node_db, "name",
1342 zdi->databaseName, zei->nmem);
1343 data1_add_tagdata_int (zei->dh, node_db, "id",
1344 zdi->sysno, zei->nmem);
1345 data1_add_tagdata_int (zei->dh, node_db, "attributeDetailsId",
1346 zdi->attributeDetails->sysno, zei->nmem);
1348 data1_add_tagdata_int (zei->dh, node_zebra, "ordinalSU",
1349 zei->ordinalSU, zei->nmem);
1351 data1_add_tagdata_int (zei->dh, node_zebra, "runNumber",
1352 zei->runNumber, zei->nmem);
1355 data1_pr_tree (zei->dh, zei->data1_target, stderr);
1357 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1359 trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
1360 memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
1361 trec->size[recInfo_storeData] = sgml_len;
1363 rec_put (zei->records, &trec);
1366 int zebraExplain_lookupSU (ZebraExplainInfo zei, int set, int use)
1368 struct zebSUInfoB *zsui;
1370 assert (zei->curDatabaseInfo);
1371 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1372 zsui; zsui=zsui->next)
1373 if (zsui->info.use == use && zsui->info.set == set)
1374 return zsui->info.ordinal;
1378 int zebraExplain_lookup_ord (ZebraExplainInfo zei, int ord,
1379 const char **db, int *set, int *use)
1381 struct zebDatabaseInfoB *zdb;
1382 for (zdb = zei->databaseInfo; zdb; zdb = zdb->next)
1384 struct zebSUInfoB *zsui = zdb->attributeDetails->SUInfo;
1385 for ( ;zsui; zsui = zsui->next)
1386 if (zsui->info.ordinal == ord)
1388 *db = zdb->databaseName;
1389 *set = zsui->info.set;
1390 *use = zsui->info.use;
1397 zebAccessObject zebraExplain_announceOid (ZebraExplainInfo zei,
1398 zebAccessObject *op,
1403 for (ao = *op; ao; ao = ao->next)
1404 if (!oid_oidcmp (oid, ao->oid))
1408 ao = (zebAccessObject) nmem_malloc (zei->nmem, sizeof(*ao));
1411 ao->oid = odr_oiddup_nmem (zei->nmem, oid);
1418 void zebraExplain_addAttributeSet (ZebraExplainInfo zei, int set)
1423 oe.proto = PROTO_Z3950;
1424 oe.oclass = CLASS_ATTSET;
1425 oe.value = (enum oid_value) set;
1427 if (oid_ent_to_oid (&oe, oid))
1429 zebraExplain_announceOid (zei, &zei->accessInfo->attributeSetIds, oid);
1430 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1431 accessInfo->attributeSetIds, oid);
1435 int zebraExplain_addSU (ZebraExplainInfo zei, int set, int use)
1437 struct zebSUInfoB *zsui;
1439 assert (zei->curDatabaseInfo);
1440 for (zsui = zei->curDatabaseInfo->attributeDetails->SUInfo;
1441 zsui; zsui=zsui->next)
1442 if (zsui->info.use == use && zsui->info.set == set)
1444 zebraExplain_addAttributeSet (zei, set);
1445 zsui = (struct zebSUInfoB *) nmem_malloc (zei->nmem, sizeof(*zsui));
1446 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1447 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1448 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1450 zsui->info.set = set;
1451 zsui->info.use = use;
1452 zsui->info.ordinal = (zei->ordinalSU)++;
1453 return zsui->info.ordinal;
1456 void zebraExplain_addSchema (ZebraExplainInfo zei, Odr_oid *oid)
1458 zebraExplain_announceOid (zei, &zei->accessInfo->schemas, oid);
1459 zebraExplain_announceOid (zei, &zei->curDatabaseInfo->
1460 accessInfo->schemas, oid);
1463 void zebraExplain_recordBytesIncrement (ZebraExplainInfo zei, int adjust_num)
1465 assert (zei->curDatabaseInfo);
1469 zei->curDatabaseInfo->recordBytes += adjust_num;
1470 zei->curDatabaseInfo->dirty = 1;
1474 void zebraExplain_recordCountIncrement (ZebraExplainInfo zei, int adjust_num)
1476 assert (zei->curDatabaseInfo);
1480 zei->curDatabaseInfo->recordCount += adjust_num;
1481 zei->curDatabaseInfo->dirty = 1;
1485 int zebraExplain_runNumberIncrement (ZebraExplainInfo zei, int adjust_num)
1489 return zei->runNumber += adjust_num;
1492 RecordAttr *rec_init_attr (ZebraExplainInfo zei, Record rec)
1494 RecordAttr *recordAttr;
1496 if (rec->info[recInfo_attr])
1497 return (RecordAttr *) rec->info[recInfo_attr];
1498 recordAttr = (RecordAttr *) xmalloc (sizeof(*recordAttr));
1499 rec->info[recInfo_attr] = (char *) recordAttr;
1500 rec->size[recInfo_attr] = sizeof(*recordAttr);
1502 recordAttr->recordSize = 0;
1503 recordAttr->recordOffset = 0;
1504 recordAttr->runNumber = zei->runNumber;
1508 static void att_loadset(void *p, const char *n, const char *name)
1510 data1_handle dh = (data1_handle) p;
1511 if (!data1_get_attset (dh, name))
1512 logf (LOG_WARN, "Couldn't load attribute set %s", name);
1515 void zebraExplain_loadAttsets (data1_handle dh, Res res)
1517 res_trav(res, "attset", dh, att_loadset);
1521 zebraExplain_addSU adds to AttributeDetails for a database and
1522 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1523 exist for the database.
1525 If the database doesn't exist globally (in TargetInfo) an
1526 AttributeSetInfo must be added (globally).