Happy new year.
[idzebra-moved-to-github.git] / dict / dcompact.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2011 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "dict-p.h"
28
29 static void dict_copy_page(Dict dict, char *to_p, char *from_p, int *map)
30 {
31     int i, slen, no = 0;
32     short *from_indxp, *to_indxp;
33     char *from_info, *to_info;
34     
35     from_indxp = (short*) ((char*) from_p+DICT_bsize(from_p));
36     to_indxp = (short*) ((char*) to_p+DICT_bsize(to_p));
37     to_info = (char*) to_p + DICT_infoffset;
38     for (i = DICT_nodir(from_p); --i >= 0; )
39     {
40         if (*--from_indxp > 0) /* tail string here! */
41         {
42             /* string (Dict_char *) DICT_EOS terminated */
43             /* unsigned char        length of information */
44             /* char *               information */
45
46             from_info = (char*) from_p + *from_indxp;
47             *--to_indxp = to_info - to_p;
48             slen = (dict_strlen((Dict_char*) from_info)+1)*sizeof(Dict_char);
49             memcpy(to_info, from_info, slen);
50             from_info += slen;
51             to_info += slen;
52         }
53         else
54         {
55             Dict_ptr subptr;
56             Dict_char subchar;
57             /* Dict_ptr             subptr */
58             /* Dict_char            sub char */
59             /* unsigned char        length of information */
60             /* char *               information */
61
62             *--to_indxp = -(to_info - to_p);
63             from_info = (char*) from_p - *from_indxp;
64
65             memcpy(&subptr, from_info, sizeof(subptr));
66             subptr = map[subptr];
67             from_info += sizeof(Dict_ptr);
68             memcpy(&subchar, from_info, sizeof(subchar));
69             from_info += sizeof(Dict_char);
70                             
71             memcpy(to_info, &subptr, sizeof(Dict_ptr));
72             to_info += sizeof(Dict_ptr);
73             memcpy(to_info, &subchar, sizeof(Dict_char));
74             to_info += sizeof(Dict_char);
75         }
76         assert(to_info < (char*) to_indxp);
77         slen = *from_info+1;
78         memcpy(to_info, from_info, slen);
79         to_info += slen;
80         ++no;
81     }
82     DICT_size(to_p) = to_info - to_p;
83     DICT_type(to_p) = 0;
84     DICT_nodir(to_p) = no;
85 }
86
87 int dict_copy_compact(BFiles bfs, const char *from_name, const char *to_name)
88 {
89     int no_dir = 0;
90     Dict dict_from, dict_to;
91     int *map, i;
92     dict_from = dict_open(bfs, from_name, 0, 0, 0, 4096);
93     if (!dict_from)
94         return -1;
95     map = (int *) xmalloc((dict_from->head.last+1) * sizeof(*map));
96     for (i = 0; i <= (int)(dict_from->head.last); i++)
97         map[i] = -1;
98     dict_to = dict_open(bfs, to_name, 0, 1, 1, 4096);
99     if (!dict_to)
100         return -1;
101     map[0] = 0;
102     map[1] = dict_from->head.page_size;
103     
104     for (i = 1; i < (int) (dict_from->head.last); i++)
105     {
106         void *buf;
107         int size;
108 #if 0
109         yaz_log(YLOG_LOG, "map[%d] = %d", i, map[i]);
110 #endif
111         dict_bf_readp(dict_from->dbf, i, &buf);
112         size = ((DICT_size(buf)+sizeof(short)-1)/sizeof(short) +
113                 DICT_nodir(buf))*sizeof(short);
114         map[i+1] = map[i] + size;
115         no_dir += DICT_nodir(buf);
116     }
117 #if 0
118     yaz_log(YLOG_LOG, "map[%d] = %d", i, map[i]);
119     yaz_log(YLOG_LOG, "nodir = %d", no_dir);
120 #endif
121     dict_to->head.root = map[1];
122     dict_to->head.last = map[i];
123     for (i = 1; i< (int) (dict_from->head.last); i++)
124     {
125         void *old_p, *new_p;
126         dict_bf_readp(dict_from->dbf, i, &old_p);
127
128         yaz_log(YLOG_LOG, "dict_bf_newp no=%d size=%d", map[i],
129               map[i+1] - map[i]);
130         dict_bf_newp(dict_to->dbf, map[i], &new_p, map[i+1] - map[i]);
131
132         DICT_type(new_p) = 0;
133         DICT_backptr(new_p) = map[i-1];
134         DICT_bsize(new_p) = map[i+1] - map[i];
135
136         dict_copy_page(dict_from, (char*) new_p, (char*) old_p, map);
137     }
138     dict_close(dict_from);
139     dict_close(dict_to);
140     return 0;
141 }
142 /*
143  * Local variables:
144  * c-basic-offset: 4
145  * c-file-style: "Stroustrup"
146  * indent-tabs-mode: nil
147  * End:
148  * vim: shiftwidth=4 tabstop=8 expandtab
149  */
150