1 <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>5. The Backend Functions</title><meta name="generator" content="DocBook XSL Stylesheets V1.73.2"><link rel="start" href="index.html" title="YAZ User's Guide and Reference"><link rel="up" href="server.html" title="Chapter 4. Generic server"><link rel="prev" href="server.main.html" title="4. Your main() Routine"><link rel="next" href="server.invocation.html" title="6. Application Invocation"></head><body><link rel="stylesheet" type="text/css" href="common/style1.css"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. The Backend Functions</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="server.main.html">Prev</a> </td><th width="60%" align="center">Chapter 4. Generic server</th><td width="20%" align="right"> <a accesskey="n" href="server.invocation.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="server.backendfunctions"></a>5. The Backend Functions</h2></div></div></div><p>
2 For each service of the protocol, the backend interface declares one or
3 two functions. You are required to provide implementations of the
4 functions representing the services that you wish to implement.
5 </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="server.init"></a>5.1. Init</h3></div></div></div><pre class="synopsis">
6 bend_initresult (*bend_init)(bend_initrequest *r);
8 This handler is called once for each new connection request, after
9 a new process/thread has been created, and an Initialize Request has
10 been received from the client. The pointer to the
11 <code class="function">bend_init</code> handler is passed in the call to
12 <code class="function">statserv_start</code>.
14 This handler is also called when operating in SRU mode - when
15 a connection has been made (even though SRU does not offer
18 Unlike previous versions of YAZ, the <code class="function">bend_init</code> also
19 serves as a handler that defines the Z39.50 services that the backend
20 wish to support. Pointers to <span class="emphasis"><em>all</em></span> service handlers,
21 including search - and fetch must be specified here in this handler.
23 The request - and result structures are defined as
24 </p><pre class="synopsis">
25 typedef struct bend_initrequest
27 /** \brief user/name/password to be read */
28 Z_IdAuthentication *auth;
29 /** \brief encoding stream (for results) */
31 /** \brief printing stream */
33 /** \brief decoding stream (use stream for results) */
35 /** \brief reference ID */
36 Z_ReferenceId *referenceId;
37 /** \brief peer address of client */
40 /** \brief character set and language negotiation
42 see include/yaz/z-charneg.h
44 Z_CharSetandLanguageNegotiation *charneg_request;
46 /** \brief character negotiation response */
47 Z_External *charneg_response;
49 /** \brief character set (encoding) for query terms
51 This is NULL by default. It should be set to the native character
52 set that the backend assumes for query terms */
55 /** \brief whehter query_charset also applies to recors
57 Is 0 (No) by default. Set to 1 (yes) if records is in the same
58 character set as queries. If in doubt, use 0 (No).
60 int records_in_same_charset;
62 char *implementation_id;
63 char *implementation_name;
64 char *implementation_version;
66 /** \brief Z39.50 sort handler */
67 int (*bend_sort)(void *handle, bend_sort_rr *rr);
68 /** \brief SRU/Z39.50 search handler */
69 int (*bend_search)(void *handle, bend_search_rr *rr);
70 /** \brief SRU/Z39.50 fetch handler */
71 int (*bend_fetch)(void *handle, bend_fetch_rr *rr);
72 /** \brief SRU/Z39.50 present handler */
73 int (*bend_present)(void *handle, bend_present_rr *rr);
74 /** \brief Z39.50 extended services handler */
75 int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
76 /** \brief Z39.50 delete result set handler */
77 int (*bend_delete)(void *handle, bend_delete_rr *rr);
78 /** \brief Z39.50 scan handler */
79 int (*bend_scan)(void *handle, bend_scan_rr *rr);
80 /** \brief Z39.50 segment facility handler */
81 int (*bend_segment)(void *handle, bend_segment_rr *rr);
82 /** \brief SRU explain handler */
83 int (*bend_explain)(void *handle, bend_explain_rr *rr);
84 /** \brief SRU scan handler */
85 int (*bend_srw_scan)(void *handle, bend_scan_rr *rr);
86 /** \brief SRU record update handler */
87 int (*bend_srw_update)(void *handle, bend_update_rr *rr);
91 typedef struct bend_initresult
93 int errcode; /* 0==OK */
94 char *errstring; /* system error string or NULL */
95 void *handle; /* private handle to the backend module */
98 In general, the server frontend expects that the
99 <code class="literal">bend_*result</code> pointer that you return is valid at
100 least until the next call to a <code class="literal">bend_* function</code>.
101 This applies to all of the functions described herein. The parameter
102 structure passed to you in the call belongs to the server frontend, and
103 you should not make assumptions about its contents after the current
104 function call has completed. In other words, if you want to retain any
105 of the contents of a request structure, you should copy them.
107 The <code class="literal">errcode</code> should be zero if the initialization of
108 the backend went well. Any other value will be interpreted as an error.
109 The <code class="literal">errstring</code> isn't used in the current version, but
110 one option would be to stick it in the initResponse as a VisibleString.
111 The <code class="literal">handle</code> is the most important parameter. It should
112 be set to some value that uniquely identifies the current session to
113 the backend implementation. It is used by the frontend server in any
114 future calls to a backend function.
115 The typical use is to set it to point to a dynamically allocated state
116 structure that is private to your backend module.
118 The <code class="literal">auth</code> member holds the authentication information
119 part of the Z39.50 Initialize Request. Interpret this if your serves
120 requires authentication.
122 The members <code class="literal">peer_name</code>,
123 <code class="literal">implementation_id</code>,
124 <code class="literal">implementation_name</code> and
125 <code class="literal">implementation_version</code> holds
126 DNS of client, ID of implementor, name
127 of client (Z39.50) implementation - and version.
129 The <code class="literal">bend_</code> - members are set to NULL when
130 <code class="function">bend_init</code> is called. Modify the pointers by
131 setting them to point to backend functions.
132 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="server.search.retrieve"></a>5.2. Search and Retrieve</h3></div></div></div><p>We now describe the handlers that are required to support search -
133 and retrieve. You must support two functions - one for search - and one
134 for fetch (retrieval of one record). If desirable you can provide a
135 third handler which is called when a present request is received which
136 allows you to optimize retrieval of multiple-records.
137 </p><pre class="synopsis">
138 int (*bend_search) (void *handle, bend_search_rr *rr);
141 char *setname; /* name to give to this set */
142 int replace_set; /* replace set, if it already exists */
143 int num_bases; /* number of databases in list */
144 char **basenames; /* databases to search */
145 Z_ReferenceId *referenceId;/* reference ID */
146 Z_Query *query; /* query structure */
147 ODR stream; /* encode stream */
148 ODR decode; /* decode stream */
149 ODR print; /* print stream */
151 bend_request request;
152 bend_association association;
154 int hits; /* number of hits */
155 int errcode; /* 0==OK */
156 char *errstring; /* system error string or NULL */
157 Z_OtherInformation *search_info; /* additional search info */
158 char *srw_sortKeys; /* holds SRU/SRW sortKeys info */
159 char *srw_setname; /* holds SRU/SRW generated resultsetID */
160 int *srw_setnameIdleTime; /* holds SRU/SRW life-time */
161 int estimated_hit_count; /* if hit count is estimated */
162 int partial_resultset; /* if result set is partial */
165 The <code class="function">bend_search</code> handler is a fairly close
166 approximation of a protocol Z39.50 Search Request - and Response PDUs
167 The <code class="literal">setname</code> is the resultSetName from the protocol.
168 You are required to establish a mapping between the set name and whatever
169 your backend database likes to use.
170 Similarly, the <code class="literal">replace_set</code> is a boolean value
171 corresponding to the resultSetIndicator field in the protocol.
172 <code class="literal">num_bases/basenames</code> is a length of/array of character
173 pointers to the database names provided by the client.
174 The <code class="literal">query</code> is the full query structure as defined in
175 the protocol ASN.1 specification.
176 It can be either of the possible query types, and it's up to you to
177 determine if you can handle the provided query type.
178 Rather than reproduce the C interface here, we'll refer you to the
179 structure definitions in the file
180 <code class="filename">include/yaz/z-core.h</code>. If you want to look at the
181 attributeSetId OID of the RPN query, you can either match it against
182 your own internal tables, or you can use the
183 <code class="literal">oid_getentbyoid</code> function provided by YAZ.
185 The structure contains a number of hits, and an
186 <code class="literal">errcode/errstring</code> pair. If an error occurs
187 during the search, or if you're unhappy with the request, you should
188 set the errcode to a value from the BIB-1 diagnostic set. The value
189 will then be returned to the user in a nonsurrogate diagnostic record
190 in the response. The <code class="literal">errstring</code>, if provided, will
191 go in the addinfo field. Look at the protocol definition for the
192 defined error codes, and the suggested uses of the addinfo field.
194 The <code class="function">bend_search</code> handler is also called when
195 the frontend server receives a SRU SearchRetrieveRequest.
196 For SRU, a CQL query is usually provided by the client.
197 The CQL query is available as part of <code class="literal">Z_Query</code>
198 structure (note that CQL is now part of Z39.50 via an external).
199 To support CQL in existing implementations that only do Type-1,
200 we refer to the CQL-to-PQF tool described
201 <a class="link" href="tools.html#cql.to.pqf" title="1.3.3. CQL to PQF conversion">here</a>.
203 To maintain backwards compatibility, the frontend server
204 of yaz always assume that error codes are BIB-1 diagnostics.
205 For SRU operation, a Bib-1 diagnostic code is mapped to
207 </p><pre class="synopsis">
208 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
210 typedef struct bend_fetch_rr {
211 char *setname; /* set name */
212 int number; /* record number */
213 Z_ReferenceId *referenceId;/* reference ID */
214 Odr_oid *request_format; /* format, transfer syntax (OID) */
215 Z_RecordComposition *comp; /* Formatting instructions */
216 ODR stream; /* encoding stream - memory source if req */
217 ODR print; /* printing stream */
219 char *basename; /* name of database that provided record */
220 int len; /* length of record or -1 if structured */
221 char *record; /* record */
222 int last_in_set; /* is it? */
223 Odr_oid *output_format; /* response format/syntax (OID) */
224 int errcode; /* 0==success */
225 char *errstring; /* system error string or NULL */
226 int surrogate_flag; /* surrogate diagnostic */
227 char *schema; /* string record schema input/output */
230 The frontend server calls the <code class="function">bend_fetch</code> handler
231 when it needs database records to fulfill a Z39.50 Search Request, a
232 Z39.50 Present Request or a SRU SearchRetrieveRequest.
233 The <code class="literal">setname</code> is simply the name of the result set
234 that holds the reference to the desired record.
235 The <code class="literal">number</code> is the offset into the set (with 1
236 being the first record in the set). The <code class="literal">format</code> field
237 is the record format requested by the client (See
238 <a class="xref" href="asn.oid.html" title="3. Object Identifiers (YAZ 2)">Section 3, “Object Identifiers (YAZ 2)”</a>).
239 A value of NULL for <code class="literal">format</code> indicates that the
240 client did not request a specific format.
241 The <code class="literal">stream</code> argument is an <acronym class="acronym">ODR</acronym> stream which
242 should be used for allocating space for structured data records.
243 The stream will be reset when all records have been assembled, and
244 the response package has been transmitted.
245 For unstructured data, the backend is responsible for maintaining a
246 static or dynamic buffer for the record between calls.
248 If a SRU SearchRetrieveRequest is received by the frontend server,
249 the <code class="literal">referenceId</code> is NULL and the
250 <code class="literal">format</code> (transfer syntax) is the OID for XML.
251 The schema for SRU is stored in both the
252 <code class="literal">Z_RecordComposition</code>
253 structure and <code class="literal">schema</code> (simple string).
255 In the structure, the <code class="literal">basename</code> is the name of the
256 database that holds the
257 record. <code class="literal">len</code> is the length of the record returned, in
258 bytes, and <code class="literal">record</code> is a pointer to the record.
259 <code class="literal">last_in_set</code> should be nonzero only if the record
260 returned is the last one in the given result set.
261 <code class="literal">errcode</code> and <code class="literal">errstring</code>, if
262 given, will be interpreted as a global error pertaining to the
263 set, and will be returned in a non-surrogate-diagnostic.
264 If you wish to return the error as a surrogate-diagnostic
265 (local error) you can do this by setting
266 <code class="literal">surrogate_flag</code> to 1 also.
268 If the <code class="literal">len</code> field has the value -1, then
269 <code class="literal">record</code> is assumed to point to a constructed data
270 type. The <code class="literal">format</code> field will be used to determine
271 which encoder should be used to serialize the data.
272 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
273 If your backend generates structured records, it should use
274 <code class="function">odr_malloc()</code> on the provided stream for allocating
275 data: This allows the frontend server to keep track of the record sizes.
277 The <code class="literal">format</code> field is mapped to an object identifier
278 in the direct reference of the resulting EXTERNAL representation
280 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
281 The current version of YAZ only supports the direct reference mode.
282 </p></div><pre class="synopsis">
283 int (*bend_present) (void *handle, bend_present_rr *rr);
286 char *setname; /* set name */
288 int number; /* record number */
289 Odr_oid *format; /* format, transfer syntax (OID) */
290 Z_ReferenceId *referenceId;/* reference ID */
291 Z_RecordComposition *comp; /* Formatting instructions */
292 ODR stream; /* encoding stream - memory source if required */
293 ODR print; /* printing stream */
294 bend_request request;
295 bend_association association;
297 int hits; /* number of hits */
298 int errcode; /* 0==OK */
299 char *errstring; /* system error string or NULL */
302 The <code class="function">bend_present</code> handler is called when
303 the server receives a Z39.50 Present Request.
304 The <code class="literal">setname</code>,
305 <code class="literal">start</code> and <code class="literal">number</code> is the
306 name of the result set - start position - and number of records to
307 be retrieved respectively. <code class="literal">format</code> and
308 <code class="literal">comp</code> is the preferred transfer syntax and element
309 specifications of the present request.
311 Note that this is handler serves as a supplement for
312 <code class="function">bend_fetch</code> and need not to be defined in order to
313 support search - and retrieve.
314 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="server.delete"></a>5.3. Delete</h3></div></div></div><p>
315 For back-ends that supports delete of a result set only one handler
317 </p><pre class="synopsis">
318 int (*bend_delete)(void *handle, bend_delete_rr *rr);
320 typedef struct bend_delete_rr {
324 Z_ReferenceId *referenceId;
325 int delete_status; /* status for the whole operation */
326 int *statuses; /* status each set - indexed as setnames */
330 </pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
331 The delete set function definition is rather primitive, mostly because
332 we have had no practical need for it as of yet. If someone wants
333 to provide a full delete service, we'd be happy to add the
334 extra parameters that are required. Are there clients out there
335 that will actually delete sets they no longer need?
336 </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="server.scan"></a>5.4. Scan</h3></div></div></div><p>
337 For servers that wish to offer the scan service one handler
339 </p><pre class="synopsis">
340 int (*bend_scan)(void *handle, bend_scan_rr *rr);
343 BEND_SCAN_SUCCESS, /* ok */
344 BEND_SCAN_PARTIAL /* not all entries could be found */
347 typedef struct bend_scan_rr {
348 int num_bases; /* number of elements in databaselist */
349 char **basenames; /* databases to search */
350 Odr_oid *attributeset;
351 Z_ReferenceId *referenceId; /* reference ID */
352 Z_AttributesPlusTerm *term;
353 ODR stream; /* encoding stream - memory source if required */
354 ODR print; /* printing stream */
356 int *step_size; /* step size */
357 int term_position; /* desired index of term in result list/returned */
358 int num_entries; /* number of entries requested/returned */
360 /* scan term entries. The called handler does not have
361 to allocate this. Size of entries is num_entries (see above) */
362 struct scan_entry *entries;
363 bend_scan_status status;
366 char *scanClause; /* CQL scan clause */
367 char *setname; /* Scan in result set (NULL if omitted) */
370 This backend server handles both Z39.50 scan
371 and SRU scan. In order for a handler to distinguish between SRU (CQL) scan
372 Z39.50 Scan , it must check for a non-NULL value of
373 <code class="literal">scanClause</code>.
374 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
375 if designed today, it would be a choice using a union or similar,
376 but that would break binary compatibility with existing servers.
377 </p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="server.main.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="server.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="server.invocation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Your main() Routine </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Application Invocation</td></tr></table></div></body></html>