1 /* This file is part of the Zebra server.
2 Copyright (C) 2004-2013 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <sys/types.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28
29 #include <idzebra/version.h>
30 #include "zinfo.h"
31
32 #define ZINFO_DEBUG 0
33
34 struct zebSUInfo {
35 char *index_type;
36 zinfo_index_category_t cat;
37 char *str;
38 int ordinal;
39 zint doc_occurrences;
40 zint term_occurrences;
41 };
42
43 struct zebSUInfoB {
44 struct zebSUInfo info;
45 struct zebSUInfoB *next;
46 };
47
48 typedef struct zebAccessObjectB *zebAccessObject;
49 struct zebAccessObjectB {
50 void *handle;
51 zint sysno;
52 Odr_oid *oid;
53 zebAccessObject next;
54 };
55
56 typedef struct zebAccessInfoB *zebAccessInfo;
57 struct zebAccessInfoB {
58 zebAccessObject attributeSetIds;
59 zebAccessObject schemas;
60 };
61
62 typedef struct {
63 struct zebSUInfoB *SUInfo;
64 zint sysno;
65 int dirty;
66 int readFlag;
67 data1_node *data1_tree;
68 } *zebAttributeDetails;
69
70 struct zebDatabaseInfoB {
71 zebAttributeDetails attributeDetails;
72 int ordinalDatabase;
73 char *databaseName;
74 data1_node *data1_database;
75 zint recordCount; /* records in db */
76 zint recordBytes; /* size of records */
77 zint sysno; /* sysno of database info */
78 int readFlag; /* 1: read is needed when referenced; 0 if not */
79 int dirty; /* 1: database is dirty: write is needed */
80 struct zebDatabaseInfoB *next;
81 zebAccessInfo accessInfo;
82 };
83
84 struct zebraExplainAttset {
85 char *name;
86 int ordinal;
87 struct zebraExplainAttset *next;
88 };
89
90 struct zebraCategoryListInfo {
91 int dirty;
92 zint sysno;
93 data1_node *data1_categoryList;
94 };
95
96 struct zebraExplainInfo {
97 int ordinalSU;
98 int ordinalDatabase;
99 zint runNumber;
100 int dirty;
101 int write_flag;
102 Records records;
103 data1_handle dh;
104 Res res;
105 struct zebraExplainAttset *attsets;
106 NMEM nmem;
107 data1_node *data1_target;
108 struct zebraCategoryListInfo *categoryList;
109 struct zebDatabaseInfoB *databaseInfo;
110 struct zebDatabaseInfoB *curDatabaseInfo;
111 zebAccessInfo accessInfo;
112 char date[15]; /* YYYY MMDD HH MM SS */
113 ZebraExplainUpdateFunc *updateFunc;
114 void *updateHandle;
115 };
116
117 static void zebraExplain_initCommonInfo(ZebraExplainInfo zei, data1_node *n);
118 static void zebraExplain_initAccessInfo(ZebraExplainInfo zei, data1_node *n);
119
read_sgml_rec(data1_handle dh,NMEM nmem,Record rec)120 static data1_node *read_sgml_rec(data1_handle dh, NMEM nmem, Record rec)
121 {
122 return data1_read_sgml(dh, nmem, rec->info[recInfo_storeData]);
123 }
124
125 static void zebraExplain_writeDatabase(ZebraExplainInfo zei,
126 struct zebDatabaseInfoB *zdi,
127 int key_flush);
128 static void zebraExplain_writeAttributeDetails(ZebraExplainInfo zei,
129 zebAttributeDetails zad,
130 const char *databaseName,
131 int key_flush);
132 static void zebraExplain_writeTarget(ZebraExplainInfo zei, int key_flush);
133 static void zebraExplain_writeAttributeSet(ZebraExplainInfo zei,
134 zebAccessObject o,
135 int key_flush);
136 static void zebraExplain_writeCategoryList(ZebraExplainInfo zei,
137 struct zebraCategoryListInfo *zcl,
138 int key_flush);
139
140
createRecord(Records records,zint * sysno)141 static Record createRecord(Records records, zint *sysno)
142 {
143 Record rec;
144 if (*sysno)
145 {
146 rec = rec_get(records, *sysno);
147 if (!rec)
148 return 0;
149 xfree(rec->info[recInfo_storeData]);
150 }
151 else
152 {
153 rec = rec_new(records);
154 if (!rec)
155 return 0;
156 *sysno = rec->sysno;
157
158 rec->info[recInfo_fileType] =
159 rec_strdup("grs.sgml", &rec->size[recInfo_fileType]);
160 rec->info[recInfo_databaseName] =
161 rec_strdup("IR-Explain-1",
162 &rec->size[recInfo_databaseName]);
163 }
164 return rec;
165 }
166
zebraExplain_flush(ZebraExplainInfo zei,void * handle)167 void zebraExplain_flush(ZebraExplainInfo zei, void *handle)
168 {
169 if (!zei)
170 return;
171 zei->updateHandle = handle;
172 if (zei->write_flag)
173 {
174 struct zebDatabaseInfoB *zdi;
175 zebAccessObject o;
176
177 /* write each database info record */
178 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
179 {
180 zebraExplain_writeDatabase(zei, zdi, 1);
181 zebraExplain_writeAttributeDetails(zei, zdi->attributeDetails,
182 zdi->databaseName, 1);
183 }
184 zebraExplain_writeTarget(zei, 1);
185 zebraExplain_writeCategoryList(zei,
186 zei->categoryList,
187 1);
188 assert(zei->accessInfo);
189 for (o = zei->accessInfo->attributeSetIds; o; o = o->next)
190 if (!o->sysno)
191 zebraExplain_writeAttributeSet(zei, o, 1);
192 for (o = zei->accessInfo->schemas; o; o = o->next)
193 if (!o->sysno)
194 {
195 /* zebraExplain_writeSchema(zei, o, 1); */
196 }
197
198 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
199 {
200 zebraExplain_writeDatabase(zei, zdi, 0);
201 zebraExplain_writeAttributeDetails(zei, zdi->attributeDetails,
202 zdi->databaseName, 0);
203 }
204 zebraExplain_writeTarget(zei, 0);
205 }
206 }
207
zebraExplain_close(ZebraExplainInfo zei)208 void zebraExplain_close(ZebraExplainInfo zei)
209 {
210 #if ZINFO_DEBUG
211 yaz_log(YLOG_LOG, "zebraExplain_close");
212 #endif
213 if (!zei)
214 return;
215 zebraExplain_flush(zei, zei->updateHandle);
216 nmem_destroy(zei->nmem);
217 }
218
zebraExplain_mergeOids(ZebraExplainInfo zei,data1_node * n,zebAccessObject * op)219 void zebraExplain_mergeOids(ZebraExplainInfo zei, data1_node *n,
220 zebAccessObject *op)
221 {
222 data1_node *np;
223
224 for (np = n->child; np; np = np->next)
225 {
226 char str[64];
227 int len;
228 Odr_oid *oid;
229 zebAccessObject ao;
230
231 if (np->which != DATA1N_tag || strcmp(np->u.tag.tag, "oid"))
232 continue;
233 len = np->child->u.data.len;
234 if (len > 63)
235 len = 63;
236 memcpy(str, np->child->u.data.data, len);
237 str[len] = '\0';
238
239 oid = odr_getoidbystr_nmem(zei->nmem, str);
240
241 for (ao = *op; ao; ao = ao->next)
242 if (!oid_oidcmp(oid, ao->oid))
243 {
244 ao->sysno = 1;
245 break;
246 }
247 if (!ao)
248 {
249 ao = (zebAccessObject) nmem_malloc(zei->nmem, sizeof(*ao));
250 ao->handle = 0;
251 ao->sysno = 1;
252 ao->oid = oid;
253 ao->next = *op;
254 *op = ao;
255 }
256 }
257 }
258
zebraExplain_mergeAccessInfo(ZebraExplainInfo zei,data1_node * n,zebAccessInfo * accessInfo)259 void zebraExplain_mergeAccessInfo(ZebraExplainInfo zei, data1_node *n,
260 zebAccessInfo *accessInfo)
261 {
262 data1_node *np;
263
264 if (!n)
265 {
266 *accessInfo = (zebAccessInfo)
267 nmem_malloc(zei->nmem, sizeof(**accessInfo));
268 (*accessInfo)->attributeSetIds = 0;
269 (*accessInfo)->schemas = 0;
270 }
271 else
272 {
273 if (!(n = data1_search_tag(zei->dh, n->child, "accessInfo")))
274 return;
275 if ((np = data1_search_tag(zei->dh, n->child, "attributeSetIds")))
276 zebraExplain_mergeOids(zei, np,
277 &(*accessInfo)->attributeSetIds);
278 if ((np = data1_search_tag(zei->dh, n->child, "schemas")))
279 zebraExplain_mergeOids(zei, np,
280 &(*accessInfo)->schemas);
281 }
282 }
283
284 /* Explain structure
285 root record
286 of type targetInfo
287 and has sysno = 1
288
289 databaseList (list of databases)
290 */
291 /*
292 Example root:
293 explain:
294 targetInfo: TargetInfo
295 name: Zebra
296 namedResultSets: 1
297 multipleDbSearch: 1
298 nicknames:
299 name: Zebra
300 commonInfo:
301 dateAdded: 20030630190601
302 dateChanged: 20030630190601
303 languageCode: EN
304 accessinfo:
305 unitSystems:
306 string: ISO
307 attributeSetIds:
308 oid: 1.2.840.10003.3.2
309 oid: 1.2.840.10003.3.5
310 oid: 1.2.840.10003.3.1
311 schemas:
312 oid: 1.2.840.10003.13.1000.81.2
313 oid: 1.2.840.10003.13.2
314 zebraInfo:
315 version: 1.3.12
316 databaseList:
317 database:
318 name: Default
319 id: 50
320 attributeDetailsId: 51
321 database:
322 name: IR-Explain-1
323 id: 52
324 attributeDetailsId: 53
325 ordinalSU: 38
326 runNumber: 1
327 nextResultSetPosition = 2
328 */
329
zebraExplain_open(Records records,data1_handle dh,Res res,int writeFlag,void * updateHandle,ZebraExplainUpdateFunc * updateFunc)330 ZebraExplainInfo zebraExplain_open(
331 Records records, data1_handle dh,
332 Res res,
333 int writeFlag,
334 void *updateHandle,
335 ZebraExplainUpdateFunc *updateFunc)
336 {
337 Record trec;
338 ZebraExplainInfo zei;
339 struct zebDatabaseInfoB **zdip;
340 time_t our_time;
341 struct tm *tm;
342 NMEM nmem = nmem_create();
343
344 #if ZINFO_DEBUG
345 yaz_log(YLOG_LOG, "zebraExplain_open wr=%d", writeFlag);
346 #endif
347 zei = (ZebraExplainInfo) nmem_malloc(nmem, sizeof(*zei));
348 zei->databaseInfo = 0;
349 zei->write_flag = writeFlag;
350 zei->updateHandle = updateHandle;
351 zei->updateFunc = updateFunc;
352 zei->dirty = 0;
353 zei->ordinalDatabase = 1;
354 zei->curDatabaseInfo = 0;
355 zei->records = records;
356 zei->nmem = nmem;
357 zei->dh = dh;
358
359 data1_get_absyn(zei->dh, "explain", DATA1_XPATH_INDEXING_DISABLE);
360
361 zei->attsets = 0;
362 zei->res = res;
363 zei->categoryList = (struct zebraCategoryListInfo *)
364 nmem_malloc(zei->nmem, sizeof(*zei->categoryList));
365 zei->categoryList->sysno = 0;
366 zei->categoryList->dirty = 0;
367 zei->categoryList->data1_categoryList = 0;
368
369 if ( atoi(res_get_def(res, "notimestamps", "0") )== 0)
370 {
371 time(&our_time);
372 tm = localtime(&our_time);
373 sprintf(zei->date, "%04d%02d%02d%02d%02d%02d",
374 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
375 tm->tm_hour, tm->tm_min, tm->tm_sec);
376 } else {
377 sprintf(zei->date, "%04d%02d%02d%02d%02d%02d",
378 0, 0, 0, 0, 0, 0);
379 }
380 zdip = &zei->databaseInfo;
381 trec = rec_get_root(records); /* get "root" record */
382
383 zei->ordinalSU = 1;
384 zei->runNumber = 0;
385
386 zebraExplain_mergeAccessInfo(zei, 0, &zei->accessInfo);
387 if (trec) /* targetInfo already exists ... */
388 {
389 data1_node *node_tgtinfo, *node_zebra, *node_list, *np;
390
391 zei->data1_target = read_sgml_rec(zei->dh, zei->nmem, trec);
392 #if 0
393 if (!zei->data1_target || !zei->data1_target->u.root.absyn)
394 #else
395 if (!zei->data1_target)
396 #endif
397 {
398 yaz_log(YLOG_FATAL, "Explain schema missing. Check profilePath");
399 nmem_destroy(zei->nmem);
400 return 0;
401 }
402 #if ZINFO_DEBUG
403 data1_pr_tree(zei->dh, zei->data1_target, stderr);
404 #endif
405 node_tgtinfo = data1_search_tag(zei->dh, zei->data1_target,
406 "/targetInfo");
407 if (!node_tgtinfo)
408 {
409 yaz_log(YLOG_FATAL, "Node node_tgtinfo missing");
410 nmem_destroy(zei->nmem);
411 return 0;
412 }
413 zebraExplain_mergeAccessInfo(zei, node_tgtinfo,
414 &zei->accessInfo);
415
416 node_zebra = data1_search_tag(zei->dh, node_tgtinfo->child,
417 "zebraInfo");
418 if (!node_zebra)
419 {
420 yaz_log(YLOG_FATAL, "Node node_zebra missing");
421 nmem_destroy(zei->nmem);
422 return 0;
423 }
424 np = 0;
425 if (node_zebra)
426 {
427 node_list = data1_search_tag(zei->dh, node_zebra->child,
428 "databaseList");
429 if (node_list)
430 np = node_list->child;
431 }
432 for(; np; np = np->next)
433 {
434 data1_node *node_name = 0;
435 data1_node *node_id = 0;
436 data1_node *node_aid = 0;
437 data1_node *np2;
438 if (np->which != DATA1N_tag || strcmp(np->u.tag.tag, "database"))
439 continue;
440 for(np2 = np->child; np2; np2 = np2->next)
441 {
442 if (np2->which != DATA1N_tag)
443 continue;
444 if (!strcmp(np2->u.tag.tag, "name"))
445 node_name = np2->child;
446 else if (!strcmp(np2->u.tag.tag, "id"))
447 node_id = np2->child;
448 else if (!strcmp(np2->u.tag.tag, "attributeDetailsId"))
449 node_aid = np2->child;
450 }
451 assert(node_id && node_name && node_aid);
452
453 *zdip =(struct zebDatabaseInfoB *)
454 nmem_malloc(zei->nmem, sizeof(**zdip));
455 (*zdip)->readFlag = 1;
456 (*zdip)->dirty = 0;
457 (*zdip)->data1_database = 0;
458 (*zdip)->recordCount = 0;
459 (*zdip)->recordBytes = 0;
460 zebraExplain_mergeAccessInfo(zei, 0, &(*zdip)->accessInfo);
461
462 (*zdip)->databaseName = (char *)
463 nmem_malloc(zei->nmem, 1+node_name->u.data.len);
464 memcpy((*zdip)->databaseName, node_name->u.data.data,
465 node_name->u.data.len);
466 (*zdip)->databaseName[node_name->u.data.len] = '\0';
467 (*zdip)->sysno = atoi_zn(node_id->u.data.data,
468 node_id->u.data.len);
469 (*zdip)->attributeDetails = (zebAttributeDetails)
470 nmem_malloc(zei->nmem, sizeof(*(*zdip)->attributeDetails));
471 (*zdip)->attributeDetails->sysno = atoi_zn(node_aid->u.data.data,
472 node_aid->u.data.len);
473 (*zdip)->attributeDetails->readFlag = 1;
474 (*zdip)->attributeDetails->dirty = 0;
475 (*zdip)->attributeDetails->SUInfo = 0;
476
477 zdip = &(*zdip)->next;
478 }
479 if (node_zebra)
480 {
481 np = data1_search_tag(zei->dh, node_zebra->child,
482 "ordinalSU");
483 np = np->child;
484 assert(np && np->which == DATA1N_data);
485 zei->ordinalSU = atoi_n(np->u.data.data, np->u.data.len);
486
487 np = data1_search_tag(zei->dh, node_zebra->child,
488 "ordinalDatabase");
489 np = np->child;
490 assert(np && np->which == DATA1N_data);
491 zei->ordinalDatabase = atoi_n(np->u.data.data, np->u.data.len);
492
493 np = data1_search_tag(zei->dh, node_zebra->child,
494 "runNumber");
495 np = np->child;
496 assert(np && np->which == DATA1N_data);
497 zei->runNumber = atoi_zn(np->u.data.data, np->u.data.len);
498 yaz_log(YLOG_DEBUG, "read runnumber=" ZINT_FORMAT, zei->runNumber);
499 *zdip = 0;
500 }
501 rec_free(&trec);
502 }
503 else /* create initial targetInfo */
504 {
505 data1_node *node_tgtinfo;
506
507 *zdip = 0;
508 if (writeFlag)
509 {
510 char *sgml_buf;
511 int sgml_len;
512
513 zei->data1_target =
514 data1_read_sgml(zei->dh, zei->nmem,
515 "<explain><targetInfo>TargetInfo\n"
516 "<name>Zebra</>\n"
517 "<namedResultSets>1</>\n"
518 "<multipleDBSearch>1</>\n"
519 "<nicknames><name>Zebra</></>\n"
520 "</></>\n" );
521 if (!zei->data1_target)
522 {
523 yaz_log(YLOG_FATAL, "Explain schema missing. Check profilePath");
524 nmem_destroy(zei->nmem);
525 return 0;
526 }
527 node_tgtinfo = data1_search_tag(zei->dh, zei->data1_target,
528 "/targetInfo");
529 assert(node_tgtinfo);
530
531 zebraExplain_initCommonInfo(zei, node_tgtinfo);
532 zebraExplain_initAccessInfo(zei, node_tgtinfo);
533
534 /* write now because we want to be sure about the sysno */
535 trec = rec_new(records);
536 if (!trec)
537 {
538 yaz_log(YLOG_FATAL, "Cannot create root Explain record");
539 nmem_destroy(zei->nmem);
540 return 0;
541 }
542 trec->info[recInfo_fileType] =
543 rec_strdup("grs.sgml", &trec->size[recInfo_fileType]);
544 trec->info[recInfo_databaseName] =
545 rec_strdup("IR-Explain-1", &trec->size[recInfo_databaseName]);
546
547 sgml_buf = data1_nodetoidsgml(dh, zei->data1_target, 0, &sgml_len);
548 trec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
549 memcpy(trec->info[recInfo_storeData], sgml_buf, sgml_len);
550 trec->size[recInfo_storeData] = sgml_len;
551
552 rec_put(records, &trec);
553 rec_free(&trec);
554 }
555
556 zebraExplain_newDatabase(zei, "IR-Explain-1", 0);
557
558 if (!zei->categoryList->dirty)
559 {
560 struct zebraCategoryListInfo *zcl = zei->categoryList;
561 data1_node *node_cl;
562
563 zcl->dirty = 1;
564 zcl->data1_categoryList =
565 data1_read_sgml(zei->dh, zei->nmem,
566 "<explain><categoryList>CategoryList\n"
567 "</></>\n");
568
569 if (zcl->data1_categoryList)
570 {
571 node_cl = data1_search_tag(zei->dh, zcl->data1_categoryList,
572 "/categoryList");
573 assert(node_cl);
574 zebraExplain_initCommonInfo(zei, node_cl);
575 }
576 }
577 }
578 return zei;
579 }
580
zebraExplain_readAttributeDetails(ZebraExplainInfo zei,zebAttributeDetails zad)581 static void zebraExplain_readAttributeDetails(ZebraExplainInfo zei,
582 zebAttributeDetails zad)
583 {
584 Record rec;
585 struct zebSUInfoB **zsuip = &zad->SUInfo;
586 data1_node *node_adinfo, *node_zebra, *node_list, *np;
587
588 assert(zad->sysno);
589 rec = rec_get(zei->records, zad->sysno);
590
591 zad->data1_tree = read_sgml_rec(zei->dh, zei->nmem, rec);
592
593 node_adinfo = data1_search_tag(zei->dh, zad->data1_tree,
594 "/attributeDetails");
595 node_zebra = data1_search_tag(zei->dh, node_adinfo->child,
596 "zebraInfo");
597 node_list = data1_search_tag(zei->dh, node_zebra->child,
598 "attrlist");
599 for (np = node_list->child; np; np = np->next)
600 {
601 data1_node *node_str = 0;
602 data1_node *node_ordinal = 0;
603 data1_node *node_type = 0;
604 data1_node *node_cat = 0;
605 data1_node *node_doc_occurrences = 0;
606 data1_node *node_term_occurrences = 0;
607 data1_node *np2;
608
609 if (np->which != DATA1N_tag || strcmp(np->u.tag.tag, "attr"))
610 continue;
611 for (np2 = np->child; np2; np2 = np2->next)
612 {
613 if (np2->which != DATA1N_tag || !np2->child ||
614 np2->child->which != DATA1N_data)
615 continue;
616 if (!strcmp(np2->u.tag.tag, "str"))
617 node_str = np2->child;
618 else if (!strcmp(np2->u.tag.tag, "ordinal"))
619 node_ordinal = np2->child;
620 else if (!strcmp(np2->u.tag.tag, "type"))
621 node_type = np2->child;
622 else if (!strcmp(np2->u.tag.tag, "cat"))
623 node_cat = np2->child;
624 else if (!strcmp(np2->u.tag.tag, "dococcurrences"))
625 node_doc_occurrences = np2->child;
626 else if (!strcmp(np2->u.tag.tag, "termoccurrences"))
627 node_term_occurrences = np2->child;
628 else
629 {
630 yaz_log(YLOG_LOG, "Unknown tag '%s' in attributeDetails",
631 np2->u.tag.tag);
632 }
633 }
634 assert(node_ordinal);
635
636 *zsuip = (struct zebSUInfoB *)
637 nmem_malloc(zei->nmem, sizeof(**zsuip));
638
639 if (node_type && node_type->u.data.len > 0)
640 (*zsuip)->info.index_type =
641 nmem_strdupn(zei->nmem,
642 node_type->u.data.data,
643 node_type->u.data.len);
644 else
645 {
646 yaz_log(YLOG_WARN, "Missing attribute 'type' in attribute info");
647 (*zsuip)->info.index_type = "w";
648 }
649 if (node_cat && node_cat->u.data.len > 0)
650 {
651 zinfo_index_category_t cat;
652
653 data1_node *np = node_cat;
654 if (!strncmp(np->u.data.data, "index", np->u.data.len))
655 cat = zinfo_index_category_index;
656 else if (!strncmp(np->u.data.data, "sort", np->u.data.len))
657 cat = zinfo_index_category_sort;
658 else if (!strncmp(np->u.data.data, "alwaysmatches",
659 np->u.data.len))
660 cat = zinfo_index_category_alwaysmatches;
661 else if (!strncmp(np->u.data.data, "anchor",
662 np->u.data.len))
663 cat = zinfo_index_category_anchor;
664 else
665 {
666 yaz_log(YLOG_WARN, "Bad index cateogry '%.*s'",
667 np->u.data.len, np->u.data.data);
668 cat = zinfo_index_category_index;
669 }
670 (*zsuip)->info.cat = cat;
671 }
672 else
673 (*zsuip)->info.cat = zinfo_index_category_index;
674
675 if (node_doc_occurrences)
676 {
677 data1_node *np = node_doc_occurrences;
678 (*zsuip)->info.doc_occurrences = atoi_zn(np->u.data.data,
679 np->u.data.len);
680 }
681 if (node_term_occurrences)
682 {
683 data1_node *np = node_term_occurrences;
684 (*zsuip)->info.term_occurrences = atoi_zn(np->u.data.data,
685 np->u.data.len);
686 }
687 if (node_str)
688 {
689 (*zsuip)->info.str = nmem_strdupn(zei->nmem,
690 node_str->u.data.data,
691 node_str->u.data.len);
692 }
693 else
694 {
695 yaz_log(YLOG_WARN, "Missing set/use/str in attribute info");
696 continue;
697 }
698 (*zsuip)->info.ordinal = atoi_n(node_ordinal->u.data.data,
699 node_ordinal->u.data.len);
700 zsuip = &(*zsuip)->next;
701 }
702 *zsuip = 0;
703 zad->readFlag = 0;
704 rec_free(&rec);
705 }
706
zebraExplain_readDatabase(ZebraExplainInfo zei,struct zebDatabaseInfoB * zdi)707 static void zebraExplain_readDatabase(ZebraExplainInfo zei,
708 struct zebDatabaseInfoB *zdi)
709 {
710 Record rec;
711 data1_node *node_dbinfo, *node_zebra, *np;
712
713 assert(zdi->sysno);
714 rec = rec_get(zei->records, zdi->sysno);
715
716 zdi->data1_database = read_sgml_rec(zei->dh, zei->nmem, rec);
717
718 node_dbinfo = data1_search_tag(zei->dh, zdi->data1_database,
719 "/databaseInfo");
720 assert(node_dbinfo);
721 zebraExplain_mergeAccessInfo(zei, node_dbinfo, &zdi->accessInfo);
722
723 node_zebra = data1_search_tag(zei->dh, node_dbinfo->child,
724 "zebraInfo");
725 if (node_zebra
726 && (np = data1_search_tag(zei->dh, node_zebra->child,
727 "recordBytes"))
728 && np->child && np->child->which == DATA1N_data)
729 zdi->recordBytes = atoi_zn(np->child->u.data.data,
730 np->child->u.data.len);
731
732 if (node_zebra
733 && (np = data1_search_tag(zei->dh, node_zebra->child,
734 "ordinalDatabase"))
735 && np->child && np->child->which == DATA1N_data)
736 zdi->ordinalDatabase = atoi_n(np->child->u.data.data,
737 np->child->u.data.len);
738
739 if ((np = data1_search_tag(zei->dh, node_dbinfo->child,
740 "recordCount")) &&
741 (np = data1_search_tag(zei->dh, np->child,
742 "recordCountActual")) &&
743 np->child->which == DATA1N_data)
744 {
745 zdi->recordCount = atoi_zn(np->child->u.data.data,
746 np->child->u.data.len);
747 }
748 zdi->readFlag = 0;
749 rec_free(&rec);
750 }
751
zebraExplain_removeDatabase(ZebraExplainInfo zei,void * update_handle)752 int zebraExplain_removeDatabase(ZebraExplainInfo zei, void *update_handle)
753 {
754 struct zebDatabaseInfoB **zdip = &zei->databaseInfo;
755
756 while (*zdip)
757 {
758 if (*zdip == zei->curDatabaseInfo)
759 {
760 struct zebDatabaseInfoB *zdi = *zdip;
761 Record rec;
762
763 zei->dirty = 1;
764 zei->updateHandle = update_handle;
765
766 if (zdi->attributeDetails)
767 {
768 /* remove attribute details keys and delete it */
769 zebAttributeDetails zad = zdi->attributeDetails;
770
771 rec = rec_get(zei->records, zad->sysno);
772 (*zei->updateFunc)(zei->updateHandle, rec, 0);
773 rec_del(zei->records, &rec);
774 }
775 /* remove database record keys and delete it */
776 rec = rec_get(zei->records, zdi->sysno);
777 (*zei->updateFunc)(zei->updateHandle, rec, 0);
778 rec_del(zei->records, &rec);
779
780 /* remove from list */
781 *zdip = zdi->next;
782
783 /* current database is IR-Explain-1 */
784 return 0;
785 }
786 zdip = &(*zdip)->next;
787 }
788 return -1;
789 }
790
zebraExplain_curDatabase(ZebraExplainInfo zei,const char * database)791 int zebraExplain_curDatabase(ZebraExplainInfo zei, const char *database)
792 {
793 struct zebDatabaseInfoB *zdi;
794 const char *database_n = strrchr(database, '/');
795
796 if (database_n)
797 database_n++;
798 else
799 database_n = database;
800
801 assert(zei);
802 if (zei->curDatabaseInfo &&
803 !STRCASECMP(zei->curDatabaseInfo->databaseName, database))
804 return 0;
805 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
806 {
807 if (!STRCASECMP(zdi->databaseName, database_n))
808 break;
809 }
810 if (!zdi)
811 return -1;
812 #if ZINFO_DEBUG
813 yaz_log(YLOG_LOG, "zebraExplain_curDatabase: %s", database);
814 #endif
815 if (zdi->readFlag)
816 {
817 #if ZINFO_DEBUG
818 yaz_log(YLOG_LOG, "zebraExplain_readDatabase: %s", database);
819 #endif
820 zebraExplain_readDatabase(zei, zdi);
821 }
822 if (zdi->attributeDetails->readFlag)
823 {
824 #if ZINFO_DEBUG
825 yaz_log(YLOG_LOG, "zebraExplain_readAttributeDetails: %s", database);
826 #endif
827 zebraExplain_readAttributeDetails(zei, zdi->attributeDetails);
828 }
829 zei->curDatabaseInfo = zdi;
830 return 0;
831 }
832
zebraExplain_initCommonInfo(ZebraExplainInfo zei,data1_node * n)833 static void zebraExplain_initCommonInfo(ZebraExplainInfo zei, data1_node *n)
834 {
835 data1_node *c = data1_mk_tag(zei->dh, zei->nmem, "commonInfo", 0, n);
836 data1_mk_tag_data_text(zei->dh, c, "dateAdded", zei->date, zei->nmem);
837 data1_mk_tag_data_text(zei->dh, c, "dateChanged", zei->date, zei->nmem);
838 data1_mk_tag_data_text(zei->dh, c, "languageCode", "EN", zei->nmem);
839 }
840
zebraExplain_updateCommonInfo(ZebraExplainInfo zei,data1_node * n)841 static void zebraExplain_updateCommonInfo(ZebraExplainInfo zei, data1_node *n)
842 {
843 data1_node *c = data1_search_tag(zei->dh, n->child, "commonInfo");
844 assert(c);
845 data1_mk_tag_data_text_uni(zei->dh, c, "dateChanged", zei->date,
846 zei->nmem);
847 }
848
zebraExplain_initAccessInfo(ZebraExplainInfo zei,data1_node * n)849 static void zebraExplain_initAccessInfo(ZebraExplainInfo zei, data1_node *n)
850 {
851 data1_node *c = data1_mk_tag(zei->dh, zei->nmem, "accessInfo", 0, n);
852 data1_node *d = data1_mk_tag(zei->dh, zei->nmem, "unitSystems", 0, c);
853 data1_mk_tag_data_text(zei->dh, d, "string", "ISO", zei->nmem);
854 }
855
zebraExplain_updateAccessInfo(ZebraExplainInfo zei,data1_node * n,zebAccessInfo accessInfo)856 static void zebraExplain_updateAccessInfo(ZebraExplainInfo zei, data1_node *n,
857 zebAccessInfo accessInfo)
858 {
859 data1_node *c = data1_search_tag(zei->dh, n->child, "accessInfo");
860 data1_node *d;
861 zebAccessObject p;
862
863 if (!c)
864 {
865 data1_pr_tree(zei->dh, n, stdout);
866 zebra_exit("zebraExplain_updateAccessInfo");
867 }
868
869 if ((p = accessInfo->attributeSetIds))
870 {
871 d = data1_mk_tag_uni(zei->dh, zei->nmem, "attributeSetIds", c);
872 for (; p; p = p->next)
873 data1_mk_tag_data_oid(zei->dh, d, "oid", p->oid, zei->nmem);
874 }
875 if ((p = accessInfo->schemas))
876 {
877 d = data1_mk_tag_uni(zei->dh, zei->nmem, "schemas", c);
878 for (; p; p = p->next)
879 data1_mk_tag_data_oid(zei->dh, d, "oid", p->oid, zei->nmem);
880 }
881 }
882
zebraExplain_newDatabase(ZebraExplainInfo zei,const char * database,int explain_database)883 int zebraExplain_newDatabase(ZebraExplainInfo zei, const char *database,
884 int explain_database)
885 {
886 struct zebDatabaseInfoB *zdi;
887 data1_node *node_dbinfo, *node_adinfo;
888 const char *database_n = strrchr(database, '/');
889
890 if (database_n)
891 database_n++;
892 else
893 database_n = database;
894
895 #if ZINFO_DEBUG
896 yaz_log(YLOG_LOG, "zebraExplain_newDatabase: %s", database);
897 #endif
898 assert(zei);
899 for (zdi = zei->databaseInfo; zdi; zdi=zdi->next)
900 {
901 if (!STRCASECMP(zdi->databaseName, database_n))
902 break;
903 }
904 if (zdi)
905 return -1;
906 /* it's new really. make it */
907 zdi = (struct zebDatabaseInfoB *) nmem_malloc(zei->nmem, sizeof(*zdi));
908 zdi->next = zei->databaseInfo;
909 zei->databaseInfo = zdi;
910 zdi->sysno = 0;
911 zdi->recordCount = 0;
912 zdi->recordBytes = 0;
913 zdi->readFlag = 0;
914 zdi->databaseName = nmem_strdup(zei->nmem, database_n);
915
916 zdi->ordinalDatabase = zei->ordinalDatabase++;
917
918 zebraExplain_mergeAccessInfo(zei, 0, &zdi->accessInfo);
919
920 assert(zei->dh);
921 assert(zei->nmem);
922
923 zdi->data1_database =
924 data1_read_sgml(zei->dh, zei->nmem,
925 "<explain><databaseInfo>DatabaseInfo\n"
926 "</></>\n");
927 if (!zdi->data1_database)
928 return -2;
929
930 node_dbinfo = data1_search_tag(zei->dh, zdi->data1_database,
931 "/databaseInfo");
932 assert(node_dbinfo);
933
934 zebraExplain_initCommonInfo(zei, node_dbinfo);
935 zebraExplain_initAccessInfo(zei, node_dbinfo);
936
937 data1_mk_tag_data_text(zei->dh, node_dbinfo, "name",
938 database, zei->nmem);
939
940 if (explain_database)
941 data1_mk_tag_data_text(zei->dh, node_dbinfo, "explainDatabase",
942 "", zei->nmem);
943
944 data1_mk_tag_data_text(zei->dh, node_dbinfo, "userFee",
945 "0", zei->nmem);
946
947 data1_mk_tag_data_text(zei->dh, node_dbinfo, "available",
948 "1", zei->nmem);
949
950 #if ZINFO_DEBUG
951 data1_pr_tree(zei->dh, zdi->data1_database, stderr);
952 #endif
953 zdi->dirty = 1;
954 zei->dirty = 1;
955 zei->curDatabaseInfo = zdi;
956
957 zdi->attributeDetails = (zebAttributeDetails)
958 nmem_malloc(zei->nmem, sizeof(*zdi->attributeDetails));
959 zdi->attributeDetails->readFlag = 0;
960 zdi->attributeDetails->sysno = 0;
961 zdi->attributeDetails->dirty = 1;
962 zdi->attributeDetails->SUInfo = 0;
963 zdi->attributeDetails->data1_tree =
964 data1_read_sgml(zei->dh, zei->nmem,
965 "<explain><attributeDetails>AttributeDetails\n"
966 "</></>\n");
967
968 node_adinfo = data1_search_tag(zei->dh, zdi->attributeDetails->data1_tree,
969 "/attributeDetails");
970 assert(node_adinfo);
971
972 zebraExplain_initCommonInfo(zei, node_adinfo);
973
974 data1_mk_tag_data_text(zei->dh, node_adinfo, "name", database, zei->nmem);
975
976 return 0;
977 }
978
979
zebraExplain_writeCategoryList(ZebraExplainInfo zei,struct zebraCategoryListInfo * zcl,int key_flush)980 static void zebraExplain_writeCategoryList(ZebraExplainInfo zei,
981 struct zebraCategoryListInfo *zcl,
982 int key_flush)
983 {
984 char *sgml_buf;
985 int sgml_len;
986 int i;
987 Record drec;
988 data1_node *node_ci, *node_categoryList;
989 zint sysno = 0;
990 static char *category[] = {
991 "CategoryList",
992 "TargetInfo",
993 "DatabaseInfo",
994 "AttributeDetails",
995 0
996 };
997
998 assert(zcl);
999 if (!zcl->dirty)
1000 return ;
1001 zcl->dirty = 0;
1002 node_categoryList = zcl->data1_categoryList;
1003
1004 #if ZINFO_DEBUG
1005 yaz_log(YLOG_LOG, "zebraExplain_writeCategoryList");
1006 #endif
1007
1008 drec = createRecord(zei->records, &sysno);
1009 if (!drec)
1010 return;
1011
1012 node_ci = data1_search_tag(zei->dh, node_categoryList,
1013 "/categoryList");
1014 assert (node_ci);
1015 node_ci = data1_mk_tag(zei->dh, zei->nmem, "categories", 0 /* attr */,
1016 node_ci);
1017 assert (node_ci);
1018
1019 for (i = 0; category[i]; i++)
1020 {
1021 data1_node *node_cat = data1_mk_tag(zei->dh, zei->nmem, "category",
1022 0 /* attr */, node_ci);
1023
1024 data1_mk_tag_data_text(zei->dh, node_cat, "name",
1025 category[i], zei->nmem);
1026 }
1027 /* extract *searchable* keys from it. We do this here, because
1028 record count, etc. is affected */
1029 if (key_flush)
1030 (*zei->updateFunc)(zei->updateHandle, drec, node_categoryList);
1031
1032 /* convert to "SGML" and write it */
1033 #if ZINFO_DEBUG
1034 data1_pr_tree(zei->dh, node_categoryList, stderr);
1035 #endif
1036 sgml_buf = data1_nodetoidsgml(zei->dh, node_categoryList, 0, &sgml_len);
1037 drec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
1038 memcpy(drec->info[recInfo_storeData], sgml_buf, sgml_len);
1039 drec->size[recInfo_storeData] = sgml_len;
1040
1041 rec_put(zei->records, &drec);
1042 }
1043
zebraExplain_writeAttributeDetails(ZebraExplainInfo zei,zebAttributeDetails zad,const char * databaseName,int key_flush)1044 static void zebraExplain_writeAttributeDetails(ZebraExplainInfo zei,
1045 zebAttributeDetails zad,
1046 const char *databaseName,
1047 int key_flush)
1048 {
1049 char *sgml_buf;
1050 int sgml_len;
1051 Record drec;
1052 data1_node *node_adinfo, *node_list, *node_zebra;
1053 struct zebSUInfoB *zsui;
1054
1055 if (!zad->dirty)
1056 return;
1057
1058 zad->dirty = 0;
1059 #if ZINFO_DEBUG
1060 yaz_log(YLOG_LOG, "zebraExplain_writeAttributeDetails");
1061 data1_pr_tree(zei->dh, zad->data1_tree, stderr);
1062 #endif
1063
1064 drec = createRecord(zei->records, &zad->sysno);
1065 if (!drec)
1066 return;
1067 assert(zad->data1_tree);
1068
1069 node_adinfo = data1_search_tag(zei->dh, zad->data1_tree,
1070 "/attributeDetails");
1071 zebraExplain_updateCommonInfo(zei, node_adinfo);
1072
1073 /* zebra info (private) .. no children yet.. so se don't index zebraInfo */
1074 node_zebra = data1_mk_tag_uni(zei->dh, zei->nmem,
1075 "zebraInfo", node_adinfo);
1076
1077 /* extract *searchable* keys from it. We do this here, because
1078 record count, etc. is affected */
1079 if (key_flush)
1080 (*zei->updateFunc)(zei->updateHandle, drec, zad->data1_tree);
1081 node_list = data1_mk_tag_uni(zei->dh, zei->nmem,
1082 "attrlist", node_zebra);
1083 for (zsui = zad->SUInfo; zsui; zsui = zsui->next)
1084 {
1085 data1_node *node_attr;
1086 node_attr = data1_mk_tag(zei->dh, zei->nmem, "attr", 0 /* attr */,
1087 node_list);
1088
1089 data1_mk_tag_data_text(zei->dh, node_attr, "type",
1090 zsui->info.index_type, zei->nmem);
1091 data1_mk_tag_data_text(zei->dh, node_attr, "str",
1092 zsui->info.str, zei->nmem);
1093 data1_mk_tag_data_int(zei->dh, node_attr, "ordinal",
1094 zsui->info.ordinal, zei->nmem);
1095
1096 data1_mk_tag_data_zint(zei->dh, node_attr, "dococcurrences",
1097 zsui->info.doc_occurrences, zei->nmem);
1098 data1_mk_tag_data_zint(zei->dh, node_attr, "termoccurrences",
1099 zsui->info.term_occurrences, zei->nmem);
1100 switch(zsui->info.cat)
1101 {
1102 case zinfo_index_category_index:
1103 data1_mk_tag_data_text(zei->dh, node_attr, "cat",
1104 "index", zei->nmem); break;
1105 case zinfo_index_category_sort:
1106 data1_mk_tag_data_text(zei->dh, node_attr, "cat",
1107 "sort", zei->nmem); break;
1108 case zinfo_index_category_alwaysmatches:
1109 data1_mk_tag_data_text(zei->dh, node_attr, "cat",
1110 "alwaysmatches", zei->nmem); break;
1111 case zinfo_index_category_anchor:
1112 data1_mk_tag_data_text(zei->dh, node_attr, "cat",
1113 "anchor", zei->nmem); break;
1114 }
1115 }
1116 /* convert to "SGML" and write it */
1117 #if ZINFO_DEBUG
1118 data1_pr_tree(zei->dh, zad->data1_tree, stderr);
1119 #endif
1120 sgml_buf = data1_nodetoidsgml(zei->dh, zad->data1_tree,
1121 0, &sgml_len);
1122 drec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
1123 memcpy(drec->info[recInfo_storeData], sgml_buf, sgml_len);
1124 drec->size[recInfo_storeData] = sgml_len;
1125
1126 rec_put(zei->records, &drec);
1127 }
1128
zebraExplain_writeDatabase(ZebraExplainInfo zei,struct zebDatabaseInfoB * zdi,int key_flush)1129 static void zebraExplain_writeDatabase(ZebraExplainInfo zei,
1130 struct zebDatabaseInfoB *zdi,
1131 int key_flush)
1132 {
1133 char *sgml_buf;
1134 int sgml_len;
1135 Record drec;
1136 data1_node *node_dbinfo, *node_count, *node_zebra;
1137
1138 if (!zdi->dirty)
1139 return;
1140
1141 zdi->dirty = 0;
1142 #if ZINFO_DEBUG
1143 yaz_log(YLOG_LOG, "zebraExplain_writeDatabase %s", zdi->databaseName);
1144 #endif
1145 drec = createRecord(zei->records, &zdi->sysno);
1146 if (!drec)
1147 return;
1148 assert(zdi->data1_database);
1149
1150 node_dbinfo = data1_search_tag(zei->dh, zdi->data1_database,
1151 "/databaseInfo");
1152
1153 assert(node_dbinfo);
1154 zebraExplain_updateCommonInfo(zei, node_dbinfo);
1155 zebraExplain_updateAccessInfo(zei, node_dbinfo, zdi->accessInfo);
1156
1157 /* record count */
1158 node_count = data1_mk_tag_uni(zei->dh, zei->nmem,
1159 "recordCount", node_dbinfo);
1160 data1_mk_tag_data_zint(zei->dh, node_count, "recordCountActual",
1161 zdi->recordCount, zei->nmem);
1162
1163 /* zebra info (private) */
1164 node_zebra = data1_mk_tag_uni(zei->dh, zei->nmem,
1165 "zebraInfo", node_dbinfo);
1166
1167 /* extract *searchable* keys from it. We do this here, because
1168 record count, etc. is affected */
1169 if (key_flush)
1170 (*zei->updateFunc)(zei->updateHandle, drec, zdi->data1_database);
1171 data1_mk_tag_data_zint(zei->dh, node_zebra,
1172 "recordBytes", zdi->recordBytes, zei->nmem);
1173
1174 data1_mk_tag_data_zint(zei->dh, node_zebra,
1175 "ordinalDatabase", zdi->ordinalDatabase, zei->nmem);
1176
1177 /* convert to "SGML" and write it */
1178 #if ZINFO_DEBUG
1179 data1_pr_tree(zei->dh, zdi->data1_database, stderr);
1180 #endif
1181 sgml_buf = data1_nodetoidsgml(zei->dh, zdi->data1_database,
1182 0, &sgml_len);
1183 drec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
1184 memcpy(drec->info[recInfo_storeData], sgml_buf, sgml_len);
1185 drec->size[recInfo_storeData] = sgml_len;
1186
1187 rec_put(zei->records, &drec);
1188 }
1189
writeAttributeValues(ZebraExplainInfo zei,data1_node * node_values,data1_attset * attset)1190 static void writeAttributeValues(ZebraExplainInfo zei,
1191 data1_node *node_values,
1192 data1_attset *attset)
1193 {
1194 data1_att *atts;
1195 data1_attset_child *c;
1196
1197 if (!attset)
1198 return;
1199
1200 for (c = attset->children; c; c = c->next)
1201 writeAttributeValues(zei, node_values, c->child);
1202 for (atts = attset->atts; atts; atts = atts->next)
1203 {
1204 data1_node *node_value;
1205
1206 node_value = data1_mk_tag(zei->dh, zei->nmem, "attributeValue",
1207 0 /* attr */, node_values);
1208 data1_mk_tag_data_text(zei->dh, node_value, "name",
1209 atts->name, zei->nmem);
1210 node_value = data1_mk_tag(zei->dh, zei->nmem, "value",
1211 0 /* attr */, node_value);
1212 data1_mk_tag_data_int(zei->dh, node_value, "numeric",
1213 atts->value, zei->nmem);
1214 }
1215 }
1216
1217
zebraExplain_writeAttributeSet(ZebraExplainInfo zei,zebAccessObject o,int key_flush)1218 static void zebraExplain_writeAttributeSet(ZebraExplainInfo zei,
1219 zebAccessObject o,
1220 int key_flush)
1221 {
1222 char *sgml_buf;
1223 int sgml_len;
1224 Record drec;
1225 data1_node *node_root, *node_attinfo, *node_attributes, *node_atttype;
1226 data1_node *node_values;
1227 struct data1_attset *attset = 0;
1228
1229 if (o->oid)
1230 attset = data1_attset_search_id(zei->dh, o->oid);
1231
1232 #if ZINFO_DEBUG
1233 yaz_log(YLOG_LOG, "zebraExplain_writeAttributeSet %s",
1234 attset ? attset->name : "<unknown>");
1235 #endif
1236
1237 drec = createRecord(zei->records, &o->sysno);
1238 if (!drec)
1239 return;
1240 node_root =
1241 data1_read_sgml(zei->dh, zei->nmem,
1242 "<explain><attributeSetInfo>AttributeSetInfo\n"
1243 "</></>\n" );
1244
1245 node_attinfo = data1_search_tag(zei->dh, node_root,
1246 "/attributeSetInfo");
1247
1248 assert(node_attinfo);
1249 zebraExplain_initCommonInfo(zei, node_attinfo);
1250 zebraExplain_updateCommonInfo(zei, node_attinfo);
1251
1252 data1_mk_tag_data_oid(zei->dh, node_attinfo,
1253 "oid", o->oid, zei->nmem);
1254 if (attset && attset->name)
1255 data1_mk_tag_data_text(zei->dh, node_attinfo,
1256 "name", attset->name, zei->nmem);
1257
1258 node_attributes = data1_mk_tag_uni(zei->dh, zei->nmem,
1259 "attributes", node_attinfo);
1260 node_atttype = data1_mk_tag_uni(zei->dh, zei->nmem,
1261 "attributeType", node_attributes);
1262 data1_mk_tag_data_text(zei->dh, node_atttype,
1263 "name", "Use", zei->nmem);
1264 data1_mk_tag_data_text(zei->dh, node_atttype,
1265 "description", "Use Attribute", zei->nmem);
1266 data1_mk_tag_data_int(zei->dh, node_atttype,
1267 "type", 1, zei->nmem);
1268 node_values = data1_mk_tag(zei->dh, zei->nmem,
1269 "attributeValues", 0 /* attr */, node_atttype);
1270 if (attset)
1271 writeAttributeValues(zei, node_values, attset);
1272
1273 /* extract *searchable* keys from it. We do this here, because
1274 record count, etc. is affected */
1275 if (key_flush)
1276 (*zei->updateFunc)(zei->updateHandle, drec, node_root);
1277 /* convert to "SGML" and write it */
1278 #if ZINFO_DEBUG
1279 data1_pr_tree(zei->dh, node_root, stderr);
1280 #endif
1281 sgml_buf = data1_nodetoidsgml(zei->dh, node_root, 0, &sgml_len);
1282 drec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
1283 memcpy(drec->info[recInfo_storeData], sgml_buf, sgml_len);
1284 drec->size[recInfo_storeData] = sgml_len;
1285
1286 rec_put(zei->records, &drec);
1287 }
1288
zebraExplain_writeTarget(ZebraExplainInfo zei,int key_flush)1289 static void zebraExplain_writeTarget(ZebraExplainInfo zei, int key_flush)
1290 {
1291 struct zebDatabaseInfoB *zdi;
1292 data1_node *node_tgtinfo, *node_list, *node_zebra;
1293 Record trec;
1294 int sgml_len;
1295 char *sgml_buf;
1296
1297 if (!zei->dirty)
1298 return;
1299 zei->dirty = 0;
1300
1301 trec = rec_get_root(zei->records);
1302 xfree(trec->info[recInfo_storeData]);
1303
1304 node_tgtinfo = data1_search_tag(zei->dh, zei->data1_target,
1305 "/targetInfo");
1306 assert(node_tgtinfo);
1307
1308 zebraExplain_updateCommonInfo(zei, node_tgtinfo);
1309 zebraExplain_updateAccessInfo(zei, node_tgtinfo, zei->accessInfo);
1310
1311 node_zebra = data1_mk_tag_uni(zei->dh, zei->nmem,
1312 "zebraInfo", node_tgtinfo);
1313 /* convert to "SGML" and write it */
1314 if (key_flush)
1315 (*zei->updateFunc)(zei->updateHandle, trec, zei->data1_target);
1316
1317 data1_mk_tag_data_text(zei->dh, node_zebra, "version",
1318 ZEBRAVER, zei->nmem);
1319 node_list = data1_mk_tag(zei->dh, zei->nmem,
1320 "databaseList", 0 /* attr */, node_zebra);
1321 for (zdi = zei->databaseInfo; zdi; zdi = zdi->next)
1322 {
1323 data1_node *node_db;
1324 node_db = data1_mk_tag(zei->dh, zei->nmem,
1325 "database", 0 /* attr */, node_list);
1326 data1_mk_tag_data_text(zei->dh, node_db, "name",
1327 zdi->databaseName, zei->nmem);
1328 data1_mk_tag_data_zint(zei->dh, node_db, "id",
1329 zdi->sysno, zei->nmem);
1330 data1_mk_tag_data_zint(zei->dh, node_db, "attributeDetailsId",
1331 zdi->attributeDetails->sysno, zei->nmem);
1332 }
1333 data1_mk_tag_data_int(zei->dh, node_zebra, "ordinalSU",
1334 zei->ordinalSU, zei->nmem);
1335
1336 data1_mk_tag_data_int(zei->dh, node_zebra, "ordinalDatabase",
1337 zei->ordinalDatabase, zei->nmem);
1338
1339 data1_mk_tag_data_zint(zei->dh, node_zebra, "runNumber",
1340 zei->runNumber, zei->nmem);
1341
1342 #if ZINFO_DEBUG
1343 data1_pr_tree(zei->dh, zei->data1_target, stderr);
1344 #endif
1345 sgml_buf = data1_nodetoidsgml(zei->dh, zei->data1_target,
1346 0, &sgml_len);
1347 trec->info[recInfo_storeData] = (char *) xmalloc(sgml_len);
1348 memcpy(trec->info[recInfo_storeData], sgml_buf, sgml_len);
1349 trec->size[recInfo_storeData] = sgml_len;
1350
1351 rec_put(zei->records, &trec);
1352 }
1353
zebraExplain_lookup_attr_str(ZebraExplainInfo zei,zinfo_index_category_t cat,const char * index_type,const char * str)1354 int zebraExplain_lookup_attr_str(ZebraExplainInfo zei,
1355 zinfo_index_category_t cat,
1356 const char *index_type,
1357 const char *str)
1358 {
1359 struct zebSUInfoB **zsui;
1360
1361 assert(zei->curDatabaseInfo);
1362 for (zsui = &zei->curDatabaseInfo->attributeDetails->SUInfo;
1363 *zsui; zsui = &(*zsui)->next)
1364 if ( (index_type == 0
1365 || !strcmp((*zsui)->info.index_type, index_type))
1366 && (*zsui)->info.cat == cat
1367 && !yaz_matchstr((*zsui)->info.str, str))
1368 {
1369 struct zebSUInfoB *zsui_this = *zsui;
1370
1371 /* take it out of the list and move to front */
1372 *zsui = (*zsui)->next;
1373 zsui_this->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1374 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui_this;
1375
1376 return zsui_this->info.ordinal;
1377 }
1378 return -1;
1379 }
1380
zebraExplain_trav_ord(ZebraExplainInfo zei,void * handle,int (* f)(void * handle,int ord,const char * index_type,const char * string_index,zinfo_index_category_t cat))1381 int zebraExplain_trav_ord(ZebraExplainInfo zei, void *handle,
1382 int (*f)(void *handle, int ord,
1383 const char *index_type,
1384 const char *string_index,
1385 zinfo_index_category_t cat))
1386 {
1387 struct zebDatabaseInfoB *zdb = zei->curDatabaseInfo;
1388 if (zdb)
1389 {
1390 struct zebSUInfoB *zsui = zdb->attributeDetails->SUInfo;
1391 for ( ;zsui; zsui = zsui->next)
1392 (*f)(handle, zsui->info.ordinal,
1393 zsui->info.index_type, zsui->info.str,
1394 zsui->info.cat);
1395 }
1396 return 0;
1397 }
1398
1399
zebraExplain_get_sui_info(ZebraExplainInfo zei,int ord,int dirty_mark,const char ** db)1400 struct zebSUInfoB *zebraExplain_get_sui_info(ZebraExplainInfo zei, int ord,
1401 int dirty_mark,
1402 const char **db)
1403 {
1404 struct zebDatabaseInfoB *zdb;
1405
1406 for (zdb = zei->databaseInfo; zdb; zdb = zdb->next)
1407 {
1408 struct zebSUInfoB **zsui;
1409
1410 if (zdb->attributeDetails->readFlag)
1411 zebraExplain_readAttributeDetails(zei, zdb->attributeDetails);
1412
1413 for (zsui = &zdb->attributeDetails->SUInfo; *zsui;
1414 zsui = &(*zsui)->next)
1415 if ((*zsui)->info.ordinal == ord)
1416 {
1417 struct zebSUInfoB *zsui_this = *zsui;
1418
1419 /* take it out of the list and move to front */
1420 *zsui = (*zsui)->next;
1421 zsui_this->next = zdb->attributeDetails->SUInfo;
1422 zdb->attributeDetails->SUInfo = zsui_this;
1423
1424 if (dirty_mark)
1425 zdb->attributeDetails->dirty = 1;
1426 if (db)
1427 *db = zdb->databaseName;
1428 return zsui_this;
1429 }
1430 }
1431 return 0;
1432 }
1433
1434
1435
zebraExplain_ord_adjust_occurrences(ZebraExplainInfo zei,int ord,int term_delta,int doc_delta)1436 int zebraExplain_ord_adjust_occurrences(ZebraExplainInfo zei, int ord,
1437 int term_delta, int doc_delta)
1438 {
1439 struct zebSUInfoB *zsui = zebraExplain_get_sui_info(zei, ord, 1, 0);
1440 if (zsui)
1441 {
1442 zsui->info.term_occurrences += term_delta;
1443 zsui->info.doc_occurrences += doc_delta;
1444 return 0;
1445 }
1446 return -1;
1447 }
1448
zebraExplain_ord_get_occurrences(ZebraExplainInfo zei,int ord,zint * term_occurrences,zint * doc_occurrences)1449 int zebraExplain_ord_get_occurrences(ZebraExplainInfo zei, int ord,
1450 zint *term_occurrences,
1451 zint *doc_occurrences)
1452 {
1453 struct zebSUInfoB *zsui = zebraExplain_get_sui_info(zei, ord, 0, 0);
1454 if (zsui)
1455 {
1456 *term_occurrences = zsui->info.term_occurrences;
1457 *doc_occurrences = zsui->info.doc_occurrences;
1458 return 0;
1459 }
1460 return -1;
1461 }
1462
zebraExplain_ord_get_doc_occurrences(ZebraExplainInfo zei,int ord)1463 zint zebraExplain_ord_get_doc_occurrences(ZebraExplainInfo zei, int ord)
1464 {
1465 struct zebSUInfoB *zsui = zebraExplain_get_sui_info(zei, ord, 0, 0);
1466 if (zsui)
1467 return zsui->info.doc_occurrences;
1468 return 0;
1469 }
1470
zebraExplain_ord_get_term_occurrences(ZebraExplainInfo zei,int ord)1471 zint zebraExplain_ord_get_term_occurrences(ZebraExplainInfo zei, int ord)
1472 {
1473 struct zebSUInfoB *zsui = zebraExplain_get_sui_info(zei, ord, 0, 0);
1474 if (zsui)
1475 return zsui->info.term_occurrences;
1476 return 0;
1477 }
1478
zebraExplain_lookup_ord(ZebraExplainInfo zei,int ord,const char ** index_type,const char ** db,const char ** string_index)1479 int zebraExplain_lookup_ord(ZebraExplainInfo zei, int ord,
1480 const char **index_type,
1481 const char **db,
1482 const char **string_index)
1483 {
1484 struct zebSUInfoB *zsui;
1485
1486 if (index_type)
1487 *index_type = 0;
1488 if (string_index)
1489 *string_index = 0;
1490
1491 zsui = zebraExplain_get_sui_info(zei, ord, 0, db);
1492 if (zsui)
1493 {
1494 if (string_index)
1495 *string_index = zsui->info.str;
1496 if (index_type)
1497 *index_type = zsui->info.index_type;
1498 return 0;
1499 }
1500 return -1;
1501 }
1502
1503
1504
zebraExplain_announceOid(ZebraExplainInfo zei,zebAccessObject * op,Odr_oid * oid)1505 zebAccessObject zebraExplain_announceOid(ZebraExplainInfo zei,
1506 zebAccessObject *op,
1507 Odr_oid *oid)
1508 {
1509 zebAccessObject ao;
1510
1511 for (ao = *op; ao; ao = ao->next)
1512 if (!oid_oidcmp(oid, ao->oid))
1513 break;
1514 if (!ao)
1515 {
1516 ao = (zebAccessObject) nmem_malloc(zei->nmem, sizeof(*ao));
1517 ao->handle = 0;
1518 ao->sysno = 0;
1519 ao->oid = odr_oiddup_nmem(zei->nmem, oid);
1520 ao->next = *op;
1521 *op = ao;
1522 }
1523 return ao;
1524 }
1525
zebraExplain_add_sui_info(ZebraExplainInfo zei,zinfo_index_category_t cat,const char * index_type)1526 struct zebSUInfoB *zebraExplain_add_sui_info(ZebraExplainInfo zei,
1527 zinfo_index_category_t cat,
1528 const char *index_type)
1529 {
1530 struct zebSUInfoB *zsui;
1531
1532 assert(zei->curDatabaseInfo);
1533 zsui = (struct zebSUInfoB *) nmem_malloc(zei->nmem, sizeof(*zsui));
1534 zsui->next = zei->curDatabaseInfo->attributeDetails->SUInfo;
1535 zei->curDatabaseInfo->attributeDetails->SUInfo = zsui;
1536 zei->curDatabaseInfo->attributeDetails->dirty = 1;
1537 zei->dirty = 1;
1538 zsui->info.index_type = nmem_strdup(zei->nmem, index_type);
1539 zsui->info.cat = cat;
1540 zsui->info.doc_occurrences = 0;
1541 zsui->info.term_occurrences = 0;
1542 zsui->info.ordinal = (zei->ordinalSU)++;
1543 return zsui;
1544 }
1545
zebraExplain_add_attr_str(ZebraExplainInfo zei,zinfo_index_category_t cat,const char * index_type,const char * index_name)1546 int zebraExplain_add_attr_str(ZebraExplainInfo zei,
1547 zinfo_index_category_t cat,
1548 const char *index_type,
1549 const char *index_name)
1550 {
1551 struct zebSUInfoB *zsui = zebraExplain_add_sui_info(zei, cat, index_type);
1552
1553 zsui->info.str = nmem_strdup(zei->nmem, index_name);
1554 return zsui->info.ordinal;
1555 }
1556
zebraExplain_addSchema(ZebraExplainInfo zei,Odr_oid * oid)1557 void zebraExplain_addSchema(ZebraExplainInfo zei, Odr_oid *oid)
1558 {
1559 zebraExplain_announceOid(zei, &zei->accessInfo->schemas, oid);
1560 zebraExplain_announceOid(zei, &zei->curDatabaseInfo->
1561 accessInfo->schemas, oid);
1562 }
1563
zebraExplain_recordBytesIncrement(ZebraExplainInfo zei,int adjust_num)1564 void zebraExplain_recordBytesIncrement(ZebraExplainInfo zei, int adjust_num)
1565 {
1566 assert(zei->curDatabaseInfo);
1567
1568 if (adjust_num)
1569 {
1570 zei->curDatabaseInfo->recordBytes += adjust_num;
1571 zei->curDatabaseInfo->dirty = 1;
1572 }
1573 }
1574
zebraExplain_recordCountIncrement(ZebraExplainInfo zei,int adjust_num)1575 void zebraExplain_recordCountIncrement(ZebraExplainInfo zei, int adjust_num)
1576 {
1577 assert(zei->curDatabaseInfo);
1578
1579 if (adjust_num)
1580 {
1581 zei->curDatabaseInfo->recordCount += adjust_num;
1582 zei->curDatabaseInfo->dirty = 1;
1583 }
1584 }
1585
zebraExplain_runNumberIncrement(ZebraExplainInfo zei,int adjust_num)1586 zint zebraExplain_runNumberIncrement(ZebraExplainInfo zei, int adjust_num)
1587 {
1588 if (adjust_num)
1589 {
1590 zei->dirty = 1;
1591 }
1592 return zei->runNumber += adjust_num;
1593 }
1594
rec_init_attr(ZebraExplainInfo zei,Record rec)1595 RecordAttr *rec_init_attr(ZebraExplainInfo zei, Record rec)
1596 {
1597 RecordAttr *recordAttr;
1598
1599 if (rec->info[recInfo_attr])
1600 return (RecordAttr *) rec->info[recInfo_attr];
1601 recordAttr = (RecordAttr *) xmalloc(sizeof(*recordAttr));
1602
1603 memset(recordAttr, '\0', sizeof(*recordAttr));
1604 rec->info[recInfo_attr] = (char *) recordAttr;
1605 rec->size[recInfo_attr] = sizeof(*recordAttr);
1606
1607 recordAttr->recordSize = 0;
1608 recordAttr->recordOffset = 0;
1609 recordAttr->runNumber = zei->runNumber;
1610 recordAttr->staticrank = 0;
1611 return recordAttr;
1612 }
1613
att_loadset(void * p,const char * n,const char * name)1614 static void att_loadset(void *p, const char *n, const char *name)
1615 {
1616 data1_handle dh = (data1_handle) p;
1617 if (!data1_get_attset(dh, name))
1618 yaz_log(YLOG_WARN, "Directive attset failed for %s", name);
1619 }
1620
zebraExplain_get_database_ord(ZebraExplainInfo zei)1621 int zebraExplain_get_database_ord(ZebraExplainInfo zei)
1622 {
1623 if (!zei->curDatabaseInfo)
1624 return -1;
1625 return zei->curDatabaseInfo->ordinalDatabase;
1626 }
1627
zebraExplain_loadAttsets(data1_handle dh,Res res)1628 void zebraExplain_loadAttsets(data1_handle dh, Res res)
1629 {
1630 res_trav(res, "attset", dh, att_loadset);
1631 }
1632
1633 /*
1634 zebraExplain_addSU adds to AttributeDetails for a database and
1635 adds attributeSet (in AccessInfo area) to DatabaseInfo if it doesn't
1636 exist for the database.
1637
1638 If the database doesn't exist globally (in TargetInfo) an
1639 AttributeSetInfo must be added (globally).
1640 */
1641 /*
1642 * Local variables:
1643 * c-basic-offset: 4
1644 * c-file-style: "Stroustrup"
1645 * indent-tabs-mode: nil
1646 * End:
1647 * vim: shiftwidth=4 tabstop=8 expandtab
1648 */
1649
1650