YAZ  4.2.57
zoom-sru.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <assert.h>
14 #include <string.h>
15 #include <errno.h>
16 #include "zoom-p.h"
17 
18 #include <yaz/log.h>
19 #include <yaz/pquery.h>
20 
21 #if YAZ_HAVE_XML2
23 {
24  const char *uri = d->uri;
25  if (uri)
26  ZOOM_set_dset_error(c, ZOOM_uri_to_code(uri), uri, d->details, 0);
27 }
28 #endif
29 
30 
31 #if YAZ_HAVE_XML2
33 {
34  Z_GDU *gdu;
35  const char *database = ZOOM_options_get(c->options, "databaseName");
36 
38  database,
39  c->proxy ? 1 : 0);
40 
41  if (c->sru_mode == zoom_sru_get)
42  {
44  }
45  else if (c->sru_mode == zoom_sru_post)
46  {
48  }
49  else if (c->sru_mode == zoom_sru_soap)
50  {
52  }
53  else if (c->sru_mode == zoom_sru_solr)
54  {
56  }
57  return ZOOM_send_GDU(c, gdu);
58 }
59 #endif
60 
61 #if YAZ_HAVE_XML2
63 {
64  Z_SRW_PDU *sr = yaz_srw_get_pdu(c->odr_out, type, c->sru_version);
65  sr->username = c->user;
66  sr->password = c->password;
67  return sr;
68 }
69 #endif
70 
71 #if YAZ_HAVE_XML2
73 {
74  ZOOM_scanset scan;
75  Z_SRW_PDU *sr = 0;
76  const char *option_val = 0;
77  Z_Query *z_query;
78 
79  if (!c->tasks)
80  return zoom_complete;
81  assert (c->tasks->which == ZOOM_TASK_SCAN);
82  scan = c->tasks->u.scan.scan;
83 
85 
86  z_query = ZOOM_query_get_Z_Query(scan->query);
87  /* SRU scan can only carry CQL and PQF */
88  if (z_query->which == Z_Query_type_104)
89  {
93  }
94  else if (z_query->which == Z_Query_type_1
95  || z_query->which == Z_Query_type_101)
96  {
100  }
101  else
102  {
104  return zoom_complete;
105  }
106 
108  c->odr_out, ZOOM_options_get_int(scan->options, "number", 10));
109 
111  c->odr_out, ZOOM_options_get_int(scan->options, "position", 1));
112 
113  option_val = ZOOM_options_get(scan->options, "extraArgs");
114  yaz_encode_sru_extra(sr, c->odr_out, option_val);
115  return send_srw(c, sr);
116 }
117 #else
119 {
120  return zoom_complete;
121 }
122 #endif
123 
124 #if YAZ_HAVE_XML2
126 {
127  const char *facets = 0;
128  int i;
129  int *start, *count;
130  ZOOM_resultset resultset = 0;
131  Z_SRW_PDU *sr = 0;
132  const char *option_val = 0;
133  Z_Query *z_query;
134  Z_FacetList *facet_list = 0;
135  if (c->error) /* don't continue on error */
136  return zoom_complete;
137  assert(c->tasks);
138  switch(c->tasks->which)
139  {
140  case ZOOM_TASK_SEARCH:
141  resultset = c->tasks->u.search.resultset;
142  if (!resultset->setname)
143  resultset->setname = xstrdup("default");
144  ZOOM_options_set(resultset->options, "setname", resultset->setname);
145  start = &c->tasks->u.search.start;
146  count = &c->tasks->u.search.count;
147  facets = ZOOM_options_get(resultset->options, "facets");
148  if (facets)
149  facet_list = yaz_pqf_parse_facet_list(c->odr_out, facets);
150  break;
151  case ZOOM_TASK_RETRIEVE:
152  resultset = c->tasks->u.retrieve.resultset;
153 
154  start = &c->tasks->u.retrieve.start;
155  count = &c->tasks->u.retrieve.count;
156 
157  if (*start >= resultset->size)
158  return zoom_complete;
159  if (*start + *count > resultset->size)
160  *count = resultset->size - *start;
161 
162  for (i = 0; i < *count; i++)
163  {
164  ZOOM_record rec =
165  ZOOM_record_cache_lookup(resultset, i + *start,
166  c->tasks->u.retrieve.syntax,
167  c->tasks->u.retrieve.elementSetName);
168  if (!rec)
169  break;
170  else
171  {
173  ZOOM_connection_put_event(c, event);
174  }
175  }
176  *start += i;
177  *count -= i;
178 
179  if (*count == 0)
180  return zoom_complete;
181  break;
182  default:
183  return zoom_complete;
184  }
185  assert(resultset->query);
186 
188  z_query = ZOOM_query_get_Z_Query(resultset->query);
189 
190  if (z_query->which == Z_Query_type_104
191  && z_query->u.type_104->which == Z_External_CQL)
192  {
194  sr->u.request->query.cql = z_query->u.type_104->u.cql;
195  }
196  else if (z_query->which == Z_Query_type_1 && z_query->u.type_1)
197  {
199  sr->u.request->query.pqf =
200  odr_strdup(c->odr_out,
201  ZOOM_query_get_query_string(resultset->query));
202  }
203  else
204  {
206  return zoom_complete;
207  }
208 
209  option_val = ZOOM_query_get_sru11(resultset->query);
210  if (option_val)
211  {
213  sr->u.request->sort.sortKeys = odr_strdup(c->odr_out, option_val);
214  }
215  sr->u.request->startRecord = odr_intdup(c->odr_out, *start + 1);
217  c->odr_out, (resultset->step > 0 && resultset->step < *count) ?
218  resultset->step : *count);
219  sr->u.request->recordSchema = resultset->schema;
220  sr->u.request->facetList = facet_list;
221 
222  option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
223  if (option_val)
224  sr->u.request->recordPacking = odr_strdup(c->odr_out, option_val);
225 
226  option_val = ZOOM_resultset_option_get(resultset, "extraArgs");
227  yaz_encode_sru_extra(sr, c->odr_out, option_val);
228  return send_srw(c, sr);
229 }
230 #else
232 {
233  return zoom_complete;
234 }
235 #endif
236 
237 #if YAZ_HAVE_XML2
240 {
241  ZOOM_resultset resultset = 0;
242  int i;
243  NMEM nmem;
244  ZOOM_Event event;
245  int *start, *count;
246  const char *syntax, *elementSetName;
247 
248  if (!c->tasks)
249  return zoom_complete;
250 
251  switch(c->tasks->which)
252  {
253  case ZOOM_TASK_SEARCH:
254  resultset = c->tasks->u.search.resultset;
255  start = &c->tasks->u.search.start;
256  count = &c->tasks->u.search.count;
257  syntax = c->tasks->u.search.syntax;
258  elementSetName = c->tasks->u.search.elementSetName;
259 
260  /* Required not for reporting client hit count multiple times into session */
261  if (!c->tasks->u.search.recv_search_fired) {
262  yaz_log(YLOG_DEBUG, "posting ZOOM_EVENT_RECV_SEARCH");
264  ZOOM_connection_put_event(c, event);
265  c->tasks->u.search.recv_search_fired = 1;
266  }
267  if (res->facetList)
268  ZOOM_handle_facet_list(resultset, res->facetList);
269  break;
270  case ZOOM_TASK_RETRIEVE:
271  resultset = c->tasks->u.retrieve.resultset;
272  start = &c->tasks->u.retrieve.start;
273  count = &c->tasks->u.retrieve.count;
274  syntax = c->tasks->u.retrieve.syntax;
275  elementSetName = c->tasks->u.retrieve.elementSetName;
276  break;
277  default:
278  return zoom_complete;
279  }
280 
281  resultset->size = 0;
282 
283  if (res->resultSetId)
284  ZOOM_resultset_option_set(resultset, "resultSetId", res->resultSetId);
285 
286  yaz_log(c->log_details, "%p handle_srw_response got SRW response OK", c);
287 
288  if (res->num_diagnostics > 0)
289  {
290  set_SRU_error(c, &res->diagnostics[0]);
291  }
292  else
293  {
294  if (res->numberOfRecords) {
295  resultset->size = *res->numberOfRecords;
296  }
297  if (res->suggestions) {
298  ZOOM_resultset_option_set(resultset, "suggestions", res->suggestions);
299  }
300  for (i = 0; i<res->num_records; i++)
301  {
302  int pos = *start + i;
303  Z_SRW_record *sru_rec;
304  Z_SRW_diagnostic *diag = 0;
305  int num_diag;
306 
308  odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
309 
310  /* only trust recordPosition if >= calculated position */
311  if (res->records[i].recordPosition &&
312  *res->records[i].recordPosition >= pos + 1)
313  pos = *res->records[i].recordPosition - 1;
314 
315  sru_rec = &res->records[i];
316 
317  npr->databaseName = 0;
319  npr->u.databaseRecord = (Z_External *)
320  odr_malloc(c->odr_in, sizeof(Z_External));
321  npr->u.databaseRecord->descriptor = 0;
326 
328  odr_malloc(c->odr_in, sizeof(Odr_oct));
329  npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)
330  sru_rec->recordData_buf;
333  sru_rec->recordData_len;
334 
335  if (sru_rec->recordSchema
336  && !strcmp(sru_rec->recordSchema,
337  "info:srw/schema/1/diagnostics-v1.1"))
338  {
340  sru_rec->recordData_len,
341  &diag, &num_diag,
342  resultset->odr);
343  }
344  ZOOM_record_cache_add(resultset, npr, pos, syntax, elementSetName,
345  sru_rec->recordSchema, diag);
346  }
347  *count -= i;
348  *start += i;
349  if (*count + *start > resultset->size)
350  *count = resultset->size - *start;
351  yaz_log(YLOG_DEBUG, "SRU result set size " ODR_INT_PRINTF " start %d count %d", resultset->size, *start, *count);
352  if (*count < 0)
353  *count = 0;
354  nmem = odr_extract_mem(c->odr_in);
355  nmem_transfer(odr_getmem(resultset->odr), nmem);
356  nmem_destroy(nmem);
357 
358  if (*count > 0)
360  }
361  return zoom_complete;
362 }
363 #endif
364 
365 #if YAZ_HAVE_XML2
367  Z_SRW_scanResponse *res)
368 {
369  NMEM nmem = odr_extract_mem(c->odr_in);
370  ZOOM_scanset scan;
371 
372  if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
373  return;
374  scan = c->tasks->u.scan.scan;
375 
376  if (res->num_diagnostics > 0)
377  set_SRU_error(c, &res->diagnostics[0]);
378 
379  scan->scan_response = 0;
380  scan->srw_scan_response = res;
381  nmem_transfer(odr_getmem(scan->odr), nmem);
382 
383  ZOOM_options_set_int(scan->options, "number", res->num_terms);
384  nmem_destroy(nmem);
385 }
386 #endif
387 
389  zoom_ret *cret, char **addinfo)
390 {
391 #if YAZ_HAVE_XML2
392  int ret = 0;
393 
394  /* not redirect (normal response) */
395  if (!yaz_srw_check_content_type(hres))
396  {
397  *addinfo = "content-type";
398  ret = -1;
399  }
400  else if (c->sru_mode == zoom_sru_solr)
401  {
402  Z_SRW_PDU *sr;
403  ret = yaz_solr_decode_response(c->odr_in, hres, &sr);
404  if (ret == 0)
405  {
407  *cret = handle_srw_response(c, sr->u.response);
408  else if (sr->which == Z_SRW_scan_response)
410  }
411  }
412  else
413  {
414  Z_SOAP *soap_package = 0;
415  ODR o = c->odr_in;
416  Z_SOAP_Handler soap_handlers[3] = {
419  {0, 0, 0}
420  };
421  ret = z_soap_codec(o, &soap_package,
422  &hres->content_buf, &hres->content_len,
423  soap_handlers);
424  if (!ret && soap_package->which == Z_SOAP_generic)
425  {
426  Z_SRW_PDU *sr = (Z_SRW_PDU*) soap_package->u.generic->p;
427 
428  ZOOM_options_set(c->options, "sru_version", sr->srw_version);
429  ZOOM_options_setl(c->options, "sru_extra_response_data",
432  *cret = handle_srw_response(c, sr->u.response);
433  else if (sr->which == Z_SRW_scan_response)
435  else
436  ret = -1;
437  }
438  else if (!ret && (soap_package->which == Z_SOAP_fault
439  || soap_package->which == Z_SOAP_error))
440  {
441  ZOOM_set_HTTP_error(c, hres->code,
442  soap_package->u.fault->fault_code,
443  soap_package->u.fault->fault_string);
444  }
445  else
446  {
447  size_t max_chars = 1000;
448  size_t sz = hres->content_len;
449  if (sz > max_chars - 1)
450  sz = max_chars;
451  *addinfo = odr_malloc(c->odr_in, sz + 4);
452  memcpy(*addinfo, hres->content_buf, sz);
453  if (sz == max_chars)
454  strcpy(*addinfo + sz, "...");
455  else
456  strcpy(*addinfo + sz, "");
457  ret = -1;
458  }
459  }
460  return ret;
461 #else
462  return -1;
463 #endif
464 }
465 
466 /*
467  * Local variables:
468  * c-basic-offset: 4
469  * c-file-style: "Stroustrup"
470  * indent-tabs-mode: nil
471  * End:
472  * vim: shiftwidth=4 tabstop=8 expandtab
473  */
474