+ zei->dirty = 1;
+ zei->curDatabaseInfo = zdi;
+
+ zdi->attributeDetails = (zebAttributeDetails)
+ nmem_malloc (zei->nmem, sizeof(*zdi->attributeDetails));
+ zdi->attributeDetails->readFlag = 0;
+ zdi->attributeDetails->sysno = 0;
+ zdi->attributeDetails->dirty = 1;
+ zdi->attributeDetails->SUInfo = NULL;
+ zdi->attributeDetails->data1_tree =
+ data1_read_sgml (zei->dh, zei->nmem,
+ "<explain><attributeDetails>AttributeDetails\n"
+ "</></>\n");
+
+ node_adinfo = data1_search_tag (zei->dh, zdi->attributeDetails->data1_tree,
+ "/attributeDetails");
+ assert (node_adinfo);
+
+ zebraExplain_initCommonInfo (zei, node_adinfo);
+
+ return 0;
+}
+
+
+static void zebraExplain_writeCategoryList (ZebraExplainInfo zei,
+ struct zebraCategoryListInfo *zcl,
+ int key_flush)
+{
+ char *sgml_buf;
+ int sgml_len;
+ int i;
+ Record drec;
+ data1_node *node_ci, *node_categoryList;
+ SYSNO sysno = 0;
+ static char *category[] = {
+ "CategoryList",
+ "TargetInfo",
+ "DatabaseInfo",
+ "AttributeDetails",
+ NULL
+ };
+
+ assert (zcl);
+ if (!zcl->dirty)
+ return ;
+ zcl->dirty = 1;
+ node_categoryList = zcl->data1_categoryList;
+
+#if ZINFO_DEBUG
+ yaz_log(YLOG_LOG, "zebraExplain_writeCategoryList");
+#endif
+
+ drec = createRecord (zei->records, &sysno);
+ if (!drec)
+ return;
+
+ node_ci = data1_search_tag (zei->dh, node_categoryList,
+ "/categoryList");
+ assert (node_ci);
+ node_ci = data1_mk_tag (zei->dh, zei->nmem, "categories", 0 /* attr */,
+ node_ci);
+ assert (node_ci);
+
+ for (i = 0; category[i]; i++)
+ {
+ data1_node *node_cat = data1_mk_tag (zei->dh, zei->nmem, "category",
+ 0 /* attr */, node_ci);
+
+ data1_mk_tag_data_text (zei->dh, node_cat, "name",
+ category[i], zei->nmem);
+ }
+ /* extract *searchable* keys from it. We do this here, because
+ record count, etc. is affected */
+ if (key_flush)
+ (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
+
+ /* convert to "SGML" and write it */
+#if ZINFO_DEBUG
+ data1_pr_tree (zei->dh, node_categoryList, stderr);
+#endif
+ sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
+ drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
+ memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
+ drec->size[recInfo_storeData] = sgml_len;
+
+ rec_put (zei->records, &drec);
+}
+
+static void zebraExplain_writeAttributeDetails (ZebraExplainInfo zei,
+ zebAttributeDetails zad,
+ const char *databaseName,
+ int key_flush)
+{
+ char *sgml_buf;
+ int sgml_len;
+ Record drec;
+ data1_node *node_adinfo, *node_list, *node_zebra;
+ struct zebSUInfoB *zsui;
+
+ if (!zad->dirty)
+ return;
+
+ zad->dirty = 0;
+#if ZINFO_DEBUG
+ yaz_log(YLOG_LOG, "zebraExplain_writeAttributeDetails");
+#endif
+
+ drec = createRecord (zei->records, &zad->sysno);
+ if (!drec)
+ return;
+ assert (zad->data1_tree);
+
+ node_adinfo = data1_search_tag (zei->dh, zad->data1_tree,
+ "/attributeDetails");
+ zebraExplain_updateCommonInfo (zei, node_adinfo);
+
+ data1_mk_tag_data_text (zei->dh, node_adinfo, "name",
+ databaseName, zei->nmem);
+
+ /* extract *searchable* keys from it. We do this here, because
+ record count, etc. is affected */
+ if (key_flush)
+ (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
+ /* zebra info (private) */
+ node_zebra = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "zebraInfo", node_adinfo);
+ node_list = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "attrlist", node_zebra);
+ for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
+ {
+ data1_node *node_attr;
+ char index_type_str[2];
+
+ node_attr = data1_mk_tag (zei->dh, zei->nmem, "attr", 0 /* attr */,
+ node_list);
+
+ index_type_str[0] = zsui->info.index_type;
+ index_type_str[1] = '\0';
+ data1_mk_tag_data_text (zei->dh, node_attr, "type",
+ index_type_str, zei->nmem);
+ if (zsui->info.which == ZEB_SU_STR)
+ {
+ data1_mk_tag_data_text (zei->dh, node_attr, "str",
+ zsui->info.u.str, zei->nmem);
+ }
+ data1_mk_tag_data_int (zei->dh, node_attr, "ordinal",
+ zsui->info.ordinal, zei->nmem);
+
+ data1_mk_tag_data_zint (zei->dh, node_attr, "dococcurrences",
+ zsui->info.doc_occurrences, zei->nmem);
+ data1_mk_tag_data_zint (zei->dh, node_attr, "termoccurrences",
+ zsui->info.term_occurrences, zei->nmem);
+ switch(zsui->info.cat)
+ {
+ case zinfo_index_category_index:
+ data1_mk_tag_data_text (zei->dh, node_attr, "cat",
+ "index", zei->nmem); break;
+ case zinfo_index_category_sort:
+ data1_mk_tag_data_text (zei->dh, node_attr, "cat",
+ "sort", zei->nmem); break;
+ case zinfo_index_category_alwaysmatches:
+ data1_mk_tag_data_text (zei->dh, node_attr, "cat",
+ "alwaysmatches", zei->nmem); break;
+ case zinfo_index_category_anchor:
+ data1_mk_tag_data_text (zei->dh, node_attr, "cat",
+ "anchor", zei->nmem); break;
+ }
+ }
+ /* convert to "SGML" and write it */
+#if ZINFO_DEBUG
+ data1_pr_tree (zei->dh, zad->data1_tree, stderr);
+#endif
+ sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
+ 0, &sgml_len);
+ drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
+ memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
+ drec->size[recInfo_storeData] = sgml_len;
+
+ rec_put (zei->records, &drec);
+}
+
+static void zebraExplain_writeDatabase (ZebraExplainInfo zei,
+ struct zebDatabaseInfoB *zdi,
+ int key_flush)
+{
+ char *sgml_buf;
+ int sgml_len;
+ Record drec;
+ data1_node *node_dbinfo, *node_count, *node_zebra;
+
+ if (!zdi->dirty)
+ return;
+
+ zdi->dirty = 0;
+#if ZINFO_DEBUG
+ yaz_log(YLOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
+#endif
+ drec = createRecord (zei->records, &zdi->sysno);
+ if (!drec)
+ return;
+ assert (zdi->data1_database);
+
+ node_dbinfo = data1_search_tag (zei->dh, zdi->data1_database,
+ "/databaseInfo");
+
+ assert (node_dbinfo);
+ zebraExplain_updateCommonInfo (zei, node_dbinfo);
+ zebraExplain_updateAccessInfo (zei, node_dbinfo, zdi->accessInfo);
+
+ /* extract *searchable* keys from it. We do this here, because
+ record count, etc. is affected */
+ if (key_flush)
+ (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
+ /* record count */
+ node_count = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "recordCount", node_dbinfo);
+ data1_mk_tag_data_zint (zei->dh, node_count, "recordCountActual",
+ zdi->recordCount, zei->nmem);
+
+ /* zebra info (private) */
+ node_zebra = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "zebraInfo", node_dbinfo);
+ data1_mk_tag_data_zint (zei->dh, node_zebra,
+ "recordBytes", zdi->recordBytes, zei->nmem);
+
+ data1_mk_tag_data_zint(zei->dh, node_zebra,
+ "ordinalDatabase", zdi->ordinalDatabase, zei->nmem);
+
+ /* convert to "SGML" and write it */
+#if ZINFO_DEBUG
+ data1_pr_tree (zei->dh, zdi->data1_database, stderr);
+#endif
+ sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
+ 0, &sgml_len);
+ drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
+ memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
+ drec->size[recInfo_storeData] = sgml_len;
+
+ rec_put (zei->records, &drec);
+}
+
+static void writeAttributeValues (ZebraExplainInfo zei,
+ data1_node *node_values,
+ data1_attset *attset)
+{
+ data1_att *atts;
+ data1_attset_child *c;
+
+ if (!attset)
+ return;
+
+ for (c = attset->children; c; c = c->next)
+ writeAttributeValues (zei, node_values, c->child);
+ for (atts = attset->atts; atts; atts = atts->next)
+ {
+ data1_node *node_value;
+
+ node_value = data1_mk_tag (zei->dh, zei->nmem, "attributeValue",
+ 0 /* attr */, node_values);
+ data1_mk_tag_data_text (zei->dh, node_value, "name",
+ atts->name, zei->nmem);
+ node_value = data1_mk_tag (zei->dh, zei->nmem, "value",
+ 0 /* attr */, node_value);
+ data1_mk_tag_data_int (zei->dh, node_value, "numeric",
+ atts->value, zei->nmem);
+ }
+}
+
+
+static void zebraExplain_writeAttributeSet (ZebraExplainInfo zei,
+ zebAccessObject o,
+ int key_flush)
+{
+ char *sgml_buf;
+ int sgml_len;
+ Record drec;
+ data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
+ data1_node *node_values;
+ struct oident *entp;
+ struct data1_attset *attset = NULL;
+
+ if ((entp = oid_getentbyoid (o->oid)))
+ attset = data1_attset_search_id (zei->dh, entp->value);
+
+#if ZINFO_DEBUG
+ yaz_log(YLOG_LOG, "zebraExplain_writeAttributeSet %s",
+ attset ? attset->name : "<unknown>");
+#endif
+
+ drec = createRecord (zei->records, &o->sysno);
+ if (!drec)
+ return;
+ node_root =
+ data1_read_sgml (zei->dh, zei->nmem,
+ "<explain><attributeSetInfo>AttributeSetInfo\n"
+ "</></>\n" );
+
+ node_attinfo = data1_search_tag (zei->dh, node_root,
+ "/attributeSetInfo");
+
+ assert (node_attinfo);
+ zebraExplain_initCommonInfo (zei, node_attinfo);
+ zebraExplain_updateCommonInfo (zei, node_attinfo);
+
+ data1_mk_tag_data_oid (zei->dh, node_attinfo,
+ "oid", o->oid, zei->nmem);
+ if (attset && attset->name)
+ data1_mk_tag_data_text (zei->dh, node_attinfo,
+ "name", attset->name, zei->nmem);
+
+ node_attributes = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "attributes", node_attinfo);
+ node_atttype = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "attributeType", node_attributes);
+ data1_mk_tag_data_text (zei->dh, node_atttype,
+ "name", "Use", zei->nmem);
+ data1_mk_tag_data_text (zei->dh, node_atttype,
+ "description", "Use Attribute", zei->nmem);
+ data1_mk_tag_data_int (zei->dh, node_atttype,
+ "type", 1, zei->nmem);
+ node_values = data1_mk_tag (zei->dh, zei->nmem,
+ "attributeValues", 0 /* attr */, node_atttype);
+ if (attset)
+ writeAttributeValues (zei, node_values, attset);
+
+ /* extract *searchable* keys from it. We do this here, because
+ record count, etc. is affected */
+ if (key_flush)
+ (*zei->updateFunc)(zei->updateHandle, drec, node_root);
+ /* convert to "SGML" and write it */
+#if ZINFO_DEBUG
+ data1_pr_tree (zei->dh, node_root, stderr);
+#endif
+ sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
+ drec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
+ memcpy (drec->info[recInfo_storeData], sgml_buf, sgml_len);
+ drec->size[recInfo_storeData] = sgml_len;
+
+ rec_put (zei->records, &drec);
+}
+
+static void zebraExplain_writeTarget (ZebraExplainInfo zei, int key_flush)
+{
+ struct zebDatabaseInfoB *zdi;
+ data1_node *node_tgtinfo, *node_list, *node_zebra;
+ Record trec;
+ int sgml_len;
+ char *sgml_buf;
+
+ if (!zei->dirty)
+ return;
+ zei->dirty = 0;
+
+ trec = rec_get_root(zei->records);
+ xfree (trec->info[recInfo_storeData]);
+
+ node_tgtinfo = data1_search_tag (zei->dh, zei->data1_target,
+ "/targetInfo");
+ assert (node_tgtinfo);
+
+ zebraExplain_updateCommonInfo (zei, node_tgtinfo);
+ zebraExplain_updateAccessInfo (zei, node_tgtinfo, zei->accessInfo);
+
+ /* convert to "SGML" and write it */
+ if (key_flush)
+ (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
+
+ node_zebra = data1_mk_tag_uni (zei->dh, zei->nmem,
+ "zebraInfo", node_tgtinfo);
+ data1_mk_tag_data_text (zei->dh, node_zebra, "version",
+ ZEBRAVER, zei->nmem);
+ node_list = data1_mk_tag (zei->dh, zei->nmem,
+ "databaseList", 0 /* attr */, node_zebra);
+ for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
+ {
+ data1_node *node_db;
+ node_db = data1_mk_tag (zei->dh, zei->nmem,
+ "database", 0 /* attr */, node_list);
+ data1_mk_tag_data_text (zei->dh, node_db, "name",
+ zdi->databaseName, zei->nmem);
+ data1_mk_tag_data_zint (zei->dh, node_db, "id",
+ zdi->sysno, zei->nmem);
+ data1_mk_tag_data_zint (zei->dh, node_db, "attributeDetailsId",
+ zdi->attributeDetails->sysno, zei->nmem);
+ }
+ data1_mk_tag_data_int (zei->dh, node_zebra, "ordinalSU",
+ zei->ordinalSU, zei->nmem);
+
+ data1_mk_tag_data_int (zei->dh, node_zebra, "ordinalDatabase",
+ zei->ordinalDatabase, zei->nmem);
+
+ data1_mk_tag_data_zint (zei->dh, node_zebra, "runNumber",
+ zei->runNumber, zei->nmem);
+
+#if ZINFO_DEBUG
+ data1_pr_tree (zei->dh, zei->data1_target, stderr);
+#endif
+ sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
+ 0, &sgml_len);
+ trec->info[recInfo_storeData] = (char *) xmalloc (sgml_len);
+ memcpy (trec->info[recInfo_storeData], sgml_buf, sgml_len);
+ trec->size[recInfo_storeData] = sgml_len;
+
+ rec_put (zei->records, &trec);
+}
+
+int zebraExplain_lookup_attr_str(ZebraExplainInfo zei,
+ zinfo_index_category_t cat,
+ int index_type,
+ const char *str)
+{
+ struct zebSUInfoB **zsui;
+
+ assert (zei->curDatabaseInfo);
+ for (zsui = &zei->curDatabaseInfo->attributeDetails->SUInfo;
+ *zsui; zsui = &(*zsui)->next)
+ if ((*zsui)->info.index_type == index_type
+ && (*zsui)->info.cat == cat
+ && (*zsui)->info.which == ZEB_SU_STR
+ && !yaz_matchstr((*zsui)->info.u.str, str))
+ {
+ struct zebSUInfoB *zsui_this = *zsui;
+
+ /* take it out of the list and move to front */
+ *zsui = (*zsui)->next;
+ zsui_this->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
+ zei->curDatabaseInfo->attributeDetails->SUInfo = zsui_this;
+
+ return zsui_this->info.ordinal;
+ }
+ return -1;
+}
+
+int zebraExplain_trav_ord(ZebraExplainInfo zei, void *handle,
+ int (*f)(void *handle, int ord))
+{
+ struct zebDatabaseInfoB *zdb = zei->curDatabaseInfo;
+ if (zdb)
+ {
+ struct zebSUInfoB *zsui = zdb->attributeDetails->SUInfo;
+ for ( ;zsui; zsui = zsui->next)
+ (*f)(handle, zsui->info.ordinal);
+ }