xfree/xmalloc used everywhere.
[idzebra-moved-to-github.git] / index / extract.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: extract.c,v $
7  * Revision 1.10  1995-09-28 09:19:41  adam
8  * xfree/xmalloc used everywhere.
9  * Extract/retrieve method seems to work for text records.
10  *
11  * Revision 1.9  1995/09/27  12:22:28  adam
12  * More work on extract in record control.
13  * Field name is not in isam keys but in prefix in dictionary words.
14  *
15  * Revision 1.8  1995/09/14  07:48:22  adam
16  * Record control management.
17  *
18  * Revision 1.7  1995/09/11  13:09:32  adam
19  * More work on relevance feedback.
20  *
21  * Revision 1.6  1995/09/08  14:52:27  adam
22  * Minor changes. Dictionary is lower case now.
23  *
24  * Revision 1.5  1995/09/06  16:11:16  adam
25  * Option: only one word key per file.
26  *
27  * Revision 1.4  1995/09/05  15:28:39  adam
28  * More work on search engine.
29  *
30  * Revision 1.3  1995/09/04  12:33:41  adam
31  * Various cleanup. YAZ util used instead.
32  *
33  * Revision 1.2  1995/09/04  09:10:34  adam
34  * More work on index add/del/update.
35  * Merge sort implemented.
36  * Initial work on z39 server.
37  *
38  * Revision 1.1  1995/09/01  14:06:35  adam
39  * Split of work into more files.
40  *
41  */
42 #include <stdio.h>
43 #include <assert.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47
48 #include <alexutil.h>
49 #include <recctrl.h>
50 #include "index.h"
51
52 static Dict file_idx;
53 static SYSNO sysno_next;
54 static int key_fd = -1;
55 static int sys_idx_fd = -1;
56 static char *key_buf;
57 static int key_offset, key_buf_size;
58 static int key_cmd;
59 static int key_sysno;
60
61 void key_open (const char *fname)
62 {
63     void *file_key;
64     if (key_fd != -1)
65         return;
66     if ((key_fd = open (fname, O_RDWR|O_CREAT, 0666)) == -1)
67     {
68         logf (LOG_FATAL|LOG_ERRNO, "open %s", fname);
69         exit (1);
70     }
71     logf (LOG_DEBUG, "key_open of %s", fname);
72     key_buf_size = 49100;
73     key_buf = xmalloc (key_buf_size);
74     key_offset = 0;
75     if (!(file_idx = dict_open (FNAME_FILE_DICT, 40, 1)))
76     {
77         logf (LOG_FATAL, "dict_open fail of %s", "fileidx");
78         exit (1);
79     }
80     file_key = dict_lookup (file_idx, ".");
81     if (file_key)
82         memcpy (&sysno_next, (char*)file_key+1, sizeof(sysno_next));
83     else
84         sysno_next = 1;
85     if ((sys_idx_fd = open (FNAME_SYS_IDX, O_RDWR|O_CREAT, 0666)) == -1)
86     {
87         logf (LOG_FATAL|LOG_ERRNO, "open %s", FNAME_SYS_IDX);
88         exit (1);
89     }
90 }
91
92 int key_close (void)
93 {
94     if (key_fd == -1)
95     {
96         logf (LOG_DEBUG, "key_close - but no file");
97         return 0;
98     }
99     close (key_fd);
100     close (sys_idx_fd);
101     dict_insert (file_idx, ".", sizeof(sysno_next), &sysno_next);
102     dict_close (file_idx);
103     key_fd = -1;
104     xfree (key_buf);
105     return 1;
106 }
107
108 void wordFlush (int sysno)
109 {
110     size_t i = 0;
111     int w;
112
113     if (key_fd == -1)
114         return; 
115     while (i < key_offset)
116     {
117         w = write (key_fd, key_buf + i, key_offset - i);
118         if (w == -1)
119         {
120             logf (LOG_FATAL|LOG_ERRNO, "Write key fail");
121             exit (1);
122         }
123         i += w;
124     }
125     key_offset = 0;
126 }
127
128 static void wordInit (RecWord *p)
129 {
130     p->attrSet = 1;
131     p->attrUse = 1;
132     p->which = Word_String;
133 }
134
135 static void wordAdd (const RecWord *p)
136 {
137     struct it_key key;
138     char x;
139     size_t i;
140     char wordPrefix[8];
141
142     if (key_offset + 1000 > key_buf_size)
143     {
144         char *new_key_buf;
145
146         key_buf_size *= 2;
147         new_key_buf = xmalloc (2*key_buf_size);
148         memcpy (new_key_buf, key_buf, key_offset);
149         xfree (key_buf);
150         key_buf = new_key_buf;
151     }
152     sprintf (wordPrefix, "%c%04d", p->attrSet + '0', p->attrUse);
153     strcpy (key_buf + key_offset, wordPrefix);
154     key_offset += strlen (wordPrefix);
155     switch (p->which)
156     {
157     case Word_String:
158         for (i = 0; p->u.string[i]; i++)
159             key_buf[key_offset++] = index_char_cvt (p->u.string[i]);
160         key_buf[key_offset++] = '\0';
161         break;
162     default:
163         return ;
164     }
165     x = (key_cmd == 'a') ? 1 : 0;
166     memcpy (key_buf + key_offset, &x, 1);
167     key_offset++;
168
169     key.sysno = key_sysno;
170     key.seqno   = p->seqno;
171     memcpy (key_buf + key_offset, &key, sizeof(key));
172     key_offset += sizeof(key);
173 }
174
175 void file_extract (int cmd, const char *fname, const char *kname)
176 {
177     int i;
178     char ext[128];
179     SYSNO sysno;
180     char ext_res[128];
181     const char *file_type;
182     void *file_info;
183     FILE *inf;
184     struct recExtractCtrl extractCtrl;
185     RecType rt;
186
187     logf (LOG_DEBUG, "%c %s k=%s", cmd, fname, kname);
188     for (i = strlen(fname); --i >= 0; )
189         if (fname[i] == '/')
190         {
191             strcpy (ext, "");
192             break;
193         }
194         else if (fname[i] == '.')
195         {
196             strcpy (ext, fname+i+1);
197             break;
198         }
199     sprintf (ext_res, "fileExtension.%s", ext);
200     if (!(file_type = res_get (common_resource, ext_res)))
201         return;
202     if (!(rt = recType_byName (file_type)))
203         return;
204     file_info = dict_lookup (file_idx, kname);
205     if (!file_info)
206     {
207         sysno = sysno_next++;
208         dict_insert (file_idx, kname, sizeof(sysno), &sysno);
209         lseek (sys_idx_fd, sysno * SYS_IDX_ENTRY_LEN, SEEK_SET);
210         write (sys_idx_fd, file_type, strlen (file_type)+1);
211         write (sys_idx_fd, kname, strlen(kname)+1);
212     }
213     else
214         memcpy (&sysno, (char*) file_info+1, sizeof(sysno));
215
216     if (!(inf = fopen (fname, "r")))
217     {
218         logf (LOG_WARN|LOG_ERRNO, "open %s", fname);
219         return;
220     }
221     extractCtrl.inf = inf;
222     extractCtrl.subType = "";
223     extractCtrl.init = wordInit;
224     extractCtrl.add = wordAdd;
225     key_sysno = sysno;
226     key_cmd = cmd;
227     (*rt->extract)(&extractCtrl);
228     fclose (inf);
229     wordFlush (sysno);
230 }
231
232