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.70.1"><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="id2570826"></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 Z_IdAuthentication *auth;
28 ODR stream; /* encoding stream */
29 ODR print; /* printing stream */
30 Z_ReferenceId *referenceId;/* reference ID */
31 char *peer_name; /* dns host of peer (client) */
33 char *implementation_id;
34 char *implementation_name;
35 char *implementation_version;
36 int (*bend_sort) (void *handle, bend_sort_rr *rr);
37 int (*bend_search) (void *handle, bend_search_rr *rr);
38 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
39 int (*bend_present) (void *handle, bend_present_rr *rr);
40 int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
41 int (*bend_delete)(void *handle, bend_delete_rr *rr);
42 int (*bend_scan)(void *handle, bend_scan_rr *rr);
43 int (*bend_segment)(void *handle, bend_segment_rr *rr);
45 ODR decode; /* decoding stream */
46 /* character set and language negotiation - see include/yaz/z-charneg.h */
47 Z_CharSetandLanguageNegotiation *charneg_request;
48 Z_External *charneg_response;
49 int (*bend_srw_explain)(void *handle, bend_explain_rr *rr);
50 int (*bend_srw_scan)(void *handle, bend_scan_rr *rr);
53 typedef struct bend_initresult
55 int errcode; /* 0==OK */
56 char *errstring; /* system error string or NULL */
57 void *handle; /* private handle to the backend module */
60 In general, the server frontend expects that the
61 <code class="literal">bend_*result</code> pointer that you return is valid at
62 least until the next call to a <code class="literal">bend_* function</code>.
63 This applies to all of the functions described herein. The parameter
64 structure passed to you in the call belongs to the server frontend, and
65 you should not make assumptions about its contents after the current
66 function call has completed. In other words, if you want to retain any
67 of the contents of a request structure, you should copy them.
69 The <code class="literal">errcode</code> should be zero if the initialization of
70 the backend went well. Any other value will be interpreted as an error.
71 The <code class="literal">errstring</code> isn't used in the current version, but
72 one option would be to stick it in the initResponse as a VisibleString.
73 The <code class="literal">handle</code> is the most important parameter. It should
74 be set to some value that uniquely identifies the current session to
75 the backend implementation. It is used by the frontend server in any
76 future calls to a backend function.
77 The typical use is to set it to point to a dynamically allocated state
78 structure that is private to your backend module.
80 The <code class="literal">auth</code> member holds the authentication information
81 part of the Z39.50 Initialize Request. Interpret this if your serves
82 requires authentication.
84 The members <code class="literal">peer_name</code>,
85 <code class="literal">implementation_id</code>,
86 <code class="literal">implementation_name</code> and
87 <code class="literal">implementation_version</code> holds
88 DNS of client, ID of implementor, name
89 of client (Z39.50) implementation - and version.
91 The <code class="literal">bend_</code> - members are set to NULL when
92 <code class="function">bend_init</code> is called. Modify the pointers by
93 setting them to point to backend functions.
94 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2571032"></a>5.2. Search and retrieve</h3></div></div></div><p>We now describe the handlers that are required to support search -
95 and retrieve. You must support two functions - one for search - and one
96 for fetch (retrieval of one record). If desirable you can provide a
97 third handler which is called when a present request is received which
98 allows you to optimize retrieval of multiple-records.
99 </p><pre class="synopsis">
100 int (*bend_search) (void *handle, bend_search_rr *rr);
103 char *setname; /* name to give to this set */
104 int replace_set; /* replace set, if it already exists */
105 int num_bases; /* number of databases in list */
106 char **basenames; /* databases to search */
107 Z_ReferenceId *referenceId;/* reference ID */
108 Z_Query *query; /* query structure */
109 ODR stream; /* encode stream */
110 ODR decode; /* decode stream */
111 ODR print; /* print stream */
113 bend_request request;
114 bend_association association;
116 int hits; /* number of hits */
117 int errcode; /* 0==OK */
118 char *errstring; /* system error string or NULL */
119 Z_OtherInformation *search_info;
122 The <code class="function">bend_search</code> handler is a fairly close
123 approximation of a protocol Z39.50 Search Request - and Response PDUs
124 The <code class="literal">setname</code> is the resultSetName from the protocol.
125 You are required to establish a mapping between the set name and whatever
126 your backend database likes to use.
127 Similarly, the <code class="literal">replace_set</code> is a boolean value
128 corresponding to the resultSetIndicator field in the protocol.
129 <code class="literal">num_bases/basenames</code> is a length of/array of character
130 pointers to the database names provided by the client.
131 The <code class="literal">query</code> is the full query structure as defined in
132 the protocol ASN.1 specification.
133 It can be either of the possible query types, and it's up to you to
134 determine if you can handle the provided query type.
135 Rather than reproduce the C interface here, we'll refer you to the
136 structure definitions in the file
137 <code class="filename">include/yaz/z-core.h</code>. If you want to look at the
138 attributeSetId OID of the RPN query, you can either match it against
139 your own internal tables, or you can use the
140 <code class="literal">oid_getentbyoid</code> function provided by YAZ.
142 The structure contains a number of hits, and an
143 <code class="literal">errcode/errstring</code> pair. If an error occurs
144 during the search, or if you're unhappy with the request, you should
145 set the errcode to a value from the BIB-1 diagnostic set. The value
146 will then be returned to the user in a nonsurrogate diagnostic record
147 in the response. The <code class="literal">errstring</code>, if provided, will
148 go in the addinfo field. Look at the protocol definition for the
149 defined error codes, and the suggested uses of the addinfo field.
151 The <code class="function">bend_search</code> handler is also called when
152 the frontend server receives a SRU SearchRetrieveRequest.
153 For SRU, a CQL query is usually provided by the client.
154 The CQL query is available as part of <code class="literal">Z_Query</code>
155 structure (note that CQL is now part of Z39.50 via an external).
156 To support CQL in existing implementations that only do Type-1,
157 we refer to the CQL-to-PQF tool described
158 <a href="tools.html#tools.cql.pqf" title="1.3.3. CQL to PQF conversion">here</a>.
160 To maintain backwards compatibility, the frontend server
161 of yaz always assume that error codes are BIB-1 diagnostics.
162 For SRU operation, a Bib-1 diagnostic code is mapped to
164 </p><pre class="synopsis">
165 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
167 typedef struct bend_fetch_rr {
168 char *setname; /* set name */
169 int number; /* record number */
170 Z_ReferenceId *referenceId;/* reference ID */
171 oid_value request_format; /* One of the CLASS_RECSYN members */
172 int *request_format_raw; /* same as above (raw OID) */
173 Z_RecordComposition *comp; /* Formatting instructions */
174 ODR stream; /* encoding stream - memory source if req */
175 ODR print; /* printing stream */
177 char *basename; /* name of database that provided record */
178 int len; /* length of record or -1 if structured */
179 char *record; /* record */
180 int last_in_set; /* is it? */
181 oid_value output_format; /* format */
182 int *output_format_raw; /* used instead of above if not-null */
183 int errcode; /* 0==success */
184 char *errstring; /* system error string or NULL */
185 int surrogate_flag; /* surrogate diagnostic */
186 char *schema; /* string record schema input/output */
189 The frontend server calls the <code class="function">bend_fetch</code> handler
190 when it needs database records to fulfill a Z39.50 Search Request, a
191 Z39.50 Present Request or a SRU SearchRetrieveRequest.
192 The <code class="literal">setname</code> is simply the name of the result set
193 that holds the reference to the desired record.
194 The <code class="literal">number</code> is the offset into the set (with 1
195 being the first record in the set). The <code class="literal">format</code> field
196 is the record format requested by the client (See
197 <a href="asn.oid.html" title="3. Object Identifiers">Section 3, “Object Identifiers”</a>).
198 The value <code class="literal">VAL_NONE</code> indicates that the client did
199 not request a specific format. The <code class="literal">stream</code> argument
200 is an <acronym class="acronym">ODR</acronym> stream which should be used for
201 allocating space for structured data records.
202 The stream will be reset when all records have been assembled, and
203 the response package has been transmitted.
204 For unstructured data, the backend is responsible for maintaining a
205 static or dynamic buffer for the record between calls.
207 If a SRU SearchRetrieveRequest is received by the frontend server,
208 the <code class="literal">referenceId</code> is NULL and the
209 <code class="literal">request_format</code> (transfer syntax) is XML (OID name
210 <code class="literal">VAL_TEXT_XML</code>).
211 The schema for SRU is stored in both the
212 <code class="literal">Z_RecordComposition</code>
213 structure and <code class="literal">schema</code> (simple string).
215 In the structure, the <code class="literal">basename</code> is the name of the
216 database that holds the
217 record. <code class="literal">len</code> is the length of the record returned, in
218 bytes, and <code class="literal">record</code> is a pointer to the record.
219 <code class="literal">last_in_set</code> should be nonzero only if the record
220 returned is the last one in the given result set.
221 <code class="literal">errcode</code> and <code class="literal">errstring</code>, if
222 given, will be interpreted as a global error pertaining to the
223 set, and will be returned in a non-surrogate-diagnostic.
224 If you wish to return the error as a surrogate-diagnostic
225 (local error) you can do this by setting
226 <code class="literal">surrogate_flag</code> to 1 also.
228 If the <code class="literal">len</code> field has the value -1, then
229 <code class="literal">record</code> is assumed to point to a constructed data
230 type. The <code class="literal">format</code> field will be used to determine
231 which encoder should be used to serialize the data.
232 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
233 If your backend generates structured records, it should use
234 <code class="function">odr_malloc()</code> on the provided stream for allocating
235 data: This allows the frontend server to keep track of the record sizes.
237 The <code class="literal">format</code> field is mapped to an object identifier
238 in the direct reference of the resulting EXTERNAL representation
240 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
241 The current version of YAZ only supports the direct reference mode.
242 </p></div><pre class="synopsis">
243 int (*bend_present) (void *handle, bend_present_rr *rr);
246 char *setname; /* set name */
248 int number; /* record number */
249 oid_value format; /* One of the CLASS_RECSYN members */
250 Z_ReferenceId *referenceId;/* reference ID */
251 Z_RecordComposition *comp; /* Formatting instructions */
252 ODR stream; /* encoding stream */
253 ODR print; /* printing stream */
254 bend_request request;
255 bend_association association;
257 int hits; /* number of hits */
258 int errcode; /* 0==OK */
259 char *errstring; /* system error string or NULL */
262 The <code class="function">bend_present</code> handler is called when
263 the server receives a Z39.50 Present Request.
264 The <code class="literal">setname</code>,
265 <code class="literal">start</code> and <code class="literal">number</code> is the
266 name of the result set - start position - and number of records to
267 be retrieved respectively. <code class="literal">format</code> and
268 <code class="literal">comp</code> is the preferred transfer syntax and element
269 specifications of the present request.
271 Note that this is handler serves as a supplement for
272 <code class="function">bend_fetch</code> and need not to be defined in order to
273 support search - and retrieve.
274 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2571502"></a>5.3. Delete</h3></div></div></div><p>
275 For back-ends that supports delete of a result set only one handler
277 </p><pre class="synopsis">
278 int (*bend_delete)(void *handle, bend_delete_rr *rr);
280 typedef struct bend_delete_rr {
284 Z_ReferenceId *referenceId;
285 int delete_status; /* status for the whole operation */
286 int *statuses; /* status each set - indexed as setnames */
290 </pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
291 The delete set function definition is rather primitive, mostly because
292 we have had no practical need for it as of yet. If someone wants
293 to provide a full delete service, we'd be happy to add the
294 extra parameters that are required. Are there clients out there
295 that will actually delete sets they no longer need?
296 </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2571537"></a>5.4. scan</h3></div></div></div><p>
297 For servers that wish to offer the scan service one handler
299 </p><pre class="synopsis">
300 int (*bend_delete)(void *handle, bend_delete_rr *rr);
303 BEND_SCAN_SUCCESS, /* ok */
304 BEND_SCAN_PARTIAL /* not all entries could be found */
307 typedef struct bend_scan_rr {
308 int num_bases; /* number of elements in database list */
309 char **basenames; /* databases to search */
310 oid_value attributeset;
311 Z_ReferenceId *referenceId; /* reference ID */
312 Z_AttributesPlusTerm *term;
313 ODR stream; /* encoding stream - memory source if required */
314 ODR print; /* printing stream */
316 int *step_size; /* step size */
317 int term_position; /* desired index of term in result list/returned */
318 int num_entries; /* number of entries requested/returned */
320 struct scan_entry *entries;
321 bend_scan_status status;
324 char *scanClause; /* CQL scan clause */
327 This backend server handles both Z39.50 scan
328 and SRU scan. In order for a handler to distinguish between SRU (CQL) scan
329 Z39.50 Scan , it must check for a non-NULL value of
330 <code class="literal">scanClause</code>.
331 </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
332 if designed today, it would be a choice using a union or similar,
333 but that would break binary compatibility with existing servers.
334 </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>