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
43 #include <yaz/snprintf.h>
45 static int log_level_extract = 0;
46 static int log_level_details = 0;
47 static int log_level_initialized = 0;
49 /* 1 if we use eliminitate identical delete/insert keys */
50 /* eventually this the 0-case code will be removed */
54 static void extract_flush_record_keys2(ZebraHandle zh, zint sysno,
55 zebra_rec_keys_t ins_keys,
57 zebra_rec_keys_t del_keys,
60 static void extract_flush_record_keys(ZebraHandle zh, zint sysno,
62 zebra_rec_keys_t reckeys,
66 static void zebra_init_log_level(void)
68 if (!log_level_initialized)
70 log_level_initialized = 1;
72 log_level_extract = yaz_log_module_level("extract");
73 log_level_details = yaz_log_module_level("indexdetails");
77 static WRBUF wrbuf_hex_str(const char *cstr)
80 WRBUF w = wrbuf_alloc();
81 for (i = 0; cstr[i]; i++)
83 if (cstr[i] < ' ' || cstr[i] > 126)
84 wrbuf_printf(w, "\\%02X", cstr[i] & 0xff);
86 wrbuf_putc(w, cstr[i]);
92 static void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
93 int cmd, zebra_rec_keys_t skp);
94 static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid);
95 static void extract_token_add(RecWord *p);
97 static void check_log_limit(ZebraHandle zh)
99 if (zh->records_processed + zh->records_skipped == zh->m_file_verbose_limit)
101 yaz_log(YLOG_LOG, "More than %d file log entries. Omitting rest",
102 zh->m_file_verbose_limit);
106 static void logRecord(ZebraHandle zh)
109 ++zh->records_processed;
110 if (!(zh->records_processed % 1000))
112 yaz_log(YLOG_LOG, "Records: "ZINT_FORMAT" i/u/d "
113 ZINT_FORMAT"/"ZINT_FORMAT"/"ZINT_FORMAT,
114 zh->records_processed, zh->records_inserted,
115 zh->records_updated, zh->records_deleted);
119 static void init_extractCtrl(ZebraHandle zh, struct recExtractCtrl *ctrl)
121 ctrl->flagShowRecords = !zh->m_flag_rw;
125 static void extract_add_index_string(RecWord *p,
126 zinfo_index_category_t cat,
127 const char *str, int length);
129 static void extract_set_store_data_prepare(struct recExtractCtrl *p);
131 static void extract_init(struct recExtractCtrl *p, RecWord *w)
134 w->index_name = "any";
142 struct snip_rec_info {
144 zebra_snippets *snippets;
148 static void snippet_add_complete_field(RecWord *p, int ord,
151 struct snip_rec_info *h = p->extractCtrl->handle;
152 if (p->term_len && p->term_buf && zebra_maps_is_index(zm))
153 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
154 p->term_buf, p->term_len);
158 static void snippet_add_incomplete_field(RecWord *p, int ord, zebra_map_t zm)
160 struct snip_rec_info *h = p->extractCtrl->handle;
161 const char *b = p->term_buf;
162 int remain = p->term_len;
164 const char **map = 0;
165 const char *start = b;
166 const char *last = b;
169 map = zebra_maps_input(zm, &b, remain, 0);
173 char buf[IT_MAX_WORD+1];
177 while (map && *map && **map == *CHR_SPACE)
179 remain = p->term_len - (b - p->term_buf);
182 map = zebra_maps_input(zm, &b, remain, 0);
188 if (start != last && zebra_maps_is_index(zm))
190 zebra_snippets_appendn(h->snippets, p->seqno, 1, ord,
191 start, last - start);
197 while (map && *map && **map != *CHR_SPACE)
199 const char *cp = *map;
201 while (i < IT_MAX_WORD && *cp)
203 remain = p->term_len - (b - p->term_buf);
206 map = zebra_maps_input(zm, &b, remain, 0);
216 if (zebra_maps_is_first_in_field(zm))
218 /* first in field marker */
222 if (start != last && zebra_maps_is_index(zm))
223 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
224 start, last - start);
231 static void snippet_add_icu(RecWord *p, int ord, zebra_map_t zm)
233 struct snip_rec_info *h = p->extractCtrl->handle;
235 const char *res_buf = 0;
238 const char *display_buf = 0;
239 size_t display_len = 0;
241 zebra_map_tokenize_start(zm, p->term_buf, p->term_len);
242 while (zebra_map_tokenize_next(zm, &res_buf, &res_len,
243 &display_buf, &display_len))
245 if (zebra_maps_is_index(zm))
246 zebra_snippets_appendn(h->snippets, p->seqno, 0, ord,
247 display_buf, display_len);
252 static void snippet_token_add(RecWord *p)
254 struct snip_rec_info *h = p->extractCtrl->handle;
255 ZebraHandle zh = h->zh;
256 zebra_map_t zm = zebra_map_get_or_add(zh->reg->zebra_maps, p->index_type);
260 ZebraExplainInfo zei = zh->reg->zei;
261 int ch = zebraExplain_lookup_attr_str(
262 zei, zinfo_index_category_index, p->index_type, p->index_name);
264 if (zebra_maps_is_icu(zm))
265 snippet_add_icu(p, ch, zm);
268 if (zebra_maps_is_complete(zm))
269 snippet_add_complete_field(p, ch, zm);
271 snippet_add_incomplete_field(p, ch, zm);
276 static void snippet_schema_add(
277 struct recExtractCtrl *p, Odr_oid *oid)
282 void extract_snippet(ZebraHandle zh, zebra_snippets *sn,
283 struct ZebraRecStream *stream,
284 RecType rt, void *recTypeClientData)
286 struct recExtractCtrl extractCtrl;
287 struct snip_rec_info info;
290 extractCtrl.stream = stream;
291 extractCtrl.first_record = 1;
292 extractCtrl.init = extract_init;
293 extractCtrl.tokenAdd = snippet_token_add;
294 extractCtrl.schemaAdd = snippet_schema_add;
298 extractCtrl.dh = zh->reg->dh;
302 extractCtrl.handle = &info;
303 extractCtrl.match_criteria[0] = '\0';
304 extractCtrl.staticrank = 0;
305 extractCtrl.action = action_insert;
307 init_extractCtrl(zh, &extractCtrl);
309 extractCtrl.setStoreData = 0;
311 r = (*rt->extract)(recTypeClientData, &extractCtrl);
315 static void searchRecordKey(ZebraHandle zh,
316 zebra_rec_keys_t reckeys,
317 const char *index_name,
318 const char **ws, int ws_length)
322 zinfo_index_category_t cat = zinfo_index_category_index;
324 for (i = 0; i<ws_length; i++)
328 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "0", index_name);
330 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "p", index_name);
332 ch = zebraExplain_lookup_attr_str(zh->reg->zei, cat, "w", index_name);
337 if (zebra_rec_keys_rewind(reckeys))
344 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
346 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
348 seqno = key.mem[key.len-1];
350 if (key.mem[0] == ch)
356 woff = seqno - startSeq;
357 if (woff >= 0 && woff < ws_length)
364 #define FILE_MATCH_BLANK "\t "
366 static char *get_match_from_spec(ZebraHandle zh,
367 zebra_rec_keys_t reckeys,
368 const char *fname, const char *spec)
370 static char dstBuf[2048]; /* static here ??? */
372 const char *s = spec;
376 for (; *s && strchr(FILE_MATCH_BLANK, *s); s++)
383 char attset_str[64], attname_str[64];
387 for (s++; strchr(FILE_MATCH_BLANK, *s); s++)
389 for (i = 0; *s && *s != ',' && *s != ')' &&
390 !strchr(FILE_MATCH_BLANK, *s); s++)
391 if (i+1 < sizeof(attset_str))
392 attset_str[i++] = *s;
393 attset_str[i] = '\0';
395 for (; strchr(FILE_MATCH_BLANK, *s); s++)
398 strcpy(attname_str, attset_str);
401 for (s++; strchr(FILE_MATCH_BLANK, *s); s++)
403 for (i = 0; *s && *s != ')' &&
404 !strchr(FILE_MATCH_BLANK, *s); s++)
405 if (i+1 < sizeof(attname_str))
406 attname_str[i++] = *s;
407 attname_str[i] = '\0';
411 yaz_log(YLOG_WARN, "Missing ) in match criteria %s in group %s",
412 spec, zh->m_group ? zh->m_group : "none");
417 searchRecordKey(zh, reckeys, attname_str, ws, 32);
418 if (0) /* for debugging */
420 for (i = 0; i<32; i++)
424 WRBUF w = wrbuf_hex_str(ws[i]);
425 yaz_log(YLOG_LOG, "ws[%d] = %s", i, wrbuf_cstr(w));
431 for (i = 0; i<32; i++)
440 dst += strlen(ws[i]);
444 yaz_log(YLOG_WARN, "Record didn't contain match"
445 " fields in (%s,%s)", attset_str, attname_str);
453 const char *spec_src = NULL;
454 const char *s1 = ++s;
455 while (*s1 && !strchr(FILE_MATCH_BLANK, *s1))
459 if (spec_len > sizeof(special)-1)
460 spec_len = sizeof(special)-1;
461 memcpy(special, s, spec_len);
462 special[spec_len] = '\0';
465 if (!strcmp(special, "group"))
466 spec_src = zh->m_group;
467 else if (!strcmp(special, "database"))
468 spec_src = zh->basenames[0];
469 else if (!strcmp(special, "filename")) {
472 else if (!strcmp(special, "type"))
473 spec_src = zh->m_record_type;
478 strcpy(dst, spec_src);
479 dst += strlen(spec_src);
482 else if (*s == '\"' || *s == '\'')
484 int stopMarker = *s++;
488 while (*s && *s != stopMarker)
490 if (i+1 < sizeof(tmpString))
491 tmpString[i++] = *s++;
496 strcpy(dst, tmpString);
497 dst += strlen(tmpString);
501 yaz_log(YLOG_WARN, "Syntax error in match criteria %s in group %s",
502 spec, zh->m_group ? zh->m_group : "none");
509 yaz_log(YLOG_WARN, "No match criteria for record %s in group %s",
510 fname, zh->m_group ? zh->m_group : "none");
515 if (0) /* for debugging */
517 WRBUF w = wrbuf_hex_str(dstBuf);
518 yaz_log(YLOG_LOG, "get_match_from_spec %s", wrbuf_cstr(w));
525 struct recordLogInfo {
528 struct recordGroup *rGroup;
531 /** \brief add the always-matches index entry and map to real record ID
532 \param ctrl record control
533 \param record_id custom record ID
534 \param sysno system record ID
536 This function serves two purposes.. It adds the always matches
537 entry and makes a pointer from the custom record ID (if defined)
538 back to the system record ID (sysno)
539 See zebra_recid_to_sysno .
541 static void all_matches_add(struct recExtractCtrl *ctrl, zint record_id,
545 extract_init(ctrl, &word);
546 word.record_id = record_id;
547 /* we use the seqno as placeholder for a way to get back to
548 record database from _ALLRECORDS.. This is used if a custom
549 RECORD was defined */
551 word.index_name = "_ALLRECORDS";
552 word.index_type = "w";
554 extract_add_index_string(&word, zinfo_index_category_alwaysmatches,
558 /* forward declaration */
559 ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh,
560 struct ZebraRecStream *stream,
561 enum zebra_recctrl_action_t action,
562 const char *recordType,
564 const char *match_criteria,
567 void *recTypeClientData);
570 ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname,
571 enum zebra_recctrl_action_t action)
573 ZEBRA_RES r = ZEBRA_OK;
578 struct file_read_info *fi = 0;
579 const char *original_record_type = 0;
581 void *recTypeClientData;
582 struct ZebraRecStream stream, *streamp;
584 zebra_init_log_level();
586 if (!zh->m_group || !*zh->m_group)
589 sprintf(gprefix, "%s.", zh->m_group);
591 yaz_log(log_level_extract, "zebra_extract_file %s", fname);
593 /* determine file extension */
595 for (i = strlen(fname); --i >= 0; )
598 else if (fname[i] == '.')
600 strcpy(ext, fname+i+1);
603 /* determine file type - depending on extension */
604 original_record_type = zh->m_record_type;
605 if (!zh->m_record_type)
607 sprintf(ext_res, "%srecordType.%s", gprefix, ext);
608 zh->m_record_type = res_get(zh->res, ext_res);
610 if (!zh->m_record_type)
613 if (zh->records_processed + zh->records_skipped
614 < zh->m_file_verbose_limit)
615 yaz_log(YLOG_LOG, "? %s", fname);
616 zh->records_skipped++;
619 /* determine match criteria */
620 if (!zh->m_record_id)
622 sprintf(ext_res, "%srecordId.%s", gprefix, ext);
623 zh->m_record_id = res_get(zh->res, ext_res);
627 recType_byName(zh->reg->recTypes, zh->res, zh->m_record_type,
628 &recTypeClientData)))
630 yaz_log(YLOG_WARN, "No such record type: %s", zh->m_record_type);
634 switch(recType->version)
639 yaz_log(YLOG_WARN, "Bad filter version: %s", zh->m_record_type);
641 if (sysno && (action == action_delete || action == action_a_delete))
650 if (zh->path_reg && !yaz_is_abspath(fname))
652 strcpy(full_rep, zh->path_reg);
653 strcat(full_rep, "/");
654 strcat(full_rep, fname);
657 strcpy(full_rep, fname);
659 if ((fd = open(full_rep, O_BINARY|O_RDONLY)) == -1)
661 yaz_log(YLOG_WARN|YLOG_ERRNO, "open %s", full_rep);
662 zh->m_record_type = original_record_type;
666 zebra_create_stream_fd(streamp, fd, 0);
668 r = zebra_extract_records_stream(zh, streamp,
672 0, /*match_criteria */
674 recType, recTypeClientData);
676 stream.destroy(streamp);
677 zh->m_record_type = original_record_type;
682 If sysno is provided, then it's used to identify the reocord.
683 If not, and match_criteria is provided, then sysno is guessed
684 If not, and a record is provided, then sysno is got from there
688 ZEBRA_RES zebra_buffer_extract_record(ZebraHandle zh,
689 const char *buf, size_t buf_size,
690 enum zebra_recctrl_action_t action,
691 const char *recordType,
693 const char *match_criteria,
696 struct ZebraRecStream stream;
701 if (recordType && *recordType)
703 yaz_log(log_level_extract,
704 "Record type explicitly specified: %s", recordType);
705 recType = recType_byName(zh->reg->recTypes, zh->res, recordType,
710 if (!(zh->m_record_type))
712 yaz_log(YLOG_WARN, "No such record type defined");
715 yaz_log(log_level_extract, "Get record type from rgroup: %s",
717 recType = recType_byName(zh->reg->recTypes, zh->res,
718 zh->m_record_type, &clientData);
719 recordType = zh->m_record_type;
724 yaz_log(YLOG_WARN, "No such record type: %s", recordType);
728 zebra_create_stream_mem(&stream, buf, buf_size);
730 res = zebra_extract_records_stream(zh, &stream,
736 recType, clientData);
737 stream.destroy(&stream);
741 static ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
742 struct ZebraRecStream *stream,
743 enum zebra_recctrl_action_t action,
744 const char *recordType,
746 const char *match_criteria,
749 void *recTypeClientData,
754 RecordAttr *recordAttr;
755 struct recExtractCtrl extractCtrl;
757 const char *matchStr = 0;
759 off_t start_offset = 0, end_offset = 0;
760 const char *pr_fname = fname; /* filename to print .. */
761 int show_progress = zh->records_processed + zh->records_skipped
762 < zh->m_file_verbose_limit ? 1:0;
764 zebra_init_log_level();
767 pr_fname = "<no file>"; /* make it printable if file is omitted */
769 zebra_rec_keys_reset(zh->reg->keys);
770 zebra_rec_keys_reset(zh->reg->sortKeys);
772 if (zebraExplain_curDatabase(zh->reg->zei, zh->basenames[0]))
774 if (zebraExplain_newDatabase(zh->reg->zei, zh->basenames[0],
775 zh->m_explain_database))
781 off_t null_offset = 0;
782 extractCtrl.stream = stream;
784 start_offset = stream->tellf(stream);
786 extractCtrl.first_record = start_offset ? 0 : 1;
788 stream->endf(stream, &null_offset);;
790 extractCtrl.init = extract_init;
791 extractCtrl.tokenAdd = extract_token_add;
792 extractCtrl.schemaAdd = extract_schema_add;
793 extractCtrl.dh = zh->reg->dh;
794 extractCtrl.handle = zh;
795 extractCtrl.match_criteria[0] = '\0';
796 extractCtrl.staticrank = 0;
797 extractCtrl.action = action;
799 init_extractCtrl(zh, &extractCtrl);
801 extract_set_store_data_prepare(&extractCtrl);
803 r = (*recType->extract)(recTypeClientData, &extractCtrl);
805 if (action == action_update)
807 action = extractCtrl.action;
812 case RECCTRL_EXTRACT_EOF:
814 case RECCTRL_EXTRACT_ERROR_GENERIC:
815 /* error occured during extraction ... */
816 yaz_log(YLOG_WARN, "extract error: generic");
818 case RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER:
819 /* error occured during extraction ... */
820 yaz_log(YLOG_WARN, "extract error: no such filter");
822 case RECCTRL_EXTRACT_SKIP:
824 yaz_log(YLOG_LOG, "skip %s %s " ZINT_FORMAT,
825 recordType, pr_fname, (zint) start_offset);
828 end_offset = stream->endf(stream, 0);
830 stream->seekf(stream, end_offset);
833 case RECCTRL_EXTRACT_OK:
836 yaz_log(YLOG_WARN, "extract error: unknown error: %d", r);
839 end_offset = stream->endf(stream, 0);
841 stream->seekf(stream, end_offset);
843 end_offset = stream->tellf(stream);
845 if (extractCtrl.match_criteria[0])
846 match_criteria = extractCtrl.match_criteria;
851 if (zh->m_flag_rw == 0)
853 yaz_log(YLOG_LOG, "test %s %s " ZINT_FORMAT, recordType,
854 pr_fname, (zint) start_offset);
855 /* test mode .. Do not perform match */
863 if (match_criteria && *match_criteria)
864 matchStr = match_criteria;
867 if (zh->m_record_id && *zh->m_record_id)
869 matchStr = get_match_from_spec(zh, zh->reg->keys, pr_fname,
873 yaz_log(YLOG_LOG, "error %s %s " ZINT_FORMAT, recordType,
874 pr_fname, (zint) start_offset);
879 WRBUF w = wrbuf_alloc();
881 for (i = 0; i < strlen(matchStr); i++)
883 wrbuf_printf(w, "%02X", matchStr[i] & 0xff);
885 yaz_log(YLOG_LOG, "Got match %s", wrbuf_cstr(w));
892 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
893 char *rinfo = dict_lookup_ord(zh->reg->matchDict, db_ord,
897 if (log_level_extract)
899 WRBUF w = wrbuf_hex_str(matchStr);
900 yaz_log(log_level_extract, "matchStr: %s", wrbuf_cstr(w));
905 assert(*rinfo == sizeof(*sysno));
906 memcpy(sysno, rinfo+1, sizeof(*sysno));
913 /* new record AKA does not exist already */
914 if (action == action_delete)
916 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
917 pr_fname, (zint) start_offset);
918 yaz_log(YLOG_WARN, "cannot delete record above (seems new)");
921 else if (action == action_a_delete)
924 yaz_log(YLOG_LOG, "adelete %s %s " ZINT_FORMAT, recordType,
925 pr_fname, (zint) start_offset);
928 else if (action == action_replace)
930 yaz_log(YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
931 pr_fname, (zint) start_offset);
932 yaz_log(YLOG_WARN, "cannot update record above (seems new)");
936 yaz_log(YLOG_LOG, "add %s %s " ZINT_FORMAT, recordType, pr_fname,
937 (zint) start_offset);
938 rec = rec_new(zh->reg->records);
945 all_matches_add(&extractCtrl,
946 zebra_rec_keys_get_custom_record_id(zh->reg->keys),
951 recordAttr = rec_init_attr(zh->reg->zei, rec);
952 if (extractCtrl.staticrank < 0)
954 yaz_log(YLOG_WARN, "Negative staticrank for record. Set to 0");
955 extractCtrl.staticrank = 0;
960 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
961 dict_insert_ord(zh->reg->matchDict, db_ord, matchStr,
962 sizeof(*sysno), sysno);
965 extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
967 extract_flush_record_keys2(zh, *sysno,
968 zh->reg->keys, extractCtrl.staticrank,
969 0, recordAttr->staticrank);
971 extract_flush_record_keys(zh, *sysno, 1, zh->reg->keys,
972 extractCtrl.staticrank);
974 recordAttr->staticrank = extractCtrl.staticrank;
975 zh->records_inserted++;
979 /* record already exists */
980 zebra_rec_keys_t delkeys = zebra_rec_keys_open();
981 zebra_rec_keys_t sortKeys = zebra_rec_keys_open();
982 if (action == action_insert)
984 yaz_log(YLOG_LOG, "skipped %s %s " ZINT_FORMAT,
985 recordType, pr_fname, (zint) start_offset);
990 rec = rec_get(zh->reg->records, *sysno);
995 all_matches_add(&extractCtrl,
996 zebra_rec_keys_get_custom_record_id(zh->reg->keys),
1000 recordAttr = rec_init_attr(zh->reg->zei, rec);
1002 /* decrease total size */
1003 zebraExplain_recordBytesIncrement(zh->reg->zei,
1004 - recordAttr->recordSize);
1006 zebra_rec_keys_set_buf(delkeys,
1007 rec->info[recInfo_delKeys],
1008 rec->size[recInfo_delKeys],
1010 zebra_rec_keys_set_buf(sortKeys,
1011 rec->info[recInfo_sortKeys],
1012 rec->size[recInfo_sortKeys],
1015 extract_flush_sort_keys(zh, *sysno, 0, sortKeys);
1017 extract_flush_record_keys(zh, *sysno, 0, delkeys,
1018 recordAttr->staticrank);
1020 if (action == action_delete || action == action_a_delete)
1022 /* record going to be deleted */
1024 extract_flush_record_keys2(zh, *sysno, 0, recordAttr->staticrank,
1025 delkeys, recordAttr->staticrank);
1027 if (zebra_rec_keys_empty(delkeys))
1029 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
1030 pr_fname, (zint) start_offset);
1031 yaz_log(YLOG_WARN, "cannot delete file above, "
1032 "storeKeys false (3)");
1037 yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
1038 pr_fname, (zint) start_offset);
1039 zh->records_deleted++;
1042 int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
1043 dict_delete_ord(zh->reg->matchDict, db_ord, matchStr);
1045 rec_del(zh->reg->records, &rec);
1047 zebra_rec_keys_close(delkeys);
1048 zebra_rec_keys_close(sortKeys);
1054 { /* update or special_update */
1056 yaz_log(YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
1057 pr_fname, (zint) start_offset);
1058 extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
1061 extract_flush_record_keys2(zh, *sysno,
1062 zh->reg->keys, extractCtrl.staticrank,
1063 delkeys, recordAttr->staticrank);
1065 extract_flush_record_keys(zh, *sysno, 1,
1066 zh->reg->keys, extractCtrl.staticrank);
1068 recordAttr->staticrank = extractCtrl.staticrank;
1069 zh->records_updated++;
1071 zebra_rec_keys_close(delkeys);
1072 zebra_rec_keys_close(sortKeys);
1074 /* update file type */
1075 xfree(rec->info[recInfo_fileType]);
1076 rec->info[recInfo_fileType] =
1077 rec_strdup(recordType, &rec->size[recInfo_fileType]);
1079 /* update filename */
1080 xfree(rec->info[recInfo_filename]);
1081 rec->info[recInfo_filename] =
1082 rec_strdup(fname, &rec->size[recInfo_filename]);
1084 /* update delete keys */
1085 xfree(rec->info[recInfo_delKeys]);
1086 if (!zebra_rec_keys_empty(zh->reg->keys) && zh->m_store_keys == 1)
1088 zebra_rec_keys_get_buf(zh->reg->keys,
1089 &rec->info[recInfo_delKeys],
1090 &rec->size[recInfo_delKeys]);
1094 rec->info[recInfo_delKeys] = NULL;
1095 rec->size[recInfo_delKeys] = 0;
1097 /* update sort keys */
1098 xfree(rec->info[recInfo_sortKeys]);
1100 zebra_rec_keys_get_buf(zh->reg->sortKeys,
1101 &rec->info[recInfo_sortKeys],
1102 &rec->size[recInfo_sortKeys]);
1106 recordAttr->recordSize = end_offset - start_offset;
1107 zebraExplain_recordBytesIncrement(zh->reg->zei,
1108 recordAttr->recordSize);
1111 /* set run-number for this record */
1112 recordAttr->runNumber =
1113 zebraExplain_runNumberIncrement(zh->reg->zei, 0);
1115 /* update store data */
1116 xfree(rec->info[recInfo_storeData]);
1118 /* update store data */
1119 if (zh->store_data_buf)
1121 rec->size[recInfo_storeData] = zh->store_data_size;
1122 rec->info[recInfo_storeData] = zh->store_data_buf;
1123 zh->store_data_buf = 0;
1124 recordAttr->recordSize = zh->store_data_size;
1126 else if (zh->m_store_data)
1128 off_t cur_offset = stream->tellf(stream);
1130 rec->size[recInfo_storeData] = recordAttr->recordSize;
1131 rec->info[recInfo_storeData] = (char *)
1132 xmalloc(recordAttr->recordSize);
1133 stream->seekf(stream, start_offset);
1134 stream->readf(stream, rec->info[recInfo_storeData],
1135 recordAttr->recordSize);
1136 stream->seekf(stream, cur_offset);
1140 rec->info[recInfo_storeData] = NULL;
1141 rec->size[recInfo_storeData] = 0;
1143 /* update database name */
1144 xfree(rec->info[recInfo_databaseName]);
1145 rec->info[recInfo_databaseName] =
1146 rec_strdup(zh->basenames[0], &rec->size[recInfo_databaseName]);
1149 recordAttr->recordOffset = start_offset;
1151 /* commit this record */
1152 rec_put(zh->reg->records, &rec);
1157 /** \brief extracts records from stream
1158 \param zh Zebra Handle
1159 \param stream stream that we read from
1160 \param action (action_insert, action_replace, action_delete, ..)
1161 \param recordType Record filter type "grs.xml", etc.
1162 \param sysno pointer to sysno if already known; NULL otherwise
1163 \param match_criteria (NULL if not already given)
1164 \param fname filename that we read from (for logging purposes only)
1165 \param recType record type
1166 \param recTypeClientData client data for record type
1167 \returns ZEBRA_OK for success; ZEBRA_FAIL for failure
1169 ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh,
1170 struct ZebraRecStream *stream,
1171 enum zebra_recctrl_action_t action,
1172 const char *recordType,
1174 const char *match_criteria,
1177 void *recTypeClientData)
1179 ZEBRA_RES res = ZEBRA_OK;
1183 res = zebra_extract_record_stream(zh, stream,
1189 recType, recTypeClientData, &more);
1195 if (res != ZEBRA_OK)
1203 ZEBRA_RES zebra_extract_explain(void *handle, Record rec, data1_node *n)
1205 ZebraHandle zh = (ZebraHandle) handle;
1206 struct recExtractCtrl extractCtrl;
1208 if (zebraExplain_curDatabase(zh->reg->zei,
1209 rec->info[recInfo_databaseName]))
1212 if (zebraExplain_newDatabase(zh->reg->zei,
1213 rec->info[recInfo_databaseName], 0))
1217 zebra_rec_keys_reset(zh->reg->keys);
1218 zebra_rec_keys_reset(zh->reg->sortKeys);
1220 extractCtrl.init = extract_init;
1221 extractCtrl.tokenAdd = extract_token_add;
1222 extractCtrl.schemaAdd = extract_schema_add;
1223 extractCtrl.dh = zh->reg->dh;
1225 init_extractCtrl(zh, &extractCtrl);
1227 extractCtrl.flagShowRecords = 0;
1228 extractCtrl.match_criteria[0] = '\0';
1229 extractCtrl.staticrank = 0;
1230 extractCtrl.action = action_update;
1232 extractCtrl.handle = handle;
1233 extractCtrl.first_record = 1;
1235 extract_set_store_data_prepare(&extractCtrl);
1238 grs_extract_tree(&extractCtrl, n);
1240 if (rec->size[recInfo_delKeys])
1242 zebra_rec_keys_t delkeys = zebra_rec_keys_open();
1244 zebra_rec_keys_t sortkeys = zebra_rec_keys_open();
1246 zebra_rec_keys_set_buf(delkeys, rec->info[recInfo_delKeys],
1247 rec->size[recInfo_delKeys],
1250 extract_flush_record_keys2(zh, rec->sysno,
1251 zh->reg->keys, 0, delkeys, 0);
1253 extract_flush_record_keys(zh, rec->sysno, 0, delkeys, 0);
1254 extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
1256 zebra_rec_keys_close(delkeys);
1258 zebra_rec_keys_set_buf(sortkeys, rec->info[recInfo_sortKeys],
1259 rec->size[recInfo_sortKeys],
1262 extract_flush_sort_keys(zh, rec->sysno, 0, sortkeys);
1263 zebra_rec_keys_close(sortkeys);
1268 extract_flush_record_keys2(zh, rec->sysno, zh->reg->keys, 0, 0, 0);
1270 extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
1273 extract_flush_sort_keys(zh, rec->sysno, 1, zh->reg->sortKeys);
1275 xfree(rec->info[recInfo_delKeys]);
1276 zebra_rec_keys_get_buf(zh->reg->keys,
1277 &rec->info[recInfo_delKeys],
1278 &rec->size[recInfo_delKeys]);
1280 xfree(rec->info[recInfo_sortKeys]);
1281 zebra_rec_keys_get_buf(zh->reg->sortKeys,
1282 &rec->info[recInfo_sortKeys],
1283 &rec->size[recInfo_sortKeys]);
1287 void zebra_it_key_str_dump(ZebraHandle zh, struct it_key *key,
1288 const char *str, size_t slen, NMEM nmem, int level)
1290 char keystr[200]; /* room for zints to print */
1292 int ord = CAST_ZINT_TO_INT(key->mem[0]);
1293 const char *index_type;
1295 const char *string_index;
1297 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type,
1298 0/* db */, &string_index);
1300 zebra_term_untrans_iconv(zh, nmem, index_type,
1303 for (i = 0; i < key->len; i++)
1305 sprintf(keystr + strlen(keystr), ZINT_FORMAT " ", key->mem[i]);
1308 if (*str < CHR_BASE_CHAR)
1311 char dst_buf[200]; /* room for special chars */
1313 strcpy(dst_buf , "?");
1315 if (!strcmp(str, ""))
1316 strcpy(dst_buf, "alwaysmatches");
1317 if (!strcmp(str, FIRST_IN_FIELD_STR))
1318 strcpy(dst_buf, "firstinfield");
1319 else if (!strcmp(str, CHR_UNKNOWN))
1320 strcpy(dst_buf, "unknown");
1321 else if (!strcmp(str, CHR_SPACE))
1322 strcpy(dst_buf, "space");
1324 for (i = 0; i<slen; i++)
1326 sprintf(dst_buf + strlen(dst_buf), " %d", str[i] & 0xff);
1328 yaz_log(level, "%s%s %s %s", keystr, index_type,
1329 string_index, dst_buf);
1333 yaz_log(level, "%s%s %s \"%s\"", keystr, index_type,
1334 string_index, dst_term);
1337 void extract_rec_keys_log(ZebraHandle zh, int is_insert,
1338 zebra_rec_keys_t reckeys,
1341 if (zebra_rec_keys_rewind(reckeys))
1346 NMEM nmem = nmem_create();
1348 while(zebra_rec_keys_read(reckeys, &str, &slen, &key))
1350 zebra_it_key_str_dump(zh, &key, str, slen, nmem, level);
1357 void extract_rec_keys_adjust(ZebraHandle zh, int is_insert,
1358 zebra_rec_keys_t reckeys)
1360 ZebraExplainInfo zei = zh->reg->zei;
1364 struct ord_stat *next;
1367 if (zebra_rec_keys_rewind(reckeys))
1369 struct ord_stat *ord_list = 0;
1373 struct it_key key_in;
1374 while(zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1376 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
1378 for (p = ord_list; p ; p = p->next)
1386 p = xmalloc(sizeof(*p));
1397 struct ord_stat *p1 = p;
1400 zebraExplain_ord_adjust_occurrences(zei, p->ord, p->no, 1);
1402 zebraExplain_ord_adjust_occurrences(zei, p->ord, - p->no, -1);
1410 static void extract_flush_record_keys2(
1411 ZebraHandle zh, zint sysno,
1412 zebra_rec_keys_t ins_keys, zint ins_rank,
1413 zebra_rec_keys_t del_keys, zint del_rank)
1415 ZebraExplainInfo zei = zh->reg->zei;
1419 if (!zh->reg->key_block)
1421 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1422 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1423 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1424 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1429 extract_rec_keys_adjust(zh, 1, ins_keys);
1431 zebraExplain_recordCountIncrement(zei, 1);
1432 zebra_rec_keys_rewind(ins_keys);
1436 extract_rec_keys_adjust(zh, 0, del_keys);
1438 zebraExplain_recordCountIncrement(zei, -1);
1439 zebra_rec_keys_rewind(del_keys);
1445 const char *del_str;
1446 struct it_key del_key_in;
1450 const char *ins_str;
1451 struct it_key ins_key_in;
1455 del = zebra_rec_keys_read(del_keys, &del_str, &del_slen,
1458 ins = zebra_rec_keys_read(ins_keys, &ins_str, &ins_slen,
1461 if (del && ins && ins_rank == del_rank
1462 && !key_compare(&del_key_in, &ins_key_in)
1463 && ins_slen == del_slen && !memcmp(del_str, ins_str, del_slen))
1473 key_block_write(zh->reg->key_block, sysno,
1474 &del_key_in, 0, del_str, del_slen,
1475 del_rank, zh->m_staticrank);
1477 key_block_write(zh->reg->key_block, sysno,
1478 &ins_key_in, 1, ins_str, ins_slen,
1479 ins_rank, zh->m_staticrank);
1481 yaz_log(log_level_extract, "normal=%d optimized=%d", normal, optimized);
1484 static void extract_flush_record_keys(
1485 ZebraHandle zh, zint sysno, int cmd,
1486 zebra_rec_keys_t reckeys,
1489 ZebraExplainInfo zei = zh->reg->zei;
1491 extract_rec_keys_adjust(zh, cmd, reckeys);
1493 if (log_level_details)
1495 yaz_log(log_level_details, "Keys for record " ZINT_FORMAT " %s",
1496 sysno, cmd ? "insert" : "delete");
1497 extract_rec_keys_log(zh, cmd, reckeys, log_level_details);
1500 if (!zh->reg->key_block)
1502 int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
1503 const char *key_tmp_dir = res_get_def(zh->res, "keyTmpDir", ".");
1504 int use_threads = atoi(res_get_def(zh->res, "threads", "1"));
1505 zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
1507 zebraExplain_recordCountIncrement(zei, cmd ? 1 : -1);
1510 yaz_log(YLOG_LOG, "sysno=" ZINT_FORMAT " cmd=%d", sysno, cmd);
1511 print_rec_keys(zh, reckeys);
1513 if (zebra_rec_keys_rewind(reckeys))
1517 struct it_key key_in;
1518 while(zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1520 key_block_write(zh->reg->key_block, sysno,
1521 &key_in, cmd, str, slen,
1522 staticrank, zh->m_staticrank);
1528 ZEBRA_RES zebra_rec_keys_to_snippets1(ZebraHandle zh,
1529 zebra_rec_keys_t reckeys,
1530 zebra_snippets *snippets)
1532 NMEM nmem = nmem_create();
1533 if (zebra_rec_keys_rewind(reckeys))
1538 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1543 const char *index_type;
1545 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1546 seqno = key.mem[key.len-1];
1547 ord = CAST_ZINT_TO_INT(key.mem[0]);
1549 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type,
1550 0/* db */, 0 /* string_index */);
1552 zebra_term_untrans_iconv(zh, nmem, index_type,
1554 zebra_snippets_append(snippets, seqno, 0, ord, dst_term);
1562 void print_rec_keys(ZebraHandle zh, zebra_rec_keys_t reckeys)
1564 yaz_log(YLOG_LOG, "print_rec_keys");
1565 if (zebra_rec_keys_rewind(reckeys))
1570 while (zebra_rec_keys_read(reckeys, &str, &slen, &key))
1572 char dst_buf[IT_MAX_WORD];
1574 const char *index_type;
1575 int ord = CAST_ZINT_TO_INT(key.mem[0]);
1577 assert(key.len <= IT_KEY_LEVEL_MAX && key.len > 2);
1579 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, 0);
1581 seqno = key.mem[key.len-1];
1583 zebra_term_untrans(zh, index_type, dst_buf, str);
1585 yaz_log(YLOG_LOG, "ord=%d seqno=" ZINT_FORMAT
1586 " term=%s", ord, seqno, dst_buf);
1591 static void extract_add_index_string(RecWord *p, zinfo_index_category_t cat,
1592 const char *str, int length)
1595 ZebraHandle zh = p->extractCtrl->handle;
1596 ZebraExplainInfo zei = zh->reg->zei;
1599 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1601 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1605 key.mem[i++] = p->record_id;
1606 key.mem[i++] = p->section_id;
1608 if (zh->m_segment_indexing)
1609 key.mem[i++] = p->segment;
1610 key.mem[i++] = p->seqno;
1613 zebra_rec_keys_write(zh->reg->keys, str, length, &key);
1616 static void extract_add_sort_string(RecWord *p, const char *str, int length)
1619 ZebraHandle zh = p->extractCtrl->handle;
1620 ZebraExplainInfo zei = zh->reg->zei;
1622 zinfo_index_category_t cat = zinfo_index_category_sort;
1624 ch = zebraExplain_lookup_attr_str(zei, cat, p->index_type, p->index_name);
1626 ch = zebraExplain_add_attr_str(zei, cat, p->index_type, p->index_name);
1629 key.mem[1] = p->record_id;
1630 key.mem[2] = p->section_id;
1632 zebra_rec_keys_write(zh->reg->sortKeys, str, length, &key);
1635 static void extract_add_staticrank_string(RecWord *p,
1636 const char *str, int length)
1639 struct recExtractCtrl *ctrl = p->extractCtrl;
1641 if (length > sizeof(valz)-1)
1642 length = sizeof(valz)-1;
1644 memcpy(valz, str, length);
1645 valz[length] = '\0';
1646 ctrl->staticrank = atozint(valz);
1649 static void extract_add_string(RecWord *p, zebra_map_t zm,
1650 const char *string, int length)
1656 if (log_level_details)
1659 WRBUF w = wrbuf_alloc();
1661 wrbuf_write_escaped(w, string, length);
1662 yaz_log(log_level_details, "extract_add_string: %s", wrbuf_cstr(w));
1665 if (zebra_maps_is_index(zm))
1667 extract_add_index_string(p, zinfo_index_category_index,
1669 if (zebra_maps_is_alwaysmatches(zm))
1672 memcpy(&word, p, sizeof(word));
1675 extract_add_index_string(
1676 &word, zinfo_index_category_alwaysmatches, "", 0);
1679 else if (zebra_maps_is_sort(zm))
1681 extract_add_sort_string(p, string, length);
1683 else if (zebra_maps_is_staticrank(zm))
1685 extract_add_staticrank_string(p, string, length);
1689 static void extract_add_incomplete_field(RecWord *p, zebra_map_t zm)
1691 const char *b = p->term_buf;
1692 int remain = p->term_len;
1694 const char **map = 0;
1697 map = zebra_maps_input(zm, &b, remain, 0);
1701 char buf[IT_MAX_WORD+1];
1705 while (map && *map && **map == *CHR_SPACE)
1707 remain = p->term_len - (b - p->term_buf);
1709 map = zebra_maps_input(zm, &b, remain, 0);
1716 while (map && *map && **map != *CHR_SPACE)
1718 const char *cp = *map;
1720 while (i < IT_MAX_WORD && *cp)
1722 remain = p->term_len - (b - p->term_buf);
1724 map = zebra_maps_input(zm, &b, remain, 0);
1734 if (zebra_maps_is_first_in_field(zm))
1736 /* first in field marker */
1737 extract_add_string(p, zm, FIRST_IN_FIELD_STR, FIRST_IN_FIELD_LEN);
1741 extract_add_string(p, zm, buf, i);
1746 static void extract_add_complete_field(RecWord *p, zebra_map_t zm)
1748 const char *b = p->term_buf;
1749 char buf[IT_MAX_WORD+1];
1750 const char **map = 0;
1751 int i = 0, remain = p->term_len;
1754 map = zebra_maps_input(zm, &b, remain, 1);
1756 while (remain > 0 && i < IT_MAX_WORD)
1758 while (map && *map && **map == *CHR_SPACE)
1760 remain = p->term_len - (b - p->term_buf);
1764 int first = i ? 0 : 1; /* first position */
1765 map = zebra_maps_input(zm, &b, remain, first);
1773 if (i && i < IT_MAX_WORD)
1774 buf[i++] = *CHR_SPACE;
1775 while (map && *map && **map != *CHR_SPACE)
1777 const char *cp = *map;
1779 if (**map == *CHR_CUT)
1785 if (i >= IT_MAX_WORD)
1787 while (i < IT_MAX_WORD && *cp)
1790 remain = p->term_len - (b - p->term_buf);
1793 map = zebra_maps_input(zm, &b, remain, 0);
1801 extract_add_string(p, zm, buf, i);
1805 static void extract_add_icu(RecWord *p, zebra_map_t zm)
1807 const char *res_buf = 0;
1810 zebra_map_tokenize_start(zm, p->term_buf, p->term_len);
1811 while (zebra_map_tokenize_next(zm, &res_buf, &res_len, 0, 0))
1813 extract_add_string(p, zm, res_buf, res_len);
1819 /** \brief top-level indexing handler for recctrl system
1820 \param p token data to be indexed
1824 extract_add_{in}_complete / extract_add_icu
1827 extract_add_index_string
1829 extract_add_sort_string
1831 extract_add_staticrank_string
1834 static void extract_token_add(RecWord *p)
1836 ZebraHandle zh = p->extractCtrl->handle;
1837 zebra_map_t zm = zebra_map_get_or_add(zh->reg->zebra_maps, p->index_type);
1840 if (log_level_details)
1842 yaz_log(log_level_details, "extract_token_add "
1843 "type=%s index=%s seqno=" ZINT_FORMAT " s=%.*s",
1844 p->index_type, p->index_name,
1845 p->seqno, p->term_len, p->term_buf);
1847 if ((wrbuf = zebra_replace(zm, 0, p->term_buf, p->term_len)))
1849 p->term_buf = wrbuf_buf(wrbuf);
1850 p->term_len = wrbuf_len(wrbuf);
1852 if (zebra_maps_is_icu(zm))
1854 extract_add_icu(p, zm);
1858 if (zebra_maps_is_complete(zm))
1859 extract_add_complete_field(p, zm);
1861 extract_add_incomplete_field(p, zm);
1865 static void extract_set_store_data_cb(struct recExtractCtrl *p,
1866 void *buf, size_t sz)
1868 ZebraHandle zh = (ZebraHandle) p->handle;
1870 xfree(zh->store_data_buf);
1871 zh->store_data_buf = 0;
1872 zh->store_data_size = 0;
1875 zh->store_data_buf = xmalloc(sz);
1876 zh->store_data_size = sz;
1877 memcpy(zh->store_data_buf, buf, sz);
1881 static void extract_set_store_data_prepare(struct recExtractCtrl *p)
1883 ZebraHandle zh = (ZebraHandle) p->handle;
1884 xfree(zh->store_data_buf);
1885 zh->store_data_buf = 0;
1886 zh->store_data_size = 0;
1887 p->setStoreData = extract_set_store_data_cb;
1890 static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid)
1892 ZebraHandle zh = (ZebraHandle) p->handle;
1893 zebraExplain_addSchema(zh->reg->zei, oid);
1896 void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
1897 int cmd, zebra_rec_keys_t reckeys)
1900 yaz_log(YLOG_LOG, "extract_flush_sort_keys cmd=%d sysno=" ZINT_FORMAT,
1902 extract_rec_keys_log(zh, cmd, reckeys, YLOG_LOG);
1905 if (zebra_rec_keys_rewind(reckeys))
1907 zebra_sort_index_t si = zh->reg->sort_index;
1910 struct it_key key_in;
1912 NMEM nmem = nmem_create();
1913 struct sort_add_ent {
1916 struct sort_add_ent *next;
1921 struct sort_add_ent *sort_ent_list = 0;
1923 while (zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
1925 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
1926 zint filter_sysno = key_in.mem[1];
1927 zint section_id = key_in.mem[2];
1929 struct sort_add_ent **e = &sort_ent_list;
1930 for (; *e; e = &(*e)->next)
1931 if ((*e)->ord == ord && section_id == (*e)->section_id)
1935 *e = nmem_malloc(nmem, sizeof(**e));
1937 (*e)->wrbuf = wrbuf_alloc();
1940 (*e)->sysno = filter_sysno ? filter_sysno : sysno;
1941 (*e)->section_id = section_id;
1944 wrbuf_write((*e)->wrbuf, str, slen);
1945 wrbuf_putc((*e)->wrbuf, '\0');
1949 zint last_sysno = 0;
1950 struct sort_add_ent *e = sort_ent_list;
1951 for (; e; e = e->next)
1953 if (last_sysno != e->sysno)
1955 zebra_sort_sysno(si, e->sysno);
1956 last_sysno = e->sysno;
1958 zebra_sort_type(si, e->ord);
1960 zebra_sort_add(si, e->section_id, e->wrbuf);
1962 zebra_sort_delete(si, e->section_id);
1963 wrbuf_destroy(e->wrbuf);
1973 * c-file-style: "Stroustrup"
1974 * indent-tabs-mode: nil
1976 * vim: shiftwidth=4 tabstop=8 expandtab