Use Odr_oid for OIDs. Require YAZ 3.0.2 or later.
[idzebra-moved-to-github.git] / index / extract.c
index 526a05f..85f91bd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: extract.c,v 1.247 2007-01-15 15:10:16 adam Exp $
+/* $Id: extract.c,v 1.257 2007-05-08 12:50:04 adam Exp $
    Copyright (C) 1995-2007
    Index Data ApS
 
@@ -40,6 +40,16 @@ static int log_level_extract = 0;
 static int log_level_details = 0;
 static int log_level_initialized = 0;
 
+/* 1 if we use eliminitate identical delete/insert keys */
+/* eventually this the 0-case code will be removed */
+#define FLUSH2 1
+
+void extract_flush_record_keys2(ZebraHandle zh, zint sysno,
+                                zebra_rec_keys_t ins_keys,
+                                zint ins_rank,
+                                zebra_rec_keys_t del_keys,
+                                zint del_rank);
+
 static void zebra_init_log_level(void)
 {
     if (!log_level_initialized)
@@ -59,8 +69,18 @@ static void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
 static void extract_schema_add (struct recExtractCtrl *p, Odr_oid *oid);
 static void extract_token_add (RecWord *p);
 
+static void check_log_limit(ZebraHandle zh)
+{
+    if (zh->records_processed + zh->records_skipped == zh->m_file_verbose_limit)
+    {
+        yaz_log(YLOG_LOG, "More than %d file log entries. Omitting rest",
+                zh->m_file_verbose_limit);
+    }
+}
+
 static void logRecord (ZebraHandle zh)
 {
+    check_log_limit(zh);
     ++zh->records_processed;
     if (!(zh->records_processed % 1000))
     {
@@ -309,6 +329,18 @@ static void all_matches_add(struct recExtractCtrl *ctrl)
                               "", 0);
 }
 
+ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh, 
+                                       struct ZebraRecStream *stream,
+                                       enum zebra_recctrl_action_t action,
+                                       int test_mode, 
+                                       const char *recordType,
+                                       zint *sysno,
+                                       const char *match_criteria,
+                                       const char *fname,
+                                       RecType recType,
+                                       void *recTypeClientData);
+
+
 ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname, 
                             int deleteFlag)
 {
@@ -351,8 +383,11 @@ ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname,
     }
     if (!zh->m_record_type)
     {
-       if (zh->records_processed < zh->m_file_verbose_limit)
+        check_log_limit(zh);
+       if (zh->records_processed + zh->records_skipped
+            < zh->m_file_verbose_limit)
             yaz_log (YLOG_LOG, "? %s", fname);
+        zh->records_skipped++;
         return 0;
     }
     /* determine match criteria */
@@ -404,26 +439,15 @@ ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname,
         streamp = &stream;
         zebra_create_stream_fd(streamp, fd, 0);
     }
-    while(1)
-    {
-        int more = 0;
-        r = zebra_extract_record_stream(zh, streamp,
-                                        deleteFlag,
-                                        0, /* tst_mode */
-                                        zh->m_record_type,
-                                        sysno,
-                                        0, /*match_criteria */
-                                        fname,
-                                        1, /* force_update */
-                                        1, /* allow_update */
-                                        recType, recTypeClientData, &more);
-        if (!more)
-            break;
-       if (sysno)
-       {
-           break;
-       }
-    }
+    r = zebra_extract_records_stream(zh, streamp,
+                                     deleteFlag ? 
+                                     action_delete : action_update,
+                                     0, /* tst_mode */
+                                     zh->m_record_type,
+                                     sysno,
+                                     0, /*match_criteria */
+                                     fname,
+                                     recType, recTypeClientData);
     if (streamp)
         stream.destroy(streamp);
     zh->m_record_type = original_record_type;
