1 <!-- $Id: zoom.xml,v 1.21 2002-12-09 23:32:29 adam Exp $ -->
2 <chapter id="zoom"><title>Building clients with ZOOM</title>
4 &zoom; is an acronym for 'Z39.50 Object-Orientation Model' and is
5 an initiative started by Mike Taylor (Mike is from the UK, which
6 explains the peculiar name of the model). The goal of &zoom; is to
7 provide a common Z39.50 client API not bound to a particular
8 programming language or toolkit.
11 The lack of a simple Z39.50 client API for &yaz; has become more
12 and more apparent over time. So when the first &zoom; specification
14 an implementation for &yaz; was quickly developed. For the first time, it is
15 now as easy (or easier!) to develop clients than servers with &yaz;. This
16 chapter describes the &zoom; C binding. Before going further, please
17 reconsider whether C is the right programming language for the job.
18 There are other language bindings available for &yaz;, and still
20 are in active development. See the
21 <ulink url="http://zoom.z3950.org/">ZOOM web-site</ulink> for
26 In order to fully understand this chapter you should read and
27 try the example programs <literal>zoomtst1.c</literal>,
28 <literal>zoomtst2.c</literal>, .. in the <literal>zoom</literal>
33 The C language misses features found in object oriented languages
34 such as C++, Java, etc. For example, you'll have to manually,
35 destroy all objects you create, even though you may think of them as
36 temporary. Most objects has a <literal>_create</literal> - and a
37 <literal>_destroy</literal> variant.
38 All objects are in fact pointers to internal stuff, but you don't see
39 that because of typedefs. All destroy methods should gracefully ignore a
40 <literal>NULL</literal> pointer.
43 In each of the sections below you'll find a sub section called
44 protocol behavior, that describes how the API maps to the Z39.50
47 <sect1 id="zoom.connections"><title>Connections</title>
49 <para>The Connection object is a session with a target.
52 #include <yaz/zoom.h>
54 ZOOM_connection ZOOM_connection_new (const char *host, int portnum);
56 ZOOM_connection ZOOM_connection_create (ZOOM_options options);
58 void ZOOM_connection_connect(ZOOM_connection c, const char *host,
60 void ZOOM_connection_destroy (ZOOM_connection c);
63 Connection objects are created with either function
64 <function>ZOOM_connection_new</function> or
65 <function>ZOOM_connection_create</function>.
66 The former creates and automatically attempts to establish a network
67 connection with the target. The latter doesn't establish
68 a connection immediately, thus allowing you to specify options
69 before establishing network connection using the function
70 <function>ZOOM_connection_connect</function>.
71 If the port number, <literal>portnum</literal>, is zero, the
72 <literal>host</literal> is consulted for a port specification.
73 If no port is given, 210 is used. A colon denotes the beginning of
74 a port number in the host string. If the host string includes a
75 slash, the following part specifies a database for the connection.
78 Connection objects should be destroyed using the function
79 <function>ZOOM_connection_destroy</function>.
82 void ZOOM_connection_option_set (ZOOM_connection c,
86 const char *ZOOM_connection_option_get (ZOOM_connection c,
90 The <function>ZOOM_connection_option_set</function> allows you to
91 set an option given by <parameter>key</parameter> to the value
92 <parameter>value</parameter> for the connection.
93 Function <function>ZOOM_connection_option_get</function> returns
94 the value for an option given by <parameter>key</parameter>.
96 <table frame="top"><title>ZOOM Connection Options</title>
98 <colspec colwidth="4*" colname="name"></colspec>
99 <colspec colwidth="7*" colname="description"></colspec>
100 <colspec colwidth="3*" colname="default"></colspec>
103 <entry>Option</entry>
104 <entry>Description</entry>
105 <entry>Default</entry>
110 implementationName</entry><entry>Name of Your client
111 </entry><entry>none</entry></row>
113 user</entry><entry>Authentication user name
114 </entry><entry>none</entry></row>
116 group</entry><entry>Authentication group name
117 </entry><entry>none</entry></row>
119 pass</entry><entry>Authentication password
120 </entry><entry>none</entry></row>
122 host</entry><entry>Target host. This setting is "read-only".
123 It's automatically set internally when connecting to a target.
124 </entry><entry>none</entry></row>
126 proxy</entry><entry>Proxy host
127 </entry><entry>none</entry></row>
129 async</entry><entry>If true (1) the connection operates in
130 asynchronous operation which means that all calls are non-blocking
132 <link linkend="zoom.events"><function>ZOOM_event</function></link>.
133 </entry><entry>0</entry></row>
135 maximumRecordSize</entry><entry> Maximum size of single record.
136 </entry><entry>1 MB</entry></row>
138 preferredMessageSize</entry><entry> Maximum size of multiple records.
139 </entry><entry>1 MB</entry></row>
141 lang</entry><entry> Language for negotiation.
142 </entry><entry>none</entry></row>
144 charset</entry><entry> Character set for negotiation.
145 </entry><entry>none</entry></row>
147 targetImplementationId</entry><entry> Implementation ID of target.
148 </entry><entry>none</entry></row>
150 targetImplementationName</entry><entry> Implementation Name of target.
151 </entry><entry>none</entry></row>
153 targetImplementationVersion</entry><entry> Implementation Version
155 </entry><entry>none</entry></row>
160 If either option <literal>lang</literal> or <literal>charset</literal>
162 <ulink url="http://lcweb.loc.gov/z3950/agency/defns/charneg-3.html">
163 Character Set and Language Negotiation</ulink> is in effect.
166 int ZOOM_connection_error (ZOOM_connection c, const char **cp,
167 const char **addinfo);
168 int ZOOM_connection_error_x (ZOOM_connection c, const char **cp,
169 const char **addinfo, const char **dset);
172 Function <function>ZOOM_connection_error</function> checks for
173 errors for the last operation(s) performed. The function returns
174 zero if no errors occurred; non-zero otherwise indicating the error.
175 Pointers <parameter>cp</parameter> and <parameter>addinfo</parameter>
176 holds messages for the error and additional-info if passed as
177 non-<literal>NULL</literal>. Function
178 <function>ZOOM_connection_error_x</function> is an extended version
179 of <function>ZOOM_connection_error</function> that is capable of
180 returning name of diagnostic set in <parameter>dset</parameter>.
182 <sect2><title>Protocol behavior</title>
184 The calls <function>ZOOM_connection_new</function> and
185 <function>ZOOM_connection_connect</function> establishes a TCP/IP
186 connection and sends an Initialize Request to the target if
187 possible. In addition, the calls waits for an Initialize Response
188 from the target and the result is inspected (OK or rejected).
191 If <literal>proxy</literal> is set then the client will establish
192 a TCP/IP connection with the peer as specified by the
193 <literal>proxy</literal> host and the hostname as part of the
194 connect calls will be set as part of the Initialize Request.
195 The proxy server will then "forward" the PDU's transparently
196 to the target behind the proxy.
199 For the authentication parameters, if option <literal>user</literal>
200 is set and both options <literal>group</literal> and
201 <literal>pass</literal> are unset, then Open style
202 authentication is used (Version 2/3) in which case the username
203 is usually followed by a slash, then by a password.
204 If either <literal>group</literal>
205 or <literal>pass</literal> is set then idPass authentication
206 (Version 3 only) is used. If none of the options are set, no
207 authentication parameters are set as part of the Initialize Request
211 When option <literal>async</literal> is 1, it really means that
212 all network operations are postponed (and queued) until the
213 function <literal>ZOOM_event</literal> is invoked. When doing so
214 it doesn't make sense to check for errors after
215 <literal>ZOOM_connection_new</literal> is called since that
216 operation "connecting - and init" is still incomplete and the
217 API cannot tell the outcome (yet).
221 <sect1 id="zoom.query"><title>Queries</title>
223 Query objects represents queries.
226 ZOOM_query ZOOM_query_create(void);
228 void ZOOM_query_destroy(ZOOM_query q);
230 int ZOOM_query_prefix(ZOOM_query q, const char *str);
232 int ZOOM_query_sortby(ZOOM_query q, const char *criteria);
235 Create query objects using <function>ZOOM_query_create</function>
236 and destroy them by calling <function>ZOOM_query_destroy</function>.
237 RPN-queries can be specified in <link linkend="PQF">PQF</link>
238 notation by using the
239 function <function>ZOOM_query_prefix</function>. More
240 query types will be added later, such as
241 <link linkend="CCL">CCL</link> to RPN-mapping, native CCL query,
242 etc. In addition to a search, a sort criteria may be set. Function
243 <function>ZOOM_query_sortby</function> specifies a
244 sort criteria using the same string notation for sort as offered by
245 the <link linkend="sortspec">YAZ client</link>.
247 <sect2><title>Protocol behavior</title>
249 The query object is just an interface for the member Query
250 in the SearchRequest. The sortby-function is an interface to the
251 sortSequence member of the SortRequest.
255 <sect1 id="zoom.resultsets"><title>Result sets</title>
257 The result set object is a container for records returned from
261 ZOOM_resultset ZOOM_connection_search(ZOOM_connection,
264 ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c,
267 void ZOOM_resultset_destroy(ZOOM_resultset r);
270 Function <function>ZOOM_connection_search</function> creates
271 a result set given a connection and query.
272 Destroy a result set by calling
273 <function>ZOOM_resultset_destroy</function>.
274 Simple clients may using PQF only may use function
275 <function>ZOOM_connection_search_pqf</function> in which case
276 creating query objects is not necessary.
279 void ZOOM_resultset_option_set (ZOOM_resultset r,
283 const char *ZOOM_resultset_option_get (ZOOM_resultset r,
286 size_t ZOOM_resultset_size (ZOOM_resultset r);
289 Functions <function>ZOOM_resultset_options_set</function> and
290 <function>ZOOM_resultset_get</function> sets and gets an option
291 for a result set similar to <function>ZOOM_connection_option_get</function>
292 and <function>ZOOM_connection_option_set</function>.
295 The number of hits also called result-count is returned by
296 function <function>ZOOM_resultset_size</function>.
298 <table frame="top"><title>ZOOM Result set Options</title>
300 <colspec colwidth="4*" colname="name"></colspec>
301 <colspec colwidth="7*" colname="description"></colspec>
302 <colspec colwidth="2*" colname="default"></colspec>
305 <entry>Option</entry>
306 <entry>Description</entry>
307 <entry>Default</entry>
312 piggyback</entry><entry>True (1) if piggyback should be
313 used in searches; false (0) if not.
314 </entry><entry>1</entry></row>
316 start</entry><entry>Offset of first record to be
317 retrieved from target. First record has offset 0 unlike the
318 protocol specifications where first record has position 1.
319 </entry><entry>0</entry></row>
321 count</entry><entry>Number of records to be retrieved.
322 </entry><entry>0</entry></row>
324 elementSetName</entry><entry>Element-Set name of records.
325 Most targets should honor element set name <literal>B</literal>
326 and <literal>F</literal> for brief and full respectively.
327 </entry><entry>none</entry></row>
329 preferredRecordSyntax</entry><entry>Preferred Syntax, such as
330 <literal>USMARC</literal>, <literal>SUTRS</literal>, etc.
331 </entry><entry>none</entry></row>
333 schema</entry><entry>Schema for retrieval, such as
334 <literal>Gils-schema</literal>, <literal>Geo-schema</literal>, etc.
335 </entry><entry>none</entry></row>
337 smallSetUpperBound</entry><entry>If hits is less than or equal to this
338 value, then target will return all records using small element set name
339 </entry><entry>0</entry></row>
341 largeSetLowerBound</entry><entry>If hits is greater than this
342 value, the target will return no records.
343 </entry><entry>1</entry></row>
345 mediumSetPresentNumber</entry><entry>This value represents
346 the number of records to be returned as part of a search when when
347 hits is less than or equal to large set lower bound and if hits
348 is greater than small set upper bound.
349 </entry><entry>0</entry></row>
351 smallSetElementSetName</entry><entry>
352 The element set name to be used for small result sets.
353 </entry><entry>none</entry></row>
355 mediumSetElementSetName</entry><entry>
356 The element set name to be for medium-sized result sets.
357 </entry><entry>none</entry></row>
359 databaseName</entry><entry>One or more database names
360 separated by character plus (<literal>+</literal>).
361 </entry><entry>Default</entry></row>
363 setname</entry><entry>Name of Result Set (Result Set ID).
364 If this option isn't set, the ZOOM module will automatically
365 allocate a result set name.
366 </entry><entry>default</entry></row>
371 <title>Protocol behavior</title>
373 The creation of a result set involves at least a SearchRequest
374 - SearchResponse protocol handshake. Following that, if a sort
375 criteria was specified as part of the query, a SortRequest -
376 SortResponse handshake takes place. Note that it is necessary to
377 perform sorting before any retrieval takes place, so no records will
378 be returned from the target as part of the SearchResponse because these
379 would be unsorted. Hence, piggyback is disabled when sort criteria
380 is set. Following Search - and a Possible sort, Retrieval takes
381 place - as one or more Present Requests - Present Response being
385 The API allows for two different modes for retrieval. A high level
386 mode which is somewhat more powerful and a low level one.
387 The low level is "enabled" when the settings
388 <literal>smallSetUpperBound</literal>,
389 <literal>mediumSetPresentNumber</literal> and
390 <literal>largeSetLowerBound</literal> are set. The low level mode
391 thus allows you to precisely set how records are returned as part
392 of a search response as offered by the Z39.50 protocol.
393 Since the client may be retrieving records as part of the
394 search response, this mode doesn't work well if sorting is used.
397 The high-level mode allows you to fetch a range of records from
398 the result set with a given start offset. When you use this mode
399 the client will automatically use piggyback if that is possible
400 with the target and perform one or more present requests as needed.
401 Even if the target returns fewer records as part of a present response
402 because of a record size limit, etc. the client will repeat sending
403 present requests. As an example, if option <literal>start</literal>
404 is 0 (default) and <literal>count</literal> is 4, and
405 <literal>piggyback</literal> is 1 (default) and no sorting criteria
406 is specified, then the client will attempt to retrieve the 4
407 records as part the search response (using piggyback). On the other
408 hand, if either <literal>start</literal> is positive or if
409 a sorting criteria is set, or if <literal>piggyback</literal>
410 is 0, then the client will not perform piggyback but send Present
414 If either of the options <literal>mediumSetElementSetName</literal> and
415 <literal>smallSetElementSetName</literal> are unset, the value
416 of option <literal>elementSetName</literal> is used for piggyback
417 searches. This means that for the high-level mode you only have
418 to specify one elementSetName option rather than three.
422 <sect1 id="zoom.records"><title>Records</title>
424 A record object is a retrieval record on the client side -
425 created from result sets.
428 void ZOOM_resultset_records (ZOOM_resultset r,
430 size_t start, size_t count);
431 ZOOM_record ZOOM_resultset_record (ZOOM_resultset s, size_t pos);
433 const char *ZOOM_record_get (ZOOM_record rec, const char *type,
436 ZOOM_record ZOOM_record_clone (ZOOM_record rec);
438 void ZOOM_record_destroy (ZOOM_record rec);
441 References to temporary records are returned by functions
442 <function>ZOOM_resultset_records</function> or
443 <function>ZOOM_resultset_record</function>.
446 If a persistent reference to a record is desired
447 <function>ZOOM_record_clone</function> should be used.
448 It returns a record reference that should be destroyed
449 by a call to <function>ZOOM_record_destroy</function>.
452 A single record is returned by function
453 <function>ZOOM_resultset_record</function> that takes a
454 position as argument. First record has position zero.
455 If no record could be obtained <literal>NULL</literal> is returned.
458 Function <function>ZOOM_resultset_records</function> retrieves
459 a number of records from a result set. Parameter <literal>start</literal>
460 and <literal>count</literal> specifies the range of records to
461 be returned. Upon completion array
462 <literal>recs[0], ..recs[count-1]</literal>
463 holds record objects for the records. The array of records
464 <literal>recs</literal> should be allocated prior the call
465 <function>ZOOM_resultset_records</function>. Note that for those
466 records that couldn't be retrieved from the target
467 <literal>recs[ ..]</literal> is set to <literal>NULL</literal>.
469 <para id="zoom.record.get">
470 In order to extract information about a single record,
471 <function>ZOOM_record_get</function> is provided. The
472 function returns a pointer to certain record information. The
473 nature (type) of the pointer depends on the parameter,
474 <function>type</function>.
475 In addition, for certain types, the length
476 <literal>len</literal> passed will be set to the size in bytes of
477 the returned information.
479 <varlistentry><term><literal>database</literal></term>
480 <listitem><para>Database of record is returned
481 as a C null-terminated string. Return type
482 <literal>const char *</literal>.
485 <varlistentry><term><literal>syntax</literal></term>
486 <listitem><para>The transfer syntax (OID) of the record is returned
487 as a C null-terminated string. Return type is
488 <literal>const char *</literal>.
491 <varlistentry><term><literal>render</literal></term>
492 <listitem><para>The record is returned in a display friendly
493 format. Upon completion buffer is returned
494 (type <literal>const char *</literal>) and length is stored in
495 <literal>*len</literal>.
498 <varlistentry><term><literal>raw</literal></term>
499 <listitem><para>The record is returned in the internal
500 YAZ specific format. For GRS-1, Explain, and others, the
501 raw data is returned as type
502 <literal>Z_External *</literal> which is just the type for
503 the member <literal>retrievalRecord</literal> in
504 type <literal>NamePlusRecord</literal>.
505 For SUTRS and octet aligned record (including all MARCs) the
506 octet buffer is returned and the length of the buffer.
511 <sect2><title>Protocol behavior</title>
513 The functions <function>ZOOM_resultset_record</function> and
514 <function>ZOOM_resultset_records</function> inspects the client-side
515 record cache. Records not found in cache are fetched using
517 The functions may block (and perform network I/O) - even though option
518 <literal>async</literal> is 1, because they return records objects.
519 (and there's no way to return records objects without retrieving them!).
522 There is a trick, however, in the usage of function
523 <function>ZOOM_resultset_records</function> that allows for
524 delayed retrieval (and makes it non-blocking). By passing
525 a null pointer for <parameter>recs</parameter> you're indicating
526 you're not interested in getting records objects
527 <emphasis>now</emphasis>.
531 <sect1 id="zoom.scan"><title>Scan</title>
533 This section describes an interface for Scan. Scan is not an
534 official part of the ZOOM model yet. The result of a scan operation
535 is the <literal>ZOOM_scanset</literal> which is a set of terms
536 returned by a target.
539 ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c,
540 const char *startterm);
542 size_t ZOOM_scanset_size(ZOOM_scanset scan);
544 const char * ZOOM_scanset_term(ZOOM_scanset scan, size_t pos,
545 int *occ, size_t *len);
548 void ZOOM_scanset_destroy (ZOOM_scanset scan);
550 const char *ZOOM_scanset_option_get (ZOOM_scanset scan,
553 void ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
557 The scan set is created by function
558 <function>ZOOM_connection_scan</function> which performs a scan
559 operation on the connection and start term given.
560 If the operation was successful, the size of the scan set can be
561 retrieved by a call to <function>ZOOM_scanset_size</function>.
562 Like result sets, the items are numbered 0,..size-1.
563 To obtain information about a particular scan term, call function
564 <function>ZOOM_scanset_term</function>. This function takes
565 a scan set offset <literal>pos</literal> and returns a pointer
566 to an actual term or <literal>NULL</literal> if non-present.
567 If present, the <literal>occ</literal> and <literal>len</literal>
568 are set to the number of occurrences and the length
569 of the actual term respectively.
570 A scan set may be freed by a call to function
571 <function>ZOOM_scanset_destroy</function>.
572 Functions <function>ZOOM_scanset_option_get</function> and
573 <function>ZOOM_scanset_option_set</function> retrieves and sets
574 an option respectively.
577 <table frame="top"><title>ZOOM Scan Set Options</title>
579 <colspec colwidth="4*" colname="name"></colspec>
580 <colspec colwidth="7*" colname="description"></colspec>
581 <colspec colwidth="2*" colname="default"></colspec>
584 <entry>Option</entry>
585 <entry>Description</entry>
586 <entry>Default</entry>
591 number</entry><entry>Number of Scan Terms requested in next scan.
592 After scan it holds the actual number of terms returned.
593 </entry><entry>10</entry></row>
595 position</entry><entry>Preferred Position of term in response
596 in next scan; actual position after completion of scan.
597 </entry><entry>1</entry></row>
599 stepSize</entry><entry>Step Size
600 </entry><entry>0</entry></row>
602 scanStatus</entry><entry>An integer indicating the Scan Status
604 </entry><entry>0</entry></row>
610 <sect1 id="zoom.options"><title>Options</title>
612 Most &zoom; objects provide a way to specify options to change behavior.
613 From an implementation point of view a set of options is just like
614 an associative array / hash array, etc.
617 ZOOM_options ZOOM_options_create (void);
619 ZOOM_options ZOOM_options_create_with_parent (ZOOM_options parent);
621 void ZOOM_options_destroy (ZOOM_options opt);
624 const char *ZOOM_options_get (ZOOM_options opt, const char *name);
626 void ZOOM_options_set (ZOOM_options opt, const char *name,
630 typedef const char *(*ZOOM_options_callback)
631 (void *handle, const char *name);
633 ZOOM_options_callback
634 ZOOM_options_set_callback (ZOOM_options opt,
635 ZOOM_options_callback c,
639 <sect1 id="zoom.events"><title>Events</title>
641 If you're developing non-blocking applications, you have to deal
645 int ZOOM_event (int no, ZOOM_connection *cs);
648 The <function>ZOOM_event</function> executes pending events for
649 a number of connections. Supply the number of connections in
650 <literal>no</literal> and an array of connections in
651 <literal>cs</literal> (<literal>cs[0] ... cs[no-1]</literal>).
652 A pending event could be a sending a search, receiving a response,
654 When an event has occurred for one of the connections, this function
655 returns a positive integer <literal>n</literal> denoting that an event
656 occurred for connection <literal>cs[n-1]</literal>.
657 When no events are pending for the connections, a value of zero is
659 To ensure that all outstanding requests are performed call this function
660 repeatedly until zero is returned.
665 <!-- Keep this comment at the end of the file
670 sgml-minimize-attributes:nil
671 sgml-always-quote-attributes:t
674 sgml-parent-document: "yaz.xml"
675 sgml-local-catalogs: nil
676 sgml-namecase-general:t