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.3 2001-04-25 18:59:30 adam
7 * Added referenceId handling for server.
9 * Revision 1.2 2001/04/04 14:02:49 adam
10 * URSULA / Z-ruth service.
12 * Revision 1.1 2001/03/27 15:02:14 adam
13 * New server facility scheme.
18 #include <yaz++/yaz-z-server.h>
20 Z_Records *Yaz_Facility_Retrieval::pack_records (Yaz_Z_Server *s,
21 const char *resultSetName,
23 Z_RecordComposition *comp,
27 int recno, total_length = 0, toget = xnum, dumped_records = 0;
29 (Z_Records *) odr_malloc (odr_encode(), sizeof(*records));
30 Z_NamePlusRecordList *reclist =
31 (Z_NamePlusRecordList *) odr_malloc (odr_encode(), sizeof(*reclist));
32 Z_NamePlusRecord **list =
33 (Z_NamePlusRecord **) odr_malloc (odr_encode(), sizeof(*list) * toget);
35 records->which = Z_Records_DBOSD;
36 records->u.databaseOrSurDiagnostics = reclist;
37 reclist->num_records = 0;
38 reclist->records = list;
39 *pres = Z_PRES_SUCCESS;
42 yaz_log(LOG_LOG, "Request to pack %d+%d", start, toget);
43 yaz_log(LOG_LOG, "pms=%d, mrs=%d", m_preferredMessageSize,
45 for (recno = start; reclist->num_records < toget; recno++)
47 Z_NamePlusRecord *this_rec =
48 (Z_NamePlusRecord *) odr_malloc (odr_encode(), sizeof(*this_rec));
49 this_rec->databaseName = 0;
50 this_rec->which = Z_NamePlusRecord_databaseRecord;
51 this_rec->u.databaseRecord = 0;
55 sr_record (resultSetName, recno, format, comp, this_rec, records);
57 if (records->which != Z_Records_DBOSD)
59 *pres = Z_PRES_FAILURE;
63 if (this_rec->which == Z_NamePlusRecord_databaseRecord &&
64 this_rec->u.databaseRecord == 0)
65 { // handler did not return a record..
66 create_surrogateDiagnostics(odr_encode(), this_rec, 0, 14, 0);
69 * we get the number of bytes allocated on the stream before any
70 * allocation done by the backend - this should give us a reasonable
71 * idea of the total size of the data so far.
73 total_length = odr_total(odr_encode()) - dumped_records;
74 this_length = odr_total(odr_encode()) - total_length;
75 yaz_log(LOG_LOG, " fetched record, len=%d, total=%d",
76 this_length, total_length);
77 if (this_length + total_length > m_preferredMessageSize)
79 /* record is small enough, really */
80 if (this_length <= m_preferredMessageSize)
82 yaz_log(LOG_LOG, " Dropped last normal-sized record");
83 *pres = Z_PRES_PARTIAL_2;
86 if (this_length >= m_maximumRecordSize)
87 { /* too big entirely */
88 yaz_log(LOG_LOG, "Record > maxrcdsz");
89 reclist->records[reclist->num_records] = this_rec;
90 create_surrogateDiagnostics(odr_encode(), this_rec,
91 this_rec->databaseName, 17, 0);
92 reclist->num_records++;
94 dumped_records += this_length;
97 else /* record can only be fetched by itself */
99 yaz_log(LOG_LOG, " Record > prefmsgsz");
102 yaz_log(LOG_DEBUG, " Dropped it");
103 reclist->records[reclist->num_records] = this_rec;
104 create_surrogateDiagnostics(odr_encode(), this_rec,
105 this_rec->databaseName,
107 reclist->num_records++;
108 // *next = freq.last_in_set ? 0 : recno + 1;
110 dumped_records += this_length;
115 reclist->records[reclist->num_records] = this_rec;
116 reclist->num_records++;
122 void Yaz_Facility_Retrieval::fetch_via_piggyback (Yaz_Z_Server *s,
123 Z_SearchRequest *req,
124 Z_SearchResponse *res)
126 bool_t *sr = (bool_t *)odr_malloc (odr_encode(), sizeof(*sr));
131 Z_RecordComposition comp, *compp = 0;
132 int hits = *res->resultCount;
134 int *nulint = (int *)odr_malloc (odr_encode(), sizeof(*nulint));
137 comp.which = Z_RecordComp_simple;
138 /* how many records does the user agent want, then? */
139 if (hits <= *req->smallSetUpperBound)
142 if ((comp.u.simple = req->smallSetElementSetNames))
145 else if (hits < *req->largeSetLowerBound)
147 toget = *req->mediumSetPresentNumber;
150 if ((comp.u.simple = req->mediumSetElementSetNames))
154 if (toget && !res->records)
156 res->presentStatus = (int *) odr_malloc (odr_encode(), sizeof(int));
157 *res->presentStatus = Z_PRES_SUCCESS;
159 pack_records(s, req->resultSetName, 1, toget, compp,
160 res->nextResultSetPosition,
162 req->preferredRecordSyntax);
165 if (res->records->which == Z_Records_DBOSD)
166 *res->numberOfRecordsReturned =
167 res->records->u.databaseOrSurDiagnostics->num_records;
168 res->searchStatus = sr;
169 res->resultSetStatus = 0;
174 *res->nextResultSetPosition = 1;
175 res->numberOfRecordsReturned = nulint;
176 res->searchStatus = sr;
177 res->resultSetStatus = 0;
178 res->presentStatus = 0;
182 void Yaz_Facility_Retrieval::fetch_via_present (Yaz_Z_Server *s,
183 Z_PresentRequest *req,
184 Z_PresentResponse *res)
187 pack_records (s, req->resultSetId,*req->resultSetStartPoint,
188 *req->numberOfRecordsRequested,
189 req->recordComposition,
190 res->nextResultSetPosition,
192 req->preferredRecordSyntax);
193 if (res->records->which == Z_Records_DBOSD)
194 *res->numberOfRecordsReturned =
195 res->records->u.databaseOrSurDiagnostics->num_records;
198 int Yaz_Facility_Retrieval::init(Yaz_Z_Server *s, Z_InitRequest *initRequest,
199 Z_InitResponse *initResponse)
201 Z_Options *req = initRequest->options;
202 Z_Options *res = initResponse->options;
204 if (ODR_MASK_GET(req, Z_Options_search))
205 ODR_MASK_SET(res, Z_Options_search);
206 if (ODR_MASK_GET(req, Z_Options_present))
207 ODR_MASK_SET(res, Z_Options_present);
208 m_preferredMessageSize = *initRequest->preferredMessageSize;
209 m_maximumRecordSize = *initRequest->maximumRecordSize;
210 return sr_init (initRequest, initResponse);
213 ODR Yaz_Facility_Retrieval::odr_encode()
218 ODR Yaz_Facility_Retrieval::odr_decode()
223 int Yaz_Facility_Retrieval::recv(Yaz_Z_Server *s, Z_APDU *apdu_request)
225 Z_APDU *apdu_response;
226 m_odr_encode = s->odr_encode();
227 m_odr_decode = s->odr_decode();
228 switch (apdu_request->which)
230 case Z_APDU_searchRequest:
231 yaz_log (LOG_LOG, "got SearchRequest p=%p", this);
232 apdu_response = s->create_Z_PDU(Z_APDU_searchResponse);
233 s->transfer_referenceId(apdu_request, apdu_response);
234 sr_search (apdu_request->u.searchRequest,
235 apdu_response->u.searchResponse);
236 if (!apdu_response->u.searchResponse->records)
238 fetch_via_piggyback(s, apdu_request->u.searchRequest,
239 apdu_response->u.searchResponse);
241 s->send_Z_PDU(apdu_response);
243 case Z_APDU_presentRequest:
244 yaz_log (LOG_LOG, "got PresentRequest p=%p", this);
245 apdu_response = s->create_Z_PDU(Z_APDU_presentResponse);
246 s->transfer_referenceId(apdu_request, apdu_response);
247 sr_present (apdu_request->u.presentRequest,
248 apdu_response->u.presentResponse);
249 if (!apdu_response->u.presentResponse->records)
250 fetch_via_present(s, apdu_request->u.presentRequest,
251 apdu_response->u.presentResponse);
252 s->send_Z_PDU(apdu_response);