+ if (!(n = data1_search_tag(zei->dh, n->child, "accessInfo")))
+ return;
+ if ((np = data1_search_tag(zei->dh, n->child, "attributeSetIds")))
+ zebraExplain_mergeOids(zei, np,
+ &(*accessInfo)->attributeSetIds);
+ if ((np = data1_search_tag(zei->dh, n->child, "schemas")))
+ zebraExplain_mergeOids(zei, np,
+ &(*accessInfo)->schemas);
+ }
+}
+
+/* Explain structure
+ root record
+ of type targetInfo
+ and has sysno = 1
+
+ databaseList (list of databases)
+*/
+/*
+Example root:
+explain:
+ targetInfo: TargetInfo
+ name: Zebra
+ namedResultSets: 1
+ multipleDbSearch: 1
+ nicknames:
+ name: Zebra
+ commonInfo:
+ dateAdded: 20030630190601
+ dateChanged: 20030630190601
+ languageCode: EN
+ accessinfo:
+ unitSystems:
+ string: ISO
+ attributeSetIds:
+ oid: 1.2.840.10003.3.2
+ oid: 1.2.840.10003.3.5
+ oid: 1.2.840.10003.3.1
+ schemas:
+ oid: 1.2.840.10003.13.1000.81.2
+ oid: 1.2.840.10003.13.2
+ zebraInfo:
+ version: 1.3.12
+ databaseList:
+ database:
+ name: Default
+ id: 50
+ attributeDetailsId: 51
+ database:
+ name: IR-Explain-1
+ id: 52
+ attributeDetailsId: 53
+ ordinalSU: 38
+ runNumber: 1
+nextResultSetPosition = 2
+*/
+
+ZebraExplainInfo zebraExplain_open(
+ Records records, data1_handle dh,
+ Res res,
+ int writeFlag,
+ void *updateHandle,
+ int (*updateFunc)(void *handle, Record drec, data1_node *n))
+{
+ Record trec;
+ ZebraExplainInfo zei;
+ struct zebDatabaseInfoB **zdip;
+ time_t our_time;
+ struct tm *tm;
+ NMEM nmem = nmem_create();
+
+#if ZINFO_DEBUG
+ yaz_log(YLOG_LOG, "zebraExplain_open wr=%d", writeFlag);
+#endif
+ zei = (ZebraExplainInfo) nmem_malloc(nmem, sizeof(*zei));
+ zei->databaseInfo = 0;
+ zei->write_flag = writeFlag;
+ zei->updateHandle = updateHandle;
+ zei->updateFunc = updateFunc;
+ zei->dirty = 0;
+ zei->ordinalDatabase = 1;
+ zei->curDatabaseInfo = NULL;
+ zei->records = records;
+ zei->nmem = nmem;
+ zei->dh = dh;
+ zei->attsets = NULL;
+ zei->res = res;
+ zei->categoryList = (struct zebraCategoryListInfo *)
+ nmem_malloc(zei->nmem, sizeof(*zei->categoryList));
+ zei->categoryList->sysno = 0;
+ zei->categoryList->dirty = 0;
+ zei->categoryList->data1_categoryList = NULL;
+
+ if ( atoi(res_get_def(res, "notimestamps", "0") )== 0)
+ {
+ time(&our_time);
+ tm = localtime(&our_time);
+ sprintf(zei->date, "%04d%02d%02d%02d%02d%02d",
+ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ } else {
+ sprintf(zei->date, "%04d%02d%02d%02d%02d%02d",
+ 0, 0, 0, 0, 0, 0);
+ }
+ zdip = &zei->databaseInfo;
+ trec = rec_get_root(records); /* get "root" record */
+
+ zei->ordinalSU = 1;
+ zei->runNumber = 0;
+
+ zebraExplain_mergeAccessInfo(zei, 0, &zei->accessInfo);
+ if (trec) /* targetInfo already exists ... */
+ {
+ data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
+
+ zei->data1_target = read_sgml_rec(zei->dh, zei->nmem, trec);
+#if 0
+ if (!zei->data1_target || !zei->data1_target->u.root.absyn)
+#else
+ if (!zei->data1_target)
+#endif
+ {
+ yaz_log(YLOG_FATAL, "Explain schema missing. Check profilePath");
+ nmem_destroy(zei->nmem);
+ return 0;
+ }
+#if ZINFO_DEBUG
+ data1_pr_tree(zei->dh, zei->data1_target, stderr);
+#endif
+ node_tgtinfo = data1_search_tag(zei->dh, zei->data1_target,
+ "/targetInfo");
+ zebraExplain_mergeAccessInfo(zei, node_tgtinfo,
+ &zei->accessInfo);
+
+ node_zebra = data1_search_tag(zei->dh, node_tgtinfo->child,
+ "zebraInfo");
+ np = 0;
+ if (node_zebra)
+ {
+ node_list = data1_search_tag(zei->dh, node_zebra->child,
+ "databaseList");
+ if (node_list)
+ np = node_list->child;
+ }
+ for(; np; np = np->next)
+ {
+ data1_node *node_name = NULL;
+ data1_node *node_id = NULL;
+ data1_node *node_aid = NULL;
+ data1_node *np2;
+ if (np->which != DATA1N_tag || strcmp(np->u.tag.tag, "database"))
+ continue;
+ for(np2 = np->child; np2; np2 = np2->next)
+ {
+ if (np2->which != DATA1N_tag)
+ continue;
+ if (!strcmp(np2->u.tag.tag, "name"))
+ node_name = np2->child;
+ else if (!strcmp(np2->u.tag.tag, "id"))
+ node_id = np2->child;
+ else if (!strcmp(np2->u.tag.tag, "attributeDetailsId"))
+ node_aid = np2->child;
+ }
+ assert(node_id && node_name && node_aid);
+
+ *zdip =(struct zebDatabaseInfoB *)
+ nmem_malloc(zei->nmem, sizeof(**zdip));
+ (*zdip)->readFlag = 1;
+ (*zdip)->dirty = 0;
+ (*zdip)->data1_database = NULL;
+ (*zdip)->recordCount = 0;
+ (*zdip)->recordBytes = 0;
+ zebraExplain_mergeAccessInfo (zei, 0, &(*zdip)->accessInfo);
+
+ (*zdip)->databaseName = (char *)
+ nmem_malloc (zei->nmem, 1+node_name->u.data.len);
+ memcpy((*zdip)->databaseName, node_name->u.data.data,
+ node_name->u.data.len);
+ (*zdip)->databaseName[node_name->u.data.len] = '\0';
+ (*zdip)->sysno = atoi_zn (node_id->u.data.data,
+ node_id->u.data.len);
+ (*zdip)->attributeDetails = (zebAttributeDetails)
+ nmem_malloc (zei->nmem, sizeof(*(*zdip)->attributeDetails));
+ (*zdip)->attributeDetails->sysno = atoi_zn (node_aid->u.data.data,
+ node_aid->u.data.len);
+ (*zdip)->attributeDetails->readFlag = 1;
+ (*zdip)->attributeDetails->dirty = 0;
+ (*zdip)->attributeDetails->SUInfo = NULL;
+
+ zdip = &(*zdip)->next;
+ }
+ if (node_zebra)
+ {
+ np = data1_search_tag(zei->dh, node_zebra->child,
+ "ordinalSU");
+ np = np->child;
+ assert (np && np->which == DATA1N_data);
+ zei->ordinalSU = atoi_n(np->u.data.data, np->u.data.len);
+
+ np = data1_search_tag(zei->dh, node_zebra->child,
+ "ordinalDatabase");
+ np = np->child;
+ assert (np && np->which == DATA1N_data);
+ zei->ordinalDatabase = atoi_n(np->u.data.data, np->u.data.len);
+
+ np = data1_search_tag(zei->dh, node_zebra->child,
+ "runNumber");
+ np = np->child;
+ assert (np && np->which == DATA1N_data);
+ zei->runNumber = atoi_zn(np->u.data.data, np->u.data.len);
+ yaz_log(YLOG_DEBUG, "read runnumber=" ZINT_FORMAT, zei->runNumber);
+ *zdip = NULL;
+ }
+ rec_rm(&trec);
+ }
+ else /* create initial targetInfo */
+ {
+ data1_node *node_tgtinfo;
+
+ *zdip = NULL;
+ if (writeFlag)
+ {
+ char *sgml_buf;
+ int sgml_len;
+
+ zei->data1_target =
+ data1_read_sgml(zei->dh, zei->nmem,
+ "<explain><targetInfo>TargetInfo\n"
+ "<name>Zebra</>\n"
+ "<namedResultSets>1</>\n"
+ "<multipleDBSearch>1</>\n"
+ "<nicknames><name>Zebra</></>\n"
+ "</></>\n" );
+ if (!zei->data1_target)
+ {
+ yaz_log(YLOG_FATAL, "Explain schema missing. Check profilePath");
+ nmem_destroy(zei->nmem);
+ return 0;
+ }
+ node_tgtinfo = data1_search_tag(zei->dh, zei->data1_target,
+ "/targetInfo");
+ assert(node_tgtinfo);
+
+ zebraExplain_initCommonInfo(zei, node_tgtinfo);
+ zebraExplain_initAccessInfo(zei, node_tgtinfo);
+
+ /* write now because we want to be sure about the sysno */
+ trec = rec_new(records);
+ if (!trec)
+ {
+ yaz_log(YLOG_FATAL, "Cannot create root Explain record");
+ nmem_destroy(zei->nmem);
+ return 0;
+ }
+ trec->info[recInfo_fileType] =
+ rec_strdup("grs.sgml", &trec->size[recInfo_fileType]);
+ trec->info[recInfo_databaseName] =
+ rec_strdup("IR-Explain-1", &trec->size[recInfo_databaseName]);
+
+ sgml_buf = data1_nodetoidsgml(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(records, &trec);
+ rec_rm(&trec);
+ }
+
+ zebraExplain_newDatabase(zei, "IR-Explain-1", 0);
+
+ if (!zei->categoryList->dirty)
+ {
+ struct zebraCategoryListInfo *zcl = zei->categoryList;
+ data1_node *node_cl;
+
+ zcl->dirty = 1;
+ zcl->data1_categoryList =
+ data1_read_sgml(zei->dh, zei->nmem,
+ "<explain><categoryList>CategoryList\n"
+ "</></>\n");
+
+ if (zcl->data1_categoryList)
+ {
+ node_cl = data1_search_tag(zei->dh, zcl->data1_categoryList,
+ "/categoryList");
+ assert(node_cl);
+ zebraExplain_initCommonInfo(zei, node_cl);
+ }
+ }
+ }
+ return zei;