New member in recRetrieveCtrl: diagnostic.
[idzebra-moved-to-github.git] / index / kinput.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: kinput.c,v $
7  * Revision 1.7  1995-10-02 15:18:52  adam
8  * New member in recRetrieveCtrl: diagnostic.
9  *
10  * Revision 1.6  1995/09/29  15:51:56  adam
11  * First work on multi-way read.
12  *
13  * Revision 1.5  1995/09/29  14:01:43  adam
14  * Bug fixes.
15  *
16  * Revision 1.4  1995/09/28  14:22:57  adam
17  * Sort uses smaller temporary files.
18  *
19  * Revision 1.3  1995/09/06  16:11:17  adam
20  * Option: only one word key per file.
21  *
22  * Revision 1.2  1995/09/04  12:33:42  adam
23  * Various cleanup. YAZ util used instead.
24  *
25  * Revision 1.1  1995/09/04  09:10:37  adam
26  * More work on index add/del/update.
27  * Merge sort implemented.
28  * Initial work on z39 server.
29  *
30  */
31
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <assert.h>
39
40 #include "index.h"
41
42 #define KEY_SIZE (1+sizeof(struct it_key))
43 #define INP_NAME_MAX 8192
44 #define INP_BUF_START 60000
45 #define INP_BUF_ADD  400000
46
47 static int no_diffs   = 0;
48 static int no_updates = 0;
49 static int no_insertions = 0;
50 static int no_iterations = 0;
51
52 static int read_one (FILE *inf, char *name, char *key)
53 {
54     int c;
55     int i = 0;
56     do
57     {
58         if ((c=getc(inf)) == EOF)
59             return 0;
60         name[i++] = c;
61     } while (c);
62     for (i = 0; i<KEY_SIZE; i++)
63         ((char *)key)[i] = getc (inf);
64     ++no_iterations;
65     return 1;
66 }
67
68 static int inp (Dict dict, ISAM isam, const char *name)
69 {
70     FILE *inf;
71     char *info;
72     char next_name[INP_NAME_MAX+1];
73     char cur_name[INP_NAME_MAX+1];
74     int key_buf_size = INP_BUF_START;
75     int key_buf_ptr;
76     char *next_key;
77     char *key_buf;
78     int more;
79     
80     next_key = xmalloc (KEY_SIZE);
81     key_buf = xmalloc (key_buf_size * (KEY_SIZE));
82     if (!(inf = fopen (name, "r")))
83     {
84         logf (LOG_FATAL|LOG_ERRNO, "cannot open `%s'", name);
85         exit (1);
86     }
87     more = read_one (inf, cur_name, key_buf);
88     while (more)                   /* EOF ? */
89     {
90         int nmemb;
91         key_buf_ptr = KEY_SIZE;
92         while (1)
93         {
94             if (!(more = read_one (inf, next_name, next_key)))
95                 break;
96             if (*next_name && strcmp (next_name, cur_name))
97                 break;
98             memcpy (key_buf + key_buf_ptr, next_key, KEY_SIZE);
99             key_buf_ptr += KEY_SIZE;
100             if (key_buf_ptr+KEY_SIZE >= key_buf_size)
101             {
102                 char *new_key_buf;
103                 new_key_buf = xmalloc (key_buf_size + INP_BUF_ADD);
104                 memcpy (new_key_buf, key_buf, key_buf_size);
105                 key_buf_size += INP_BUF_ADD;
106                 xfree (key_buf);
107                 key_buf = new_key_buf;
108             }
109         }
110         no_diffs++;
111         nmemb = key_buf_ptr / KEY_SIZE;
112         assert (nmemb*KEY_SIZE == key_buf_ptr);
113         if ((info = dict_lookup (dict, cur_name)))
114         {
115             ISAM_P isam_p, isam_p2;
116             logf (LOG_DEBUG, "updating %s", cur_name);
117             no_updates++;
118             memcpy (&isam_p, info+1, sizeof(ISAM_P));
119             isam_p2 = is_merge (isam, isam_p, nmemb, key_buf);
120             if (isam_p2 != isam_p)
121                 dict_insert (dict, cur_name, sizeof(ISAM_P), &isam_p2);
122         }
123         else
124         {
125             ISAM_P isam_p;
126             logf (LOG_DEBUG, "inserting %s", cur_name);
127             no_insertions++;
128             isam_p = is_merge (isam, 0, nmemb, key_buf);
129             dict_insert (dict, cur_name, sizeof(ISAM_P), &isam_p);
130         }
131         memcpy (key_buf, next_key, KEY_SIZE);
132         strcpy (cur_name, next_name);
133     }
134     fclose (inf);
135     return 0;
136 }
137
138 void key_input (const char *dict_fname, const char *isam_fname,
139                 const char *key_fname, int cache)
140 {
141     Dict dict;
142     ISAM isam;
143
144     dict = dict_open (dict_fname, cache, 1);
145     if (!dict)
146     {
147         logf (LOG_FATAL, "dict_open fail of `%s'", dict_fname);
148         exit (1);
149     }
150     isam = is_open (isam_fname, key_compare, 1, sizeof(struct it_key));
151     if (!isam)
152     {
153         logf (LOG_FATAL, "is_open fail of `%s'", isam_fname);
154         exit (1);
155     }
156     inp (dict, isam, key_fname);
157     dict_close (dict);
158     is_close (isam);
159     logf (LOG_LOG, "Iterations . . .%7d", no_iterations);
160     logf (LOG_LOG, "Distinct words .%7d", no_diffs);
161     logf (LOG_LOG, "Updates. . . . .%7d", no_updates);
162     logf (LOG_LOG, "Insertions . . .%7d", no_insertions);
163 }
164
165
166 struct key_file {
167     int   no;            /* file no */
168     off_t offset;        /* file offset */
169     unsigned char *buf;  /* buffer block */
170     size_t buf_size;     /* number of read bytes in block */
171     size_t chunk;        /* number of bytes allocated */
172     size_t buf_ptr;      /* current position in buffer */
173     char *prev_name;     /* last word read */
174 };
175
176 void key_file_chunk_read (struct key_file *f)
177 {
178     int nr = 0, r, fd;
179     char fname[256];
180     sprintf (fname, TEMP_FNAME, f->no);
181     fd = open (fname, O_RDONLY);
182     if (fd == -1)
183     {
184         logf (LOG_FATAL|LOG_ERRNO, "cannot open %s", fname);
185         exit (1);
186     }
187     if (lseek (fd, f->offset, SEEK_SET) == -1)
188     {
189         logf (LOG_FATAL|LOG_ERRNO, "cannot seek %s", fname);
190         exit (1);
191     }
192     while (f->chunk - nr > 0)
193     {
194         r = read (fd, f->buf + nr, f->chunk - nr);
195         if (r <= 0)
196             break;
197         nr += r;
198     }
199     if (r == -1)
200     {
201         logf (LOG_FATAL|LOG_ERRNO, "read of %s", fname);
202         exit (1);
203     }
204     f->buf_size = nr;
205 }
206
207 void key_file_init (struct key_file *f)
208 {
209     f->buf = xmalloc (f->chunk);
210     f->prev_name = xmalloc (256);
211     *f->prev_name = '\0';
212 }
213
214 int key_file_getc (struct key_file *f)
215 {
216     if (f->buf_ptr < f->buf_size)
217         return f->buf[(f->buf_ptr)++];
218     if (f->buf_size < f->chunk)
219         return EOF;
220     f->offset += f->buf_size;
221     key_file_chunk_read (f);
222     if (f->buf_ptr < f->buf_size)
223         return f->buf[(f->buf_ptr)++];
224     else
225         return EOF;
226 }
227
228 int key_file_read (struct key_file *f, char *name, char *key)
229 {
230     int i, c;
231
232     c = key_file_getc (f);
233     if (c == 0)
234         strcpy (name, f->prev_name);
235     else if (c == EOF)
236         return 0;
237     else
238     {
239         i = 0;
240         name[i++] = c;
241         while ((name[i++] = key_file_getc (f)))
242             ;
243         strcpy (f->prev_name, name);
244     }
245     for (i = 0; i<KEY_SIZE; i++)
246         key[i++] = key_file_getc (f);
247     return 1;
248 }
249
250 int inp2 (Dict dict, ISAM isam, const char *name)
251 {
252     FILE *inf;
253     char *info;
254     char next_name[INP_NAME_MAX+1];
255     char cur_name[INP_NAME_MAX+1];
256     int key_buf_size = INP_BUF_START;
257     int key_buf_ptr;
258     char *next_key;
259     char *key_buf;
260     int more;
261     
262     next_key = xmalloc (KEY_SIZE);
263     key_buf = xmalloc (key_buf_size * (KEY_SIZE));
264     if (!(inf = fopen (name, "r")))
265     {
266         logf (LOG_FATAL|LOG_ERRNO, "cannot open `%s'", name);
267         exit (1);
268     }
269     more = read_one (inf, cur_name, key_buf);
270     while (more)                   /* EOF ? */
271     {
272         int nmemb;
273         key_buf_ptr = KEY_SIZE;
274         while (1)
275         {
276             if (!(more = read_one (inf, next_name, next_key)))
277                 break;
278             if (*next_name && strcmp (next_name, cur_name))
279                 break;
280             memcpy (key_buf + key_buf_ptr, next_key, KEY_SIZE);
281             key_buf_ptr += KEY_SIZE;
282             if (key_buf_ptr+KEY_SIZE >= key_buf_size)
283             {
284                 char *new_key_buf;
285                 new_key_buf = xmalloc (key_buf_size + INP_BUF_ADD);
286                 memcpy (new_key_buf, key_buf, key_buf_size);
287                 key_buf_size += INP_BUF_ADD;
288                 xfree (key_buf);
289                 key_buf = new_key_buf;
290             }
291         }
292         no_diffs++;
293         nmemb = key_buf_ptr / KEY_SIZE;
294         assert (nmemb*KEY_SIZE == key_buf_ptr);
295         if ((info = dict_lookup (dict, cur_name)))
296         {
297             ISAM_P isam_p, isam_p2;
298             logf (LOG_DEBUG, "updating %s", cur_name);
299             no_updates++;
300             memcpy (&isam_p, info+1, sizeof(ISAM_P));
301             isam_p2 = is_merge (isam, isam_p, nmemb, key_buf);
302             if (isam_p2 != isam_p)
303                 dict_insert (dict, cur_name, sizeof(ISAM_P), &isam_p2);
304         }
305         else
306         {
307             ISAM_P isam_p;
308             logf (LOG_DEBUG, "inserting %s", cur_name);
309             no_insertions++;
310             isam_p = is_merge (isam, 0, nmemb, key_buf);
311             dict_insert (dict, cur_name, sizeof(ISAM_P), &isam_p);
312         }
313         memcpy (key_buf, next_key, KEY_SIZE);
314         strcpy (cur_name, next_name);
315     }
316     fclose (inf);
317     return 0;
318 }
319
320 void key_input2 (const char *dict_fname, const char *isam_fname,
321                  int nkeys, int cache)
322 {
323     Dict dict;
324     ISAM isam;
325
326     dict = dict_open (dict_fname, cache, 1);
327     if (!dict)
328     {
329         logf (LOG_FATAL, "dict_open fail of `%s'", dict_fname);
330         exit (1);
331     }
332     isam = is_open (isam_fname, key_compare, 1, sizeof(struct it_key));
333     if (!isam)
334     {
335         logf (LOG_FATAL, "is_open fail of `%s'", isam_fname);
336         exit (1);
337     }
338     inp2 (dict, isam, NULL);
339     dict_close (dict);
340     is_close (isam);
341     logf (LOG_LOG, "Iterations . . .%7d", no_iterations);
342     logf (LOG_LOG, "Distinct words .%7d", no_diffs);
343     logf (LOG_LOG, "Updates. . . . .%7d", no_updates);
344     logf (LOG_LOG, "Insertions . . .%7d", no_insertions);
345 }
346
347