using yaz/log.h again
[idzebra-moved-to-github.git] / perl / zebra_perl.c
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <yaz/yaz-util.h>
6 #include <yaz/proto.h>
7 #include <yaz/log.h>
8 #include <yaz/cql.h>
9 #include <yaz/pquery.h>
10
11 #include "zebra_perl.h"
12 #include "../recctrl/perlread.h"
13 #include <idzebra/data1.h>
14
15 NMEM handles;
16
17 void init (void) {
18   nmem_init ();
19   yaz_log_init_prefix ("ZebraPerl");
20   yaz_log (YLOG_LOG, "Zebra API initialized");
21 }
22
23 void DESTROY (void) {
24   nmem_exit ();
25   yaz_log (YLOG_LOG, "Zebra API destroyed");
26 }   
27
28 /* Logging facilities from yaz */
29 void logMsg (int level, const char *message) {
30   yaz_log(level, "%s", message);
31 }
32
33 /* debug tool for data1... maybe should be moved to data1. 
34    perl can't really pass filehandles */
35 void data1_print_tree(data1_handle dh, data1_node *n) {
36   data1_pr_tree(dh, n, stdout);
37 }
38
39 /* ---------------------------------------------------------------------------
40   Record retrieval 
41   2 phase retrieval - I didn't manage to return array of blessed references
42   to wrapped structures... it's feasible, but I'll need some time 
43   / pop - 2002-11-17
44 */
45
46 void record_retrieve(RetrievalObj *ro,
47                      ODR stream,
48                      RetrievalRecord *res,
49                      int pos) 
50 {
51   int i = pos - 1;
52
53
54   RetrievalRecordBuf *buf = 
55     (RetrievalRecordBuf *) odr_malloc(stream, sizeof(*buf));  
56
57   res->errCode    = ro->records[i].errCode;
58   if (ro->records[i].errString) {
59     res->errString  = odr_strdup(stream, ro->records[i].errString);
60   } else {
61     res->errString = "";
62   }
63   res->position   = ro->records[i].position;
64   res->base       = odr_strdup(stream, ro->records[i].base);
65   res->format     = (char *) 
66     yaz_z3950_oid_value_to_str(ro->records[i].format, CLASS_RECSYN); 
67   res->buf        = buf;
68   res->buf->len   = ro->records[i].len;
69   res->buf->buf   = ro->records[i].buf;
70   res->score      = ro->records[i].score;
71   res->sysno      = ro->records[i].sysno;
72
73 }
74
75
76
77 /* most of the code here was copied from yaz-client */
78 void records_retrieve(ZebraHandle zh,
79                       ODR stream,
80                       const char *setname,
81                       const char *a_eset, 
82                       const char *a_schema,
83                       const char *a_format,
84                       int from,
85                       int to,
86                       RetrievalObj *res) 
87 {
88   static enum oid_value recordsyntax = VAL_SUTRS;
89   static enum oid_value schema = VAL_NONE;
90   static Z_ElementSetNames *elementSetNames = 0; 
91   static Z_RecordComposition compo;
92   static Z_ElementSetNames esn;
93   static char what[100];
94   int i;
95   int oid[OID_SIZE];
96
97   compo.which = -1;
98
99   if (from < 1) from = 1;
100   if (from > to) to = from;
101   res->noOfRecords = to - from + 1;
102
103   res->records = odr_malloc (stream, 
104                              sizeof(*res->records) * (res->noOfRecords));  
105
106   for (i = 0; i<res->noOfRecords; i++) res->records[i].position = from+i;
107
108   if (!a_eset || !*a_eset) {
109     elementSetNames = 0;
110   } else {
111     strcpy(what, a_eset);
112     esn.which = Z_ElementSetNames_generic;
113     esn.u.generic = what;
114     elementSetNames = &esn;
115   }
116
117   if (!a_schema || !*a_schema) {
118     schema = VAL_NONE;
119   } else {
120     schema = oid_getvalbyname (a_schema);
121     if (schema == VAL_NONE) {
122       yaz_log(YLOG_WARN,"unknown schema '%s'",a_schema);
123     }
124   }
125
126   
127   if (!a_format || !*a_format) {
128     recordsyntax = VAL_SUTRS;
129   } else {
130     recordsyntax = oid_getvalbyname (a_format);
131     if (recordsyntax == VAL_NONE) {
132       yaz_log(YLOG_WARN,"unknown record syntax '%s', using SUTRS",a_schema);
133       recordsyntax = VAL_SUTRS;
134     }
135   }
136
137   if (schema != VAL_NONE) {
138     oident prefschema;
139
140     prefschema.proto = PROTO_Z3950;
141     prefschema.oclass = CLASS_SCHEMA;
142     prefschema.value = schema;
143     
144     compo.which = Z_RecordComp_complex;
145     compo.u.complex = (Z_CompSpec *)
146       odr_malloc(stream, sizeof(*compo.u.complex));
147     compo.u.complex->selectAlternativeSyntax = (bool_t *) 
148       odr_malloc(stream, sizeof(bool_t));
149     *compo.u.complex->selectAlternativeSyntax = 0;
150     
151     compo.u.complex->generic = (Z_Specification *)
152       odr_malloc(stream, sizeof(*compo.u.complex->generic));
153     compo.u.complex->generic->which = Z_Schema_oid;
154     compo.u.complex->generic->schema.oid = (Odr_oid *)
155       odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
156     if (!compo.u.complex->generic->schema.oid)
157       {
158         /* OID wasn't a schema! Try record syntax instead. */
159         prefschema.oclass = CLASS_RECSYN;
160         compo.u.complex->generic->schema.oid = (Odr_oid *)
161           odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
162       }
163     if (!elementSetNames)
164       compo.u.complex->generic->elementSpec = 0;
165     else
166       {
167         compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
168           odr_malloc(stream, sizeof(Z_ElementSpec));
169         compo.u.complex->generic->elementSpec->which =
170           Z_ElementSpec_elementSetName;
171         compo.u.complex->generic->elementSpec->u.elementSetName =
172           elementSetNames->u.generic;
173       }
174     compo.u.complex->num_dbSpecific = 0;
175     compo.u.complex->dbSpecific = 0;
176     compo.u.complex->num_recordSyntax = 0;
177     compo.u.complex->recordSyntax = 0;
178   } 
179   else if (elementSetNames) {
180     compo.which = Z_RecordComp_simple;
181     compo.u.simple = elementSetNames;
182   }
183
184   if (compo.which == -1) {
185     api_records_retrieve (zh, stream, setname, 
186                             NULL, 
187                             recordsyntax,
188                             res->noOfRecords, res->records);
189   } else {
190     api_records_retrieve (zh, stream, setname, 
191                             &compo,
192                             recordsyntax,
193                             res->noOfRecords, res->records);
194   }
195
196 }
197  
198 int zebra_cql2pqf (cql_transform_t ct, 
199                    const char *query, char *res, int len) {
200   
201   int status;
202   const char *addinfo = "";
203   CQL_parser cp = cql_parser_create();
204
205   if (status = cql_parser_string(cp, query)) {
206     cql_parser_destroy(cp);
207     return (status);
208   }
209
210   if (cql_transform_buf(ct, cql_parser_result(cp), res, len)) {
211     status = cql_transform_error(ct, &addinfo);
212     yaz_log (YLOG_WARN,"Transform error %d %s\n", status, addinfo ? addinfo : "");
213     cql_parser_destroy(cp);
214     return (status);
215   }
216
217   cql_parser_destroy(cp);
218   return (0);
219 }
220
221 void zebra_scan_PQF (ZebraHandle zh,
222                      ScanObj *so,
223                      ODR stream,
224                      const char *pqf_query)
225 {
226   Z_AttributesPlusTerm *zapt;
227   Odr_oid *attrsetid;
228   const char* oidname;
229   oid_value attributeset;
230   ZebraScanEntry *entries;
231   int i, class;
232
233   yaz_log(YLOG_DEBUG,  
234        "scan req: pos:%d, num:%d, partial:%d", 
235        so->position, so->num_entries, so->is_partial);
236
237   zapt = p_query_scan (stream, PROTO_Z3950, &attrsetid, pqf_query);
238
239   oidname = yaz_z3950oid_to_str (attrsetid, &class); 
240   yaz_log (YLOG_DEBUG, "Attributreset: %s", oidname);
241   attributeset = oid_getvalbyname(oidname);
242
243   if (!zapt) {
244     yaz_log (YLOG_WARN, "bad query %s\n", pqf_query);
245     odr_reset (stream);
246     return;
247   }
248
249   so->entries = (scanEntry *)
250     odr_malloc (stream, sizeof(so->entries) * (so->num_entries));
251
252
253   zebra_scan (zh, stream, zapt, attributeset, 
254               &so->position, &so->num_entries, 
255               (ZebraScanEntry **) &so->entries, &so->is_partial);
256
257   yaz_log(YLOG_DEBUG, 
258        "scan res: pos:%d, num:%d, partial:%d", 
259        so->position, so->num_entries, so->is_partial);
260 }
261
262 scanEntry *getScanEntry(ScanObj *so, int pos) {
263   return (&so->entries[pos-1]);
264 }
265
266 #if 1
267 void Filter_store_buff (struct perl_context *context, char *buff, size_t len)
268 {
269     dSP;
270     
271     ENTER;
272     SAVETMPS;
273     
274     PUSHMARK(SP) ;
275     XPUSHs(context->filterRef);
276     XPUSHs(sv_2mortal(newSVpv(buff, len)));  
277     PUTBACK ;
278     call_method("_store_buff", 0);
279     SPAGAIN ;
280     PUTBACK ;
281     
282     FREETMPS;
283     LEAVE;
284 }
285
286 /*  The "file" manipulation function wrappers */
287 int grs_perl_readf(struct perl_context *context, size_t len)
288 {
289     int r;
290     char *buf = (char *) xmalloc (len+1);
291     r = (*context->readf)(context->fh, buf, len);
292     if (r > 0) Filter_store_buff (context, buf, r);
293     xfree (buf);
294     return (r);
295 }
296
297 int grs_perl_readline(struct perl_context *context)
298 {
299     int r;
300     char *buf = (char *) xmalloc (4096);
301     char *p = buf;
302     
303     while ((r = (*context->readf)(context->fh,p,1)) && (p-buf < 4095)) {
304         p++;
305         if (*(p-1) == 10) break;
306     }
307     
308     *p = 0;
309     
310     if (p != buf) Filter_store_buff (context, buf, p - buf);
311     xfree (buf);
312     return (p - buf);
313 }
314
315 char grs_perl_getc(struct perl_context *context)
316 {
317     int r;
318     char *p;
319     if ((r = (*context->readf)(context->fh,p,1))) {
320         return (*p);
321     } else {
322         return (0);
323     }
324 }
325
326 off_t grs_perl_seekf(struct perl_context *context, off_t offset)
327 {
328     return ((*context->seekf)(context->fh, offset));
329 }
330
331 off_t grs_perl_tellf(struct perl_context *context)
332 {
333     return ((*context->tellf)(context->fh));
334 }
335
336 void grs_perl_endf(struct perl_context *context, off_t offset)
337 {
338     (*context->endf)(context->fh, offset);
339 }
340
341 /* Get pointers from the context. Easyer to wrap this by SWIG */
342 data1_handle *grs_perl_get_dh(struct perl_context *context)
343 {
344     return(&context->dh);
345 }
346
347 NMEM *grs_perl_get_mem(struct perl_context *context)
348 {
349     return(&context->mem);
350 }
351
352 /* Set the result in the context */
353 void grs_perl_set_res(struct perl_context *context, data1_node *n)
354 {
355     context->res = n;
356 }
357 #endif