1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2011 Index Data
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
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
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
21 \brief indexes records and extract tokens for indexing and sorting
40 #include <yaz/snprintf.h>
42 static int log_level_extract = 0;
43 static int log_level_details = 0;
44 static int log_level_initialized = 0;
46 /* 1 if we use eliminitate identical delete/insert keys */
47 /* eventually this the 0-case code will be removed */
51 static void extract_flush_record_keys2(ZebraHandle zh, zint sysno,
52 zebra_rec_keys_t ins_keys,
54 zebra_rec_keys_t del_keys,
57 static void extract_flush_record_keys(ZebraHandle zh, zint sysno,
59 zebra_rec_keys_t reckeys,
63 static void zebra_init_log_level(void)
65 if (!log_level_initialized)
67 log_level_initialized = 1;
69 log_level_extract = yaz_log_module_level("extract");
70 log_level_details = yaz_log_module_level("indexdetails");
74 static WRBUF wrbuf_hex_str(const char *cstr)
77 WRBUF w = wrbuf_alloc();
78 for (i = 0; cstr[i]; i++)
80 if (cstr[i] < ' ' || cstr[i] > 126)
81 wrbuf_printf(w, "\\%02X", cstr[i] & 0xff);
83 wrbuf_putc(w, cstr[i]);
89 static void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
90 int cmd, zebra_rec_keys_t skp);
91 static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid);
92 static void extract_token_add(RecWord *p);
94 static void check_log_limit(ZebraHandle zh)
96 if (zh->records_processed + zh->records_skipped == zh->m_file_verbose_limit)
98 yaz_log(YLOG_LOG, "More than %d file log entries. Omitting rest",
99 zh->m_file_verbose_limit);
103 static void logRecord(ZebraHandle zh)
106 ++zh->records_processed;
107 if (!(zh->records_processed % 1000))
109 yaz_log(YLOG_LOG, "Records: "ZINT_FORMAT" i/u/d "
110 ZINT_FORMAT"/"ZINT_FORMAT"/"ZINT_FORMAT,
111 zh->records_processed, zh->records_inserted,
112 zh->records_updated, zh->records_deleted);
116 static void init_extractCtrl(ZebraHandle zh, struct recExtractCtrl *ctrl)
118 ctrl->flagShowRecords = !zh->m_flag_rw;
122 static void extract_add_index_string(RecWord *p,
123 zinfo_index_category_t cat,
124 const char *str, int length);
126 static void extract_set_store_data_prepare(struct recExtractCtrl *p);
128 static void extract_init(struct recExtractCtrl *p, RecWord *w)
131 w->index_name = "any";
139 struct snip_rec_info {
141 zebra_snippets *snippets;
145 static void snippet_add_complete_field(RecWord *p, int ord,
148 struct snip_rec_info *h = p->extractCtrl->handle;
150 const char *b = p->term_buf;
151 char buf[IT_MAX_WORD+1];
152 const char **map = 0;
153 int i = 0, remain = p->term_len;
154 const char *start = b;
155 const char *last = 0;
158 map = zebra_maps_input(zm, &b, remain, 1);
160 while (remain > 0 && i < IT_MAX_WORD)
162 while (map && *map && **map == *CHR_SPACE)
164 remain = p->term_len - (b - p->term_buf);
167 start = b; /* set to first non-ws area */
170 int first = i ? 0 : 1; /* first position */
172 map = zebra_maps_input(zm, &b, remain, first);
180 if (i && i < IT_MAX_WORD)
181 buf[i++] = *CHR_SPACE;
182 while (map && *map && **map != *CHR_SPACE)
184 const char *cp = *map;
186 if (**map == *CHR_CUT)
192 if (i >= IT_MAX_WORD)
194 while (i < IT_MAX_WORD && *cp)
198 remain = p->term_len - (b - p->term_buf);
201 map = zebra_maps_input(zm, &b, remain, 0);
209 if (last && start != last && zebra_maps_is_index(zm))
210 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
211 start, last - start);
214 static void snippet_add_incomplete_field(RecWord *p, int ord, zebra_map_t zm)
216 struct snip_rec_info *h = p->extractCtrl->handle;
217 const char *b = p->term_buf;
218 int remain = p->term_len;
220 const char **map = 0;
221 const char *start = b;
222 const char *last = b;
225 map = zebra_maps_input(zm, &b, remain, 0);
229 char buf[IT_MAX_WORD+1];
233 while (map && *map && **map == *CHR_SPACE)
235 remain = p->term_len - (b - p->term_buf);
238 map = zebra_maps_input(zm, &b, remain, 0);
244 if (start != last && zebra_maps_is_index(zm))
246 zebra_snippets_appendn(h->snippets, p->seqno, 1, ord,
247 start, last - start);
253 while (map && *map && **map != *CHR_SPACE)
255 const char *cp = *map;
257 while (i < IT_MAX_WORD && *cp)
259 remain = p->term_len - (b - p->term_buf);
262 map = zebra_maps_input(zm, &b, remain, 0);
272 if (zebra_maps_is_first_in_field(zm))
274 /* first in field marker */
278 if (start != last && zebra_maps_is_index(zm))
279 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
280 start, last - start);
287 static void snippet_add_icu(RecWord *p, int ord, zebra_map_t zm)
289 struct snip_rec_info *h = p->extractCtrl->handle;
291 const char *res_buf = 0;
294 const char *display_buf = 0;
295 size_t display_len = 0;
297 zebra_map_tokenize_start(zm, p->term_buf, p->term_len);
298 while (zebra_map_tokenize_next(zm, &res_buf, &res_len,
299 &display_buf, &display_len))
301 if (zebra_maps_is_index(zm))
302 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
303 display_buf, display_len);
308 static void snippet_token_add(RecWord *p)
310 struct snip_rec_info *h = p->extractCtrl->handle;
311 ZebraHandle zh = h->zh;
312 zebra_map_t zm = zebra_map_get_or_add(zh->reg->zebra_maps, p->index_type);
316 ZebraExplainInfo zei = zh->reg->zei;
317 int ch = zebraExplain_lookup_attr_str(
318 zei, zinfo_index_category_index, p->index_type, p->index_name);
320 if (zebra_maps_is_icu(zm))
321 snippet_add_icu(p, ch, zm);
324 if (zebra_maps_is_complete(zm))
325 snippet_add_complete_field(p, ch, zm);
327 snippet_add_incomplete_field(p, ch, zm);
332 static void snippet_schema_add(
333 struct recExtractCtrl *p, Odr_oid *oid)
338 void extract_snippet(ZebraHandle zh, zebra_snippets *sn,
339 struct ZebraRecStream *stream,
340 RecType rt, void *recTypeClientData)
342 struct recExtractCtrl extractCtrl;
343 struct snip_rec_info info;
346 extractCtrl.stream = stream;
347 extractCtrl.first_record = 1;
348 extractCtrl.init = extract_init;
349 extractCtrl.tokenAdd = snippet_token_add;
350 extractCtrl.schemaAdd = snippet_schema_add;
354 extractCtrl.dh = zh->reg->dh;
358 extractCtrl.handle = &info;
359 extractCtrl.match_criteria[0] = '\0';
360 extractCtrl.staticrank = 0;
361 extractCtrl.action = action_insert;
363 init_extractCtrl(zh, &extractCtrl);
365 extractCtrl.setStoreData = 0;
367 r = (*rt->extract)(recTypeClientData, &extractCtrl);
371 static void searchRecordKey(ZebraHandle zh,
372 zebra_rec_keys_t reckeys,
373 const char *index_name,
374 const char **ws, int ws_length)
378 zinfo_index_category_t cat = zinfo_index_category_index;
380 for (i = 0; i<ws_length; i++)
384 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "0", index_name);
386 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "p", index_name);
388 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "w", index_name);
393 if (zebra_rec_keys_rewind(reckeys))
400 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
402 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
404 seqno = key.mem[key.len-1];
406 if (key.mem[0] == ch)
412 woff = seqno - startSeq;
413 if (woff >= 0 && woff < ws_length)
420 #define FILE_MATCH_BLANK "\t "
422 static char *get_match_from_spec(ZebraHandle zh,
423 zebra_rec_keys_t reckeys,
424 const char *fname, const char *spec)
426 static char dstBuf[2048]; /* static here ??? */
428 const char *s = spec;
432 for (; *s && strchr(FILE_MATCH_BLANK, *s); s++)
439 char attset_str[64], attname_str[64];
443 for (s++; strchr(FILE_MATCH_BLANK, *s); s++)
445 for (i = 0; *s && *s != ',' && *s != ')' &&
446 !strchr(FILE_MATCH_BLANK, *s); s++)
447 if (i+1 < sizeof(attset_str))
448 attset_str[i++] = *s;
449 attset_str[i] = '\0';
451 for (; strchr(FILE_MATCH_BLANK, *s); s++)
454 strcpy(attname_str, attset_str);
457 for (s++; strchr(FILE_MATCH_BLANK, *s); s++)
459 for (i = 0; *s && *s != ')' &&
460 !strchr(FILE_MATCH_BLANK, *s); s++)
461 if (i+1 < sizeof(attname_str))
462 attname_str[i++] = *s;
463 attname_str[i] = '\0';
467 yaz_log(YLOG_WARN, "Missing ) in match criteria %s in group %s",
468 spec, zh->m_group ? zh->m_group : "none");
473 searchRecordKey(zh, reckeys, attname_str, ws, 32);
474 if (0) /* for debugging */
476 for (i = 0; i<32; i++)
480 WRBUF w = wrbuf_hex_str(ws[i]);
481 yaz_log(YLOG_LOG, "ws[%d] = %s", i, wrbuf_cstr(w));
487 for (i = 0; i<32; i++)
496 dst += strlen(ws[i]);
500 yaz_log(YLOG_WARN, "Record didn't contain match"
501 " fields in (%s,%s)", attset_str, attname_str);
509 const char *spec_src = NULL;
510 const char *s1 = ++s;
511 while (*s1 && !strchr(FILE_MATCH_BLANK, *s1))
515 if (spec_len > sizeof(special)-1)
516 spec_len = sizeof(special)-1;
517 memcpy(special, s, spec_len);
518 special[spec_len] = '\0';
521 if (!strcmp(special, "group"))
522 spec_src = zh->m_group;
523 else if (!strcmp(special, "database"))
524 spec_src = zh->basenames[0];
525 else if (!strcmp(special, "filename")) {
528 else if (!strcmp(special, "type"))
529 spec_src = zh->m_record_type;
534 strcpy(dst, spec_src);
535 dst += strlen(spec_src);
538 else if (*s == '\"' || *s == '\'')
540 int stopMarker = *s++;
544 while (*s && *s != stopMarker)
546 if (i+1 < sizeof(tmpString))
547 tmpString[i++] = *s++;
552 strcpy(dst, tmpString);
553 dst += strlen(tmpString);
557 yaz_log(YLOG_WARN, "Syntax error in match criteria %s in group %s",
558 spec, zh->m_group ? zh->m_group : "none");
565 yaz_log(YLOG_WARN, "No match criteria for record %s in group %s",
566 fname, zh->m_group ? zh->m_group : "none");
571 if (0) /* for debugging */
573 WRBUF w = wrbuf_hex_str(dstBuf);
574 yaz_log(YLOG_LOG, "get_match_from_spec %s", wrbuf_cstr(w));
581 struct recordLogInfo {
584 struct recordGroup *rGroup;
587 /** \brief add the always-matches index entry and map to real record ID
588 \param ctrl record control
589 \param record_id custom record ID
590 \param sysno system record ID
592 This function serves two purposes.. It adds the always matches
593 entry and makes a pointer from the custom record ID (if defined)
594 back to the system record ID (sysno)
595 See zebra_recid_to_sysno .
597 static void all_matches_add(struct recExtractCtrl *ctrl, zint record_id,
601 extract_init(ctrl, &word);
602 word.record_id = record_id;
603 /* we use the seqno as placeholder for a way to get back to
604 record database from _ALLRECORDS.. This is used if a custom
605 RECORD was defined */
607 word.index_name = "_ALLRECORDS";
608 word.index_type = "w";
610 extract_add_index_string(&word, zinfo_index_category_alwaysmatches,
614 /* forward declaration */
615 ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh,
616 struct ZebraRecStream *stream,
617 enum zebra_recctrl_action_t action,
618 const char *recordType,
620 const char *match_criteria,
623 void *recTypeClientData);
626 ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname,
627 enum zebra_recctrl_action_t action)
629 ZEBRA_RES r = ZEBRA_OK;
634 struct file_read_info *fi = 0;
635 const char *original_record_type = 0;
637 void *recTypeClientData;
638 struct ZebraRecStream stream, *streamp;
640 zebra_init_log_level();
642 if (!zh->m_group || !*zh->m_group)
645 sprintf(gprefix, "%s.", zh->m_group);
647 yaz_log(log_level_extract, "zebra_extract_file %s", fname);
649 /* determine file extension */
651 for (i = strlen(fname); --i >= 0; )
654 else if (fname[i] == '.')
656 strcpy(ext, fname+i+1);
659 /* determine file type - depending on extension */
660 original_record_type = zh->m_record_type;
661 if (!zh->m_record_type)
663 sprintf(ext_res, "%srecordType.%s", gprefix, ext);
664 zh->m_record_type = res_get(zh->res, ext_res);
666 if (!zh->m_record_type)
669 if (zh->records_processed + zh->records_skipped
670 < zh->m_file_verbose_limit)
671 yaz_log(YLOG_LOG, "? %s", fname);
672 zh->records_skipped++;
675 /* determine match criteria */
676 if (!zh->m_record_id)
678 sprintf(ext_res, "%srecordId.%s", gprefix, ext);
679 zh->m_record_id = res_get(zh->res, ext_res);
683 recType_byName(zh->reg->recTypes, zh->res, zh->m_record_type,
684 &recTypeClientData)))
686 yaz_log(YLOG_WARN, "No such record type: %s", zh->m_record_type);
690 switch(recType->version)
695 yaz_log(YLOG_WARN, "Bad filter version: %s", zh->m_record_type);
697 if (sysno && (action == action_delete || action == action_a_delete))
706 if (zh->path_reg && !yaz_is_abspath(fname))
708 strcpy(full_rep, zh->path_reg);
709 strcat(full_rep, "/");
710 strcat(full_rep, fname);
713 strcpy(full_rep, fname);
715 if ((fd = open(full_rep, O_BINARY|O_RDONLY)) == -1)
717 yaz_log(YLOG_WARN|YLOG_ERRNO, "open %s", full_rep);
718 zh->m_record_type = original_record_type;
722 zebra_create_stream_fd(streamp, fd, 0);
724 r = zebra_extract_records_stream(zh, streamp,
728 0, /*match_criteria */
730 recType, recTypeClientData);
732 stream.destroy(streamp);
733 zh->m_record_type = original_record_type;
738 If sysno is provided, then it's used to identify the reocord.
739 If not, and match_criteria is provided, then sysno is guessed
740 If not, and a record is provided, then sysno is got from there
744 ZEBRA_RES zebra_buffer_extract_record(ZebraHandle zh,
745 const char *buf, size_t buf_size,
746 enum zebra_recctrl_action_t action,
747 const char *recordType,
749 const char *match_criteria,
752 struct ZebraRecStream stream;
757 if (recordType && *recordType)
759 yaz_log(log_level_extract,
760 "Record type explicitly specified: %s", recordType);
761 recType = recType_byName(zh->reg->recTypes, zh->res, recordType,
766 if (!(zh->m_record_type))
768 yaz_log(YLOG_WARN, "No such record type defined");
771 yaz_log(log_level_extract, "Get record type from rgroup: %s",
773 recType = recType_byName(zh->reg->recTypes, zh->res,
774 zh->m_record_type, &clientData);
775 recordType = zh->m_record_type;
780 yaz_log(YLOG_WARN, "No such record type: %s", recordType);
784 zebra_create_stream_mem(&stream, buf, buf_size);
786 res = zebra_extract_records_stream(zh, &stream,
792 recType, clientData);
793 stream.destroy(&stream);
797 static ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
798 struct ZebraRecStream *stream,
799 enum zebra_recctrl_action_t action,
800 const char *recordType,
802 const char *match_criteria,
805 void *recTypeClientData,
810 RecordAttr *recordAttr;
811 struct recExtractCtrl extractCtrl;
813 const char *matchStr = 0;
815 off_t start_offset = 0, end_offset = 0;
816 const char *pr_fname = fname; /* filename to print .. */
817 int show_progress = zh->records_processed + zh->records_skipped
818 < zh->m_file_verbose_limit ? 1:0;
820 zebra_init_log_level();
823 pr_fname = "<no file>"; /* make it printable if file is omitted */
825 zebra_rec_keys_reset(zh->reg->keys);
826 zebra_rec_keys_reset(zh->reg->sortKeys);
828 if (zebraExplain_curDatabase(zh->reg->zei, zh->basenames[0]))
830 if (zebraExplain_newDatabase(zh->reg->zei, zh->basenames[0],
831 zh->m_explain_database))
837 off_t null_offset = 0;
838 extractCtrl.stream = stream;
840 start_offset = stream->tellf(stream);
842 extractCtrl.first_record = start_offset ? 0 : 1;
844 stream->endf(stream, &null_offset);;
846 extractCtrl.init = extract_init;
847 extractCtrl.tokenAdd = extract_token_add;
848 extractCtrl.schemaAdd = extract_schema_add;
849 extractCtrl.dh = zh->reg->dh;
850 extractCtrl.handle = zh;
851 extractCtrl.match_criteria[0] = '\0';
852 extractCtrl.staticrank = 0;
853 extractCtrl.action = action;
855 init_extractCtrl(zh, &extractCtrl);
857 extract_set_store_data_prepare(&extractCtrl);
859 r = (*recType->extract)(recTypeClientData, &extractCtrl);
861 if (action == action_update)
863 action = extractCtrl.action;
868 case RECCTRL_EXTRACT_EOF:
870 case RECCTRL_EXTRACT_ERROR_GENERIC:
871 /* error occured during extraction ... */
872 yaz_log(YLOG_WARN, "extract error: generic");
874 case RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER:
875 /* error occured during extraction ... */
876 yaz_log(YLOG_WARN, "extract error: no such filter");
878 case RECCTRL_EXTRACT_SKIP:
880 yaz_log(YLOG_LOG, "skip %s %s " ZINT_FORMAT,
881 recordType, pr_fname, (zint) start_offset);
884 end_offset = stream->endf(stream, 0);
886 stream->seekf(stream, end_offset);
889 case RECCTRL_EXTRACT_OK:
892 yaz_log(YLOG_WARN, "extract error: unknown error: %d", r);
895 end_offset = stream->endf(stream, 0);
897 stream->seekf(stream, end_offset);
899 end_offset = stream->tellf(stream);
901 if (extractCtrl.match_criteria[0])
902 match_criteria = extractCtrl.match_criteria;
907 if (zh->m_flag_rw == 0)
909 yaz_log(YLOG_LOG, "test %s %s " ZINT_FORMAT, recordType,
910 pr_fname, (zint) start_offset);
911 /* test mode .. Do not perform match */
919 if (match_criteria && *match_criteria)
920 matchStr = match_criteria;
923 if (zh->m_record_id && *zh->m_record_id)
925 matchStr = get_match_from_spec(zh, zh->reg->keys, pr_fname,
929 yaz_log(YLOG_LOG, "error %s %s " ZINT_FORMAT, recordType,
930 pr_fname, (zint) start_offset);
935 WRBUF w = wrbuf_alloc();
937 for (i = 0; i < strlen(matchStr); i++)
939 wrbuf_printf(w, "%02X", matchStr[i] & 0xff);
941 yaz_log(YLOG_LOG, "Got match %s", wrbuf_cstr(w));
948 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
949 char *rinfo = dict_lookup_ord(zh->reg->matchDict, db_ord,
953 if (log_level_extract)
955 WRBUF w = wrbuf_hex_str(matchStr);
956 yaz_log(log_level_extract, "matchStr: %s", wrbuf_cstr(w));
961 assert(*rinfo == sizeof(*sysno));
962 memcpy(sysno, rinfo+1, sizeof(*sysno));
969 /* new record AKA does not exist already */
970 if (action == action_delete)
972 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
973 pr_fname, (zint) start_offset);
974 yaz_log(YLOG_WARN, "cannot delete record above (seems new)");
977 else if (action == action_a_delete)
980 yaz_log(YLOG_LOG, "adelete %s %s " ZINT_FORMAT, recordType,
981 pr_fname, (zint) start_offset);
984 else if (action == action_replace)
986 yaz_log(YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
987 pr_fname, (zint) start_offset);
988 yaz_log(YLOG_WARN, "cannot update record above (seems new)");
992 yaz_log(YLOG_LOG, "add %s %s " ZINT_FORMAT, recordType, pr_fname,
993 (zint) start_offset);
994 rec = rec_new(zh->reg->records);
1001 all_matches_add(&extractCtrl,
1002 zebra_rec_keys_get_custom_record_id(zh->reg->keys),
1007 recordAttr = rec_init_attr(zh->reg->zei, rec);
1008 if (extractCtrl.staticrank < 0)
1010 yaz_log(YLOG_WARN, "Negative staticrank for record. Set to 0");
1011 extractCtrl.staticrank = 0;
1016 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
1017 dict_insert_ord(zh->reg->matchDict, db_ord, matchStr,
1018 sizeof(*sysno), sysno);
1021 extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
1023 extract_flush_record_keys2(zh, *sysno,
1024 zh->reg->keys, extractCtrl.staticrank,
1025 0, recordAttr->staticrank);
1027 extract_flush_record_keys(zh, *sysno, 1, zh->reg->keys,
1028 extractCtrl.staticrank);
1030 recordAttr->staticrank = extractCtrl.staticrank;
1031 zh->records_inserted++;
1035 /* record already exists */
1036 zebra_rec_keys_t delkeys = zebra_rec_keys_open();
1037 zebra_rec_keys_t sortKeys = zebra_rec_keys_open();
1038 if (action == action_insert)
1040 yaz_log(YLOG_LOG, "skipped %s %s " ZINT_FORMAT,
1041 recordType, pr_fname, (zint) start_offset);
1046 rec = rec_get(zh->reg->records, *sysno);
1051 all_matches_add(&extractCtrl,
1052 zebra_rec_keys_get_custom_record_id(zh->reg->keys),
1056 recordAttr = rec_init_attr(zh->reg->zei, rec);
1058 /* decrease total size */
1059 zebraExplain_recordBytesIncrement(zh->reg->zei,
1060 - recordAttr->recordSize);
1062 zebra_rec_keys_set_buf(delkeys,
1063 rec->info[recInfo_delKeys],
1064 rec->size[recInfo_delKeys],
1066 zebra_rec_keys_set_buf(sortKeys,
1067 rec->info[recInfo_sortKeys],
1068 rec->size[recInfo_sortKeys],
1071 extract_flush_sort_keys(zh, *sysno, 0, sortKeys);
1073 extract_flush_record_keys(zh, *sysno, 0, delkeys,
1074 recordAttr->staticrank);
1076 if (action == action_delete || action == action_a_delete)
1078 /* record going to be deleted */
1080 extract_flush_record_keys2(zh, *sysno, 0, recordAttr->staticrank,
1081 delkeys, recordAttr->staticrank);
1083 if (zebra_rec_keys_empty(delkeys))
1085 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
1086 pr_fname, (zint) start_offset);
1087 yaz_log(YLOG_WARN, "cannot delete file above, "
1088 "storeKeys false (3)");
1093 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
1094 pr_fname, (zint) start_offset);
1095 zh->records_deleted++;
1098 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
1099 dict_delete_ord(zh->reg->matchDict, db_ord, matchStr);
1101 rec_del(zh->reg->records, &rec);
1103 zebra_rec_keys_close(delkeys);
1104 zebra_rec_keys_close(sortKeys);
1110 { /* update or special_update */
1112 yaz_log(YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
1113 pr_fname, (zint) start_offset);
1114 extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
1117 extract_flush_record_keys2(zh, *sysno,
1118 zh->reg->keys, extractCtrl.staticrank,
1119 delkeys, recordAttr->staticrank);
1121 extract_flush_record_keys(zh, *sysno, 1,
1122 zh->reg->keys, extractCtrl.staticrank);
1124 recordAttr->staticrank = extractCtrl.staticrank;
1125 zh->records_updated++;
1127 zebra_rec_keys_close(delkeys);
1128 zebra_rec_keys_close(sortKeys);
1130 /* update file type */
1131 xfree(rec->info[recInfo_fileType]);
1132 rec->info[recInfo_fileType] =
1133 rec_strdup(recordType, &rec->size[recInfo_fileType]);
1135 /* update filename */
1136 xfree(rec->info[recInfo_filename]);
1137 rec->info[recInfo_filename] =
1138 rec_strdup(fname, &rec->size[recInfo_filename]);
1140 /* update delete keys */
1141 xfree(rec->info[recInfo_delKeys]);
1142 if (!zebra_rec_keys_empty(zh->reg->keys) && zh->m_store_keys == 1)
1144 zebra_rec_keys_get_buf(zh->reg->keys,
1145 &rec->info[recInfo_delKeys],
1146 &rec->size[recInfo_delKeys]);
1150 rec->info[recInfo_delKeys] = NULL;
1151 rec->size[recInfo_delKeys] = 0;
1153 /* update sort keys */
1154 xfree(rec->info[recInfo_sortKeys]);
1156 zebra_rec_keys_get_buf(zh->reg->sortKeys,
1157 &rec->info[recInfo_sortKeys],
1158 &rec->size[recInfo_sortKeys]);
1162 recordAttr->recordSize = end_offset - start_offset;
1163 zebraExplain_recordBytesIncrement(zh->reg->zei,
1164 recordAttr->recordSize);
1167 /* set run-number for this record */
1168 recordAttr->runNumber =
1169 zebraExplain_runNumberIncrement(zh->reg->zei, 0);
1171 /* update store data */
1172 xfree(rec->info[recInfo_storeData]);
1174 /* update store data */
1175 if (zh->store_data_buf)
1177 rec->size[recInfo_storeData] = zh->store_data_size;
1178 rec->info[recInfo_storeData] = zh->store_data_buf;
1179 zh->store_data_buf = 0;
1180 recordAttr->recordSize = zh->store_data_size;
1182 else if (zh->m_store_data)
1184 off_t cur_offset = stream->tellf(stream);
1186 rec->size[recInfo_storeData] = recordAttr->recordSize;
1187 rec->info[recInfo_storeData] = (char *)
1188 xmalloc(recordAttr->recordSize);
1189 stream->seekf(stream, start_offset);
1190 stream->readf(stream, rec->info[recInfo_storeData],
1191 recordAttr->recordSize);
1192 stream->seekf(stream, cur_offset);
1196 rec->info[recInfo_storeData] = NULL;
1197 rec->size[recInfo_storeData] = 0;
1199 /* update database name */
1200 xfree(rec->info[recInfo_databaseName]);
1201 rec->info[recInfo_databaseName] =
1202 rec_strdup(zh->basenames[0], &rec->size[recInfo_databaseName]);
1205 recordAttr->recordOffset = start_offset;
1207 /* commit this record */
1208 rec_put(zh->reg->records, &rec);
1213 /** \brief extracts records from stream
1214 \param zh Zebra Handle
1215 \param stream stream that we read from
1216 \param action (action_insert, action_replace, action_delete, ..)
1217 \param recordType Record filter type "grs.xml", etc.
1218 \param sysno pointer to sysno if already known; NULL otherwise
1219 \param match_criteria (NULL if not already given)
1220 \param fname filename that we read from (for logging purposes only)
1221 \param recType record type
1222 \param recTypeClientData client data for record type
1223 \returns ZEBRA_OK for success; ZEBRA_FAIL for failure
1225 ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh,
1226 struct ZebraRecStream *stream,
1227 enum zebra_recctrl_action_t action,
1228 const char *recordType,
1230 const char *match_criteria,
1233 void *recTypeClientData)
1235 ZEBRA_RES res = ZEBRA_OK;
1239 res = zebra_extract_record_stream(zh, stream,
1245 recType, recTypeClientData, &more);
1251 if (res != ZEBRA_OK)
1259 ZEBRA_RES zebra_extract_explain(void *handle, Record rec, data1_node *n)
1261 ZebraHandle zh = (ZebraHandle) handle;
1262 struct recExtractCtrl extractCtrl;
1264 if (zebraExplain_curDatabase(zh->reg->zei,
1265 rec->info[recInfo_databaseName]))
1268 if (zebraExplain_newDatabase(zh->reg->zei,
1269 rec->info[recInfo_databaseName], 0))
1273 zebra_rec_keys_reset(zh->reg->keys);
1274 zebra_rec_keys_reset(zh->reg->sortKeys);
1276 extractCtrl.init = extract_init;
1277 extractCtrl.tokenAdd = extract_token_add;
1278 extractCtrl.schemaAdd = extract_schema_add;
1279 extractCtrl.dh = zh->reg->dh;
1281 init_extractCtrl(zh, &extractCtrl);
1283 extractCtrl.flagShowRecords = 0;
1284 extractCtrl.match_criteria[0] = '\0';
1285 extractCtrl.staticrank = 0;
1286 extractCtrl.action = action_update;
1288 extractCtrl.handle = handle;
1289 extractCtrl.first_record = 1;
1291 extract_set_store_data_prepare(&extractCtrl);
1294 grs_extract_tree(&extractCtrl, n);
1296 if (rec->size[recInfo_delKeys])
1298 zebra_rec_keys_t delkeys = zebra_rec_keys_open();
1300 zebra_rec_keys_t sortkeys = zebra_rec_keys_open();
1302 zebra_rec_keys_set_buf(delkeys, rec->info[recInfo_delKeys],
1303 rec->size[recInfo_delKeys],
1306 extract_flush_record_keys2(zh, rec->sysno,
1307 zh->reg->keys, 0, delkeys, 0);
1309 extract_flush_record_keys(zh, rec->sysno, 0, delkeys, 0);
1310 extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
1312 zebra_rec_keys_close(delkeys);
1314 zebra_rec_keys_set_buf(sortkeys, rec->info[recInfo_sortKeys],
1315 rec->size[recInfo_sortKeys],
1318 extract_flush_sort_keys(zh, rec->sysno, 0, sortkeys);
1319 zebra_rec_keys_close(sortkeys);
1324 extract_flush_record_keys2(zh, rec->sysno, zh->reg->keys, 0, 0, 0);
1326 extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
1329 extract_flush_sort_keys(zh, rec->sysno, 1, zh->reg->sortKeys);
1331 xfree(rec->info[recInfo_delKeys]);
1332 zebra_rec_keys_get_buf(zh->reg->keys,
1333 &rec->info[recInfo_delKeys],
1334 &rec->size[recInfo_delKeys]);
1336 xfree(rec->info[recInfo_sortKeys]);
1337 zebra_rec_keys_get_buf(zh->reg->sortKeys,
1338 &rec->info[recInfo_sortKeys],
1339 &rec->size[recInfo_sortKeys]);
1343 void zebra_it_key_str_dump(ZebraHandle zh, struct it_key *key,
1344 const char *str, size_t slen, NMEM nmem, int level)
1346 char keystr[200]; /* room for zints to print */
1348 int ord = CAST_ZINT_TO_INT(key->mem[0]);
1349 const char *index_type;
1351 const char *string_index;
1353 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type,
1354 0/* db */, &string_index);
1356 zebra_term_untrans_iconv(zh, nmem, index_type,
1359 for (i = 0; i < key->len; i++)
1361 sprintf(keystr + strlen(keystr), ZINT_FORMAT " ", key->mem[i]);
1364 if (*str < CHR_BASE_CHAR)
1367 char dst_buf[200]; /* room for special chars */
1369 strcpy(dst_buf , "?");
1371 if (!strcmp(str, ""))
1372 strcpy(dst_buf, "alwaysmatches");
1373 if (!strcmp(str, FIRST_IN_FIELD_STR))
1374 strcpy(dst_buf, "firstinfield");
1375 else if (!strcmp(str, CHR_UNKNOWN))
1376 strcpy(dst_buf, "unknown");
1377 else if (!strcmp(str, CHR_SPACE))
1378 strcpy(dst_buf, "space");
1380 for (i = 0; i<slen; i++)
1382 sprintf(dst_buf + strlen(dst_buf), " %d", str[i] & 0xff);
1384 yaz_log(level, "%s%s %s %s", keystr, index_type,
1385 string_index, dst_buf);
1389 yaz_log(level, "%s%s %s \"%s\"", keystr, index_type,
1390 string_index, dst_term);
1393 void extract_rec_keys_log(ZebraHandle zh, int is_insert,
1394 zebra_rec_keys_t reckeys,
1397 if (zebra_rec_keys_rewind(reckeys))
1402 NMEM nmem = nmem_create();
1404 while(zebra_rec_keys_read(reckeys, &str, &slen, &key))
1406 zebra_it_key_str_dump(zh, &key, str, slen, nmem, level);
1413 void extract_rec_keys_adjust(ZebraHandle zh, int is_insert,
1414 zebra_rec_keys_t reckeys)
1416 ZebraExplainInfo zei = zh->reg->zei;
1420 struct ord_stat *next;
1423 if (zebra_rec_keys_rewind(reckeys))
1425 struct ord_stat *ord_list = 0;
1429 struct it_key key_in;
1430 while(zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1432 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
1434 for (p = ord_list; p ; p = p->next)
1442 p = xmalloc(sizeof(*p));
1453 struct ord_stat *p1 = p;
1456 zebraExplain_ord_adjust_occurrences(zei, p->ord, p->no, 1);
1458 zebraExplain_ord_adjust_occurrences(zei, p->ord, - p->no, -1);
1465 static void extract_flush_record_keys(
1466 ZebraHandle zh, zint sysno, int cmd,
1467 zebra_rec_keys_t reckeys,
1470 ZebraExplainInfo zei = zh->reg->zei;
1472 extract_rec_keys_adjust(zh, cmd, reckeys);
1474 if (log_level_details)
1476 yaz_log(log_level_details, "Keys for record " ZINT_FORMAT " %s",
1477 sysno, cmd ? "insert" : "delete");
1478 extract_rec_keys_log(zh, cmd, reckeys, log_level_details);
1481 if (!zh->reg->key_block)
1483 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1484 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1485 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1486 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1488 zebraExplain_recordCountIncrement(zei, cmd ? 1 : -1);
1491 yaz_log(YLOG_LOG, "sysno=" ZINT_FORMAT " cmd=%d", sysno, cmd);
1492 print_rec_keys(zh, reckeys);
1494 if (zebra_rec_keys_rewind(reckeys))
1498 struct it_key key_in;
1499 while(zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1501 key_block_write(zh->reg->key_block, sysno,
1502 &key_in, cmd, str, slen,
1503 staticrank, zh->m_staticrank);
1508 static void extract_flush_record_keys2(
1509 ZebraHandle zh, zint sysno,
1510 zebra_rec_keys_t ins_keys, zint ins_rank,
1511 zebra_rec_keys_t del_keys, zint del_rank)
1513 ZebraExplainInfo zei = zh->reg->zei;
1517 if (!zh->reg->key_block)
1519 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1520 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1521 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1522 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1527 extract_rec_keys_adjust(zh, 1, ins_keys);
1529 zebraExplain_recordCountIncrement(zei, 1);
1530 zebra_rec_keys_rewind(ins_keys);
1534 extract_rec_keys_adjust(zh, 0, del_keys);
1536 zebraExplain_recordCountIncrement(zei, -1);
1537 zebra_rec_keys_rewind(del_keys);
1543 const char *del_str;
1544 struct it_key del_key_in;
1548 const char *ins_str;
1549 struct it_key ins_key_in;
1553 del = zebra_rec_keys_read(del_keys, &del_str, &del_slen,
1556 ins = zebra_rec_keys_read(ins_keys, &ins_str, &ins_slen,
1559 if (del && ins && ins_rank == del_rank
1560 && !key_compare(&del_key_in, &ins_key_in)
1561 && ins_slen == del_slen && !memcmp(del_str, ins_str, del_slen))
1571 key_block_write(zh->reg->key_block, sysno,
1572 &del_key_in, 0, del_str, del_slen,
1573 del_rank, zh->m_staticrank);
1575 key_block_write(zh->reg->key_block, sysno,
1576 &ins_key_in, 1, ins_str, ins_slen,
1577 ins_rank, zh->m_staticrank);
1579 yaz_log(log_level_extract, "normal=%d optimized=%d", normal, optimized);
1583 ZEBRA_RES zebra_rec_keys_to_snippets1(ZebraHandle zh,
1584 zebra_rec_keys_t reckeys,
1585 zebra_snippets *snippets)
1587 NMEM nmem = nmem_create();
1588 if (zebra_rec_keys_rewind(reckeys))
1593 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1598 const char *index_type;
1600 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1601 seqno = key.mem[key.len-1];
1602 ord = CAST_ZINT_TO_INT(key.mem[0]);
1604 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type,
1605 0/* db */, 0 /* string_index */);
1607 zebra_term_untrans_iconv(zh, nmem, index_type,
1609 zebra_snippets_append(snippets, seqno, 0, ord, dst_term);
1617 void print_rec_keys(ZebraHandle zh, zebra_rec_keys_t reckeys)
1619 yaz_log(YLOG_LOG, "print_rec_keys");
1620 if (zebra_rec_keys_rewind(reckeys))
1625 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1627 char dst_buf[IT_MAX_WORD];
1629 const char *index_type;
1630 int ord = CAST_ZINT_TO_INT(key.mem[0]);
1632 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1634 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, 0);
1636 seqno = key.mem[key.len-1];
1638 zebra_term_untrans(zh, index_type, dst_buf, str);
1640 yaz_log(YLOG_LOG, "ord=%d seqno=" ZINT_FORMAT
1641 " term=%s", ord, seqno, dst_buf);
1646 static void extract_add_index_string(RecWord *p, zinfo_index_category_t cat,
1647 const char *str, int length)
1650 ZebraHandle zh = p->extractCtrl->handle;
1651 ZebraExplainInfo zei = zh->reg->zei;
1654 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1656 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1660 key.mem[i++] = p->record_id;
1661 key.mem[i++] = p->section_id;
1663 if (zh->m_segment_indexing)
1664 key.mem[i++] = p->segment;
1665 key.mem[i++] = p->seqno;
1668 zebra_rec_keys_write(zh->reg->keys, str, length, &key);
1671 static void extract_add_sort_string(RecWord *p, const char *str, int length)
1674 ZebraHandle zh = p->extractCtrl->handle;
1675 ZebraExplainInfo zei = zh->reg->zei;
1677 zinfo_index_category_t cat = zinfo_index_category_sort;
1679 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1681 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1684 key.mem[1] = p->record_id;
1685 key.mem[2] = p->section_id;
1687 zebra_rec_keys_write(zh->reg->sortKeys, str, length, &key);
1690 static void extract_add_staticrank_string(RecWord *p,
1691 const char *str, int length)
1694 struct recExtractCtrl *ctrl = p->extractCtrl;
1696 if (length > sizeof(valz)-1)
1697 length = sizeof(valz)-1;
1699 memcpy(valz, str, length);
1700 valz[length] = '\0';
1701 ctrl->staticrank = atozint(valz);
1704 static void extract_add_string(RecWord *p, zebra_map_t zm,
1705 const char *string, int length)
1711 if (log_level_details)
1714 WRBUF w = wrbuf_alloc();
1716 wrbuf_write_escaped(w, string, length);
1717 yaz_log(log_level_details, "extract_add_string: %s", wrbuf_cstr(w));
1720 if (zebra_maps_is_index(zm))
1722 extract_add_index_string(p, zinfo_index_category_index,
1724 if (zebra_maps_is_alwaysmatches(zm))
1727 memcpy(&word, p, sizeof(word));
1730 extract_add_index_string(
1731 &word, zinfo_index_category_alwaysmatches, "", 0);
1734 else if (zebra_maps_is_sort(zm))
1736 extract_add_sort_string(p, string, length);
1738 else if (zebra_maps_is_staticrank(zm))
1740 extract_add_staticrank_string(p, string, length);
1744 static void extract_add_incomplete_field(RecWord *p, zebra_map_t zm)
1746 const char *b = p->term_buf;
1747 int remain = p->term_len;
1749 const char **map = 0;
1752 map = zebra_maps_input(zm, &b, remain, 0);
1756 char buf[IT_MAX_WORD+1];
1760 while (map && *map && **map == *CHR_SPACE)
1762 remain = p->term_len - (b - p->term_buf);
1764 map = zebra_maps_input(zm, &b, remain, 0);
1771 while (map && *map && **map != *CHR_SPACE)
1773 const char *cp = *map;
1775 while (i < IT_MAX_WORD && *cp)
1777 remain = p->term_len - (b - p->term_buf);
1779 map = zebra_maps_input(zm, &b, remain, 0);
1789 if (zebra_maps_is_first_in_field(zm))
1791 /* first in field marker */
1792 extract_add_string(p, zm, FIRST_IN_FIELD_STR, FIRST_IN_FIELD_LEN);
1796 extract_add_string(p, zm, buf, i);
1801 static void extract_add_complete_field(RecWord *p, zebra_map_t zm)
1803 const char *b = p->term_buf;
1804 char buf[IT_MAX_WORD+1];
1805 const char **map = 0;
1806 int i = 0, remain = p->term_len;
1809 map = zebra_maps_input(zm, &b, remain, 1);
1811 while (remain > 0 && i < IT_MAX_WORD)
1813 while (map && *map && **map == *CHR_SPACE)
1815 remain = p->term_len - (b - p->term_buf);
1819 int first = i ? 0 : 1; /* first position */
1820 map = zebra_maps_input(zm, &b, remain, first);
1828 if (i && i < IT_MAX_WORD)
1829 buf[i++] = *CHR_SPACE;
1830 while (map && *map && **map != *CHR_SPACE)
1832 const char *cp = *map;
1834 if (**map == *CHR_CUT)
1840 if (i >= IT_MAX_WORD)
1842 while (i < IT_MAX_WORD && *cp)
1845 remain = p->term_len - (b - p->term_buf);
1848 map = zebra_maps_input(zm, &b, remain, 0);
1856 extract_add_string(p, zm, buf, i);
1859 static void extract_add_icu(RecWord *p, zebra_map_t zm)
1861 const char *res_buf = 0;
1864 zebra_map_tokenize_start(zm, p->term_buf, p->term_len);
1865 while (zebra_map_tokenize_next(zm, &res_buf, &res_len, 0, 0))
1867 extract_add_string(p, zm, res_buf, res_len);
1873 /** \brief top-level indexing handler for recctrl system
1874 \param p token data to be indexed
1878 extract_add_{in}_complete / extract_add_icu
1881 extract_add_index_string
1883 extract_add_sort_string
1885 extract_add_staticrank_string
1888 static void extract_token_add(RecWord *p)
1890 ZebraHandle zh = p->extractCtrl->handle;
1891 zebra_map_t zm = zebra_map_get_or_add(zh->reg->zebra_maps, p->index_type);
1894 if (log_level_details)
1896 yaz_log(log_level_details, "extract_token_add "
1897 "type=%s index=%s seqno=" ZINT_FORMAT " s=%.*s",
1898 p->index_type, p->index_name,
1899 p->seqno, p->term_len, p->term_buf);
1901 if ((wrbuf = zebra_replace(zm, 0, p->term_buf, p->term_len)))
1903 p->term_buf = wrbuf_buf(wrbuf);
1904 p->term_len = wrbuf_len(wrbuf);
1906 if (zebra_maps_is_icu(zm))
1908 extract_add_icu(p, zm);
1912 if (zebra_maps_is_complete(zm))
1913 extract_add_complete_field(p, zm);
1915 extract_add_incomplete_field(p, zm);
1919 static void extract_set_store_data_cb(struct recExtractCtrl *p,
1920 void *buf, size_t sz)
1922 ZebraHandle zh = (ZebraHandle) p->handle;
1924 xfree(zh->store_data_buf);
1925 zh->store_data_buf = 0;
1926 zh->store_data_size = 0;
1929 zh->store_data_buf = xmalloc(sz);
1930 zh->store_data_size = sz;
1931 memcpy(zh->store_data_buf, buf, sz);
1935 static void extract_set_store_data_prepare(struct recExtractCtrl *p)
1937 ZebraHandle zh = (ZebraHandle) p->handle;
1938 xfree(zh->store_data_buf);
1939 zh->store_data_buf = 0;
1940 zh->store_data_size = 0;
1941 p->setStoreData = extract_set_store_data_cb;
1944 static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid)
1946 ZebraHandle zh = (ZebraHandle) p->handle;
1947 zebraExplain_addSchema(zh->reg->zei, oid);
1950 void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
1951 int cmd, zebra_rec_keys_t reckeys)
1954 yaz_log(YLOG_LOG, "extract_flush_sort_keys cmd=%d sysno=" ZINT_FORMAT,
1956 extract_rec_keys_log(zh, cmd, reckeys, YLOG_LOG);
1959 if (zebra_rec_keys_rewind(reckeys))
1961 zebra_sort_index_t si = zh->reg->sort_index;
1964 struct it_key key_in;
1966 NMEM nmem = nmem_create();
1967 struct sort_add_ent {
1970 struct sort_add_ent *next;
1975 struct sort_add_ent *sort_ent_list = 0;
1977 while (zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1979 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
1980 zint filter_sysno = key_in.mem[1];
1981 zint section_id = key_in.mem[2];
1983 struct sort_add_ent **e = &sort_ent_list;
1984 for (; *e; e = &(*e)->next)
1985 if ((*e)->ord == ord && section_id == (*e)->section_id)
1989 *e = nmem_malloc(nmem, sizeof(**e));
1991 (*e)->wrbuf = wrbuf_alloc();
1994 (*e)->sysno = filter_sysno ? filter_sysno : sysno;
1995 (*e)->section_id = section_id;
1998 wrbuf_write((*e)->wrbuf, str, slen);
1999 wrbuf_putc((*e)->wrbuf, '\0');
2003 zint last_sysno = 0;
2004 struct sort_add_ent *e = sort_ent_list;
2005 for (; e; e = e->next)
2007 if (last_sysno != e->sysno)
2009 zebra_sort_sysno(si, e->sysno);
2010 last_sysno = e->sysno;
2012 zebra_sort_type(si, e->ord);
2014 zebra_sort_add(si, e->section_id, e->wrbuf);
2016 zebra_sort_delete(si, e->section_id);
2017 wrbuf_destroy(e->wrbuf);
2027 * c-file-style: "Stroustrup"
2028 * indent-tabs-mode: nil
2030 * vim: shiftwidth=4 tabstop=8 expandtab