2 * Copyright (c) 2000-2001, Index Data.
3 * See the file LICENSE for details.
5 * $Log: yaz-z-server.cpp,v $
6 * Revision 1.7 2001-03-26 14:43:49 adam
7 * New threaded PDU association.
9 * Revision 1.6 2001/01/29 11:18:24 adam
10 * Server sets OPTIONS search and present.
12 * Revision 1.5 2000/10/24 12:29:57 adam
13 * Fixed bug in proxy where a Yaz_ProxyClient could be owned by
14 * two Yaz_Proxy's (fatal).
16 * Revision 1.4 2000/10/11 11:58:17 adam
17 * Moved header files to include/yaz++. Switched to libtool and automake.
18 * Configure script creates yaz++-config script.
20 * Revision 1.3 2000/09/21 21:43:20 adam
21 * Better high-level server API.
23 * Revision 1.2 2000/09/12 12:09:53 adam
24 * More work on high-level server.
26 * Revision 1.1 2000/09/08 10:23:42 adam
27 * Added skeleton of yaz-z-server.
32 #include <yaz++/yaz-z-server.h>
35 Yaz_Z_Server::Yaz_Z_Server(IYaz_PDU_Observable *the_PDU_Observable)
36 : Yaz_Z_Assoc(the_PDU_Observable)
43 void Yaz_Z_Server::create_databaseRecord (
44 Z_NamePlusRecord *rec, const char *dbname, int format, const void *buf, int len)
46 rec->databaseName = dbname ? odr_strdup (odr_encode(), dbname) : 0;
47 rec->which = Z_NamePlusRecord_databaseRecord;
48 rec->u.databaseRecord = z_ext_record (odr_encode(), format,
49 (const char *) buf, len);
53 * surrogate diagnostic.
55 void Yaz_Z_Server::create_surrogateDiagnostics(
56 Z_NamePlusRecord *rec, const char *dbname, int error, char *const addinfo)
59 int *err = (int *)odr_malloc (odr_encode(), sizeof(*err));
61 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (odr_encode(), sizeof(*drec));
62 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
63 odr_malloc (odr_encode(), sizeof(*dr));
65 bib1.proto = PROTO_Z3950;
66 bib1.oclass = CLASS_DIAGSET;
67 bib1.value = VAL_BIB1;
69 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
71 rec->databaseName = dbname ? odr_strdup (odr_encode(), dbname) : 0;
72 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
73 rec->u.surrogateDiagnostic = drec;
74 drec->which = Z_DiagRec_defaultFormat;
75 drec->u.defaultFormat = dr;
76 dr->diagnosticSetId = odr_oiddup (odr_encode(),
77 oid_ent_to_oid(&bib1, oid));
79 dr->which = Z_DefaultDiagFormat_v2Addinfo;
80 dr->u.v2Addinfo = odr_strdup (odr_encode(), addinfo ? addinfo : "");
83 Z_Records *Yaz_Z_Server::create_nonSurrogateDiagnostics (
84 int error, const char *addinfo)
87 Z_Records *rec = (Z_Records *)
88 odr_malloc (odr_encode(), sizeof(*rec));
91 odr_malloc (odr_encode(), sizeof(*err));
92 Z_DiagRec *drec = (Z_DiagRec *)
93 odr_malloc (odr_encode(), sizeof(*drec));
94 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
95 odr_malloc (odr_encode(), sizeof(*dr));
97 bib1.proto = PROTO_Z3950;
98 bib1.oclass = CLASS_DIAGSET;
99 bib1.value = VAL_BIB1;
102 rec->which = Z_Records_NSD;
103 rec->u.nonSurrogateDiagnostic = dr;
104 dr->diagnosticSetId =
105 odr_oiddup (odr_encode(), oid_ent_to_oid(&bib1, oid));
107 dr->which = Z_DefaultDiagFormat_v2Addinfo;
108 dr->u.v2Addinfo = odr_strdup (odr_encode(), addinfo ? addinfo : "");
112 Z_Records *Yaz_Z_Server::pack_records (const char *resultSetName,
114 Z_RecordComposition *comp,
115 int *next, int *pres,
118 int recno, total_length = 0, toget = xnum, dumped_records = 0;
120 (Z_Records *) odr_malloc (odr_encode(), sizeof(*records));
121 Z_NamePlusRecordList *reclist =
122 (Z_NamePlusRecordList *) odr_malloc (odr_encode(), sizeof(*reclist));
123 Z_NamePlusRecord **list =
124 (Z_NamePlusRecord **) odr_malloc (odr_encode(), sizeof(*list) * toget);
126 records->which = Z_Records_DBOSD;
127 records->u.databaseOrSurDiagnostics = reclist;
128 reclist->num_records = 0;
129 reclist->records = list;
130 *pres = Z_PRES_SUCCESS;
133 yaz_log(LOG_LOG, "Request to pack %d+%d", start, toget);
134 yaz_log(LOG_LOG, "pms=%d, mrs=%d", m_preferredMessageSize,
135 m_maximumRecordSize);
136 for (recno = start; reclist->num_records < toget; recno++)
138 Z_NamePlusRecord *this_rec =
139 (Z_NamePlusRecord *) odr_malloc (odr_encode(), sizeof(*this_rec));
140 this_rec->databaseName = 0;
141 this_rec->which = Z_NamePlusRecord_databaseRecord;
142 this_rec->u.databaseRecord = 0;
146 recv_Z_record (resultSetName, recno, format, comp, this_rec, records);
148 if (records->which != Z_Records_DBOSD)
150 *pres = Z_PRES_FAILURE;
154 if (this_rec->which == Z_NamePlusRecord_databaseRecord &&
155 this_rec->u.databaseRecord == 0)
156 { // handler did not return a record..
157 create_surrogateDiagnostics(this_rec, 0, 14, 0);
160 * we get the number of bytes allocated on the stream before any
161 * allocation done by the backend - this should give us a reasonable
162 * idea of the total size of the data so far.
164 total_length = odr_total(odr_encode()) - dumped_records;
165 this_length = odr_total(odr_encode()) - total_length;
166 yaz_log(LOG_LOG, " fetched record, len=%d, total=%d",
167 this_length, total_length);
168 if (this_length + total_length > m_preferredMessageSize)
170 /* record is small enough, really */
171 if (this_length <= m_preferredMessageSize)
173 yaz_log(LOG_LOG, " Dropped last normal-sized record");
174 *pres = Z_PRES_PARTIAL_2;
177 if (this_length >= m_maximumRecordSize)
178 { /* too big entirely */
179 yaz_log(LOG_LOG, "Record > maxrcdsz");
180 reclist->records[reclist->num_records] = this_rec;
181 create_surrogateDiagnostics(this_rec,
182 this_rec->databaseName, 17, 0);
183 reclist->num_records++;
185 dumped_records += this_length;
188 else /* record can only be fetched by itself */
190 yaz_log(LOG_LOG, " Record > prefmsgsz");
193 yaz_log(LOG_DEBUG, " Dropped it");
194 reclist->records[reclist->num_records] = this_rec;
195 create_surrogateDiagnostics(this_rec,
196 this_rec->databaseName,
198 reclist->num_records++;
199 // *next = freq.last_in_set ? 0 : recno + 1;
201 dumped_records += this_length;
206 reclist->records[reclist->num_records] = this_rec;
207 reclist->num_records++;
213 void Yaz_Z_Server::fetch_via_piggyback (Z_SearchRequest *req,
214 Z_SearchResponse *res)
216 bool_t *sr = (bool_t *)odr_malloc (odr_encode(), sizeof(*sr));
221 Z_RecordComposition comp, *compp = 0;
222 int hits = *res->resultCount;
224 int *nulint = (int *)odr_malloc (odr_encode(), sizeof(*nulint));
227 comp.which = Z_RecordComp_simple;
228 /* how many records does the user agent want, then? */
229 if (hits <= *req->smallSetUpperBound)
232 if ((comp.u.simple = req->smallSetElementSetNames))
235 else if (hits < *req->largeSetLowerBound)
237 toget = *req->mediumSetPresentNumber;
240 if ((comp.u.simple = req->mediumSetElementSetNames))
244 if (toget && !res->records)
246 res->presentStatus = (int *) odr_malloc (odr_encode(), sizeof(int));
247 *res->presentStatus = Z_PRES_SUCCESS;
249 pack_records(req->resultSetName, 1, toget, compp,
250 res->nextResultSetPosition,
252 req->preferredRecordSyntax);
255 if (res->records->which == Z_Records_DBOSD)
256 *res->numberOfRecordsReturned =
257 res->records->u.databaseOrSurDiagnostics->num_records;
258 res->searchStatus = sr;
259 res->resultSetStatus = 0;
264 *res->nextResultSetPosition = 1;
265 res->numberOfRecordsReturned = nulint;
266 res->searchStatus = sr;
267 res->resultSetStatus = 0;
268 res->presentStatus = 0;
272 void Yaz_Z_Server::fetch_via_present (Z_PresentRequest *req,
273 Z_PresentResponse *res)
275 res->records = pack_records (req->resultSetId,*req->resultSetStartPoint,
276 *req->numberOfRecordsRequested,
277 req->recordComposition,
278 res->nextResultSetPosition,
280 req->preferredRecordSyntax);
281 if (res->records->which == Z_Records_DBOSD)
282 *res->numberOfRecordsReturned =
283 res->records->u.databaseOrSurDiagnostics->num_records;
286 void Yaz_Z_Server::recv_Z_PDU (Z_APDU *apdu_request)
288 Z_Options *req, *res;
289 Z_APDU *apdu_response;
290 switch (apdu_request->which)
292 case Z_APDU_initRequest:
293 yaz_log (LOG_LOG, "got InitRequest p=%p", this);
294 apdu_response = create_Z_PDU(Z_APDU_initResponse);
295 req = apdu_request->u.initRequest->options;
296 res = apdu_response->u.initResponse->options;
298 if (ODR_MASK_GET(req, Z_Options_search))
299 ODR_MASK_SET(res, Z_Options_search);
300 if (ODR_MASK_GET(req, Z_Options_present))
301 ODR_MASK_SET(res, Z_Options_present);
302 recv_Z_init (apdu_request->u.initRequest,
303 apdu_response->u.initResponse);
304 m_preferredMessageSize =
305 *apdu_request->u.initRequest->preferredMessageSize;
306 m_maximumRecordSize =
307 *apdu_request->u.initRequest->maximumRecordSize;
308 send_Z_PDU(apdu_response);
310 case Z_APDU_searchRequest:
311 yaz_log (LOG_LOG, "got SearchRequest p=%p", this);
312 apdu_response = create_Z_PDU(Z_APDU_searchResponse);
313 recv_Z_search (apdu_request->u.searchRequest,
314 apdu_response->u.searchResponse);
315 if (!apdu_response->u.searchResponse->records)
317 fetch_via_piggyback(apdu_request->u.searchRequest,
318 apdu_response->u.searchResponse);
320 send_Z_PDU(apdu_response);
322 case Z_APDU_presentRequest:
323 yaz_log (LOG_LOG, "got PresentRequest p=%p", this);
324 apdu_response = create_Z_PDU(Z_APDU_presentResponse);
325 recv_Z_present (apdu_request->u.presentRequest,
326 apdu_response->u.presentResponse);
327 if (!apdu_response->u.presentResponse->records)
328 fetch_via_present(apdu_request->u.presentRequest,
329 apdu_response->u.presentResponse);
330 send_Z_PDU(apdu_response);