Merge branch 'bug2338'
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 5 Jan 2009 09:56:02 +0000 (10:56 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 5 Jan 2009 09:56:02 +0000 (10:56 +0100)
bfile/cfile.c
bfile/cfile.h
bfile/commit.c
examples/gils/zebra.cfg
index/invstat.c
index/recindex.h
index/records.c
index/zebraapi.c
index/zinfo.c
index/zinfo.h

index ab6efb9..003044b 100644 (file)
@@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "mfile.h"
 #include "cfile.h"
 
-/* set to 1 if extra commit/shadow check is to be performed */
+/** \brief set to 1 if extra commit/shadow check is to be performed */
 #define EXTRA_CHECK 0
 
 static int write_head(CFile cf)
@@ -131,7 +131,7 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname,
     if (ret == 0 || !cf->head.state)
     {
         *firstp = 1;
-        cf->head.state = 1;
+        cf->head.state = CFILE_STATE_HASH;
         cf->head.block_size = block_size;
         cf->head.hash_size = 199;
         hash_bytes = cf->head.hash_size * sizeof(zint);
@@ -163,7 +163,7 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname,
         hash_bytes = cf->head.hash_size * sizeof(zint);
         assert(cf->head.next_bucket > 0);
         assert(cf->head.next_block > 0);
-        if (cf->head.state == 1)
+        if (cf->head.state == CFILE_STATE_HASH)
             cf->array = (zint *) xmalloc(hash_bytes);
         else
             cf->array = NULL;
@@ -173,7 +173,7 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname,
             return 0;
         }
     }
-    if (cf->head.state == 1)
+    if (cf->head.state == CFILE_STATE_HASH)
     {
         cf->parray = (struct CFile_hash_bucket **)
            xmalloc(cf->head.hash_size * sizeof(*cf->parray));
@@ -395,7 +395,7 @@ static int cf_moveto_flat(CFile cf)
          ZINT_FORMAT,
        cf->no_hits, cf->no_miss, cf->bucket_in_memory, 
         cf->head.next_bucket - cf->head.first_bucket);
-    assert(cf->head.state == 1);
+    assert(cf->head.state == CFILE_STATE_HASH);
     if (flush_bucket(cf, -1))
         return -1;
     assert(cf->bucket_in_memory == 0);
@@ -422,7 +422,7 @@ static int cf_moveto_flat(CFile cf)
     cf->array = NULL;
     xfree(cf->parray);
     cf->parray = NULL;
-    cf->head.state = 2;
+    cf->head.state = CFILE_STATE_FLAT;
     cf->dirty = 1;
     return 0;
 }
index e0f9567..f8e0985 100644 (file)
@@ -26,15 +26,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 YAZ_BEGIN_CDECL
 
+/** \brief number of blocks in hash bucket */
 #define HASH_BUCKET 15
 
