1 <!-- $Id: zoom.xml,v 1.8 2001-11-13 23:00:42 adam Exp $ -->
2 <chapter id="zoom"><title>Building clients with ZOOM</title>
5 &zoom; is an acronym for 'Z39.50 Object-Orientation Model' and is
6 an initiative started by Mike Taylor (Mike is from the UK, which
7 explains the peculiar name of the model). The goal of &zoom; is to
8 provide a common Z39.50 client API not bound to a particular
9 programming language or toolkit.
12 The lack of a simple Z39.50 client API for &yaz; has become more
13 and more apparent over time. So when the first ZOOM specification
15 an implementation for &yaz; was quickly developed. For the first time, it is
16 now as easy (or easier!) to develop clients than servers with &yaz;. This
17 chapter describes the ZOOM C binding. Before going futher, please
18 reconsider whether C is the right programming language for the job.
19 There are other language bindings available for &yaz;, and still
21 are in active development. See the ZOOM website at
22 <ulink url="http://zoom.z3950.org/">zoom.z3950.org</ulink> for
27 In order to fully understand this chapter you should read and
28 try the example programs <literal>zoomtst1.c</literal>,
29 <literal>zoomtst2.c</literal>, .. in the <literal>zoom</literal>
34 The C language misses many features found in object oriented languages
35 such as C++, Java, etc. For example, you'll have to manually,
36 destroy all objects you create, even though you may think of them as
37 temporary. Most objects has a <literal>_create</literal> - and a
38 <literal>_destroy</literal> variant.
39 All objects are in fact pointers to internal stuff, but you don't see
40 that because of typedefs. All destroy methods should gracefully ignore a
41 <literal>NULL</literal> pointer.
44 In each of the sections below you'll find a sub section called
45 protocol behavior, that descries how the API maps to the Z39.50
48 <sect1 id="zoom.connections"><title>Connections</title>
50 <para>The Connection object is a session with a target.
53 #include <yaz/zoom.h>
55 Z3950_connection Z3950_connection_new (const char *host, int portnum);
57 Z3950_connection Z3950_connection_create (Z3950_options options);
59 void Z3950_connection_connect(Z3950_connection c, const char *host,
61 void Z3950_connection_destroy (Z3950_connection c);
64 Connection objects are created with either function
65 <function>Z3950_connection_new</function> or
66 <function>Z3950_connection_create</function>.
67 The former creates and automatically attempts to establish a network
68 connection with the target. The latter doesn't establish
69 a connection immediately, thus allowing you to specify options
70 before establishing network connection using the function
71 <function>Z3950_connection_connect</function>.
72 If the portnumber, <literal>portnum</literal>, is zero, the
73 <literal>host</literal> is consulted for a port specification.
74 If no port is given, 210 is used. A colon denotes the beginning of
75 a port number in the host string. If the host string includes a
76 slash, the following part specifies a database for the connection.
79 Connection objects should be destroyed using the function
80 <function>Z3950_connection_destroy</function>.
83 const char *Z3950_connection_option (Z3950_connection c,
86 const char *Z3950_connection_host (Z3950_connection c);
89 The <function>Z3950_connection_option</function> allows you to
90 inspect or set an option given by <parameter>key</parameter>
92 If <parameter>val</parameter> is non-<literal>NULL</literal> that
93 holds the new value for option.
94 Otherwise, if <parameter>val</parameter> is
95 <literal>NULL</literal>,
96 the option is unchanged.
97 The function returns the (new) value of the option.
99 <table frame="top"><title>ZOOM Connection Options</title>
101 <colspec colwidth="4*" colname="name"></colspec>
102 <colspec colwidth="7*" colname="description"></colspec>
103 <colspec colwidth="3*" colname="default"></colspec>
106 <entry>Option</entry>
107 <entry>Description</entry>
108 <entry>Default</entry>
113 implementationName</entry><entry>Name of Your client
114 </entry><entry>none</entry></row>
116 user</entry><entry>Authentication user name
117 </entry><entry>none</entry></row>
119 group</entry><entry>Authentication group name
120 </entry><entry>none</entry></row>
122 pass</entry><entry>Authentication password
123 </entry><entry>none</entry></row>
125 proxy</entry><entry>Proxy host
126 </entry><entry>none</entry></row>
128 async</entry><entry>If true (1) the connection operates in
129 asynchronous operation which means that all calls are non-blocking
131 <link linkend="zoom.events"><function>Z3950_event</function></link>.
132 </entry><entry>0</entry></row>
134 maximumRecordSize</entry><entry> Maximum size of single record.
135 </entry><entry>1 MB</entry></row>
137 preferredMessageSize</entry><entry> Maximum size of multiple records.
138 </entry><entry>1 MB</entry></row>
143 Function <function>Z3950_connection_host</function> returns
144 the host for the connection as specified in a call to
145 <function>Z3950_connection_new</function> or
146 <function>Z3950_connection_connect</function>.
147 This function returns <literal>NULL</literal> if host isn't
148 set for the connection.
151 int Z3950_connection_error (Z3950_connection c, const char **cp,
152 const char **addinfo);
155 Use <function>Z3950_connection_error</function> to check for
156 errors for the last operation(s) performed. The function returns
157 zero if no errors occurred; non-zero otherwise indicating the error.
158 Pointers <parameter>cp</parameter> and <parameter>addinfo</parameter>
159 holds messages for the error and additional-info if passed as
160 non-<literal>NULL</literal>.
162 <sect2><title>Protocol behavior</title>
164 The calls <function>Z3950_connection_new</function> and
165 <function>Z3950_connection_connect</function> establises a TCP/IP
166 connection and sends an Initialize Request to the target if
167 possible. In addition, the calls waits for an Initialize Response
168 from the target and the result is inspected (OK or rejected).
171 If <literal>proxy</literal> is set then the client will establish
172 a TCP/IP connection with the peer as specified by the
173 <literal>proxy</literal> host and the hostname as part of the
174 connect calls will be set as part of the Initialize Request.
175 The proxy server will then "forward" the PDU's transparently
176 to the target behind the proxy.
179 For the authentication parameters, if option <literal>user</literal>
180 is set and both options <literal>group</literal> and
181 <literal>pass</literal> are unset, then Open style
182 authentication is used (Version 2/3) in which case the username
183 is usually followed by a slash, then by a password.
184 If either <literal>group</literal>
185 or <literal>pass</literal> is set then idPass authentication
186 (Version 3 only) is used. If none of the options are set, no
187 authentication parameters are set as part of the Initialize Request
191 When option <literal>async</literal> is 1, it really means that
192 all network operations are postponed (and queued) until the
193 function <literal>Z3950_event</literal> is invoked. When doing so
194 it doesn't make sense to check for errors after
195 <literal>Z3950_connection_new</literal> is called since that
196 operation "connecting - and init" is still incomplete and the
197 API cannot tell the outcome (yet).
201 <sect1 id="zoom.query"><title>Queries</title>
203 Query objects represents queries.
206 Z3950_query Z3950_query_create(void);
208 void Z3950_query_destroy(Z3950_query q);
210 int Z3950_query_prefix(Z3950_query q, const char *str);
212 int Z3950_query_sortby(Z3950_query q, const char *criteria);
215 Create query objects using <function>Z3950_query_create</function>
216 and destroy them by calling <function>Z3950_query_destroy</function>.
217 RPN-queries can be specified in <link linkend="PQF">PQF</link>
218 notation by using the
219 function <function>Z3950_query_prefix</function>. More
220 query types will be added later, such as
221 <link linkend="CCL">CCL</link> to RPN-mapping, native CCL query,
222 etc. In addition to a search, a sort criteria may be set. Function
223 <function>Z3950_query_sortby</function> specifies a
224 sort criteria using the same string notation for sort as offered by
225 the <link linkend="sortspec">YAZ client</link>.
227 <sect2><title>Protocol behavior</title>
229 The query object is just an interface for the member Query
230 in the SearchRequest. The sortby-function is an interface to the
231 sortSequence member of the SortRequest.
235 <sect1 id="zoom.resultsets"><title>Result sets</title>
237 The result set object is a container for records returned from
241 Z3950_resultset Z3950_connection_search(Z3950_connection,
244 Z3950_resultset Z3950_connection_search_pqf(Z3950_connection c,
247 void Z3950_resultset_destroy(Z3950_resultset r);
250 Function <function>Z3950_connection_search</function> creates
251 a result set given a connection and query.
252 Destroy a result set by calling
253 <function>Z3950_resultset_destroy</function>.
254 Simple clients may using PQF only may use function
255 <function>Z3950_connection_search_pqf</function> in which case
256 creating query objects is not necessary.
259 const char *Z3950_resultset_option (Z3950_resultset r,
263 int Z3950_resultset_size (Z3950_resultset r);
265 void *Z3950_resultset_get (Z3950_resultset s, size_t pos,
266 const char *type, size_t *len);
269 Function <function>Z3950_resultset_options</function> sets or
270 modifies an option for a result set similar to
271 <function>Z3950_connection_option</function>.
274 The number of hits also called result-count is returned by
275 function <function>Z3950_resultset_size</function>.
278 Function <function>Z3950_resultset_get</function> is similar to
279 <link linkend="zoom.record.get">
280 <function>Z3950_record_get</function></link> but
281 instead of operating on a record object, it operates on a record on
282 a given offset within a result set.
284 <table frame="top"><title>ZOOM Result set Options</title>
286 <colspec colwidth="4*" colname="name"></colspec>
287 <colspec colwidth="7*" colname="description"></colspec>
288 <colspec colwidth="2*" colname="default"></colspec>
291 <entry>Option</entry>
292 <entry>Description</entry>
293 <entry>Default</entry>
298 piggyback</entry><entry>True (1) if piggyback should be
299 used in searches; false (0) if not.
300 </entry><entry>1</entry></row>
302 start</entry><entry>Offset of first record to be
303 retrieved from target. First record has offset 0 unlike the
304 protocol specifications where first record has position 1.
305 </entry><entry>0</entry></row>
307 count</entry><entry>Number of records to be retrieved.
308 </entry><entry>0</entry></row>
310 elementSetName</entry><entry>Element-Set name of records.
311 Most targets should honor element set name <literal>B</literal>
312 and <literal>F</literal> for brief and full respectively.
313 </entry><entry>none</entry></row>
315 preferredRecordSyntax</entry><entry>Preferred Syntax, such as
316 <literal>USMARC</literal>, <literal>SUTRS</literal>, etc.
317 </entry><entry>none</entry></row>
319 smallSetUpperBound</entry><entry>If hits is less than or equal to this
320 value, then target will return all records using small element set name
321 </entry><entry>0</entry></row>
323 largeSetLowerBound</entry><entry>If hits is greator than this
324 value, the target will return no records.
325 </entry><entry>1</entry></row>
327 mediumSetPresentNumber</entry><entry>This value represents
328 the number of records to be returned as part of a search when when
329 hits is less than or equal to large set lower bound and if hits
330 is greator than small set upper bound.
331 </entry><entry>0</entry></row>
333 smallSetElementSetName</entry><entry>
334 The element set name to be used for small result sets.
335 </entry><entry>none</entry></row>
337 mediumSetElementSetName</entry><entry>
338 The element set name to be for medium-sized result sets.
339 </entry><entry>none</entry></row>
341 databaseName</entry><entry>One or more database names
342 separated by character plus (<literal>+</literal>).
343 </entry><entry>Default</entry></row>
348 <title>Protocol behavior</title>
350 The creation of a result set involves at least a SearchRequest
351 - SearchResponse protocol handshake. Following that, if a sort
352 critieria was specified as part of the query, a sortRequest -
353 SortResponse handshake takes place. Note that it is necessary to
354 perform sorting before any retrieval takes place, so no records will
355 be returned from the target as part of the SearchResponse because these
356 would be unsorted. Hence, piggyback is disabled when sort critieria
357 is set. Following Search - and a Possible sort, Retrieval takes
358 place - as one or more Present Requests - Present Response being
362 The API allows for two different modes for retrieval. A high level
363 mode which is somewhat more powerful and a low level one.
364 The low level is "enabled" when the settings
365 <literal>smallSetUpperBound</literal>,
366 <literal>mediumSetPresentNumber</literal> and
367 <literal>largeSetLowerBound</literal> are set. The low level mode
368 thus allows you to precisely set how records are returned as part
369 of a search response as offered by the Z39.50 protocol.
370 Since the client may be retrieving records as part of the
371 search response, this mode doesn't work well if sorting is used.
374 The high-level mode allows you to fetch a range of records from
375 the result set with a given start offset. When you use this mode
376 the client will automatically use piggyback if that is possible
377 with the target and perform one or more present requests as needed.
378 Even if the target returns fewer records as part of a present response
379 because of a record size limit, etc. the client will repeat sending
380 present requests. As an example, if option <literal>start</literal>
381 is 0 (default) and <literal>count</literal> is 4, and
382 <literal>piggyback</literal> is 1 (default) and no sorting critieria
383 is specified, then the client will attempt to retrieve the 4
384 records as part the search response (using piggyback). On the other
385 hand, if either <literal>start</literal> is positive or if
386 a sorting criteria is set, or if <literal>piggyback</literal>
387 is 0, then the client will not perform piggyback but send Present
391 If either of the options <literal>mediumSetElementSetName</literal> and
392 <literal>smallSetElementSetName</literal> are unset, the value
393 of option <literal>elementSetName</literal> is used for piggyback
394 searches. This means that for the high-level mode you only have
395 to specify one elementSetName option rather than three.
399 <sect1 id="zoom.records"><title>Records</title>
401 A record object is a retrival record on the client side -
402 created from result sets.
405 void Z3950_resultset_records (Z3950_resultset r,
407 size_t start, size_t count);
408 Z3950_record Z3950_resultset_record (Z3950_resultset s, size_t pos);
410 void *Z3950_record_get (Z3950_record rec, const char *type,
413 void Z3950_record_destroy (Z3950_record rec);
416 Records are created by functions
417 <function>Z3950_resultset_records</function> or
418 <function>Z3950_resultset_record</function>
419 and destroyed by <function>Z3950_record_destroy</function>.
422 A single record is created and returned by function
423 <function>Z3950_resultset_record</function> that takes a
424 position as argument. First record has position zero.
425 If no record could be obtained <literal>NULL</literal> is returned.
428 Function <function>Z3950_resultset_records</function> retrieves
429 a number of records from a result set. Parameter <literal>start</literal>
430 and <literal>count</literal> specifies the range of records to
431 be returned. Upon completion array
432 <literal>recs[0], ..recs[count-1]</literal>
433 holds record objects for the records. The array of records
434 <literal>recs</literal> should be allocate prior to calling
435 <function>Z3950_resultset_records</function>. Note that for those
436 records that couldn't be retrieved from the target
437 <literal>recs[ ..]</literal> is set to <literal>NULL</literal>.
439 <para id="zoom.record.get">
440 In order to extract information about a single record,
441 <function>Z3950_record_get</function> is provided. The
442 function returns a pointer to certain record information. The
443 nature (type) of the pointer depends on the <function>type</function>
444 given. In addition for certain types, the length
445 <literal>len</literal> passed will be set to the size in bytes of
446 the returned information.
448 <varlistentry><term><literal>database</literal></term>
449 <listitem><para>The database that holds the record is returned
450 as a C string. Return type <literal>char *</literal>.
453 <varlistentry><term><literal>syntax</literal></term>
454 <listitem><para>The transfer syntax (OID) of the record is returned
455 as a C string. Return type <literal>char *</literal>.
458 <varlistentry><term><literal>render</literal></term>
459 <listitem><para>The record is returned in a display friendly
460 format. Upon completion buffer is returned
461 (type <literal>char *</literal>) and length is stored in
462 <literal>*len</literal>.
465 <varlistentry><term><literal>raw</literal></term>
466 <listitem><para>The record is returned in the internal
467 YAZ specific format. The raw data is returned as type
468 <literal>Z_External *</literal> is just the type for
469 the member <literal>retrievalRecord</literal> in
470 type <literal>NamePlusRecord</literal>.
475 <sect2><title>Protocol behavior</title>
477 The functions <function>Z3950_resultset_record</function> and
478 <function>Z3950_resultset_records</function> inspects the client-side
479 record cache. If the records(s) were not found, i.e. not yet retrieved
480 from, they are fetched using Present Requests.
484 <sect1 id="zoom.options"><title>Options</title>
486 Most &zoom; objects provide a way to specify options to default behavior.
487 From an implementation point of view a set of options is just like
488 an associate array / hash array, etc.
491 Z3950_options Z3950_options_create (void);
493 Z3950_options Z3950_options_create_with_parent (Z3950_options parent);
495 void Z3950_options_destroy (Z3950_options opt);
498 const char *Z3950_options_get (Z3950_options opt, const char *name);
500 void Z3950_options_set (Z3950_options opt, const char *name,
504 typedef const char *(*Z3950_options_callback)
505 (void *handle, const char *name);
507 Z3950_options_callback
508 Z3950_options_set_callback (Z3950_options opt,
509 Z3950_options_callback c,
513 <sect1 id="zoom.events"><title>Events</title>
515 If you're developing non-blocking applications, you have to deal
519 int Z3950_event (int no, Z3950_connection *cs);
522 The <function>Z3950_event</function> executes pending events for
523 a number of connections. Supply the number of connections in
524 <literal>no</literal> and an array of connections in
525 <literal>cs</literal> (<literal>cs[0] ... cs[no-1]</literal>).
526 A pending event could be a sending a search, receiving a response,
528 When an event has a occured for one of the connections, this function
529 returns a positive integer <literal>n</literal> denoting that an event
530 occurred for connection <literal>cs[n-1]</literal>.
531 When no events are pending for the connections, a value of zero is
533 To ensure that all outstanding requests are performed call this function
534 repeatedly until zero is returned.
539 <!-- Keep this comment at the end of the file
544 sgml-minimize-attributes:nil
545 sgml-always-quote-attributes:t
548 sgml-parent-document: "yaz.xml"
549 sgml-local-catalogs: nil
550 sgml-namecase-general:t