Towards GPL
[idzebra-moved-to-github.git] / index / retrieve.c
1 /* $Id: retrieve.c,v 1.20 2002-08-02 19:26:55 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24
25 #include <stdio.h>
26 #include <assert.h>
27
28 #include <fcntl.h>
29 #ifdef WIN32
30 #include <io.h>
31 #include <process.h>
32 #else
33 #include <unistd.h>
34 #endif
35
36 #include "index.h"
37 #include <direntz.h>
38
39 int zebra_record_ext_read (void *fh, char *buf, size_t count)
40 {
41     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
42     return read (fc->fd, buf, count);
43 }
44
45 off_t zebra_record_ext_seek (void *fh, off_t offset)
46 {
47     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
48     return lseek (fc->fd, offset + fc->record_offset, SEEK_SET);
49 }
50
51 off_t zebra_record_ext_tell (void *fh)
52 {
53     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
54     return lseek (fc->fd, 0, SEEK_CUR) - fc->record_offset;
55 }
56
57 off_t zebra_record_int_seek (void *fh, off_t offset)
58 {
59     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
60     return (off_t) (fc->record_int_pos = offset);
61 }
62
63 off_t zebra_record_int_tell (void *fh)
64 {
65     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
66     return (off_t) fc->record_int_pos;
67 }
68
69 int zebra_record_int_read (void *fh, char *buf, size_t count)
70 {
71     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
72     int l = fc->record_int_len - fc->record_int_pos;
73     if (l <= 0)
74         return 0;
75     l = (l < (int) count) ? l : count;
76     memcpy (buf, fc->record_int_buf + fc->record_int_pos, l);
77     fc->record_int_pos += l;
78     return l;
79 }
80
81 void zebra_record_int_end (void *fh, off_t off)
82 {
83     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
84     fc->offset_end = off;
85 }
86
87 int zebra_record_fetch (ZebraHandle zh, int sysno, int score, ODR stream,
88                         oid_value input_format, Z_RecordComposition *comp,
89                         oid_value *output_format, char **rec_bufp,
90                         int *rec_lenp, char **basenamep)
91 {
92     Record rec;
93     char *fname, *file_type, *basename;
94     RecType rt;
95     struct recRetrieveCtrl retrieveCtrl;
96     char subType[128];
97     struct zebra_fetch_control fc;
98     RecordAttr *recordAttr;
99     void *clientData;
100
101     rec = rec_get (zh->reg->records, sysno);
102     if (!rec)
103     {
104         logf (LOG_DEBUG, "rec_get fail on sysno=%d", sysno);
105         *basenamep = 0;
106         return 14;
107     }
108     recordAttr = rec_init_attr (zh->reg->zei, rec);
109
110     file_type = rec->info[recInfo_fileType];
111     fname = rec->info[recInfo_filename];
112     basename = rec->info[recInfo_databaseName];
113     *basenamep = (char *) odr_malloc (stream, strlen(basename)+1);
114     strcpy (*basenamep, basename);
115
116     if (comp && comp->which == Z_RecordComp_simple &&
117         comp->u.simple->which == Z_ElementSetNames_generic)
118     {
119         if (!strcmp (comp->u.simple->u.generic, "R"))
120             file_type = "text";
121     }
122     if (!(rt = recType_byName (zh->reg->recTypes,
123                                file_type, subType, &clientData)))
124     {
125         logf (LOG_WARN, "Retrieve: Cannot handle type %s",  file_type);
126         return 14;
127     }
128     logf (LOG_DEBUG, "retrieve localno=%d score=%d", sysno, score);
129     retrieveCtrl.fh = &fc;
130     fc.fd = -1;
131     retrieveCtrl.fname = fname;
132     if (rec->size[recInfo_storeData] > 0)
133     {
134         retrieveCtrl.readf = zebra_record_int_read;
135         retrieveCtrl.seekf = zebra_record_int_seek;
136         retrieveCtrl.tellf = zebra_record_int_tell;
137         fc.record_int_len = rec->size[recInfo_storeData];
138         fc.record_int_buf = rec->info[recInfo_storeData];
139         fc.record_int_pos = 0;
140         logf (LOG_DEBUG, "Internal retrieve. %d bytes", fc.record_int_len);
141     }
142     else
143     {
144         char full_rep[1024];
145
146         if (zh->path_reg && !yaz_is_abspath (fname))
147         {
148             strcpy (full_rep, zh->path_reg);
149             strcat (full_rep, "/");
150             strcat (full_rep, fname);
151         }
152         else
153             strcpy (full_rep, fname);
154         
155
156         if ((fc.fd = open (full_rep, O_BINARY|O_RDONLY)) == -1)
157         {
158             logf (LOG_WARN|LOG_ERRNO, "Retrieve fail; missing file: %s",
159                   full_rep);
160             rec_rm (&rec);
161             return 14;
162         }
163         fc.record_offset = recordAttr->recordOffset;
164
165         retrieveCtrl.readf = zebra_record_ext_read;
166         retrieveCtrl.seekf = zebra_record_ext_seek;
167         retrieveCtrl.tellf = zebra_record_ext_tell;
168
169         zebra_record_ext_seek (retrieveCtrl.fh, 0);
170     }
171     retrieveCtrl.subType = subType;
172     retrieveCtrl.localno = sysno;
173     retrieveCtrl.score = score;
174     retrieveCtrl.recordSize = recordAttr->recordSize;
175     retrieveCtrl.odr = stream;
176     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
177     retrieveCtrl.comp = comp;
178     retrieveCtrl.encoding = zh->record_encoding;
179     retrieveCtrl.diagnostic = 0;
180     retrieveCtrl.dh = zh->reg->dh;
181     retrieveCtrl.res = zh->res;
182     retrieveCtrl.rec_buf = 0;
183     retrieveCtrl.rec_len = -1;
184     
185     (*rt->retrieve)(clientData, &retrieveCtrl);
186     *output_format = retrieveCtrl.output_format;
187     *rec_bufp = (char *) retrieveCtrl.rec_buf;
188     *rec_lenp = retrieveCtrl.rec_len;
189     if (fc.fd != -1)
190         close (fc.fd);
191     rec_rm (&rec);
192
193     return retrieveCtrl.diagnostic;
194 }