metaproxy  1.13.0
filter_present_chunk.cpp
Go to the documentation of this file.
1 /* This file is part of Metaproxy.
2  Copyright (C) Index Data
3 
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "config.hpp"
20 #include "filter_present_chunk.hpp"
21 
22 #include <time.h>
23 #include <yaz/log.h>
24 #include <yaz/copy_types.h>
25 #include <metaproxy/package.hpp>
26 #include <metaproxy/util.hpp>
27 
28 namespace mp = metaproxy_1;
29 namespace yf = mp::filter;
30 
31 namespace metaproxy_1 {
32  namespace filter {
34  public:
35  Impl();
36  ~Impl();
37  void process(metaproxy_1::Package & package);
38  void configure(const xmlNode * ptr);
39  void chunk_it(metaproxy_1::Package & package, Z_APDU *apdu);
40  private:
41  Odr_int chunk_number;
42  };
43  }
44 }
45 
46 yf::PresentChunk::PresentChunk() : m_p(new Impl)
47 {
48 }
49 
50 yf::PresentChunk::~PresentChunk()
51 { // must have a destructor because of boost::scoped_ptr
52 }
53 
54 void yf::PresentChunk::configure(const xmlNode *xmlnode, bool test_only,
55  const char *path)
56 {
57  m_p->configure(xmlnode);
58 }
59 
60 void yf::PresentChunk::process(mp::Package &package) const
61 {
62  m_p->process(package);
63 }
64 
65 yf::PresentChunk::Impl::Impl() : chunk_number(0)
66 {
67 }
68 
69 yf::PresentChunk::Impl::~Impl()
70 {
71 }
72 
73 void yf::PresentChunk::Impl::configure(const xmlNode *ptr)
74 {
75  for (ptr = ptr->children; ptr; ptr = ptr->next)
76  {
77  if (ptr->type != XML_ELEMENT_NODE)
78  continue;
79  if (!strcmp((const char *) ptr->name, "chunk"))
80  {
81  chunk_number = mp::xml::get_int(ptr, 0);
82  }
83  else
84  {
85  throw mp::filter::FilterException("Bad element "
86  + std::string((const char *)
87  ptr->name));
88  }
89  }
90 }
91 
92 void yf::PresentChunk::Impl::chunk_it(mp::Package &package,
93  Z_APDU *apdu)
94 {
95  mp::odr odr;
96  Z_PresentRequest *pr = apdu->u.presentRequest;
97 
98  Odr_int total = *pr->numberOfRecordsRequested;
99  Odr_int start = *pr->resultSetStartPoint;
100  Odr_int offset = 0;
101  Z_NamePlusRecordList *npl = (Z_NamePlusRecordList *)
102  odr_malloc(odr, sizeof(*npl));
103  npl->num_records = total;
104  npl->records = (Z_NamePlusRecord **)
105  odr_malloc(odr, sizeof(*npl->records) * total);
106  while (offset < total)
107  {
108  Odr_int left = total - offset;
109 
110  Package pp(package.session(), package.origin());
111 
112  *pr->numberOfRecordsRequested =
113  left > chunk_number ? chunk_number : left;
114 
115  *pr->resultSetStartPoint = start + offset;
116 
117  pp.copy_filter(package);
118  pp.request() = apdu;
119 
120  pp.move();
121 
122  if (pp.session().is_closed())
123  {
124  package.session().close();
125  return;
126  }
127  Z_GDU *gdu_res = pp.response().get();
128  if (gdu_res && gdu_res->which == Z_GDU_Z3950 &&
129  gdu_res->u.z3950->which == Z_APDU_presentResponse)
130  {
131  Z_PresentResponse *pres =
132  gdu_res->u.z3950->u.presentResponse;
133  if (pres->records &&
134  pres->records->which == Z_Records_DBOSD)
135  {
136  Z_NamePlusRecordList *nprl =
137  pres->records->u.databaseOrSurDiagnostics;
138  int i;
139  for (i = 0; i < nprl->num_records; i++)
140  {
141  ODR o = odr;
142  npl->records[offset+i] = yaz_clone_z_NamePlusRecord(
143  nprl->records[i], o->mem);
144  }
145  offset += nprl->num_records;
146  }
147  else
148  {
149  package.response() = pp.response();
150  return;
151  }
152  }
153  else
154  {
155  package.response() = pp.response();
156  return;
157  }
158  }
159 
160  yaz_log(YLOG_LOG, "building response . %lld", offset);
161 
162  Z_APDU *a = zget_APDU(odr, Z_APDU_presentResponse);
163  Z_PresentResponse *pres = a->u.presentResponse;
164  pres->records = (Z_Records *)
165  odr_malloc(odr, sizeof(Z_Records));
166  pres->records->which = Z_Records_DBOSD;
167  pres->records->u.databaseOrSurDiagnostics = npl;
168  npl->num_records = offset;
169  *pres->numberOfRecordsReturned = offset;
170 
171  package.response() = a;
172 }
173 
174 void yf::PresentChunk::Impl::process(mp::Package &package)
175 {
176  Z_GDU *gdu = package.request().get();
177  if (gdu && gdu->which == Z_GDU_Z3950)
178  {
179  Z_APDU *apdu = gdu->u.z3950;
180  if (apdu->which == Z_APDU_presentRequest && chunk_number > 0)
181  chunk_it(package, apdu);
182  else
183  package.move();
184  }
185  else
186  package.move();
187 }
188 
189 static mp::filter::Base* filter_creator()
190 {
191  return new mp::filter::PresentChunk;
192 }
193 
194 extern "C" {
195  struct metaproxy_1_filter_struct metaproxy_1_filter_present_chunk = {
196  0,
197  "present_chunk",
199  };
200 }
201 
202 
203 /*
204  * Local variables:
205  * c-basic-offset: 4
206  * c-file-style: "Stroustrup"
207  * indent-tabs-mode: nil
208  * End:
209  * vim: shiftwidth=4 tabstop=8 expandtab
210  */
211 
void configure(const xmlNode *ptr)
void chunk_it(metaproxy_1::Package &package, Z_APDU *apdu)
void process(metaproxy_1::Package &package)
struct metaproxy_1_filter_struct metaproxy_1_filter_present_chunk
static mp::filter::Base * filter_creator()