2 * Copyright (c) 2000-2001, Index Data.
3 * See the file LICENSE for details.
5 * $Log: yaz-z-server-sr.cpp,v $
6 * Revision 1.1 2001-03-27 15:02:14 adam
7 * New server facility scheme.
12 #include <yaz++/yaz-z-server.h>
17 void Yaz_Facility_Retrieval::create_databaseRecord (
18 Z_NamePlusRecord *rec, const char *dbname, int format,
19 const void *buf, int len)
21 rec->databaseName = dbname ? odr_strdup (m_odr, dbname) : 0;
22 rec->which = Z_NamePlusRecord_databaseRecord;
23 rec->u.databaseRecord = z_ext_record (m_odr, format,
24 (const char *) buf, len);
28 * surrogate diagnostic.
30 void Yaz_Facility_Retrieval::create_surrogateDiagnostics(
31 Z_NamePlusRecord *rec, const char *dbname, int error, char *const addinfo)
34 int *err = (int *)odr_malloc (m_odr, sizeof(*err));
36 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (m_odr, sizeof(*drec));
37 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
38 odr_malloc (m_odr, sizeof(*dr));
40 bib1.proto = PROTO_Z3950;
41 bib1.oclass = CLASS_DIAGSET;
42 bib1.value = VAL_BIB1;
44 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
46 rec->databaseName = dbname ? odr_strdup (m_odr, dbname) : 0;
47 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
48 rec->u.surrogateDiagnostic = drec;
49 drec->which = Z_DiagRec_defaultFormat;
50 drec->u.defaultFormat = dr;
51 dr->diagnosticSetId = odr_oiddup (m_odr,
52 oid_ent_to_oid(&bib1, oid));
54 dr->which = Z_DefaultDiagFormat_v2Addinfo;
55 dr->u.v2Addinfo = odr_strdup (m_odr, addinfo ? addinfo : "");
58 Z_Records *Yaz_Facility_Retrieval::create_nonSurrogateDiagnostics (
59 int error, const char *addinfo)
62 Z_Records *rec = (Z_Records *)
63 odr_malloc (m_odr, sizeof(*rec));
66 odr_malloc (m_odr, sizeof(*err));
67 Z_DiagRec *drec = (Z_DiagRec *)
68 odr_malloc (m_odr, sizeof(*drec));
69 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
70 odr_malloc (m_odr, sizeof(*dr));
72 bib1.proto = PROTO_Z3950;
73 bib1.oclass = CLASS_DIAGSET;
74 bib1.value = VAL_BIB1;
77 rec->which = Z_Records_NSD;
78 rec->u.nonSurrogateDiagnostic = dr;
80 odr_oiddup (m_odr, oid_ent_to_oid(&bib1, oid));
82 dr->which = Z_DefaultDiagFormat_v2Addinfo;
83 dr->u.v2Addinfo = odr_strdup (m_odr, addinfo ? addinfo : "");
87 Z_Records *Yaz_Facility_Retrieval::pack_records (const char *resultSetName,
89 Z_RecordComposition *comp,
93 int recno, total_length = 0, toget = xnum, dumped_records = 0;
95 (Z_Records *) odr_malloc (m_odr, sizeof(*records));
96 Z_NamePlusRecordList *reclist =
97 (Z_NamePlusRecordList *) odr_malloc (m_odr, sizeof(*reclist));
98 Z_NamePlusRecord **list =
99 (Z_NamePlusRecord **) odr_malloc (m_odr, sizeof(*list) * toget);
101 records->which = Z_Records_DBOSD;
102 records->u.databaseOrSurDiagnostics = reclist;
103 reclist->num_records = 0;
104 reclist->records = list;
105 *pres = Z_PRES_SUCCESS;
108 yaz_log(LOG_LOG, "Request to pack %d+%d", start, toget);
109 yaz_log(LOG_LOG, "pms=%d, mrs=%d", m_preferredMessageSize,
110 m_maximumRecordSize);
111 for (recno = start; reclist->num_records < toget; recno++)
113 Z_NamePlusRecord *this_rec =
114 (Z_NamePlusRecord *) odr_malloc (m_odr, sizeof(*this_rec));
115 this_rec->databaseName = 0;
116 this_rec->which = Z_NamePlusRecord_databaseRecord;
117 this_rec->u.databaseRecord = 0;
121 sr_record (resultSetName, recno, format, comp, this_rec, records);
123 if (records->which != Z_Records_DBOSD)
125 *pres = Z_PRES_FAILURE;
129 if (this_rec->which == Z_NamePlusRecord_databaseRecord &&
130 this_rec->u.databaseRecord == 0)
131 { // handler did not return a record..
132 create_surrogateDiagnostics(this_rec, 0, 14, 0);
135 * we get the number of bytes allocated on the stream before any
136 * allocation done by the backend - this should give us a reasonable
137 * idea of the total size of the data so far.
139 total_length = odr_total(m_odr) - dumped_records;
140 this_length = odr_total(m_odr) - total_length;
141 yaz_log(LOG_LOG, " fetched record, len=%d, total=%d",
142 this_length, total_length);
143 if (this_length + total_length > m_preferredMessageSize)
145 /* record is small enough, really */
146 if (this_length <= m_preferredMessageSize)
148 yaz_log(LOG_LOG, " Dropped last normal-sized record");
149 *pres = Z_PRES_PARTIAL_2;
152 if (this_length >= m_maximumRecordSize)
153 { /* too big entirely */
154 yaz_log(LOG_LOG, "Record > maxrcdsz");
155 reclist->records[reclist->num_records] = this_rec;
156 create_surrogateDiagnostics(this_rec,
157 this_rec->databaseName, 17, 0);
158 reclist->num_records++;
160 dumped_records += this_length;
163 else /* record can only be fetched by itself */
165 yaz_log(LOG_LOG, " Record > prefmsgsz");
168 yaz_log(LOG_DEBUG, " Dropped it");
169 reclist->records[reclist->num_records] = this_rec;
170 create_surrogateDiagnostics(this_rec,
171 this_rec->databaseName,
173 reclist->num_records++;
174 // *next = freq.last_in_set ? 0 : recno + 1;
176 dumped_records += this_length;
181 reclist->records[reclist->num_records] = this_rec;
182 reclist->num_records++;
188 void Yaz_Facility_Retrieval::fetch_via_piggyback (Z_SearchRequest *req,
189 Z_SearchResponse *res)
191 bool_t *sr = (bool_t *)odr_malloc (m_odr, sizeof(*sr));
196 Z_RecordComposition comp, *compp = 0;
197 int hits = *res->resultCount;
199 int *nulint = (int *)odr_malloc (m_odr, sizeof(*nulint));
202 comp.which = Z_RecordComp_simple;
203 /* how many records does the user agent want, then? */
204 if (hits <= *req->smallSetUpperBound)
207 if ((comp.u.simple = req->smallSetElementSetNames))
210 else if (hits < *req->largeSetLowerBound)
212 toget = *req->mediumSetPresentNumber;
215 if ((comp.u.simple = req->mediumSetElementSetNames))
219 if (toget && !res->records)
221 res->presentStatus = (int *) odr_malloc (m_odr, sizeof(int));
222 *res->presentStatus = Z_PRES_SUCCESS;
224 pack_records(req->resultSetName, 1, toget, compp,
225 res->nextResultSetPosition,
227 req->preferredRecordSyntax);
230 if (res->records->which == Z_Records_DBOSD)
231 *res->numberOfRecordsReturned =
232 res->records->u.databaseOrSurDiagnostics->num_records;
233 res->searchStatus = sr;
234 res->resultSetStatus = 0;
239 *res->nextResultSetPosition = 1;
240 res->numberOfRecordsReturned = nulint;
241 res->searchStatus = sr;
242 res->resultSetStatus = 0;
243 res->presentStatus = 0;
247 void Yaz_Facility_Retrieval::fetch_via_present (Z_PresentRequest *req,
248 Z_PresentResponse *res)
250 res->records = pack_records (req->resultSetId,*req->resultSetStartPoint,
251 *req->numberOfRecordsRequested,
252 req->recordComposition,
253 res->nextResultSetPosition,
255 req->preferredRecordSyntax);
256 if (res->records->which == Z_Records_DBOSD)
257 *res->numberOfRecordsReturned =
258 res->records->u.databaseOrSurDiagnostics->num_records;
261 ODR Yaz_Facility_Retrieval::odr_encode()
266 int Yaz_Facility_Retrieval::init(Yaz_Z_Server *s, Z_InitRequest *initRequest,
267 Z_InitResponse *initResponse)
269 Z_Options *req = initRequest->options;
270 Z_Options *res = initResponse->options;
272 if (ODR_MASK_GET(req, Z_Options_search))
273 ODR_MASK_SET(res, Z_Options_search);
274 if (ODR_MASK_GET(req, Z_Options_present))
275 ODR_MASK_SET(res, Z_Options_present);
276 m_preferredMessageSize = *initRequest->preferredMessageSize;
277 m_maximumRecordSize = *initRequest->maximumRecordSize;
278 return sr_init (initRequest, initResponse);
281 int Yaz_Facility_Retrieval::recv(Yaz_Z_Server *s, Z_APDU *apdu_request)
283 Z_APDU *apdu_response;
284 m_odr = s->odr_encode();
285 switch (apdu_request->which)
287 case Z_APDU_searchRequest:
288 yaz_log (LOG_LOG, "got SearchRequest p=%p", this);
289 apdu_response = s->create_Z_PDU(Z_APDU_searchResponse);
290 sr_search (apdu_request->u.searchRequest,
291 apdu_response->u.searchResponse);
292 if (!apdu_response->u.searchResponse->records)
294 fetch_via_piggyback(apdu_request->u.searchRequest,
295 apdu_response->u.searchResponse);
297 s->send_Z_PDU(apdu_response);
299 case Z_APDU_presentRequest:
300 yaz_log (LOG_LOG, "got PresentRequest p=%p", this);
301 apdu_response = s->create_Z_PDU(Z_APDU_presentResponse);
302 sr_present (apdu_request->u.presentRequest,
303 apdu_response->u.presentResponse);
304 if (!apdu_response->u.presentResponse->records)
305 fetch_via_present(apdu_request->u.presentRequest,
306 apdu_response->u.presentResponse);
307 s->send_Z_PDU(apdu_response);