1 <!-- $Id: zoom.xml,v 1.17 2002-01-28 09:27:48 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
22 <ulink url="http://zoom.z3950.org/">ZOOM website</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 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 ZOOM_connection ZOOM_connection_new (const char *host, int portnum);
57 ZOOM_connection ZOOM_connection_create (ZOOM_options options);
59 void ZOOM_connection_connect(ZOOM_connection c, const char *host,
61 void ZOOM_connection_destroy (ZOOM_connection c);
64 Connection objects are created with either function
65 <function>ZOOM_connection_new</function> or
66 <function>ZOOM_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>ZOOM_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>ZOOM_connection_destroy</function>.
83 void ZOOM_connection_option_set (ZOOM_connection c,
87 const char *ZOOM_connection_option_get (ZOOM_connection c,
91 The <function>ZOOM_connection_option_set</function> allows you to
92 set an option given by <parameter>key</parameter> to the value
93 <parameter>value</parameter> for the connection.
94 Function <function>ZOOM_connection_option_get</function> returns
95 the value for an option given by <parameter>key</parameter>.
97 <table frame="sides" colsep="1"><title>ZOOM Connection Options</title>
99 <colspec colwidth="4*" colname="name"></colspec>
100 <colspec colwidth="7*" colname="description"></colspec>
101 <colspec colwidth="3*" colname="default"></colspec>
104 <entry>Option</entry>
105 <entry>Description</entry>
106 <entry>Default</entry>
111 implementationName</entry><entry>Name of Your client
112 </entry><entry>none</entry></row>
114 user</entry><entry>Authentication user name
115 </entry><entry>none</entry></row>
117 group</entry><entry>Authentication group name
118 </entry><entry>none</entry></row>
120 pass</entry><entry>Authentication password
121 </entry><entry>none</entry></row>
123 host</entry><entry>Target host. This setting is "read-only".
124 It's automatically set internally when connecting to a target.
125 </entry><entry>none</entry></row>
127 proxy</entry><entry>Proxy host
128 </entry><entry>none</entry></row>
130 async</entry><entry>If true (1) the connection operates in
131 asynchronous operation which means that all calls are non-blocking
133 <link linkend="zoom.events"><function>ZOOM_event</function></link>.
134 </entry><entry>0</entry></row>
136 maximumRecordSize</entry><entry> Maximum size of single record.
137 </entry><entry>1 MB</entry></row>
139 preferredMessageSize</entry><entry> Maximum size of multiple records.
140 </entry><entry>1 MB</entry></row>
145 int ZOOM_connection_error (ZOOM_connection c, const char **cp,
146 const char **addinfo);
149 Use <function>ZOOM_connection_error</function> to check for
150 errors for the last operation(s) performed. The function returns
151 zero if no errors occurred; non-zero otherwise indicating the error.
152 Pointers <parameter>cp</parameter> and <parameter>addinfo</parameter>
153 holds messages for the error and additional-info if passed as
154 non-<literal>NULL</literal>.
156 <sect2><title>Protocol behavior</title>
158 The calls <function>ZOOM_connection_new</function> and
159 <function>ZOOM_connection_connect</function> establises a TCP/IP
160 connection and sends an Initialize Request to the target if
161 possible. In addition, the calls waits for an Initialize Response
162 from the target and the result is inspected (OK or rejected).
165 If <literal>proxy</literal> is set then the client will establish
166 a TCP/IP connection with the peer as specified by the
167 <literal>proxy</literal> host and the hostname as part of the
168 connect calls will be set as part of the Initialize Request.
169 The proxy server will then "forward" the PDU's transparently
170 to the target behind the proxy.
173 For the authentication parameters, if option <literal>user</literal>
174 is set and both options <literal>group</literal> and
175 <literal>pass</literal> are unset, then Open style
176 authentication is used (Version 2/3) in which case the username
177 is usually followed by a slash, then by a password.
178 If either <literal>group</literal>
179 or <literal>pass</literal> is set then idPass authentication
180 (Version 3 only) is used. If none of the options are set, no
181 authentication parameters are set as part of the Initialize Request
185 When option <literal>async</literal> is 1, it really means that
186 all network operations are postponed (and queued) until the
187 function <literal>ZOOM_event</literal> is invoked. When doing so
188 it doesn't make sense to check for errors after
189 <literal>ZOOM_connection_new</literal> is called since that
190 operation "connecting - and init" is still incomplete and the
191 API cannot tell the outcome (yet).
195 <sect1 id="zoom.query"><title>Queries</title>
197 Query objects represents queries.
200 ZOOM_query ZOOM_query_create(void);
202 void ZOOM_query_destroy(ZOOM_query q);
204 int ZOOM_query_prefix(ZOOM_query q, const char *str);
206 int ZOOM_query_sortby(ZOOM_query q, const char *criteria);
209 Create query objects using <function>ZOOM_query_create</function>
210 and destroy them by calling <function>ZOOM_query_destroy</function>.
211 RPN-queries can be specified in <link linkend="PQF">PQF</link>
212 notation by using the
213 function <function>ZOOM_query_prefix</function>. More
214 query types will be added later, such as
215 <link linkend="CCL">CCL</link> to RPN-mapping, native CCL query,
216 etc. In addition to a search, a sort criteria may be set. Function
217 <function>ZOOM_query_sortby</function> specifies a
218 sort criteria using the same string notation for sort as offered by
219 the <link linkend="sortspec">YAZ client</link>.
221 <sect2><title>Protocol behavior</title>
223 The query object is just an interface for the member Query
224 in the SearchRequest. The sortby-function is an interface to the
225 sortSequence member of the SortRequest.
229 <sect1 id="zoom.resultsets"><title>Result sets</title>
231 The result set object is a container for records returned from
235 ZOOM_resultset ZOOM_connection_search(ZOOM_connection,
238 ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c,
241 void ZOOM_resultset_destroy(ZOOM_resultset r);
244 Function <function>ZOOM_connection_search</function> creates
245 a result set given a connection and query.
246 Destroy a result set by calling
247 <function>ZOOM_resultset_destroy</function>.
248 Simple clients may using PQF only may use function
249 <function>ZOOM_connection_search_pqf</function> in which case
250 creating query objects is not necessary.
253 void ZOOM_resultset_option_set (ZOOM_resultset r,
257 const char *ZOOM_resultset_option_get (ZOOM_resultset r,
260 size_t ZOOM_resultset_size (ZOOM_resultset r);
263 Functions <function>ZOOM_resultset_options_set</function> and
264 <function>ZOOM_resultset_get</function> sets and gets an option
265 for a result set similar to <function>ZOOM_connection_option_get</function>
266 and <function>ZOOM_connection_option_set</function>.
269 The number of hits also called result-count is returned by
270 function <function>ZOOM_resultset_size</function>.
272 <table frame="top"><title>ZOOM Result set Options</title>
274 <colspec colwidth="4*" colname="name"></colspec>
275 <colspec colwidth="7*" colname="description"></colspec>
276 <colspec colwidth="2*" colname="default"></colspec>
279 <entry>Option</entry>
280 <entry>Description</entry>
281 <entry>Default</entry>
286 piggyback</entry><entry>True (1) if piggyback should be
287 used in searches; false (0) if not.
288 </entry><entry>1</entry></row>
290 start</entry><entry>Offset of first record to be
291 retrieved from target. First record has offset 0 unlike the
292 protocol specifications where first record has position 1.
293 </entry><entry>0</entry></row>
295 count</entry><entry>Number of records to be retrieved.
296 </entry><entry>0</entry></row>
298 elementSetName</entry><entry>Element-Set name of records.
299 Most targets should honor element set name <literal>B</literal>
300 and <literal>F</literal> for brief and full respectively.
301 </entry><entry>none</entry></row>
303 preferredRecordSyntax</entry><entry>Preferred Syntax, such as
304 <literal>USMARC</literal>, <literal>SUTRS</literal>, etc.
305 </entry><entry>none</entry></row>
307 schema</entry><entry>Schema for retrieval, such as
308 <literal>Gils-schema</literal>, <literal>Geo-schema</literal>, etc.
309 </entry><entry>none</entry></row>
311 smallSetUpperBound</entry><entry>If hits is less than or equal to this
312 value, then target will return all records using small element set name
313 </entry><entry>0</entry></row>
315 largeSetLowerBound</entry><entry>If hits is greator than this
316 value, the target will return no records.
317 </entry><entry>1</entry></row>
319 mediumSetPresentNumber</entry><entry>This value represents
320 the number of records to be returned as part of a search when when
321 hits is less than or equal to large set lower bound and if hits
322 is greator than small set upper bound.
323 </entry><entry>0</entry></row>
325 smallSetElementSetName</entry><entry>
326 The element set name to be used for small result sets.
327 </entry><entry>none</entry></row>
329 mediumSetElementSetName</entry><entry>
330 The element set name to be for medium-sized result sets.
331 </entry><entry>none</entry></row>
333 databaseName</entry><entry>One or more database names
334 separated by character plus (<literal>+</literal>).
335 </entry><entry>Default</entry></row>
337 setname</entry><entry>Name of Result Set (Result Set ID).
338 If this option isn't set, the ZOOM module will automatically
339 allocate a result set name.
340 </entry><entry>default</entry></row>
345 <title>Protocol behavior</title>
347 The creation of a result set involves at least a SearchRequest
348 - SearchResponse protocol handshake. Following that, if a sort
349 critieria was specified as part of the query, a sortRequest -
350 SortResponse handshake takes place. Note that it is necessary to
351 perform sorting before any retrieval takes place, so no records will
352 be returned from the target as part of the SearchResponse because these
353 would be unsorted. Hence, piggyback is disabled when sort critieria
354 is set. Following Search - and a Possible sort, Retrieval takes
355 place - as one or more Present Requests - Present Response being
359 The API allows for two different modes for retrieval. A high level
360 mode which is somewhat more powerful and a low level one.
361 The low level is "enabled" when the settings
362 <literal>smallSetUpperBound</literal>,
363 <literal>mediumSetPresentNumber</literal> and
364 <literal>largeSetLowerBound</literal> are set. The low level mode
365 thus allows you to precisely set how records are returned as part
366 of a search response as offered by the Z39.50 protocol.
367 Since the client may be retrieving records as part of the
368 search response, this mode doesn't work well if sorting is used.
371 The high-level mode allows you to fetch a range of records from
372 the result set with a given start offset. When you use this mode
373 the client will automatically use piggyback if that is possible
374 with the target and perform one or more present requests as needed.
375 Even if the target returns fewer records as part of a present response
376 because of a record size limit, etc. the client will repeat sending
377 present requests. As an example, if option <literal>start</literal>
378 is 0 (default) and <literal>count</literal> is 4, and
379 <literal>piggyback</literal> is 1 (default) and no sorting critieria
380 is specified, then the client will attempt to retrieve the 4
381 records as part the search response (using piggyback). On the other
382 hand, if either <literal>start</literal> is positive or if
383 a sorting criteria is set, or if <literal>piggyback</literal>
384 is 0, then the client will not perform piggyback but send Present
388 If either of the options <literal>mediumSetElementSetName</literal> and
389 <literal>smallSetElementSetName</literal> are unset, the value
390 of option <literal>elementSetName</literal> is used for piggyback
391 searches. This means that for the high-level mode you only have
392 to specify one elementSetName option rather than three.
396 <sect1 id="zoom.records"><title>Records</title>
398 A record object is a retrival record on the client side -
399 created from result sets.
402 void ZOOM_resultset_records (ZOOM_resultset r,
404 size_t start, size_t count);
405 ZOOM_record ZOOM_resultset_record (ZOOM_resultset s, size_t pos);
407 const char *ZOOM_record_get (ZOOM_record rec, const char *type,
410 ZOOM_record ZOOM_record_clone (ZOOM_record rec);
412 void ZOOM_record_destroy (ZOOM_record rec);
415 References to temporary records are returned by functions
416 <function>ZOOM_resultset_records</function> or
417 <function>ZOOM_resultset_record</function>.
420 If a persistent reference to a record is desired
421 <function>ZOOM_record_clone</function> should be used.
422 It returns a record reference that should be destroyed
423 by a call to <function>ZOOM_record_destroy</function>.
426 A single record is returned by function
427 <function>ZOOM_resultset_record</function> that takes a
428 position as argument. First record has position zero.
429 If no record could be obtained <literal>NULL</literal> is returned.
432 Function <function>ZOOM_resultset_records</function> retrieves
433 a number of records from a result set. Parameter <literal>start</literal>
434 and <literal>count</literal> specifies the range of records to
435 be returned. Upon completion array
436 <literal>recs[0], ..recs[count-1]</literal>
437 holds record objects for the records. The array of records
438 <literal>recs</literal> should be allocated prior the call
439 <function>ZOOM_resultset_records</function>. Note that for those
440 records that couldn't be retrieved from the target
441 <literal>recs[ ..]</literal> is set to <literal>NULL</literal>.
443 <para id="zoom.record.get">
444 In order to extract information about a single record,
445 <function>ZOOM_record_get</function> is provided. The
446 function returns a pointer to certain record information. The
447 nature (type) of the pointer depends on the parameter,
448 <function>type</function>.
449 In addition, for certain types, the length
450 <literal>len</literal> passed will be set to the size in bytes of
451 the returned information.
453 <varlistentry><term><literal>database</literal></term>
454 <listitem><para>Database of record is returned
455 as a C null-terminated string. Return type
456 <literal>const char *</literal>.
459 <varlistentry><term><literal>syntax</literal></term>
460 <listitem><para>The transfer syntax (OID) of the record is returned
461 as a C null-terminated string. Return type is
462 <literal>const char *</literal>.
465 <varlistentry><term><literal>render</literal></term>
466 <listitem><para>The record is returned in a display friendly
467 format. Upon completion buffer is returned
468 (type <literal>const char *</literal>) and length is stored in
469 <literal>*len</literal>.
472 <varlistentry><term><literal>raw</literal></term>
473 <listitem><para>The record is returned in the internal
474 YAZ specific format. For GRS-1, Explain, and others, t
475 he raw data is returned as type
476 <literal>Z_External *</literal> which is just the type for
477 the member <literal>retrievalRecord</literal> in
478 type <literal>NamePlusRecord</literal>.
479 For SUTRS and octet aligned record (including all MARCs) the
480 octet buffer is returned and the length of the buffer.
485 <sect2><title>Protocol behavior</title>
487 The functions <function>ZOOM_resultset_record</function> and
488 <function>ZOOM_resultset_records</function> inspects the client-side
489 record cache. Records not found in cache are fetched using
491 The functions may block (and perform network I/O) - even though option
492 <literal>async</literal> is 1, because they return records objects.
493 (and there's no way to return records objects without retrieving them!).
496 There is a trick, however, in the usage of function
497 <function>ZOOM_resultset_records</function> that allows for
498 delayed retrieval (and makes it non-blocking). By passing
499 a null pointer for <parameter>recs</parameter> you're indicating
500 you're not interested in getting records objects
501 <emphasis>now</emphasis>.
505 <sect1 id="zoom.scan"><title>Scan</title>
507 This section describes an interface for Scan. Scan is not an
508 official part of the ZOOM model yet. The result of a scan operation
509 is the <literal>ZOOM_scanset</literal> which is a set of terms
510 returned by a target.
513 ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c,
514 const char *startterm);
516 size_t ZOOM_scanset_size(ZOOM_scanset scan);
518 const char * ZOOM_scanset_term(ZOOM_scanset scan, size_t pos,
519 int *occ, size_t *len);
522 void ZOOM_scanset_destroy (ZOOM_scanset scan);
524 const char *ZOOM_scanset_option_get (ZOOM_scanset scan,
527 void ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
531 The scan set is created by function
532 <function>ZOOM_connection_scan</function> which performs a scan
533 operation on the connection and start term given.
534 If the operation was successful, the size of the scan set can be
535 retrived by a call to <function>ZOOM_scanset_size</function>.
536 Like result sets, the items are numbered 0,..size-1.
537 To obtain information about a particular scan term, call function
538 <function>ZOOM_scanset_term</function>. This function takes
539 a scan set offset <literal>pos</literal> and returns a pointer
540 to an actual term or <literal>NULL</literal> if non-present.
541 If present, the <literal>occ</literal> and <literal>len</literal>
542 are set to the number of occurrences and the length
543 of the actual term respectively.
544 A scan set may be freed by a call to function
545 <function>ZOOM_scanset_destroy</function>.
546 Functions <function>ZOOM_scanset_option_get</function> and
547 <function>ZOOM_scanset_option_set</function> retrieves and sets
548 an option respectively.
551 <table frame="top"><title>ZOOM Scan Set Options</title>
553 <colspec colwidth="4*" colname="name"></colspec>
554 <colspec colwidth="7*" colname="description"></colspec>
555 <colspec colwidth="2*" colname="default"></colspec>
558 <entry>Option</entry>
559 <entry>Description</entry>
560 <entry>Default</entry>
565 number</entry><entry>Number of Scan Terms requested in next scan.
566 After scan it holds the actual number of terms returend.
567 </entry><entry>10</entry></row>
569 position</entry><entry>Preferred Position of term in response
570 in next scan; actual position after completion of scan.
571 </entry><entry>1</entry></row>
573 stepSize</entry><entry>Step Size
574 </entry><entry>0</entry></row>
576 scanStatus</entry><entry>An integer indicating the Scan Status
578 </entry><entry>0</entry></row>
584 <sect1 id="zoom.options"><title>Options</title>
586 Most &zoom; objects provide a way to specify options to change behavior.
587 From an implementation point of view a set of options is just like
588 an associative array / hash array, etc.
591 ZOOM_options ZOOM_options_create (void);
593 ZOOM_options ZOOM_options_create_with_parent (ZOOM_options parent);
595 void ZOOM_options_destroy (ZOOM_options opt);
598 const char *ZOOM_options_get (ZOOM_options opt, const char *name);
600 void ZOOM_options_set (ZOOM_options opt, const char *name,
604 typedef const char *(*ZOOM_options_callback)
605 (void *handle, const char *name);
607 ZOOM_options_callback
608 ZOOM_options_set_callback (ZOOM_options opt,
609 ZOOM_options_callback c,
613 <sect1 id="zoom.events"><title>Events</title>
615 If you're developing non-blocking applications, you have to deal
619 int ZOOM_event (int no, ZOOM_connection *cs);
622 The <function>ZOOM_event</function> executes pending events for
623 a number of connections. Supply the number of connections in
624 <literal>no</literal> and an array of connections in
625 <literal>cs</literal> (<literal>cs[0] ... cs[no-1]</literal>).
626 A pending event could be a sending a search, receiving a response,
628 When an event has occured for one of the connections, this function
629 returns a positive integer <literal>n</literal> denoting that an event
630 occurred for connection <literal>cs[n-1]</literal>.
631 When no events are pending for the connections, a value of zero is
633 To ensure that all outstanding requests are performed call this function
634 repeatedly until zero is returned.
639 <!-- Keep this comment at the end of the file
644 sgml-minimize-attributes:nil
645 sgml-always-quote-attributes:t
648 sgml-parent-document: "yaz.xml"
649 sgml-local-catalogs: nil
650 sgml-namecase-general:t