@@ -439,20 +463,17 @@ ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname,
 
 ZEBRA_RES zebra_buffer_extract_record(ZebraHandle zh, 
                                       const char *buf, size_t buf_size,
-                                      int delete_flag,
+                                      enum zebra_recctrl_action_t action,
                                       int test_mode, 
                                       const char *recordType,
                                       zint *sysno,
                                       const char *match_criteria,
-                                      const char *fname,
-                                      int force_update,
-                                      int allow_update)
+                                      const char *fname)
 {
     struct ZebraRecStream stream;
     ZEBRA_RES res;
     void *clientData;
     RecType recType = 0;
-    int more = 0;
 
     if (recordType && *recordType)
     {
@@ -483,31 +504,77 @@ ZEBRA_RES zebra_buffer_extract_record(ZebraHandle zh,
 
     zebra_create_stream_mem(&stream, buf, buf_size);
 
-    res = zebra_extract_record_stream(zh, &stream,
-                                      delete_flag,
-                                      test_mode, 
-                                      recordType,
-                                      sysno,
-                                      match_criteria,
-                                      fname,
-                                      force_update,
-                                      allow_update,
-                                      recType, clientData, &more);
+    res = zebra_extract_records_stream(zh, &stream,
+                                       action,
+                                       test_mode, 
+                                       recordType,
+                                       sysno,
+                                       match_criteria,
+                                       fname,
+                                       recType, clientData);
     stream.destroy(&stream);
     return res;
 }
 
+ZEBRA_RES zebra_extract_records_stream(ZebraHandle zh, 
+                                       struct ZebraRecStream *stream,
+                                       enum zebra_recctrl_action_t action,
+                                       int test_mode, 
+                                       const char *recordType,
+                                       zint *sysno,
+                                       const char *match_criteria,
+                                       const char *fname,
+                                       RecType recType,
+                                       void *recTypeClientData)
+{
+    ZEBRA_RES res = ZEBRA_OK;
+    while (1)
+    {
+        int more = 0;
+        res = zebra_extract_record_stream(zh, stream,
+                                          action,
+                                          test_mode, 
+                                          recordType,
+                                          sysno,
+                                          match_criteria,
+                                          fname,
+                                          recType, recTypeClientData, &more);
+        if (!more)
+        {
+            res = ZEBRA_OK;
+            break;
+        }
+        if (res != ZEBRA_OK)
+            break;
+        if (sysno)
+            break;
+    }
+    return res;
+}
+
+
+static WRBUF wrbuf_hex_str(const char *cstr)
+{
+    size_t i;
+    WRBUF w = wrbuf_alloc();
+    for (i = 0; cstr[i]; i++)
+    {
+        if (cstr[i] < ' ' || cstr[i] > 126)
+            wrbuf_printf(w, "\\%02X", cstr[i] & 0xff);
+        else
+            wrbuf_putc(w, cstr[i]);
+    }
+    return w;
+}
 
 ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh, 
                                       struct ZebraRecStream *stream,
-                                      int delete_flag,
+                                      enum zebra_recctrl_action_t action,
                                       int test_mode, 
                                       const char *recordType,
                                       zint *sysno,
                                       const char *match_criteria,
                                       const char *fname,
-                                      int force_update,
-                                      int allow_update,
                                       RecType recType,
                                       void *recTypeClientData,
                                       int *more)
@@ -521,7 +588,8 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
     Record rec;
     off_t start_offset = 0, end_offset = 0;
     const char *pr_fname = fname;  /* filename to print .. */
-    int show_progress = zh->records_processed < zh->m_file_verbose_limit ? 1:0;
+    int show_progress = zh->records_processed + zh->records_skipped 
+        < zh->m_file_verbose_limit ? 1:0;
 
     zebra_init_log_level();
 
@@ -556,44 +624,60 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
         extractCtrl.handle = zh;
         extractCtrl.match_criteria[0] = '\0';
         extractCtrl.staticrank = 0;
+        extractCtrl.action = action;
 
         init_extractCtrl(zh, &extractCtrl);
-        
+
         extract_set_store_data_prepare(&extractCtrl);
         
         r = (*recType->extract)(recTypeClientData, &extractCtrl);
+
+        if (action == action_update)
+        {
+            action = extractCtrl.action;
+        }
         
-        if (r == RECCTRL_EXTRACT_EOF)
-            return ZEBRA_FAIL;
-        else if (r == RECCTRL_EXTRACT_ERROR_GENERIC)
+        switch (r)
         {
+        case RECCTRL_EXTRACT_EOF:
+            return ZEBRA_FAIL;
+        case RECCTRL_EXTRACT_ERROR_GENERIC:
             /* error occured during extraction ... */
             yaz_log (YLOG_WARN, "extract error: generic");
             return ZEBRA_FAIL;
-        }
-        else if (r == RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER)
-        {
+        case RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER:
             /* error occured during extraction ... */
             yaz_log (YLOG_WARN, "extract error: no such filter");
             return ZEBRA_FAIL;
+        case RECCTRL_EXTRACT_SKIP:
+            if (show_progress)
+                yaz_log (YLOG_LOG, "skip %s %s " ZINT_FORMAT,
+                         recordType, pr_fname, (zint) start_offset);
+            *more = 1;
+            
+            end_offset = stream->endf(stream, 0);
+            if (end_offset)
+                stream->seekf(stream, end_offset);
+
+            return ZEBRA_OK;
+        case RECCTRL_EXTRACT_OK:
+            break;
+        default:
+            yaz_log (YLOG_WARN, "extract error: unknown error: %d", r);
+            return ZEBRA_FAIL;
         }
-        
+        end_offset = stream->endf(stream, 0);
+        if (end_offset)
+            stream->seekf(stream, end_offset);
+        else
+            end_offset = stream->tellf(stream);
+
         all_matches_add(&extractCtrl);
         
         if (extractCtrl.match_criteria[0])
             match_criteria = extractCtrl.match_criteria;
-
-
-        end_offset = stream->endf(stream, 0);
-
-        if (!end_offset)
-            end_offset = stream->tellf(stream);
-        else
-            stream->seekf(stream, end_offset);
-
     }
 