-struct CFile_ph_bucket {     /* structure on disc */
-    zint no[HASH_BUCKET];    /* block number in original file */
-    zint vno[HASH_BUCKET];   /* block number in shadow file */
-    zint this_bucket;        /* this bucket number */
-    zint next_bucket;        /* next bucket number */
+/** \brief CFile hash structure on disc */
+struct CFile_ph_bucket {
+    zint no[HASH_BUCKET]; /**< block number in original file */
+    zint vno[HASH_BUCKET];/**< block number in shadow file */
+    zint this_bucket;     /**< this bucket number */
+    zint next_bucket;     /**< next bucket number */
 };
 
+/** \brief CFile hash structure info in memory */
 struct CFile_hash_bucket {
     struct CFile_ph_bucket ph;
     int dirty;
@@ -44,35 +47,46 @@ struct CFile_hash_bucket {
 
 #define HASH_BSIZE sizeof(struct CFile_ph_bucket)
 
-#define CFILE_FLAT 1
+/** \brief state of CFile is a hash structure */
+#define CFILE_STATE_HASH 1
+
+/** \brief state of CFile is a flat file file */
+#define CFILE_STATE_FLAT 2
+
+/** \brief CFile file header */
+struct CFile_head {
+    int state;         /**< CFILE_STATE_HASH, CFILE_STATE_FLAT, .. */
+    zint next_block;   /**< next free block / last block */
+    int block_size;    /**< mfile/bfile block size */
+    int hash_size;     /**< no of chains in hash table */
+    zint first_bucket; /**< first hash bucket */
+    zint next_bucket;  /**< last hash bucket + 1 = first flat bucket */
+    zint flat_bucket;  /**< last flat bucket + 1 */
+};
 
+/** \brief All in-memory information per CFile */
 typedef struct CFile_struct
 {
-    struct CFile_head {
-        int state;               /* 1 = hash, 2 = flat */
-        zint next_block;          /* next free block / last block */
-        int block_size;          /* mfile/bfile block size */
-        int hash_size;           /* no of chains in hash table */
-        zint first_bucket;       /* first hash bucket */
-        zint next_bucket;        /* last hash bucket + 1 = first flat bucket */
-        zint flat_bucket;        /* last flat bucket + 1 */
-    } head;
-    MFile block_mf;
-    MFile hash_mf;
-    zint *array;
-    struct CFile_hash_bucket **parray;
-    struct CFile_hash_bucket *bucket_lru_front, *bucket_lru_back;
-    int dirty;
-    zint bucket_in_memory;
-    zint max_bucket_in_memory;
-    char *iobuf;
-    MFile rmf;
-    int  no_hits;
-    int  no_miss;
+    struct CFile_head head;
+    
+    MFile block_mf;  /**< block meta file */
+    MFile hash_mf;   /**< hash or index file (depending on state) */
+    zint *array;     /**< array for hash */
+    struct CFile_hash_bucket **parray; /**< holds all hash bucket in memory */
+    struct CFile_hash_bucket *bucket_lru_front; /**< LRU front for hash */
+    struct CFile_hash_bucket *bucket_lru_back;  /**< LRU back for hash */
+    int dirty;   /**< whether CFile is dirty / header must be rewritten */
+    zint bucket_in_memory;  /**< number of buckets in memory */
+    zint max_bucket_in_memory; /**< max number of buckets in memory */
+    char *iobuf;  /**< data block .. of size block size */
+    MFile rmf;   /**< read meta file (original data / not dirty) */
+    int  no_hits;  /**< number of bucket cache hits */
+    int  no_miss;  /**< number of bucket cache misses */
     Zebra_mutex mutex;
 } *CFile;
 
 int cf_close (CFile cf);
+
 CFile cf_open (MFile mf, MFile_area area, const char *fname, int block_size,
                int wflag, int *firstp);
 int cf_read (CFile cf, zint no, int offset, int nbytes, void *buf);
index 03f0b25..0faba91 100644 (file)
@@ -261,9 +261,9 @@ int cf_commit(CFile cf)
         return -1;
     }
     yaz_log(log_level, "cf_commit: state=%d", cf->head.state);
-    if (cf->head.state == 1)
+    if (cf->head.state == CFILE_STATE_HASH)
         return cf_commit_hash(cf);
-    else if (cf->head.state == 2)
+    else if (cf->head.state == CFILE_STATE_FLAT)
         return cf_commit_flat(cf);
     else
     {
index 128b3bb..1fe604b 100644 (file)
@@ -9,7 +9,7 @@ attset: gils.att
 attset: explain.att
 
 recordtype: grs.sgml
-isam: c
+isam: b
 
 # Flags for the non-authenticated user. w=write (allows ES Updates)
 perm.anonymous: rw
index 514378d..52dcd01 100644 (file)
@@ -291,6 +291,7 @@ int zebra_register_statistics (ZebraHandle zh, int dumpdict)
     }
     fprintf (stdout, "%7d-        %7d\n",
              prev, stat_info.isam_occurrences[i]);
+    rec_prstat(zh->reg->records, 0);
     xmalloc_trav("unfreed"); /*! while hunting memory leaks */    
     zebra_end_read (zh);
     return 0;
index d353c3c..68d0ac6 100644 (file)
@@ -86,7 +86,7 @@ ZEBRA_RES rec_close (Records *p);
 Records rec_open(BFiles bfs, int rw, int compression_method);
 
 char *rec_strdup(const char *s, size_t *len);
-void rec_prstat(Records p);
+void rec_prstat(Records p, int verbose);
 
 zint rec_sysno_to_int(zint sysno);
 
index c38091e..07f9e81 100644 (file)
@@ -171,6 +171,7 @@ static ZEBRA_RES rec_release_blocks(Records p, zint sysno)
            memcpy(block_and_ref + sizeof(freeblock), &ref, sizeof(ref));
            if (ref)
            {
+                /* there is still a reference to this block.. */
                if (bf_write(p->data_BFile[dst_type], freeblock, 0,
                              sizeof(block_and_ref), block_and_ref))
                {
@@ -179,7 +180,8 @@ static ZEBRA_RES rec_release_blocks(Records p, zint sysno)
                }
                return ZEBRA_OK;
            }
-           first = 0;
+            /* the list of blocks can all be removed (ref == 0) */
+            first = 0;
        }
        
         if (bf_write(p->data_BFile[dst_type], freeblock, 0, sizeof(freeblock),
@@ -522,8 +524,10 @@ static ZEBRA_RES rec_write_multiple(Records p, int saveCount)
 
            e->flag = recordFlagNop;
             break;
-       default:
+        case recordFlagNop:
            break;
+       default:
+            break;
         }
     }
 
@@ -982,7 +986,7 @@ char *rec_strdup(const char *s, size_t *len)
     return p;
 }
 
