Work on isc_merge.
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 29 Oct 1996 16:44:56 +0000 (16:44 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 29 Oct 1996 16:44:56 +0000 (16:44 +0000)
isamc/isamc.c

index 611f3fa..6dd1fd9 100644 (file)
@@ -4,7 +4,10 @@
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: isamc.c,v $
- * Revision 1.1  1996-10-29 13:40:48  adam
+ * Revision 1.2  1996-10-29 16:44:56  adam
+ * Work on isc_merge.
+ *
+ * Revision 1.1  1996/10/29  13:40:48  adam
  * First work.
  *
  */
@@ -113,12 +116,6 @@ int isc_close (ISAMC is)
     return 0;
 }
 
-void isc_catpos (ISAMC_P ipos, int *cat, int *pos)
-{
-    *pos = ipos >> 3;
-    *cat = ipos & 7;
-}
-
 int isc_read_block (ISAMC is, int cat, int pos, char *dst)
 {
     if (is->method->debug > 1)
@@ -290,8 +287,164 @@ ISAMC_P isc_merge_first (ISAMC is, ISAMC_I data)
 
 ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data)
 {
-    assert (ipos == 0);
-    return isc_merge_first (is, data);
+    char i_item[128], *i_item_ptr;
+    int i_more, i_mode, i;
+
+    ISAMC_PP pp; 
+    char f_item[128], *f_item_ptr;
+    int f_more;
+    int block_ptr[100];   /* block pointer (0 if none) */
+    int dirty_ptr[100];   /* dirty flag pointer (1 if dirty) */
+    int firstpos = 0;
+    int nextpos = 0;    
+    int cat = 0;
+    char r_item_buf[128]; /* temporary result output */
+    char *r_buf;          /* block with resulting data */
+    int r_offset = 0;     /* current offset in r_buf */
+    int r_ptr[100];       /* offset pointer */
+    int r_ptri = 0;       /* pointer */
+    void *r_clientData;   /* encode client data */
+
+    if (ipos == 0)
+        return isc_merge_first (is, data);
+
+    r_clientData = (*is->method->code_start)(ISAMC_ENCODE);
+    r_buf = is->r_buf + ISAMC_BLOCK_OFFSET;
+
+    pp = isc_pp_open (is, ipos);
+    f_item_ptr = f_item;
+    f_more = isc_read_item (pp, &f_item_ptr);
+    cat = pp->cat;
+
+    /* read first item from i */
+    i_item_ptr = i_item;
+    i_more = (*data->read_item)(data->clientData, &i_item_ptr, &i_mode);
+    block_ptr[r_ptri] = pp->pos;
+    dirty_ptr[r_ptri] = 0;
+    r_ptr[r_ptri++] = 0;
+
+    while (i_more || f_more)
+    {
+        char *r_item = r_item_buf;
+        int cmp;
+
+        if (!f_more)
+            cmp = -1;
+        else if (!i_more)
+            cmp = 1;
+        else
+            cmp = (*is->method->compare_item)(i_item, f_item);
+        if (cmp == 0)                   /* insert i=f */
+        {
+            if (!i_mode) 
+            {
+                r_item = NULL;
+                dirty_ptr[r_ptri-1] = 1;
+            }
+            else
+                memcpy (r_item, f_item, f_item_ptr - f_item);
+
+            /* move i */
+            i_item_ptr = i_item;
+            i_more = (*data->read_item)(data->clientData, &i_item_ptr,
+                                        &i_mode);
+            /* move f */
+            f_item_ptr = f_item;
+            f_more = isc_read_item (pp, &f_item_ptr);
+        }
+        else if (cmp > 0)               /* insert f */
+        {
+            memcpy (r_item, f_item, f_item_ptr - f_item);
+            /* move f */
+            f_item_ptr = f_item;
+            f_more = isc_read_item (pp, &f_item_ptr);
+        }
+        else                            /* insert i */
+        {
+            if (!i_mode)                /* delete item which isn't there? */
+            {
+                logf (LOG_FATAL, "Inconsistent register");
+                abort ();
+            }
+            memcpy (r_item, i_item, i_item_ptr - i_item);
+            dirty_ptr[r_ptri-1] = 1;
+            /* move i */
+            i_item_ptr = i_item;
+            i_more = (*data->read_item)(data->clientData, &i_item_ptr,
+                                        &i_mode);
+        }
+        if (r_item)  /* insert resulting item? */
+        {
+            char *r_out_ptr = r_buf + r_offset;
+            int new_offset;
+            int border;
+
+            /* border set to initial fill or block size depending on
+               whether we are creating a new one or updating and old
+             */
+            if (block_ptr[r_ptri-1])
+                border = r_ptr[r_ptri-1] + is->method->filecat[cat].bsize
+                         -ISAMC_BLOCK_OFFSET;
+            else
+                border = r_ptr[r_ptri-1] + is->method->filecat[cat].ifill
+                         -ISAMC_BLOCK_OFFSET;
+
+            (*is->method->code_item)(ISAMC_ENCODE, r_clientData,
+                                     &r_out_ptr, &r_item);
+            new_offset = r_out_ptr - r_buf; 
+
+            if (border >= r_offset && border < new_offset)
+            {
+                /* Initial fill of current block category reached... 
+                   Save offset in r_ptr 
+                 */
+                r_ptr[r_ptri++] = r_offset;
+                if (cat == is->max_cat)
+                {
+                    /* We are dealing with block of max size. Block(s)
+                       will be flushed. Note: the block(s) are surely not
+                       the last one(s).
+                     */
+                    if (is->method->debug > 1)
+                        logf (LOG_LOG, "isc: flush %d sections", r_ptri-1);
+                    isc_flush_blocks (is, r_ptr, r_ptri, r_buf,
+                                      &nextpos, &firstpos, cat, 0);
+                    r_ptri = 0;
+                    r_ptr[r_ptri++] = 0;
+                    memcpy (r_buf, r_buf + r_offset, new_offset - r_offset);
+                    new_offset = (new_offset - r_offset);
+                }
+            }
+            r_offset = new_offset;
+            if (cat < is->max_cat &&
+                r_ptri>is->method->filecat[cat].mblocks)
+            {
+                /* Max number blocks in current category reached ->
+                   must switch to next category (with larger block size) 
+                */
+                int j = 1;
+                cat++;
+                /* r_ptr[0] = r_ptr[0] = 0 true anyway.. */
+                /* AD: Any old blocks should be deleted */
+                for (i = 2; i < r_ptri; i++)
+                {
+                    border = is->method->filecat[cat].ifill -
+                             ISAMC_BLOCK_OFFSET + r_ptr[j-1];
+                    if (r_ptr[i] > border && r_ptr[i-1] <= border)
+                        r_ptr[j++] = r_ptr[i-1];
+                }
+                r_ptri = j;
+            }
+        }
+    }
+    r_ptr[r_ptri++] = r_offset;
+    /* flush rest of block(s) in r_buf */
+    if (is->method->debug > 1)
+        logf (LOG_LOG, "isc: flush rest, %d sections", r_ptri-1);
+    isc_flush_blocks (is, r_ptr, r_ptri, r_buf, &nextpos, &firstpos, cat, 1);
+    (*is->method->code_stop)(ISAMC_ENCODE, r_clientData);
+    return cat + firstpos * 8;
 }
 
 
@@ -434,8 +587,9 @@ ISAMC_PP isc_pp_open (ISAMC is, ISAMC_P ipos)
 {
     ISAMC_PP pp = xmalloc (sizeof(*pp));
     char *src;
-    
-    isc_catpos (ipos, &pp->cat, &pp->next);
+   
+    pp->cat = isc_type(ipos);
+    pp->next = isc_block(ipos); 
 
     src = pp->buf = xmalloc (is->method->filecat[pp->cat].bsize);