-
     *more = 1;
     if (!sysno)
     {
@@ -618,12 +702,20 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
            int db_ord = zebraExplain_get_database_ord(zh->reg->zei);
            char *rinfo = dict_lookup_ord(zh->reg->matchDict, db_ord,
                                          matchStr);
+
+            
+            if (1)
+            {
+                WRBUF w = wrbuf_hex_str(matchStr);
+                yaz_log(YLOG_LOG, "matchStr: %s", wrbuf_cstr(w));
+                wrbuf_destroy(w);
+            }
             if (rinfo)
            {
                assert(*rinfo == sizeof(*sysno));
                 memcpy (sysno, rinfo+1, sizeof(*sysno));
            }
-        }
+       }
     }
     if (zebra_rec_keys_empty(zh->reg->keys))
     {
@@ -636,13 +728,20 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
     if (! *sysno)
     {
         /* new record */
-        if (delete_flag)
+        if (action == action_delete)
         {
            yaz_log (YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
                         pr_fname, (zint) start_offset);
             yaz_log (YLOG_WARN, "cannot delete record above (seems new)");
             return ZEBRA_FAIL;
         }
+       else if (action == action_replace)
+       {
+           yaz_log (YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
+                        pr_fname, (zint) start_offset);
+            yaz_log (YLOG_WARN, "cannot update record above (seems new)");
+            return ZEBRA_FAIL;
+       }
        if (show_progress)
            yaz_log (YLOG_LOG, "add %s %s " ZINT_FORMAT, recordType, pr_fname,
                     (zint) start_offset);
@@ -656,7 +755,6 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
             yaz_log(YLOG_WARN, "Negative staticrank for record. Set to 0");
            extractCtrl.staticrank = 0;
         }
-       recordAttr->staticrank = extractCtrl.staticrank;
 
         if (matchStr)
         {
@@ -666,8 +764,15 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
         }
 
        extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
+#if FLUSH2
+        extract_flush_record_keys2(zh, *sysno,
+                                   zh->reg->keys, extractCtrl.staticrank,
+                                   0, recordAttr->staticrank);
+#else
         extract_flush_record_keys(zh, *sysno, 1, zh->reg->keys,
-                                  recordAttr->staticrank);
+                                  extractCtrl.staticrank);
+#endif
+       recordAttr->staticrank = extractCtrl.staticrank;
         zh->records_inserted++;
     } 
     else
@@ -675,7 +780,7 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
         /* record already exists */
        zebra_rec_keys_t delkeys = zebra_rec_keys_open();
        zebra_rec_keys_t sortKeys = zebra_rec_keys_open();
-       if (!allow_update)
+       if (action == action_insert)
        {
            yaz_log (YLOG_LOG, "skipped %s %s " ZINT_FORMAT, 
                         recordType, pr_fname, (zint) start_offset);
@@ -702,11 +807,17 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
                               0);
 
        extract_flush_sort_keys(zh, *sysno, 0, sortKeys);
+#if !FLUSH2
         extract_flush_record_keys(zh, *sysno, 0, delkeys,
                                   recordAttr->staticrank);