-void rec_prstat(Records records)
+void rec_prstat(Records records, int verbose)
 {
     int i;
     zint total_bytes = 0;
@@ -1002,6 +1006,34 @@ void rec_prstat(Records records)
               records->head.block_used[i] * records->head.block_size[i]);
         total_bytes +=
             records->head.block_used[i] * records->head.block_size[i];
+
+        yaz_log(YLOG_LOG, " Block Last " ZINT_FORMAT, records->head.block_last[i]);
+        if (verbose)
+        {   /* analyse free lists */
+            zint no_free = 0;
+            zint block_free = records->head.block_free[i];
+            WRBUF w = wrbuf_alloc();
+            while (block_free)
+            {
+                zint nblock;
+                no_free++;
+                wrbuf_printf(w, " " ZINT_FORMAT, block_free);
+                if (bf_read(records->data_BFile[i],
+                            block_free, 0, sizeof(nblock), &nblock) != 1)
+                {
+                    yaz_log(YLOG_FATAL|YLOG_ERRNO, "read in %s at free block "
+                            ZINT_FORMAT,
+                            records->data_fname[i], block_free);
+                    break;
+                }
+                block_free = nblock;
+            }
+            yaz_log (YLOG_LOG,
+                     " Number in free list       %8" ZINT_FORMAT0, no_free);
+            if (no_free)
+                yaz_log(YLOG_LOG, "%s", wrbuf_cstr(w));
+            wrbuf_destroy(w);
+        }
     }
     yaz_log (YLOG_LOG,
           "Total size of record index in bytes  %8" ZINT_FORMAT0,
index 202f7bb..0705070 100644 (file)
@@ -1427,7 +1427,6 @@ int delete_w_handle(const char *info, void *handle)
 {
     ZebraHandle zh = (ZebraHandle) handle;
     ISAM_P pos;
-    ASSERTZH;
 
     if (*info == sizeof(pos))
     {
@@ -1437,18 +1436,52 @@ int delete_w_handle(const char *info, void *handle)
     return 0;
 }
 
-static int delete_SU_handle(void *handle, int ord)
+int delete_w_all_handle(const char *info, void *handle)
+{
+    ZebraHandle zh = (ZebraHandle) handle;
+    ISAM_P pos;
+
+    if (*info == sizeof(pos))
+    {
+        ISAMB_PP pt;
+       memcpy(&pos, info+1, sizeof(pos));
+        pt = isamb_pp_open(zh->reg->isamb, pos, 2);
+        if (pt)
+        {
+            struct it_key key;
+            key.mem[0] = 0;
+            while (isamb_pp_read(pt, &key))
+            {
+                Record rec;
+                rec = rec_get(zh->reg->records, key.mem[0]);
+                rec_del(zh->reg->records, &rec);
+            }
+            isamb_pp_close(pt);
+        }
+    }
+    return delete_w_handle(info, handle);
+}
+
+static int delete_SU_handle(void *handle, int ord,
+                            const char *index_type, const char *string_index,
+                            zinfo_index_category_t cat)
 {
     ZebraHandle zh = (ZebraHandle) handle;
     char ord_buf[20];
     int ord_len;
-
+#if 0
+    yaz_log(YLOG_LOG, "ord=%d index_type=%s index=%s cat=%d", ord,
+            index_type, string_index, (int) cat);
+#endif
     ord_len = key_SU_encode(ord, ord_buf);
     ord_buf[ord_len] = '\0';
 
     assert(zh->reg->isamb);
+    assert(zh->reg->records);
     dict_delete_subtree(zh->reg->dict, ord_buf,
-                       zh, delete_w_handle);
+                       zh, 
+                        !strcmp(string_index, "_ALLRECORDS") ?
+                        delete_w_all_handle : delete_w_handle);
     return 0;
 }
 
index 9f893e9..c0281e0 100644 (file)
@@ -767,12 +767,12 @@ int zebraExplain_removeDatabase(ZebraExplainInfo zei, void *update_handle)
                
                rec = rec_get(zei->records, zad->sysno);
                (*zei->updateFunc)(zei->updateHandle, rec, 0);
-               rec_free(&rec);
+               rec_del(zei->records, &rec);
            }
            /* remove database record keys and delete it */
            rec = rec_get(zei->records, zdi->sysno);
            (*zei->updateFunc)(zei->updateHandle, rec, 0);
