Implemented sorting via the ISAMB system. To enable, use sortindex:b
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 18 Dec 2006 23:40:06 +0000 (23:40 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 18 Dec 2006 23:40:06 +0000 (23:40 +0000)
in zebra.cfg. The sort keys can also be fetched using zebra::sort:field .

12 files changed:
NEWS
examples/gils/zebra.cfg
include/idzebra/isamb.h
include/sortidx.h
index/check_res.c
index/extract.c
index/index.h
index/retrieve.c
index/sortidx.c
index/zebraapi.c
index/zsets.c
isamb/isamb.c

diff --git a/NEWS b/NEWS
index e7c16ba..ffcb297 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+Implemented sorting via the ISAMB system. To enable, use sortindex:b
+in zebra.cfg. The sort keys can also be fetched using zebra::sort:field .
+
 Added support for specification of approximative limits for whole query.
 This is specified as attribute type 12. Semantics is the same as
 estimatehits in zebra.cfg.
 Added support for specification of approximative limits for whole query.
 This is specified as attribute type 12. Semantics is the same as
 estimatehits in zebra.cfg.
index 7fc2886..4cb52d4 100644 (file)
@@ -1,5 +1,5 @@
 # Simple Zebra configuration file
 # Simple Zebra configuration file
-# $Id: zebra.cfg,v 1.14 2006-08-22 13:39:23 adam Exp $
+# $Id: zebra.cfg,v 1.15 2006-12-18 23:40:06 adam Exp $
 #
 # Where the schema files, attribute files, etc are located.
 profilePath: .:../../tab
 #
 # Where the schema files, attribute files, etc are located.
 profilePath: .:../../tab
@@ -20,6 +20,8 @@ recordId: (bib-1,title)
 
 storedata: 1
 
 
 storedata: 1
 
+sortindex: i
+
 modulePath: ../../index/.libs
 #shadow: shadow:100M
 # register: register:100M
 modulePath: ../../index/.libs
 #shadow: shadow:100M
 # register: register:100M
index 183e13b..d42a1ef 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isamb.h,v 1.8 2006-12-12 13:46:42 adam Exp $
+/* $Id: isamb.h,v 1.9 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -36,6 +36,10 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
                   int cache);
 
 YAZ_EXPORT
                   int cache);
 
 YAZ_EXPORT
+ISAMB isamb_open2(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
+                  int cache, int no_cat, int *sizes, int use_root_ptr);
+
+YAZ_EXPORT
 void isamb_close(ISAMB isamb);
 
 YAZ_EXPORT 
 void isamb_close(ISAMB isamb);
 
 YAZ_EXPORT 
@@ -84,6 +88,13 @@ void isamb_set_int_count(ISAMB b, int v);
 YAZ_EXPORT
 void isamb_set_cache_size(ISAMB b, int sz);
 
 YAZ_EXPORT
 void isamb_set_cache_size(ISAMB b, int sz);
 
+YAZ_EXPORT
+zint isamb_get_root_ptr(ISAMB b);
+
+YAZ_EXPORT
+void isamb_set_root_ptr(ISAMB b, zint root_ptr);
+
+
 YAZ_END_CDECL
 
 #endif
 YAZ_END_CDECL
 
 #endif
index 6ee16c4..cf3ae64 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sortidx.h,v 1.11 2006-11-21 22:17:49 adam Exp $
+/* $Id: sortidx.h,v 1.12 2006-12-18 23:40:06 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -31,14 +31,18 @@ YAZ_BEGIN_CDECL
 
 #define SORT_IDX_ENTRYSIZE 64
 
 
 #define SORT_IDX_ENTRYSIZE 64
 
-typedef struct sortIdx *SortIdx;
+typedef struct zebra_sort_index *zebra_sort_index_t;
 
 
-SortIdx sortIdx_open(BFiles bfs, int write_flag);
-void sortIdx_close(SortIdx si);
-int sortIdx_type(SortIdx si, int type);
-void sortIdx_sysno(SortIdx si, zint sysno);
-void sortIdx_add(SortIdx si, const char *buf, int len);
-void sortIdx_read(SortIdx si, char *buf);
+#define ZEBRA_SORT_TYPE_FLAT 1
+#define ZEBRA_SORT_TYPE_ISAMB 2
+
+zebra_sort_index_t zebra_sort_open(BFiles bfs, int write_flag, int sort_type);
+void zebra_sort_close(zebra_sort_index_t si);
+int zebra_sort_type(zebra_sort_index_t si, int type);
+void zebra_sort_sysno(zebra_sort_index_t si, zint sysno);
+void zebra_sort_add(zebra_sort_index_t si, const char *buf, int len);
+void zebra_sort_delete(zebra_sort_index_t si);
+void zebra_sort_read(zebra_sort_index_t si, char *buf);
 
 YAZ_END_CDECL
 
 
 YAZ_END_CDECL
 
index 0e7091d..33def9d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: check_res.c,v 1.2 2006-12-06 10:26:54 adam Exp $
+/* $Id: check_res.c,v 1.3 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -57,6 +57,7 @@ int zebra_check_res(Res res)
     res_add(v, "shadow", "");
     res_add(v, "segment", "");
     res_add(v, "setTmpDir", "");
     res_add(v, "shadow", "");
     res_add(v, "segment", "");
     res_add(v, "setTmpDir", "");
+    res_add(v, "sortindex", "");
     res_add(v, "staticrank", "");
     res_add(v, "threads", "");
     res_add(v, "database", "p");
     res_add(v, "staticrank", "");
     res_add(v, "threads", "");
     res_add(v, "database", "p");
index 665640e..614c0f1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: extract.c,v 1.245 2006-12-11 17:08:03 adam Exp $
+/* $Id: extract.c,v 1.246 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -1361,24 +1361,30 @@ static void extract_schema_add(struct recExtractCtrl *p, Odr_oid *oid)
 void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
                              int cmd, zebra_rec_keys_t reckeys)
 {
 void extract_flush_sort_keys(ZebraHandle zh, zint sysno,
                              int cmd, zebra_rec_keys_t reckeys)
 {
+#if 0
+    yaz_log(YLOG_LOG, "extract_flush_sort_keys cmd=%d sysno=" ZINT_FORMAT,
+            cmd, sysno);
+    extract_rec_keys_log(zh, cmd, reckeys, YLOG_LOG);
+#endif
+
     if (zebra_rec_keys_rewind(reckeys))
     {
     if (zebra_rec_keys_rewind(reckeys))
     {
-        SortIdx sortIdx = zh->reg->sortIdx;
+        zebra_sort_index_t si = zh->reg->sort_index;
        size_t slen;
        const char *str;
        struct it_key key_in;
 
        size_t slen;
        const char *str;
        struct it_key key_in;
 
-        sortIdx_sysno (sortIdx, sysno);
+        zebra_sort_sysno(si, sysno);
 
        while (zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
         {
             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
             
 
        while (zebra_rec_keys_read(reckeys, &str, &slen, &key_in))
         {
             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
             
-            sortIdx_type(sortIdx, ord);
+            zebra_sort_type(si, ord);
             if (cmd == 1)
             if (cmd == 1)
-                sortIdx_add(sortIdx, str, slen);
+                zebra_sort_add(si, str, slen);
             else
             else
-                sortIdx_add(sortIdx, "", 1);
+                zebra_sort_delete(si);
         }
     }
 }
         }
     }
 }
index 5e6cd48..46ebddf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: index.h,v 1.186 2006-12-05 14:06:29 adam Exp $
+/* $Id: index.h,v 1.187 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -134,7 +134,7 @@ struct zebra_register {
     ISAMB isamb;
     Dict dict;
     Dict matchDict;
     ISAMB isamb;
     Dict dict;
     Dict matchDict;
-    SortIdx sortIdx;
+    zebra_sort_index_t sort_index;
     int registerState; /* 0 (no commit pages), 1 (use commit pages) */
     time_t registerChange;
     BFiles bfs;
     int registerState; /* 0 (no commit pages), 1 (use commit pages) */
     time_t registerChange;
     BFiles bfs;
index d75e937..1afe24f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: retrieve.c,v 1.60 2006-11-29 09:01:53 marc Exp $
+/* $Id: retrieve.c,v 1.61 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -75,8 +75,8 @@ static int zebra_create_record_stream(ZebraHandle zh,
 
 
 static int parse_zebra_elem(const char *elem,
 
 
 static int parse_zebra_elem(const char *elem,
-                             const char **index, size_t *index_len,
-                             const char **type, size_t *type_len)
+                            const char **index, size_t *index_len,
+                            const char **type, size_t *type_len)
 {
     *index = 0;
     *index_len = 0;
 {
     *index = 0;
     *index_len = 0;
@@ -119,6 +119,103 @@ static int parse_zebra_elem(const char *elem,
 }
 
 
 }
 
 
+int zebra_special_sort_fetch(ZebraHandle zh, zint sysno, ODR odr,
+                             const char *elemsetname,
+                             oid_value input_format,
+                             oid_value *output_format,
+                             char **rec_bufp, int *rec_lenp)
+{
+    const char *retrieval_index;
+    size_t retrieval_index_len; 
+    const char *retrieval_type;
+    size_t retrieval_type_len;
+    char retrieval_index_cstr[256];
+    int ord;
+
+    /* only accept XML and SUTRS requests */
+    if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
+    {
+        yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
+                elemsetname);
+        *output_format = VAL_NONE;
+        return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
+    }
+    
+    if (!parse_zebra_elem(elemsetname,
+                          &retrieval_index, &retrieval_index_len,
+                          &retrieval_type,  &retrieval_type_len))
+    {
+        return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+    }
+    
+    if (retrieval_type_len != 0 && retrieval_type_len != 1)
+    {
+        return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+    }
+    if (!retrieval_index_len ||
+        retrieval_index_len >= sizeof(retrieval_index_cstr)-1)
+    {
+        return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+    }
+        
+    memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
+    retrieval_index_cstr[retrieval_index_len] = '\0';
+
+    ord = zebraExplain_lookup_attr_str(zh->reg->zei,
+                                       zinfo_index_category_sort,
+                                       (retrieval_type_len == 0 ? -1 : 
+                                        retrieval_type[0]),
+                                       retrieval_index_cstr);
+    if (ord == -1)
+        return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+    else
+    {
+        char dst_buf[IT_MAX_WORD];
+        char str[IT_MAX_WORD];
+        int index_type;
+        const char *db = 0;
+        const char *string_index = 0;
+        WRBUF wrbuf = wrbuf_alloc();
+        
+        zebra_sort_sysno(zh->reg->sort_index, sysno);
+        zebra_sort_type(zh->reg->sort_index, ord);
+        zebra_sort_read(zh->reg->sort_index, str);
+
+        zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, &string_index);
+        
+        zebra_term_untrans(zh, index_type, dst_buf, str);
+        
+
+        if (input_format == VAL_TEXT_XML)
+        {
+            *output_format = VAL_TEXT_XML;
+            wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
+                         " sysno=\"" ZINT_FORMAT "\""
+                         " set=\"zebra::sort%s/\">\n",
+                         sysno, elemsetname);
+
+            wrbuf_printf(wrbuf, "  <sort name=\"%s\"", 
+                         string_index);
+            wrbuf_printf(wrbuf, " type=\"%c\">", index_type);
+            wrbuf_xmlputs(wrbuf, dst_buf);
+            wrbuf_printf(wrbuf, "</sort>\n");
+            wrbuf_printf(wrbuf, "</record>\n");
+        }
+        else if (input_format == VAL_SUTRS)
+        {
+            *output_format = VAL_SUTRS;
+            
+            wrbuf_printf(wrbuf, "%s %c %s\n", string_index, index_type,
+                         dst_buf);
+        }
+        *rec_lenp = wrbuf_len(wrbuf);
+        *rec_bufp = odr_malloc(odr, *rec_lenp);
+        memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
+        wrbuf_free(wrbuf, 1);
+        return 0;
+    }
+}
+                            
 int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
                               Record rec,
                               const char *elemsetname,
 int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
                               Record rec,
                               const char *elemsetname,