-        if (delete_flag)
+#endif
+        if (action == action_delete)
         {
             /* record going to be deleted */
+#if FLUSH2
+            extract_flush_record_keys2(zh, *sysno, 0, recordAttr->staticrank,
+                                       delkeys, recordAttr->staticrank);
+#endif       
             if (zebra_rec_keys_empty(delkeys))
             {
                yaz_log(YLOG_LOG, "delete %s %s " ZINT_FORMAT, recordType,
@@ -727,19 +838,28 @@ ZEBRA_RES zebra_extract_record_stream(ZebraHandle zh,
                }
                 rec_del (zh->reg->records, &rec);
             }
+            zebra_rec_keys_close(delkeys);
+            zebra_rec_keys_close(sortKeys);
            rec_free(&rec);
             logRecord(zh);
             return ZEBRA_OK;
         }
         else
-        {
+        {   /* update or special_update */
            if (show_progress)
                 yaz_log(YLOG_LOG, "update %s %s " ZINT_FORMAT, recordType,
                         pr_fname, (zint) start_offset);
-           recordAttr->staticrank = extractCtrl.staticrank;
             extract_flush_sort_keys(zh, *sysno, 1, zh->reg->sortKeys);
-            extract_flush_record_keys(zh, *sysno, 1, zh->reg->keys, 
-                                      recordAttr->staticrank);
+
+#if FLUSH2
+            extract_flush_record_keys2(zh, *sysno,
+                                       zh->reg->keys, extractCtrl.staticrank,
+                                       delkeys, recordAttr->staticrank);
+#else
+            extract_flush_record_keys(zh, *sysno, 1, 
+                                      zh->reg->keys, extractCtrl.staticrank);
+#endif
+           recordAttr->staticrank = extractCtrl.staticrank;
             zh->records_updated++;
         }
        zebra_rec_keys_close(delkeys);
@@ -855,6 +975,8 @@ ZEBRA_RES zebra_extract_explain(void *handle, Record rec, data1_node *n)
     extractCtrl.flagShowRecords = 0;
     extractCtrl.match_criteria[0] = '\0';
     extractCtrl.staticrank = 0;
+    extractCtrl.action = action_update;
+
     extractCtrl.handle = handle;
     extractCtrl.first_record = 1;
     
@@ -872,7 +994,13 @@ ZEBRA_RES zebra_extract_explain(void *handle, Record rec, data1_node *n)
        zebra_rec_keys_set_buf(delkeys, rec->info[recInfo_delKeys],
                               rec->size[recInfo_delKeys],
                               0);
+#if FLUSH2
+       extract_flush_record_keys2(zh, rec->sysno, 
+                                   zh->reg->keys, 0, delkeys, 0);
+#else
        extract_flush_record_keys(zh, rec->sysno, 0, delkeys, 0);
+        extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
+#endif
        zebra_rec_keys_close(delkeys);
 
        zebra_rec_keys_set_buf(sortkeys, rec->info[recInfo_sortKeys],
@@ -882,7 +1010,14 @@ ZEBRA_RES zebra_extract_explain(void *handle, Record rec, data1_node *n)
        extract_flush_sort_keys(zh, rec->sysno, 0, sortkeys);
        zebra_rec_keys_close(sortkeys);
     }
-    extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);
+    else
+    {
+#if FLUSH2
+       extract_flush_record_keys2(zh, rec->sysno, zh->reg->keys, 0, 0, 0);
+#else
+        extract_flush_record_keys(zh, rec->sysno, 1, zh->reg->keys, 0);        
+#endif
+    }
     extract_flush_sort_keys(zh, rec->sysno, 1, zh->reg->sortKeys);
     
     xfree (rec->info[recInfo_delKeys]);
@@ -1013,6 +1148,79 @@ void extract_rec_keys_adjust(ZebraHandle zh, int is_insert,
     }
 }
 
+void extract_flush_record_keys2(ZebraHandle zh, zint sysno,
+                                zebra_rec_keys_t ins_keys, zint ins_rank,
+                                zebra_rec_keys_t del_keys, zint del_rank)
+{
+    ZebraExplainInfo zei = zh->reg->zei;
+    int normal = 0;
+    int optimized = 0;
+
+    if (!zh->reg->key_block)
+    {
+       int mem = 1024*1024 * atoi( res_get_def( zh->res, "memmax", "8"));
+        const char *key_tmp_dir = res_get_def (zh->res, "keyTmpDir", ".");
+        int use_threads = atoi(res_get_def (zh->res, "threads", "1"));
+        zh->reg->key_block = key_block_create(mem, key_tmp_dir, use_threads);
+    }
+
+    if (ins_keys)
+    {
+        extract_rec_keys_adjust(zh, 1, ins_keys);
+        if (!del_keys)
+            zebraExplain_recordCountIncrement (zei, 1);
+        zebra_rec_keys_rewind(ins_keys);
+    }
+    if (del_keys)
+    {
+        extract_rec_keys_adjust(zh, 0, del_keys);
+        if (!ins_keys)
+            zebraExplain_recordCountIncrement (zei, -1);
+        zebra_rec_keys_rewind(del_keys);
+    }
+
+    while (1)
+    {
+       size_t del_slen;
+       const char *del_str;
+       struct it_key del_key_in;
+        int del = 0;
+
+       size_t ins_slen;
+       const char *ins_str;
+       struct it_key ins_key_in;
+        int ins = 0;
+
+        if (del_keys)
+            del = zebra_rec_keys_read(del_keys, &del_str, &del_slen,
+                                      &del_key_in);
+        if (ins_keys)
+            ins = zebra_rec_keys_read(ins_keys, &ins_str, &ins_slen,
+                                      &ins_key_in);
+
+        if (del && ins && ins_rank == del_rank
+            && !key_compare(&del_key_in, &ins_key_in) 
+            && ins_slen == del_slen && !memcmp(del_str, ins_str, del_slen))
+        {
+            optimized++;
+            continue;
+        }
+        if (!del && !ins)
+            break;
+        
+        normal++;
+        if (del)
+            key_block_write(zh->reg->key_block, sysno, 
+                            &del_key_in, 0, del_str, del_slen,
+                            del_rank, zh->m_staticrank);
+        if (ins)
+            key_block_write(zh->reg->key_block, sysno, 
+                            &ins_key_in, 1, ins_str, ins_slen,
+                            ins_rank, zh->m_staticrank);
+    }
+    yaz_log(log_level_extract, "normal=%d optimized=%d", normal, optimized);
+}
+
 void extract_flush_record_keys(ZebraHandle zh, zint sysno, int cmd,
                                zebra_rec_keys_t reckeys,
                                zint staticrank)