-           rec_free(&rec);
+           rec_del(zei->records, &rec);
 
            /* remove from list */
            *zdip = zdi->next;
@@ -1376,14 +1376,19 @@ int zebraExplain_lookup_attr_str(ZebraExplainInfo zei,
 }
 
 int zebraExplain_trav_ord(ZebraExplainInfo zei, void *handle,
-                         int (*f)(void *handle, int ord))
+                         int (*f)(void *handle, int ord,
+                                   const char *index_type,
+                                   const char *string_index,
+                                   zinfo_index_category_t cat))
 {
     struct zebDatabaseInfoB *zdb = zei->curDatabaseInfo;
     if (zdb)
     {
        struct zebSUInfoB *zsui = zdb->attributeDetails->SUInfo;
        for ( ;zsui; zsui = zsui->next)
-           (*f)(handle,  zsui->info.ordinal);
+           (*f)(handle,  zsui->info.ordinal,
+                 zsui->info.index_type, zsui->info.str,
+                 zsui->info.cat);
     }
     return 0;
 }
index 6f63d4c..95b1f01 100644 (file)
@@ -94,7 +94,10 @@ zint zebraExplain_ord_get_term_occurrences(ZebraExplainInfo zei, int ord);
 zint zebraExplain_ord_get_doc_occurrences(ZebraExplainInfo zei, int ord);
 
 int zebraExplain_trav_ord(ZebraExplainInfo zei, void *handle,
-                         int (*f)(void *handle, int ord));
+                         int (*f)(void *handle, int ord,
+                                   const char *index_type,
+                                   const char *string_index,
+                                   zinfo_index_category_t cat));
 
 int zebraExplain_get_database_ord(ZebraExplainInfo zei);
 int zebraExplain_removeDatabase(ZebraExplainInfo zei, void *updateHandle);