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);
1466 static void extract_flush_record_keys2(
1467 ZebraHandle zh, zint sysno,
1468 zebra_rec_keys_t ins_keys, zint ins_rank,
1469 zebra_rec_keys_t del_keys, zint del_rank)
1471 ZebraExplainInfo zei = zh->reg->zei;
1475 if (!zh->reg->key_block)
1477 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1478 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1479 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1480 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1485 extract_rec_keys_adjust(zh, 1, ins_keys);
1487 zebraExplain_recordCountIncrement(zei, 1);
1488 zebra_rec_keys_rewind(ins_keys);
1492 extract_rec_keys_adjust(zh, 0, del_keys);
1494 zebraExplain_recordCountIncrement(zei, -1);
1495 zebra_rec_keys_rewind(del_keys);
1501 const char *del_str;
1502 struct it_key del_key_in;
1506 const char *ins_str;
1507 struct it_key ins_key_in;
1511 del = zebra_rec_keys_read(del_keys, &del_str, &del_slen,
1514 ins = zebra_rec_keys_read(ins_keys, &ins_str, &ins_slen,
1517 if (del && ins && ins_rank == del_rank
1518 && !key_compare(&del_key_in, &ins_key_in)
1519 && ins_slen == del_slen && !memcmp(del_str, ins_str, del_slen))
1529 key_block_write(zh->reg->key_block, sysno,
1530 &del_key_in, 0, del_str, del_slen,
1531 del_rank, zh->m_staticrank);
1533 key_block_write(zh->reg->key_block, sysno,
1534 &ins_key_in, 1, ins_str, ins_slen,
1535 ins_rank, zh->m_staticrank);
1537 yaz_log(log_level_extract, "normal=%d optimized=%d", normal, optimized);
1540 static void extract_flush_record_keys(
1541 ZebraHandle zh, zint sysno, int cmd,
1542 zebra_rec_keys_t reckeys,
1545 ZebraExplainInfo zei = zh->reg->zei;
1547 extract_rec_keys_adjust(zh, cmd, reckeys);
1549 if (log_level_details)
1551 yaz_log(log_level_details, "Keys for record " ZINT_FORMAT " %s",
1552 sysno, cmd ? "insert" : "delete");
1553 extract_rec_keys_log(zh, cmd, reckeys, log_level_details);
1556 if (!zh->reg->key_block)
1558 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1559 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1560 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1561 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1563 zebraExplain_recordCountIncrement(zei, cmd ? 1 : -1);
1566 yaz_log(YLOG_LOG, "sysno=" ZINT_FORMAT " cmd=%d", sysno, cmd);
1567 print_rec_keys(zh, reckeys);
1569 if (zebra_rec_keys_rewind(reckeys))
1573 struct it_key key_in;
1574 while(zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1576 key_block_write(zh->reg->key_block, sysno,
1577 &key_in, cmd, str, slen,
1578 staticrank, zh->m_staticrank);
1584 ZEBRA_RES zebra_rec_keys_to_snippets1(ZebraHandle zh,
1585 zebra_rec_keys_t reckeys,
1586 zebra_snippets *snippets)
1588 NMEM nmem = nmem_create();
1589 if (zebra_rec_keys_rewind(reckeys))
1594 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1599 const char *index_type;
1601 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1602 seqno = key.mem[key.len-1];
1603 ord = CAST_ZINT_TO_INT(key.mem[0]);
1605 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type,
1606 0/* db */, 0 /* string_index */);
1608 zebra_term_untrans_iconv(zh, nmem, index_type,
1610 zebra_snippets_append(snippets, seqno, 0, ord, dst_term);
1618 void print_rec_keys(ZebraHandle zh, zebra_rec_keys_t reckeys)
1620 yaz_log(YLOG_LOG, "print_rec_keys");
1621 if (zebra_rec_keys_rewind(reckeys))
1626 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1628 char dst_buf[IT_MAX_WORD];
1630 const char *index_type;
1631 int ord = CAST_ZINT_TO_INT(key.mem[0]);
1633 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1635 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, 0);
1637 seqno = key.mem[key.len-1];
1639 zebra_term_untrans(zh, index_type, dst_buf, str);
1641 yaz_log(YLOG_LOG, "ord=%d seqno=" ZINT_FORMAT
1642 " term=%s", ord, seqno, dst_buf);
1647 static void extract_add_index_string(RecWord *p, zinfo_index_category_t cat,
1648 const char *str, int length)
1651 ZebraHandle zh = p->extractCtrl->handle;
1652 ZebraExplainInfo zei = zh->reg->zei;
1655 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1657 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1661 key.mem[i++] = p->record_id;
1662 key.mem[i++] = p->section_id;
1664 if (zh->m_segment_indexing)
1665 key.mem[i++] = p->segment;
1666 key.mem[i++] = p->seqno;
1669 zebra_rec_keys_write(zh->reg->keys, str, length, &key);
1672 static void extract_add_sort_string(RecWord *p, const char *str, int length)
1675 ZebraHandle zh = p->extractCtrl->handle;
1676 ZebraExplainInfo zei = zh->reg->zei;
1678 zinfo_index_category_t cat = zinfo_index_category_sort;
1680 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1682 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1685 key.mem[1] = p->record_id;
1686 key.mem[2] = p->section_id;
1688 zebra_rec_keys_write(zh->reg->sortKeys, str, length, &key);
1691 static void extract_add_staticrank_string(RecWord *p,
1692 const char *str, int length)
1695 struct recExtractCtrl *ctrl = p->extractCtrl;
1697 if (length > sizeof(valz)-1)
1698 length = sizeof(valz)-1;
1700 memcpy(valz, str, length);
1701 valz[length] = '\0';
1702 ctrl->staticrank = atozint(valz);
1705 static void extract_add_string(RecWord *p, zebra_map_t zm,
1706 const char *string, int length)
1712 if (log_level_details)
1715 WRBUF w = wrbuf_alloc();
1717 wrbuf_write_escaped(w, string, length);
1718 yaz_log(log_level_details, "extract_add_string: %s", wrbuf_cstr(w));
1721 if (zebra_maps_is_index(zm))
1723 extract_add_index_string(p, zinfo_index_category_index,
1725 if (zebra_maps_is_alwaysmatches(zm))
1728 memcpy(&word, p, sizeof(word));
1731 extract_add_index_string(
1732 &word, zinfo_index_category_alwaysmatches, "", 0);
1735 else if (zebra_maps_is_sort(zm))
1737 extract_add_sort_string(p, string, length);
1739 else if (zebra_maps_is_staticrank(zm))
1741 extract_add_staticrank_string(p, string, length);
1745 static void extract_add_incomplete_field(RecWord *p, zebra_map_t zm)
1747 const char *b = p->term_buf;
1748 int remain = p->term_len;
1750 const char **map = 0;
1753 map = zebra_maps_input(zm, &b, remain, 0);
1757 char buf[IT_MAX_WORD+1];
1761 while (map && *map && **map == *CHR_SPACE)
1763 remain = p->term_len - (b - p->term_buf);
1765 map = zebra_maps_input(zm, &b, remain, 0);
1772 while (map && *map && **map != *CHR_SPACE)
1774 const char *cp = *map;
1776 while (i < IT_MAX_WORD && *cp)
1778 remain = p->term_len - (b - p->term_buf);
1780 map = zebra_maps_input(zm, &b, remain, 0);
1790 if (zebra_maps_is_first_in_field(zm))
1792 /* first in field marker */
1793 extract_add_string(p, zm, FIRST_IN_FIELD_STR, FIRST_IN_FIELD_LEN);
1797 extract_add_string(p, zm, buf, i);
1802 static void extract_add_complete_field(RecWord *p, zebra_map_t zm)
1804 const char *b = p->term_buf;
1805 char buf[IT_MAX_WORD+1];
1806 const char **map = 0;
1807 int i = 0, remain = p->term_len;
1810 map = zebra_maps_input(zm, &b, remain, 1);
1812 while (remain > 0 && i < IT_MAX_WORD)
1814 while (map && *map && **map == *CHR_SPACE)
1816 remain = p->term_len - (b - p->term_buf);
1820 int first = i ? 0 : 1; /* first position */
1821 map = zebra_maps_input(zm, &b, remain, first);
1829 if (i && i < IT_MAX_WORD)
1830 buf[i++] = *CHR_SPACE;
1831 while (map && *map && **map != *CHR_SPACE)
1833 const char *cp = *map;
1835 if (**map == *CHR_CUT)
1841 if (i >= IT_MAX_WORD)
1843 while (i < IT_MAX_WORD && *cp)
1846 remain = p->term_len - (b - p->term_buf);
1849 map = zebra_maps_input(zm, &b, remain, 0);
1857 extract_add_string(p, zm, buf, i);
1860 static void extract_add_icu(RecWord *p, zebra_map_t zm)
1862 const char *res_buf = 0;
1865 zebra_map_tokenize_start(zm, p->term_buf, p->term_len);
1866 while (zebra_map_tokenize_next(zm, &res_buf, &res_len, 0, 0))
1868 extract_add_string(p, zm, res_buf, res_len);
1874 /** \brief top-level indexing handler for recctrl system
1875 \param p token data to be indexed
1879 extract_add_{in}_complete / extract_add_icu
1882 extract_add_index_string
1884 extract_add_sort_string
1886 extract_add_staticrank_string
1889 static void extract_token_add(RecWord *p)
1891 ZebraHandle zh = p->extractCtrl->handle;
1892 zebra_map_t zm = zebra_map_get_or_add(zh->reg->zebra_maps, p->index_type);
1895 if (log_level_details)
1897 yaz_log(log_level_details, "extract_token_add "
1898 "type=%s index=%s seqno=" ZINT_FORMAT " s=%.*s",
1899 p->index_type, p->index_name,
1900 p->seqno, p->term_len, p->term_buf);
1902 if ((wrbuf = zebra_replace(zm, 0, p->term_buf, p->term_len)))
1904 p->term_buf = wrbuf_buf(wrbuf);
1905 p->term_len = wrbuf_len(wrbuf);
1907 if (zebra_maps_is_icu(zm))
1909 extract_add_icu(p, zm);
1913 if (zebra_maps_is_complete(zm))
1914 extract_add_complete_field(p, zm);
1916 extract_add_incomplete_field(p, zm);
1920 static void extract_set_store_data_cb(struct recExtractCtrl *p,
1921 void *buf, size_t sz)
1923 ZebraHandle zh = (ZebraHandle) p->handle;
1925 xfree(zh->store_data_buf);
1926 zh->store_data_buf = 0;
1927 zh->store_data_size = 0;
1930 zh->store_data_buf = xmalloc(sz);
1931 zh->store_data_size = sz;
1932 memcpy(zh->store_data_buf, buf, sz);
1936 static void extract_set_store_data_prepare(struct recExtractCtrl *p)
1938 ZebraHandle zh = (ZebraHandle) p->handle;
1939 xfree(zh->store_data_buf);
1940 zh->store_data_buf = 0;
1941 zh->store_data_size = 0;
1942 p->setStoreData = extract_set_store_data_cb;
1945 static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid)
1947 ZebraHandle zh = (ZebraHandle) p->handle;
1948 zebraExplain_addSchema(zh->reg->zei, oid);
1951 void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
1952 int cmd, zebra_rec_keys_t reckeys)
1955 yaz_log(YLOG_LOG, "extract_flush_sort_keys cmd=%d sysno=" ZINT_FORMAT,
1957 extract_rec_keys_log(zh, cmd, reckeys, YLOG_LOG);
1960 if (zebra_rec_keys_rewind(reckeys))
1962 zebra_sort_index_t si = zh->reg->sort_index;
1965 struct it_key key_in;
1967 NMEM nmem = nmem_create();
1968 struct sort_add_ent {
1971 struct sort_add_ent *next;
1976 struct sort_add_ent *sort_ent_list = 0;
1978 while (zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1980 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
1981 zint filter_sysno = key_in.mem[1];
1982 zint section_id = key_in.mem[2];
1984 struct sort_add_ent **e = &sort_ent_list;
1985 for (; *e; e = &(*e)->next)
1986 if ((*e)->ord == ord && section_id == (*e)->section_id)
1990 *e = nmem_malloc(nmem, sizeof(**e));
1992 (*e)->wrbuf = wrbuf_alloc();
1995 (*e)->sysno = filter_sysno ? filter_sysno : sysno;
1996 (*e)->section_id = section_id;
1999 wrbuf_write((*e)->wrbuf, str, slen);
2000 wrbuf_putc((*e)->wrbuf, '\0');
2004 zint last_sysno = 0;
2005 struct sort_add_ent *e = sort_ent_list;
2006 for (; e; e = e->next)
2008 if (last_sysno != e->sysno)
2010 zebra_sort_sysno(si, e->sysno);
2011 last_sysno = e->sysno;
2013 zebra_sort_type(si, e->ord);
2015 zebra_sort_add(si, e->section_id, e->wrbuf);
2017 zebra_sort_delete(si, e->section_id);
2018 wrbuf_destroy(e->wrbuf);
2028 * c-file-style: "Stroustrup"
2029 * indent-tabs-mode: nil
2031 * vim: shiftwidth=4 tabstop=8 expandtab