More work on relevance feedback.
[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.7  1995-09-11 13:09:32  adam
8  * More work on relevance feedback.
9  *
10  * Revision 1.6  1995/09/08  14:52:27  adam
11  * Minor changes. Dictionary is lower case now.
12  *
13  * Revision 1.5  1995/09/06  16:11:16  adam
14  * Option: only one word key per file.
15  *
16  * Revision 1.4  1995/09/05  15:28:39  adam
17  * More work on search engine.
18  *
19  * Revision 1.3  1995/09/04  12:33:41  adam
20  * Various cleanup. YAZ util used instead.
21  *
22  * Revision 1.2  1995/09/04  09:10:34  adam
23  * More work on index add/del/update.
24  * Merge sort implemented.
25  * Initial work on z39 server.
26  *
27  * Revision 1.1  1995/09/01  14:06:35  adam
28  * Split of work into more files.
29  *
30  */
31 #include <stdio.h>
32 #include <assert.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36
37 #include <alexutil.h>
38 #include "index.h"
39
40 #define KEY_BUF_SIZE 100000
41
42 static Dict file_idx;
43 static SYSNO sysno_next;
44 static int key_fd = -1;
45 static int sys_idx_fd = -1;
46 static char *key_buf;
47 static int key_offset;
48
49 void key_open (const char *fname)
50 {
51     void *file_key;
52     if (key_fd != -1)
53         return;
54     if ((key_fd = open (fname, O_RDWR|O_CREAT, 0666)) == -1)
55     {
56         logf (LOG_FATAL|LOG_ERRNO, "open %s", fname);
57         exit (1);
58     }
59     logf (LOG_DEBUG, "key_open of %s", fname);
60     if (!(key_buf = malloc (KEY_BUF_SIZE)))
61     {
62         logf (LOG_FATAL|LOG_ERRNO, "malloc");
63         exit (1);
64     }
65     key_offset = 0;
66     if (!(file_idx = dict_open (FNAME_FILE_DICT, 40, 1)))
67     {
68         logf (LOG_FATAL, "dict_open fail of %s", "fileidx");
69         exit (1);
70     }
71     file_key = dict_lookup (file_idx, ".");
72     if (file_key)
73         memcpy (&sysno_next, (char*)file_key+1, sizeof(sysno_next));
74     else
75         sysno_next = 1;
76     if ((sys_idx_fd = open (FNAME_SYS_IDX, O_RDWR|O_CREAT, 0666)) == -1)
77     {
78         logf (LOG_FATAL|LOG_ERRNO, "open %s", FNAME_SYS_IDX);
79         exit (1);
80     }
81 }
82
83 int key_close (void)
84 {
85     if (key_fd == -1)
86     {
87         logf (LOG_DEBUG, "key_close - but no file");
88         return 0;
89     }
90     close (key_fd);
91     close (sys_idx_fd);
92     dict_insert (file_idx, ".", sizeof(sysno_next), &sysno_next);
93     dict_close (file_idx);
94     key_fd = -1;
95     logf (LOG_DEBUG, "key close - key file exist");
96     return 1;
97 }
98
99 void key_flush (void)
100 {
101     size_t i = 0;
102     int w;
103
104     if (key_fd == -1)
105         return; 
106     while (i < key_offset)
107     {
108         w = write (key_fd, key_buf + i, key_offset - i);
109         if (w == -1)
110         {
111             logf (LOG_FATAL|LOG_ERRNO, "Write key fail");
112             exit (1);
113         }
114         i += w;
115     }
116     key_offset = 0;
117 }
118
119 void key_write (int cmd, struct it_key *k, const char *str)
120 {
121     char x;
122     size_t slen = strlen(str);
123
124     if (key_offset + sizeof(*k) + slen >= KEY_BUF_SIZE - 2)
125         key_flush ();
126     x = (cmd == 'a') ? 1 : 0;
127     memcpy (key_buf + key_offset, str, slen+1);
128     key_offset += slen+1;
129     memcpy (key_buf + key_offset, &x, 1);
130     key_offset++;
131     memcpy (key_buf + key_offset, k, sizeof(*k));
132     key_offset += sizeof(*k);
133 }
134
135 #if !IT_KEY_HAVE_SEQNO
136 void key_write_x (struct strtab *t, int cmd, struct it_key *k, const char *str)
137 {
138     void **oldinfo;
139
140     if (strtab_src (t, str, &oldinfo))
141         ((struct it_key *) *oldinfo)->freq++;
142     else
143     {
144         *oldinfo = xmalloc (sizeof(*k));
145         memcpy (*oldinfo, k, sizeof(*k));
146         ((struct it_key *) *oldinfo)->freq = 1;
147     }
148 }
149 #endif
150
151 void key_rec_flush (const char *str, void *info, void *data)
152 {
153     key_write (*((int*) data), (struct it_key *)info, str);
154     xfree (info);
155 }
156
157 void text_extract (struct strtab *t, SYSNO sysno, int cmd, const char *fname)
158 {
159     FILE *inf;
160     struct it_key k;
161 #if IT_KEY_HAVE_SEQNO
162     int seqno = 1;
163 #endif
164     int c;
165     char w[IT_MAX_WORD];
166
167     logf (LOG_DEBUG, "Text extract of %d", sysno);
168     k.sysno = sysno;
169     inf = fopen (fname, "r");
170     if (!inf)
171     {
172         logf (LOG_WARN|LOG_ERRNO, "open %s", fname);
173         return;
174     }
175     while ((c=getc (inf)) != EOF)
176     {
177         int i = 0;
178         while (i < IT_MAX_WORD-1 && c != EOF && isalnum(c))
179         {
180             w[i++] = index_char_cvt (c);
181             c = getc (inf);
182         }
183         if (i)
184         {
185             w[i] = 0;
186             
187 #if IT_KEY_HAVE_FIELD
188             k.field = 0;
189 #endif
190 #if IT_KEY_HAVE_SEQNO
191             k.seqno = seqno++;
192             key_write (cmd, &k, w);
193 #else
194             key_write_x (t, cmd, &k, w);
195 #endif
196         }
197         if (c == EOF)
198             break;
199     }
200     fclose (inf);
201 }
202
203 void file_extract (int cmd, const char *fname, const char *kname)
204 {
205     int i;
206     char ext[128];
207     SYSNO sysno;
208     char ext_res[128];
209     const char *file_type;
210     void *file_info;
211     struct strtab *t;
212
213     logf (LOG_DEBUG, "%c %s k=%s", cmd, fname, kname);
214     for (i = strlen(fname); --i >= 0; )
215         if (fname[i] == '/')
216         {
217             strcpy (ext, "");
218             break;
219         }
220         else if (fname[i] == '.')
221         {
222             strcpy (ext, fname+i+1);
223             break;
224         }
225     sprintf (ext_res, "fileExtension.%s", ext);
226     if (!(file_type = res_get (common_resource, ext_res)))
227         return;
228     
229     file_info = dict_lookup (file_idx, kname);
230     if (!file_info)
231     {
232         sysno = sysno_next++;
233         dict_insert (file_idx, kname, sizeof(sysno), &sysno);
234         lseek (sys_idx_fd, sysno * SYS_IDX_ENTRY_LEN, SEEK_SET);
235         write (sys_idx_fd, kname, strlen(kname)+1);
236     }
237     else
238         memcpy (&sysno, (char*) file_info+1, sizeof(sysno));
239     t = strtab_mk ();
240     if (!strcmp (file_type, "text"))
241         text_extract (t, sysno, cmd, fname);
242     strtab_del (t, key_rec_flush, &cmd);
243 }
244
245