@@ -137,8 +234,8 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
     /* *rec_lenp = 0; */
 
     /* only accept XML and SUTRS requests */
     /* *rec_lenp = 0; */
 
     /* only accept XML and SUTRS requests */
-    if (input_format != VAL_TEXT_XML
-        && input_format != VAL_SUTRS){
+    if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
+    {
         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
                 elemsetname);
         *output_format = VAL_NONE;
         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
                 elemsetname);
         *output_format = VAL_NONE;
@@ -159,7 +256,7 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
     {
         char retrieval_index_cstr[256];
 
     {
         char retrieval_index_cstr[256];
 
-        if (retrieval_index_len  < sizeof(retrieval_index_cstr) -1)
+        if (retrieval_index_len < sizeof(retrieval_index_cstr) -1)
         {
             memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
             retrieval_index_cstr[retrieval_index_len] = '\0';
         {
             memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
             retrieval_index_cstr[retrieval_index_len] = '\0';
@@ -194,7 +291,8 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
         else if (input_format == VAL_SUTRS)
             *output_format = VAL_SUTRS;
 
         else if (input_format == VAL_SUTRS)
             *output_format = VAL_SUTRS;
 
-        while(zebra_rec_keys_read(keys, &str, &slen, &key_in)){
+        while (zebra_rec_keys_read(keys, &str, &slen, &key_in))
+        {
             int i;
             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
             int index_type;
             int i;
             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
             int index_type;
@@ -212,17 +310,16 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
             if (retrieval_index == 0 
                 || (string_index_len == retrieval_index_len 
                     && !memcmp(string_index, retrieval_index,
             if (retrieval_index == 0 
                 || (string_index_len == retrieval_index_len 
                     && !memcmp(string_index, retrieval_index,
-                               string_index_len))){
-               
+                               string_index_len)))
+            {
                 /* process only if type is not defined, or is matching */
                 if (retrieval_type == 0 
                     || (retrieval_type_len == 1 
                 /* process only if type is not defined, or is matching */
                 if (retrieval_type == 0 
                     || (retrieval_type_len == 1 
-                        && retrieval_type[0] == index_type)){
-                    
-
+                        && retrieval_type[0] == index_type))
+                {
                     zebra_term_untrans(zh, index_type, dst_buf, str);
                     zebra_term_untrans(zh, index_type, dst_buf, str);
-                    if (strlen(dst_buf)){
-
+                    if (strlen(dst_buf))
+                    {
                         if (input_format == VAL_TEXT_XML){
                             wrbuf_printf(wrbuf, "  <index name=\"%s\"", 
                                          string_index);
                         if (input_format == VAL_TEXT_XML){
                             wrbuf_printf(wrbuf, "  <index name=\"%s\"", 
                                          string_index);
@@ -256,7 +353,7 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
         }
         if (input_format == VAL_TEXT_XML)
             wrbuf_printf(wrbuf, "</record>\n");
         }
         if (input_format == VAL_TEXT_XML)
             wrbuf_printf(wrbuf, "</record>\n");
-     }
+    }
     *rec_lenp = wrbuf_len(wrbuf);
     *rec_bufp = odr_malloc(odr, *rec_lenp);
     memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
     *rec_lenp = wrbuf_len(wrbuf);
     *rec_bufp = odr_malloc(odr, *rec_lenp);
     memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
@@ -335,6 +432,16 @@ int zebra_special_fetch(ZebraHandle zh, zint sysno, int score, ODR odr,
         return ret;
     }
 
         return ret;
     }
 
+    /* processing special elementsetnames zebra::sort:: */
+    if (elemsetname && 0 == strncmp(elemsetname, "sort", 4))
+    {
+        return zebra_special_sort_fetch(zh, sysno, odr,
+                                        elemsetname + 4,
+                                        input_format, output_format,
+                                        rec_bufp, rec_lenp);
+    }
+
+
     /* fetching binary record up for all other display elementsets */
     rec = rec_get(zh->reg->records, sysno);
     if (!rec)
     /* fetching binary record up for all other display elementsets */
     rec = rec_get(zh->reg->records, sysno);
     if (!rec)
@@ -424,8 +531,8 @@ int zebra_special_fetch(ZebraHandle zh, zint sysno, int score, ODR odr,
     }
 
     /* processing special elementsetnames zebra::index:: */
     }
 
     /* processing special elementsetnames zebra::index:: */
-    if (elemsetname && 0 == strncmp(elemsetname, "index", 5)){
-        
+    if (elemsetname && 0 == strncmp(elemsetname, "index", 5))
+    {
         int ret = zebra_special_index_fetch(zh, sysno, odr, rec,
                                             elemsetname + 5,
                                             input_format, output_format,
         int ret = zebra_special_index_fetch(zh, sysno, odr, rec,
                                             elemsetname + 5,
                                             input_format, output_format,
index 08b16e6..464bfaa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sortidx.c,v 1.19 2006-11-21 22:17:49 adam Exp $
+/* $Id: sortidx.c,v 1.20 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -26,126 +26,405 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include <yaz/log.h>
 #include <yaz/xmalloc.h>
 
 #include <yaz/log.h>
 #include <yaz/xmalloc.h>
+#include <idzebra/isamb.h>
 #include <idzebra/bfile.h>
 #include <sortidx.h>
 #include "recindex.h"
 
 #include <idzebra/bfile.h>
 #include <sortidx.h>
 #include "recindex.h"
 
+#define SORT_MAX_TERM 127
+
 #define SORT_IDX_BLOCKSIZE 64
 
 #define SORT_IDX_BLOCKSIZE 64
 
+struct sort_term {
+    zint sysno;
+    char term[SORT_MAX_TERM];
+};
+
+
+static void sort_term_log_item(int level, const void *b, const char *txt)
+{
+    struct sort_term a1;
+
+    memcpy(&a1, b, sizeof(a1));
+
+    yaz_log(level, "%s " ZINT_FORMAT " %s", txt, a1.sysno, a1.term);
+}
+
+int sort_term_compare(const void *a, const void *b)
+{
+    struct sort_term a1, b1;
+
+    memcpy(&a1, a, sizeof(a1));
+    memcpy(&b1, b, sizeof(b1));
+
+    if (a1.sysno > b1.sysno)
+        return 1;
+    else if (a1.sysno < b1.sysno)
+        return -1;
+    return 0;
+}
+
+void *sort_term_code_start(void)
+{
+    return 0;
+}
+
+void sort_term_encode(void *p, char **dst, const char **src)
+{
+    struct sort_term a1;
+
+    memcpy(&a1, *src, sizeof(a1));
+    *src += sizeof(a1);
+
+    zebra_zint_encode(dst, a1.sysno); /* encode record id */
+    strcpy(*dst, a1.term); /* then sort term, 0 terminated */
+    *dst += strlen(a1.term) + 1;
+}
+
+void sort_term_decode(void *p, char **dst, const char **src)
+{
+    struct sort_term a1;
+
+    zebra_zint_decode(src, &a1.sysno);
+
+    strcpy(a1.term, *src);
+    *src += strlen(a1.term) + 1;
+
+    memcpy(*dst, &a1, sizeof(a1));
+    *dst += sizeof(a1);
+}
+
+void sort_term_code_reset(void *p)
+{
+}
+
+void sort_term_code_stop(void *p)
+{
+}
+
+
+struct sort_term_stream {
+    int no;
+    int insert_flag;
+    struct sort_term st;
+};
+
+int sort_term_code_read(void *vp, char **dst, int *insertMode)
+{
+    struct sort_term_stream *s = (struct sort_term_stream *) vp;
+
+    if (s->no == 0)
+        return 0;
+
+    (s->no)--;
+    
+    *insertMode = s->insert_flag;
+    memcpy(*dst, &s->st, sizeof(s->st));
+    *dst += sizeof(s->st);
+    return 1;
+}
+
+        
 struct sortFileHead {
     zint sysno_max;
 };
 
 struct sortFile {
 struct sortFileHead {
     zint sysno_max;
 };
 
 struct sortFile {
-    int type;
-    BFile bf;
+    int id;
+    union {
+        BFile bf;
+        ISAMB isamb;
+    } u;
+    ISAM_P isam_p;
+    ISAMB_PP isam_pp;
     struct sortFile *next;
     struct sortFileHead head;
     struct sortFile *next;
     struct sortFileHead head;
+    int no_inserted;
+    int no_deleted;
 };
 
 };
 
-struct sortIdx {
+struct zebra_sort_index {
     BFiles bfs;
     int write_flag;
     zint sysno;
     BFiles bfs;
     int write_flag;
     zint sysno;
+    int type;
     char *entry_buf;
     struct sortFile *current_file;
     struct sortFile *files;
 };
 
     char *entry_buf;
     struct sortFile *current_file;
     struct sortFile *files;
 };
 
-SortIdx sortIdx_open (BFiles bfs, int write_flag)
+zebra_sort_index_t zebra_sort_open(BFiles bfs, int write_flag, int type)
 {
 {
-    SortIdx si = (SortIdx) xmalloc (sizeof(*si));
+    zebra_sort_index_t si = (zebra_sort_index_t) xmalloc(sizeof(*si));
     si->bfs = bfs;
     si->write_flag = write_flag;
     si->current_file = NULL;
     si->files = NULL;
     si->bfs = bfs;
     si->write_flag = write_flag;
     si->current_file = NULL;
     si->files = NULL;
-    si->entry_buf = (char *) xmalloc (SORT_IDX_ENTRYSIZE);
+    si->type = type;
+    si->entry_buf = (char *) xmalloc(SORT_IDX_ENTRYSIZE);
     return si;
 }
 
     return si;
 }
 
-void sortIdx_close (SortIdx si)
+void zebra_sort_close(zebra_sort_index_t si)
 {
     struct sortFile *sf = si->files;
     while (sf)
     {
        struct sortFile *sf_next = sf->next;
 {
     struct sortFile *sf = si->files;
     while (sf)
     {
        struct sortFile *sf_next = sf->next;
-       if (sf->bf)
-           bf_close (sf->bf);
-       xfree (sf);
+        switch(si->type)
+        {
+        case ZEBRA_SORT_TYPE_FLAT:
+           bf_close(sf->u.bf);
+            break;
+        case ZEBRA_SORT_TYPE_ISAMB:
+            if (sf->isam_pp)
+                isamb_pp_close(sf->isam_pp);
+            isamb_set_root_ptr(sf->u.isamb, sf->isam_p);
+            isamb_close(sf->u.isamb);
+            break;
+        }
+       xfree(sf);
        sf = sf_next;
     }
        sf = sf_next;
     }
-    xfree (si->entry_buf);
-    xfree (si);
+    xfree(si->entry_buf);
+    xfree(si);
 }
 
 }
 
-int sortIdx_type (SortIdx si, int type)
+int zebra_sort_type(zebra_sort_index_t si, int id)
 {
 {
+    int isam_block_size = 4096;
+    ISAMC_M method;
     char fname[80];
     struct sortFile *sf;
     char fname[80];
     struct sortFile *sf;
-    if (si->current_file && si->current_file->type == type)
+    if (si->current_file && si->current_file->id == id)
        return 0;
     for (sf = si->files; sf; sf = sf->next)
        return 0;
     for (sf = si->files; sf; sf = sf->next)
-       if (sf->type == type)
+       if (sf->id == id)
        {
            si->current_file = sf;
            return 0;
        }
        {
            si->current_file = sf;
            return 0;
        }
-    sf = (struct sortFile *) xmalloc (sizeof(*sf));
-    sf->type = type;
-    sf->bf = NULL;
-    sprintf (fname, "sort%d", type);
-    yaz_log (YLOG_DEBUG, "sort idx %s wr=%d", fname, si->write_flag);
-    sf->bf = bf_open (si->bfs, fname, SORT_IDX_BLOCKSIZE, si->write_flag);
-    if (!sf->bf)
-    {
-        xfree (sf);
-       return -1;
-    }
-    if (!bf_read (sf->bf, 0, 0, sizeof(sf->head), &sf->head))
+    sf = (struct sortFile *) xmalloc(sizeof(*sf));
+    sf->id = id;
+
+    method.compare_item = sort_term_compare;
+    method.log_item = sort_term_log_item;
+    method.codec.start = sort_term_code_start;
+    method.codec.encode = sort_term_encode;
+    method.codec.decode = sort_term_decode;
+    method.codec.reset = sort_term_code_reset;
+    method.codec.stop = sort_term_code_stop;
+   
+    switch(si->type)
     {
     {
-       sf->head.sysno_max = 0;
-       if (!si->write_flag)
+    case ZEBRA_SORT_TYPE_FLAT:
+        sf->u.bf = NULL;
+        sprintf(fname, "sort%d", id);
+        yaz_log(YLOG_DEBUG, "sort idx %s wr=%d", fname, si->write_flag);
+        sf->u.bf = bf_open(si->bfs, fname, SORT_IDX_BLOCKSIZE, si->write_flag);
+        if (!sf->u.bf)
+        {
+            xfree(sf);
+            return -1;
+        }
+        if (!bf_read(sf->u.bf, 0, 0, sizeof(sf->head), &sf->head))
+        {
+            sf->head.sysno_max = 0;
+            if (!si->write_flag)
+            {
+                bf_close(sf->u.bf);
+                xfree(sf);
+                return -1;
+            }
+        }
+        break;
+    case ZEBRA_SORT_TYPE_ISAMB:
+        sprintf(fname, "sortb%d", id);
+        
+        sf->u.isamb = isamb_open2(si->bfs, fname, si->write_flag, &method,
+                                  /* cache */ 0,
+                                  /* no_cat */ 1, &isam_block_size,
+                                  /* use_root_ptr */ 1);
+        if (!sf->u.isamb)
+        {
+            xfree(sf);
+            return -1;
+        }
+        else
         {
         {
-            bf_close (sf->bf);
-            xfree (sf);
-           return -1;
+            sf->isam_p = isamb_get_root_ptr(sf->u.isamb);
+            sf->isam_pp = 0;
         }
         }
+        break;
     }
     }
+    sf->no_inserted = 0;
+    sf->no_deleted = 0;
     sf->next = si->files;
     si->current_file = si->files = sf;
     return 0;
 }
 
     sf->next = si->files;
     si->current_file = si->files = sf;
     return 0;
 }
 
-void sortIdx_sysno(SortIdx si, zint sysno)
+void zebra_sort_sysno(zebra_sort_index_t si, zint sysno)
 {
 {
-    si->sysno = rec_sysno_to_int(sysno);
+    struct sortFile *sf = si->current_file;
+    zint new_sysno = rec_sysno_to_int(sysno);
+
+    for (sf = si->files; sf; sf = sf->next)
+    {
+        sf->no_inserted = 0;
+        sf->no_deleted = 0;
+        if (new_sysno < si->sysno && sf->isam_pp)
+        {
+            isamb_pp_close(sf->isam_pp);
+            sf->isam_pp = 0;
+        }
+    }
+    si->sysno = new_sysno;
 }
 
 }
 
-void sortIdx_add(SortIdx si, const char *buf, int len)
+
+void zebra_sort_delete(zebra_sort_index_t si)
 {
 {
-    if (!si->current_file || !si->current_file->bf)
-       return;
-    if (len > SORT_IDX_ENTRYSIZE)
+    struct sortFile *sf = si->current_file;
+
+    if (!sf || !sf->u.bf)
+        return;
+    switch(si->type)
     {
     {
-       len = SORT_IDX_ENTRYSIZE;
-       memcpy (si->entry_buf, buf, len);
+    case ZEBRA_SORT_TYPE_FLAT:
+        zebra_sort_add(si, "", 0);
+        break;
+    case ZEBRA_SORT_TYPE_ISAMB:
+        assert(sf->u.isamb);
+        if (sf->no_deleted == 0)
+        {
+            struct sort_term_stream s;
+            ISAMC_I isamc_i;
+
+            s.st.sysno = si->sysno;
+            s.st.term[0] = '\0';
+            
+            s.no = 1;
+            s.insert_flag = 0;
+            isamc_i.clientData = &s;
+            isamc_i.read_item = sort_term_code_read;
+            
+            isamb_merge(sf->u.isamb, &sf->isam_p, &isamc_i);
+            sf->no_deleted++;
+        }
+        break;
     }
     }
-    else
+}
+
+void zebra_sort_add(zebra_sort_index_t si, const char *buf, int len)
+{
+    struct sortFile *sf = si->current_file;
+
+    if (!sf || !sf->u.bf)
+        return;
+    switch(si->type)
     {
     {
-       memcpy (si->entry_buf, buf, len);
-       memset (si->entry_buf+len, 0, SORT_IDX_ENTRYSIZE-len);
+    case ZEBRA_SORT_TYPE_FLAT:
+        if (len > SORT_IDX_ENTRYSIZE)
+        {
+            len = SORT_IDX_ENTRYSIZE;
+            memcpy(si->entry_buf, buf, len);
+        }
+        else
+        {
+            memcpy(si->entry_buf, buf, len);
+            memset(si->entry_buf+len, 0, SORT_IDX_ENTRYSIZE-len);
+        }
+        bf_write(sf->u.bf, si->sysno+1, 0, 0, si->entry_buf);
+        break;
+    case ZEBRA_SORT_TYPE_ISAMB:
+        assert(sf->u.isamb);
+        if (sf->no_inserted == 0)
+        {
+            struct sort_term_stream s;
+            ISAMC_I isamc_i;
+
+            s.st.sysno = si->sysno;
+            if (len >= SORT_MAX_TERM)
+                len = SORT_MAX_TERM-1;
+            memcpy(s.st.term, buf, len);
+            s.st.term[len] = '\0';
+            s.no = 1;
+            s.insert_flag = 1;
+            isamc_i.clientData = &s;
+            isamc_i.read_item = sort_term_code_read;
+            
+            isamb_merge(sf->u.isamb, &sf->isam_p, &isamc_i);
+            sf->no_inserted++;
+        }
+        break;
     }
     }
-    bf_write (si->current_file->bf, si->sysno+1, 0, 0, si->entry_buf);
 }
 
 }
 
-void sortIdx_read (SortIdx si, char *buf)
+void zebra_sort_read(zebra_sort_index_t si, char *buf)
 {
     int r;
 {
     int r;
+    struct sortFile *sf = si->current_file;
+
+    assert(sf);
+
+    switch(si->type)
+    {
+    case ZEBRA_SORT_TYPE_FLAT:
+        r = bf_read(sf->u.bf, si->sysno+1, 0, 0, buf);
+        if (!r)
+            memset(buf, 0, SORT_IDX_ENTRYSIZE);
+        break;
+    case ZEBRA_SORT_TYPE_ISAMB:
+        memset(buf, 0, SORT_IDX_ENTRYSIZE);
+        assert(sf->u.bf);
+        if (sf->u.bf)
+        {
+            struct sort_term st, st_untilbuf;
+
+            st.sysno = 99999;
+            if (!sf->isam_pp)
+            {
+                yaz_log(YLOG_LOG, "isamb_pp_open " ZINT_FORMAT, sf->isam_p);
+                sf->isam_pp = isamb_pp_open(sf->u.isamb, sf->isam_p, 1);
+            }
+            if (!sf->isam_pp)
+                return;
 
 
-    assert(si->current_file);
-    r = bf_read (si->current_file->bf, si->sysno+1, 0, 0, buf);
-    if (!r)
-        memset (buf, 0, SORT_IDX_ENTRYSIZE);
+#if 0
+            while (1)
+            {
+                r = isamb_pp_read(sf->isam_pp, &st);
+                if (!r)
+                    break;
+                if (st.sysno == si->sysno)
+                    break;
+                yaz_log(YLOG_LOG, "Received sysno=" ZINT_FORMAT " looking for "
+                        ZINT_FORMAT, st.sysno, si->sysno);
+            }
+#else
+            st_untilbuf.sysno = si->sysno;
+            st_untilbuf.term[0] = '\0';
+            r = isamb_pp_forward(sf->isam_pp, &st, &st_untilbuf);
+            if (!r)
+                return;
+#endif
+            if (r)
+            {
+                if (st.sysno != si->sysno)
+                {
+                    yaz_log(YLOG_LOG, "Received sysno=" ZINT_FORMAT " looking for "
+                            ZINT_FORMAT, st.sysno, si->sysno);
+                    return;
+                }
+                if (strlen(st.term) < SORT_IDX_ENTRYSIZE)
+                    strcpy(buf, st.term);
+                else
+                    memcpy(buf, st.term, SORT_IDX_ENTRYSIZE);
+            }
+        }
+        break;
+    }
 }
 /*
  * Local variables:
 }
 /*
  * Local variables:
index 7b14661..9905413 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zebraapi.c,v 1.237 2006-12-05 14:06:29 adam Exp $
+/* $Id: zebraapi.c,v 1.238 2006-12-18 23:40:07 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -314,6 +314,7 @@ struct zebra_register *zebra_register_open(ZebraService zs, const char *name,
     const char *recordCompression = 0;
     const char *profilePath;
     char cwd[1024];
     const char *recordCompression = 0;
     const char *profilePath;
     char cwd[1024];
+    int sort_type = ZEBRA_SORT_TYPE_FLAT;
     ZEBRA_RES ret = ZEBRA_OK;
 
     ASSERTZS;
     ZEBRA_RES ret = ZEBRA_OK;
 
     ASSERTZS;
@@ -385,7 +386,7 @@ struct zebra_register *zebra_register_open(ZebraService zs, const char *name,
 
     reg->records = 0;
     reg->dict = 0;
 
     reg->records = 0;
     reg->dict = 0;
-    reg->sortIdx = 0;
+    reg->sort_index = 0;
     reg->isams = 0;
     reg->matchDict = 0;
     reg->isamc = 0;
     reg->isams = 0;
     reg->matchDict = 0;
     reg->isamc = 0;
@@ -427,9 +428,22 @@ struct zebra_register *zebra_register_open(ZebraService zs, const char *name,
        yaz_log (YLOG_WARN, "dict_open failed");
        ret = ZEBRA_FAIL;
     }
        yaz_log (YLOG_WARN, "dict_open failed");
        ret = ZEBRA_FAIL;
     }
-    if (!(reg->sortIdx = sortIdx_open (reg->bfs, rw)))
+
+    
+    if (res_get_match (res, "sortindex", "f", "f"))
+        sort_type = ZEBRA_SORT_TYPE_FLAT;
+    else if (res_get_match (res, "sortindex", "i", "f"))
+        sort_type = ZEBRA_SORT_TYPE_ISAMB;
+    else
+    {
+       yaz_log (YLOG_WARN, "bad_value for 'sort:'");
+       ret = ZEBRA_FAIL;
+    }
+
+
+    if (!(reg->sort_index = zebra_sort_open(reg->bfs, rw, sort_type)))
     {
     {
-       yaz_log (YLOG_WARN, "sortIdx_open failed");
+       yaz_log (YLOG_WARN, "zebra_sort_open failed");
        ret = ZEBRA_FAIL;
     }
     if (res_get_match (res, "isam", "s", ISAM_DEFAULT))
        ret = ZEBRA_FAIL;
     }
     if (res_get_match (res, "isam", "s", ISAM_DEFAULT))
@@ -540,7 +554,7 @@ static void zebra_register_close(ZebraService zs, struct zebra_register *reg)
     dict_close (reg->dict);
     if (reg->matchDict)
        dict_close (reg->matchDict);
     dict_close (reg->dict);
     if (reg->matchDict)
        dict_close (reg->matchDict);
-    sortIdx_close (reg->sortIdx);
+    zebra_sort_close(reg->sort_index);
     if (reg->isams)
        isams_close (reg->isams);
     if (reg->isamc)
     if (reg->isams)
        isams_close (reg->isams);
     if (reg->isamc)
index 5c02dd4..a20056b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zsets.c,v 1.113 2006-11-30 10:33:19 adam Exp $
+/* $Id: zsets.c,v 1.114 2006-12-18 23:40:08 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -552,15 +552,15 @@ void resultSetInsertSort(ZebraHandle zh, ZebraSet sset,
     struct zset_sort_info *sort_info = sset->sort_info;
     int i, j;
 
     struct zset_sort_info *sort_info = sset->sort_info;
     int i, j;
 
-    sortIdx_sysno (zh->reg->sortIdx, sysno);
+    zebra_sort_sysno(zh->reg->sort_index, sysno);
     for (i = 0; i<num_criteria; i++)
     {
         char *this_entry_buf = tmp_cmp_buf[i];
         memset(this_entry_buf, '\0', SORT_IDX_ENTRYSIZE);
         if (criteria[i].ord != -1)
         {
     for (i = 0; i<num_criteria; i++)
     {
         char *this_entry_buf = tmp_cmp_buf[i];
         memset(this_entry_buf, '\0', SORT_IDX_ENTRYSIZE);
         if (criteria[i].ord != -1)
         {
-            sortIdx_type(zh->reg->sortIdx, criteria[i].ord);
-            sortIdx_read(zh->reg->sortIdx, this_entry_buf);
+            zebra_sort_type(zh->reg->sort_index, criteria[i].ord);
+            zebra_sort_read(zh->reg->sort_index, this_entry_buf);
         }
     }
     i = sort_info->num_entries;
         }
     }
     i = sort_info->num_entries;
index 3e85ee1..7cd0ea9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isamb.c,v 1.88 2006-12-12 13:46:41 adam Exp $
+/* $Id: isamb.c,v 1.89 2006-12-18 23:40:08 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -33,7 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
 #define ISAMB_MAJOR_VERSION 3
 
 
 #define ISAMB_MAJOR_VERSION 3
-#define ISAMB_MINOR_VERSION 0
+#define ISAMB_MINOR_VERSION_NO_ROOT 0
+#define ISAMB_MINOR_VERSION_WITH_ROOT 1
 
 struct ISAMB_head {
     zint first_block;
 
 struct ISAMB_head {
     zint first_block;
@@ -104,6 +105,8 @@ struct ISAMB_s {
     zint number_of_leaf_splits;
     int enable_int_count; /* whether we count nodes (or not) */
     int cache_size; /* size of blocks to cache (if cache=1) */
     zint number_of_leaf_splits;
     int enable_int_count; /* whether we count nodes (or not) */
     int cache_size; /* size of blocks to cache (if cache=1) */
+    int minor_version;
+    zint root_ptr;
 };
 
 struct ISAMB_block {
 };
 
 struct ISAMB_block {
@@ -195,16 +198,18 @@ void isamb_set_cache_size(ISAMB b, int v)
     b->cache_size = v;
 }
 
     b->cache_size = v;
 }
 
-ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
-                int cache)
+ISAMB isamb_open2(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
+                  int cache, int no_cat, int *sizes, int use_root_ptr)
 {
     ISAMB isamb = xmalloc(sizeof(*isamb));
 {
     ISAMB isamb = xmalloc(sizeof(*isamb));
-    int i, b_size = ISAMB_MIN_SIZE;
+    int i;
+
+    assert(no_cat <= CAT_MAX);
 
     isamb->bfs = bfs;
     isamb->method = (ISAMC_M *) xmalloc(sizeof(*method));
     memcpy(isamb->method, method, sizeof(*method));
 
     isamb->bfs = bfs;
     isamb->method = (ISAMC_M *) xmalloc(sizeof(*method));
     memcpy(isamb->method, method, sizeof(*method));
-    isamb->no_cat = CAT_NO;
+    isamb->no_cat = no_cat;
     isamb->log_io = 0;
     isamb->log_freelist = 0;
     isamb->cache = cache;
     isamb->log_io = 0;
     isamb->log_freelist = 0;
     isamb->cache = cache;
@@ -215,6 +220,13 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
     isamb->enable_int_count = 1;
     isamb->cache_size = 40;
 
     isamb->enable_int_count = 1;
     isamb->cache_size = 40;
 
+    if (use_root_ptr)
+        isamb->minor_version = ISAMB_MINOR_VERSION_WITH_ROOT;
+    else
+        isamb->minor_version = ISAMB_MINOR_VERSION_NO_ROOT;
+
+    isamb->root_ptr = 0;
+
     for (i = 0; i<ISAMB_MAX_LEVEL; i++)
        isamb->skipped_nodes[i] = isamb->accessed_nodes[i] = 0;
 
     for (i = 0; i<ISAMB_MAX_LEVEL; i++)
        isamb->skipped_nodes[i] = isamb->accessed_nodes[i] = 0;
 
@@ -245,7 +257,7 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
             isamb->file[i].bf = bf_open(bfs, fname, ISAMB_CACHE_ENTRY_SIZE,
                                          writeflag);
         else
             isamb->file[i].bf = bf_open(bfs, fname, ISAMB_CACHE_ENTRY_SIZE,
                                          writeflag);
         else
-            isamb->file[i].bf = bf_open(bfs, fname, b_size, writeflag);
+            isamb->file[i].bf = bf_open(bfs, fname, sizes[i], writeflag);
 
         if (!isamb->file[i].bf)
         {
 
         if (!isamb->file[i].bf)
         {
@@ -254,12 +266,12 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
         }
 
         /* fill-in default values (for empty isamb) */
         }
 
         /* fill-in default values (for empty isamb) */
-       isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/b_size+1;
+       isamb->file[i].head.first_block = ISAMB_CACHE_ENTRY_SIZE/sizes[i]+1;
        isamb->file[i].head.last_block = isamb->file[i].head.first_block;
        isamb->file[i].head.last_block = isamb->file[i].head.first_block;
-       isamb->file[i].head.block_size = b_size;
-        assert(b_size <= ISAMB_CACHE_ENTRY_SIZE);
+       isamb->file[i].head.block_size = sizes[i];
+        assert(sizes[i] <= ISAMB_CACHE_ENTRY_SIZE);
 #if ISAMB_PTR_CODEC
 #if ISAMB_PTR_CODEC
-       if (i == isamb->no_cat-1 || b_size > 128)
+       if (i == isamb->no_cat-1 || sizes[i] > 128)
            isamb->file[i].head.block_offset = 8;
        else
            isamb->file[i].head.block_offset = 4;
            isamb->file[i].head.block_offset = 8;
        else
            isamb->file[i].head.block_offset = 4;
@@ -267,7 +279,7 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
        isamb->file[i].head.block_offset = 11;
 #endif
        isamb->file[i].head.block_max =
        isamb->file[i].head.block_offset = 11;
 #endif
        isamb->file[i].head.block_max =
-           b_size - isamb->file[i].head.block_offset;
+           sizes[i] - isamb->file[i].head.block_offset;
        isamb->file[i].head.free_list = 0;
        if (bf_read(isamb->file[i].bf, 0, 0, 0, hbuf))
        {
        isamb->file[i].head.free_list = 0;
        if (bf_read(isamb->file[i].bf, 0, 0, 0, hbuf))
        {
@@ -292,10 +304,10 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
                     fname, major, ISAMB_MAJOR_VERSION);
                return 0;
            }
                     fname, major, ISAMB_MAJOR_VERSION);
                return 0;
            }
-           for (left = len - b_size; left > 0; left = left - b_size)
+           for (left = len - sizes[i]; left > 0; left = left - sizes[i])
            {
                pos++;
            {
                pos++;
-               if (!bf_read(isamb->file[i].bf, pos, 0, 0, hbuf + pos*b_size))
+               if (!bf_read(isamb->file[i].bf, pos, 0, 0, hbuf + pos*sizes[i]))
                {
                    yaz_log(YLOG_WARN, "truncated isamb header for " 
                         "file=%s len=%d pos=%d",
                {
                    yaz_log(YLOG_WARN, "truncated isamb header for " 
                         "file=%s len=%d pos=%d",
@@ -311,11 +323,12 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
            decode_ptr(&src, &zint_tmp);
            isamb->file[i].head.block_max = (int) zint_tmp;
            decode_ptr(&src, &isamb->file[i].head.free_list);
            decode_ptr(&src, &zint_tmp);
            isamb->file[i].head.block_max = (int) zint_tmp;
            decode_ptr(&src, &isamb->file[i].head.free_list);
+            if (isamb->minor_version >= ISAMB_MINOR_VERSION_WITH_ROOT)
+                decode_ptr(&src, &isamb->root_ptr);
        }
         assert (isamb->file[i].head.block_size >= isamb->file[i].head.block_offset);
         isamb->file[i].head_dirty = 0;
        }
         assert (isamb->file[i].head.block_size >= isamb->file[i].head.block_offset);
         isamb->file[i].head_dirty = 0;
-        assert(isamb->file[i].head.block_size == b_size);
-        b_size = b_size * ISAMB_FAC_SIZE;
+        assert(isamb->file[i].head.block_size == sizes[i]);
     }
 #if ISAMB_DEBUG
     yaz_log(YLOG_WARN, "isamb debug enabled. Things will be slower than usual");
     }
 #if ISAMB_DEBUG
     yaz_log(YLOG_WARN, "isamb debug enabled. Things will be slower than usual");
@@ -323,6 +336,21 @@ ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
     return isamb;
 }
 
     return isamb;
 }
 
+ISAMB isamb_open(BFiles bfs, const char *name, int writeflag, ISAMC_M *method,
+                int cache)
+{
+    int sizes[CAT_NO];
+    int i, b_size = ISAMB_MIN_SIZE;
+    
+    for (i = 0; i<CAT_NO; i++)
+    {
+        sizes[i] = b_size;
+        b_size = b_size * ISAMB_FAC_SIZE;
+    }
+    return isamb_open2(bfs, name, writeflag, method, cache,
+                       CAT_NO, sizes, 0);
+}
+
 static void flush_blocks (ISAMB b, int cat)
 {
     while (b->file[cat].cache_entries)
 static void flush_blocks (ISAMB b, int cat)
 {
     while (b->file[cat].cache_entries)
@@ -429,7 +457,6 @@ void isamb_close (ISAMB isamb)
        {
            char hbuf[DST_BUF_SIZE];
            int major = ISAMB_MAJOR_VERSION;
        {
            char hbuf[DST_BUF_SIZE];
            int major = ISAMB_MAJOR_VERSION;
-           int minor = ISAMB_MINOR_VERSION;
            int len = 16;
            char *dst = hbuf + 16;
            int pos = 0, left;
            int len = 16;
            char *dst = hbuf + 16;
            int pos = 0, left;
@@ -440,12 +467,17 @@ void isamb_close (ISAMB isamb)
            encode_ptr(&dst, isamb->file[i].head.block_size);
            encode_ptr(&dst, isamb->file[i].head.block_max);
            encode_ptr(&dst, isamb->file[i].head.free_list);
            encode_ptr(&dst, isamb->file[i].head.block_size);
            encode_ptr(&dst, isamb->file[i].head.block_max);
            encode_ptr(&dst, isamb->file[i].head.free_list);
+
+            if (isamb->minor_version >= ISAMB_MINOR_VERSION_WITH_ROOT)
+                encode_ptr(&dst, isamb->root_ptr);
+
            memset(dst, '\0', b_size); /* ensure no random bytes are written */
 
            len = dst - hbuf;
 
            /* print exactly 16 bytes (including trailing 0) */
            memset(dst, '\0', b_size); /* ensure no random bytes are written */
 
            len = dst - hbuf;
 
            /* print exactly 16 bytes (including trailing 0) */
-           sprintf(hbuf, "isamb%02d %02d %02d\r\n", major, minor, len);
+           sprintf(hbuf, "isamb%02d %02d %02d\r\n", major,
+                    isamb->minor_version, len);
 
             bf_write(isamb->file[i].bf, pos, 0, 0, hbuf);
 
 
             bf_write(isamb->file[i].bf, pos, 0, 0, hbuf);
 
@@ -2009,6 +2041,17 @@ zint isamb_get_leaf_splits(ISAMB b)
     return b->number_of_leaf_splits;
 }
 
     return b->number_of_leaf_splits;
 }
 
+zint isamb_get_root_ptr(ISAMB b)
+{
+    return b->root_ptr;
+}
+
+void isamb_set_root_ptr(ISAMB b, zint root_ptr)
+{
+    b->root_ptr = root_ptr;
+}
+
+
 /*
  * Local variables:
  * c-basic-offset: 4
 /*
  * Local variables:
  * c-basic-offset: 4