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