Fix long-int overflow when calculating number of microseconds elapsed
[idzebra-moved-to-github.git] / index / kinput.c
index 01a074c..a590587 100644 (file)
@@ -1,15 +1,26 @@
-/*
- * Copyright (C) 1994-2002, Index Data
- * All rights reserved.
- * Sebastian Hammer, Adam Dickmeiss, Heikki Levanto
- *
- * $Id: kinput.c,v 1.50 2002-04-23 13:39:10 adam Exp $
- *
- * Bugs
- *  - Allocates a lot of memory for the merge process, but never releases it.
- *    Doesn't matter, as the program terminates soon after.  
- */
+/* $Id: kinput.c,v 1.56 2003-06-23 15:35:25 adam Exp $
+   Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
+   Index Data Aps
+
+This file is part of the Zebra server.
+
+Zebra is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Zebra; see the file LICENSE.zebra.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+*/
+
+
  
 #include <fcntl.h>
 #ifdef WIN32
@@ -263,7 +274,7 @@ struct heap_info *key_heap_init (int nkeys,
 void key_heap_destroy (struct heap_info *hi, int nkeys)
 {
     int i;
-    yaz_log (LOG_LOG, "key_heap_destroy");
+    yaz_log (LOG_DEBUG, "key_heap_destroy");
     for (i = 0; i<=nkeys; i++)
         xfree (hi->info.buf[i]);
     
@@ -347,26 +358,119 @@ static int heap_read_one (struct heap_info *hi, char *name, char *key)
     return 1;
 }
 
+#define PR_KEY 0
+
+#if PR_KEY
+static void pkey(const char *b, int mode)
+{
+    struct it_key *key = (struct it_key *) b;
+    printf ("%c %d:%d\n", mode + 48, key->sysno, key->seqno);
+}
+#endif
+
 struct heap_cread_info {
     char prev_name[INP_NAME_MAX];
     char cur_name[INP_NAME_MAX];
     char *key;
+    char *key_1, *key_2;
+    int mode_1, mode_2;
+    int sz_1, sz_2;
     struct heap_info *hi;
-    int mode;
+    int first_in_list;
     int more;
+    int ret;
 };
+
+static int heap_cread_item (void *vp, char **dst, int *insertMode);
+
+int heap_cread_item2 (void *vp, char **dst, int *insertMode)
+{
+    struct heap_cread_info *p = (struct heap_cread_info *) vp;
+    int level = 0;
+
+    if (p->ret == 0)    /* lookahead was 0?. Return that in read next round */
+    {
+        p->ret = -1;
+        return 0;
+    }
+    else if (p->ret == -1) /* Must read new item ? */
+    {
+        char *dst_1 = p->key_1;
+        p->ret = heap_cread_item(vp, &dst_1, &p->mode_1);
+        p->sz_1 = dst_1 - p->key_1;
+    }
+    else
+    {        /* lookahead in 2 . Now in 1. */
+        p->sz_1 = p->sz_2;
+        p->mode_1 = p->mode_2;
+        memcpy (p->key_1, p->key_2, p->sz_2);
+    }
+    if (p->mode_1)
+        level = 1;     /* insert */
+    else
+        level = -1;    /* delete */
+    while(1)
+    {
+        char *dst_2 = p->key_2;
+        p->ret = heap_cread_item(vp, &dst_2, &p->mode_2);
+        if (!p->ret)
+        {
+            if (level)
+                break;
+            p->ret = -1;
+            return 0;
+        }
+        p->sz_2 = dst_2 - p->key_2;
+        if (p->sz_1 == p->sz_2 && memcmp(p->key_1, p->key_2, p->sz_1) == 0)
+        {
+            if (p->mode_2) /* adjust level according to deletes/inserts */
+                level++;
+            else
+                level--;
+        }
+        else
+        {
+            if (level)
+                break;
+            /* all the same. new round .. */
+            p->sz_1 = p->sz_2;
+            p->mode_1 = p->mode_2;
+            memcpy (p->key_1, p->key_2, p->sz_1);
+            if (p->mode_1)
+                level = 1;     /* insert */
+            else
+                level = -1;    /* delete */
+        }
+    }
+    /* outcome is insert (1) or delete (0) depending on final level */
+    if (level > 0)
+        *insertMode = 1;
+    else
+        *insertMode = 0;
+    memcpy (*dst, p->key_1, p->sz_1);
+#if PR_KEY
+    printf ("top: ");
+    pkey(*dst, *insertMode); fflush(stdout);
+#endif
+    (*dst) += p->sz_1;
+    return 1;
+}
       
 int heap_cread_item (void *vp, char **dst, int *insertMode)
 {
     struct heap_cread_info *p = (struct heap_cread_info *) vp;
     struct heap_info *hi = p->hi;
 
-    if (p->mode == 1)
+    if (p->first_in_list)
     {
         *insertMode = p->key[0];
         memcpy (*dst, p->key+1, sizeof(struct it_key));
+#if PR_KEY
+        printf ("sub1: ");
+        pkey(*dst, *insertMode);
+#endif
         (*dst) += sizeof(struct it_key);
-        p->mode = 2;
+        p->first_in_list = 0;
         return 1;
     }
     strcpy (p->prev_name, p->cur_name);
@@ -374,11 +478,15 @@ int heap_cread_item (void *vp, char **dst, int *insertMode)
         return 0;
     if (*p->cur_name && strcmp (p->cur_name, p->prev_name))
     {
-        p->mode = 1;
+        p->first_in_list = 1;
         return 0;
     }
     *insertMode = p->key[0];
     memcpy (*dst, p->key+1, sizeof(struct it_key));
+#if PR_KEY
+    printf ("sub2: ");
+    pkey(*dst, *insertMode);
+#endif
     (*dst) += sizeof(struct it_key);
     return 1;
 }
@@ -386,15 +494,18 @@ int heap_cread_item (void *vp, char **dst, int *insertMode)
 int heap_inpc (struct heap_info *hi)
 {
     struct heap_cread_info hci;
-    ISAMC_I isamc_i = (ISAMC_I) xmalloc (sizeof(*isamc_i));
+    ISAMC_I *isamc_i = (ISAMC_I *) xmalloc (sizeof(*isamc_i));
 
     hci.key = (char *) xmalloc (KEY_SIZE);
-    hci.mode = 1;
+    hci.key_1 = (char *) xmalloc (KEY_SIZE);
+    hci.key_2 = (char *) xmalloc (KEY_SIZE);
+    hci.ret = -1;
+    hci.first_in_list = 1;
     hci.hi = hi;
     hci.more = heap_read_one (hi, hci.cur_name, hci.key);
 
     isamc_i->clientData = &hci;
-    isamc_i->read_item = heap_cread_item;
+    isamc_i->read_item = heap_cread_item2;
 
     while (hci.more)
     {
@@ -432,9 +543,12 @@ int heap_inpc (struct heap_info *hi)
     }
     xfree (isamc_i);
     xfree (hci.key);
+    xfree (hci.key_1);
+    xfree (hci.key_2);
     return 0;
 } 
 
+#if 0
 /* for debugging only */
 static void print_dict_item (ZebraMaps zm, const char *s)
 {
@@ -455,19 +569,23 @@ static void print_dict_item (ZebraMaps zm, const char *s)
     *to = '\0';
     yaz_log (LOG_LOG, "%s", keybuf);
 }
+#endif
 
 int heap_inpb (struct heap_info *hi)
 {
     struct heap_cread_info hci;
-    ISAMC_I isamc_i = (ISAMC_I) xmalloc (sizeof(*isamc_i));
+    ISAMC_I *isamc_i = (ISAMC_I *) xmalloc (sizeof(*isamc_i));
 
     hci.key = (char *) xmalloc (KEY_SIZE);
-    hci.mode = 1;
+    hci.key_1 = (char *) xmalloc (KEY_SIZE);
+    hci.key_2 = (char *) xmalloc (KEY_SIZE);
+    hci.ret = -1;
+    hci.first_in_list = 1;
     hci.hi = hi;
     hci.more = heap_read_one (hi, hci.cur_name, hci.key);
 
     isamc_i->clientData = &hci;
-    isamc_i->read_item = heap_cread_item;
+    isamc_i->read_item = heap_cread_item2;
 
     while (hci.more)
     {
@@ -509,6 +627,8 @@ int heap_inpb (struct heap_info *hi)
     }
     xfree (isamc_i);
     xfree (hci.key);
+    xfree (hci.key_1);
+    xfree (hci.key_2);
     return 0;
 } 
 
@@ -518,7 +638,10 @@ int heap_inpd (struct heap_info *hi)
     ISAMD_I isamd_i = (ISAMD_I) xmalloc (sizeof(*isamd_i));
 
     hci.key = (char *) xmalloc (KEY_SIZE);
-    hci.mode = 1;
+    hci.key_1 = (char *) xmalloc (KEY_SIZE);
+    hci.key_2 = (char *) xmalloc (KEY_SIZE);
+    hci.ret = -1;
+    hci.first_in_list = 1;
     hci.hi = hi;
     hci.more = heap_read_one (hi, hci.cur_name, hci.key);
 
@@ -528,38 +651,65 @@ int heap_inpd (struct heap_info *hi)
     while (hci.more)
     {
         char this_name[INP_NAME_MAX];
-        ISAMD_P isamd_p, isamd_p2;
         char *dict_info;
+        char dictentry[ISAMD_MAX_DICT_LEN+1];
+        char dictlen;
 
         strcpy (this_name, hci.cur_name);
+        
+        /* print_dict_item (hi->reg->zebra_maps, hci.cur_name); */
+        /*!*/ /* FIXME: depend on isamd-debug */
+
        assert (hci.cur_name[1]);
         hi->no_diffs++;
         if ((dict_info = dict_lookup (hi->reg->dict, hci.cur_name)))
         {
-            memcpy (&isamd_p, dict_info+1, sizeof(ISAMD_P));
-            isamd_p2 = isamd_append (hi->reg->isamd, isamd_p, isamd_i);
-            if (!isamd_p2)
+            dictlen=dict_info[0];
+            memcpy (dictentry, dict_info+1, dictlen );
+#ifdef SKIPTHIS
+            logf(LOG_LOG,"dictentry before. len=%d: %d %d %d %d %d %d %d %d %d",
+               dictlen,dictentry[0], dictentry[1], dictentry[2],
+                       dictentry[3], dictentry[4], dictentry[5],
+                       dictentry[6], dictentry[7], dictentry[8]); /*!*/
+#endif
+            dictlen= isamd_append(hi->reg->isamd, dictentry, dictlen, isamd_i);
+             /* logf dictentry after */
+            if (dictlen)
             {
-                hi->no_deletions++;
-                if (!dict_delete (hi->reg->dict, this_name))
-                    abort();
+                hi->no_updates++;
+                if ( (dictlen!=dict_info[0]) ||
+                     (0!=memcmp(dictentry, dict_info+1, dictlen)) )
+                {
+                    dict_insert(hi->reg->dict, this_name,
+                                dictlen,dictentry);
+                }
             }
-            else 
+            else
             {
-                hi->no_updates++;
-                if (isamd_p2 != isamd_p)
-                    dict_insert (hi->reg->dict, this_name,
-                                 sizeof(ISAMD_P), &isamd_p2);
+                hi->no_deletions++;
+                if (!dict_delete (hi->reg->dict, this_name)) 
+                {
+                   logf (LOG_FATAL, "dict_delete failed");
+                    abort();
+                }
             }
         } 
         else
         {
-            isamd_p = isamd_append (hi->reg->isamd, 0, isamd_i);
+            dictlen=0;
+            memset (dictentry, '\0', ISAMD_MAX_DICT_LEN);
+            dictlen= isamd_append(hi->reg->isamd, dictentry, dictlen, isamd_i);
+             /* logf dictentry first */
             hi->no_insertions++;
-            dict_insert (hi->reg->dict, this_name, sizeof(ISAMD_P), &isamd_p);
+            if (dictlen)
+                dict_insert(hi->reg->dict, this_name,
+                                dictlen,dictentry);
         }
     }
     xfree (isamd_i);
+    xfree (hci.key);
+    xfree (hci.key_1);
+    xfree (hci.key_2);
     return 0;
 } 
 
@@ -640,7 +790,10 @@ int heap_inps (struct heap_info *hi)
     ISAMS_I isams_i = (ISAMS_I) xmalloc (sizeof(*isams_i));
 
     hci.key = (char *) xmalloc (KEY_SIZE);
-    hci.mode = 1;
+    hci.key_1 = (char *) xmalloc (KEY_SIZE);
+    hci.key_2 = (char *) xmalloc (KEY_SIZE);
+    hci.first_in_list = 1;
+    hci.ret = -1;
     hci.hi = hi;
     hci.more = heap_read_one (hi, hci.cur_name, hci.key);