@@ -1037,6 +1245,10 @@ void extract_flush_record_keys(ZebraHandle zh, zint sysno, int cmd,
     }
     zebraExplain_recordCountIncrement (zei, cmd ? 1 : -1);
 
+#if 0
+    yaz_log(YLOG_LOG, "sysno=" ZINT_FORMAT " cmd=%d", sysno, cmd);
+    print_rec_keys(zh, reckeys);
+#endif
     if (zebra_rec_keys_rewind(reckeys))
     {
        size_t slen;
@@ -1051,7 +1263,6 @@ void extract_flush_record_keys(ZebraHandle zh, zint sysno, int cmd,
     }
 }
 
-
 ZEBRA_RES zebra_rec_keys_to_snippets(ZebraHandle zh,
                                      zebra_rec_keys_t reckeys,
                                      zebra_snippets *snippets)
@@ -1158,6 +1369,20 @@ static void extract_add_sort_string(RecWord *p, const char *str, int length)
     zebra_rec_keys_write(zh->reg->sortKeys, str, length, &key);
 }
 
+static void extract_add_staticrank_string(RecWord *p,
+                                          const char *str, int length)
+{
+    char valz[40];
+    struct recExtractCtrl *ctrl = p->extractCtrl;
+
+    if (length > sizeof(valz)-1)
+        length = sizeof(valz)-1;
+
+    memcpy(valz, str, length);
+    valz[length] = '\0';
+    ctrl->staticrank = atozint(valz);
+}
+
 static void extract_add_string(RecWord *p, const char *string, int length)
 {
     ZebraHandle zh = p->extractCtrl->handle;
@@ -1166,9 +1391,7 @@ static void extract_add_string(RecWord *p, const char *string, int length)
     if (!p->index_name)
         return;
 
-    if (zebra_maps_is_sort(zh->reg->zebra_maps, p->index_type))
-       extract_add_sort_string(p, string, length);
-    else
+    if (zebra_maps_is_index(zh->reg->zebra_maps, p->index_type))
     {
        extract_add_index_string(p, zinfo_index_category_index,
                                  string, length);
@@ -1182,6 +1405,14 @@ static void extract_add_string(RecWord *p, const char *string, int length)
                 &word, zinfo_index_category_alwaysmatches, "", 0);
         }
     }
+    else if (zebra_maps_is_sort(zh->reg->zebra_maps, p->index_type))
+    {
+       extract_add_sort_string(p, string, length);
+    }
+    else if (zebra_maps_is_staticrank(zh->reg->zebra_maps, p->index_type))
+    {
+       extract_add_staticrank_string(p, string, length);
+    }
 }
 
 static void extract_add_incomplete_field(RecWord *p)
@@ -1308,9 +1539,9 @@ static void extract_token_add(RecWord *p)
     ZebraHandle zh = p->extractCtrl->handle;
     WRBUF wrbuf;
 
-    if (log_level_extract)
+    if (log_level_details)
     {
-        yaz_log(log_level_extract, "extract_token_add "
+        yaz_log(log_level_details, "extract_token_add "
                 "type=%c index=%s seqno=" ZINT_FORMAT " s=%.*s",
                 p->index_type, p->index_name, 
                 p->seqno, p->term_len, p->term_buf);