1 <!-- $Id: zoom.xml,v 1.20 2002-09-25 20:32:53 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 further, 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 web-site</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 describes 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 port number, <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="top"><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>
142 lang</entry><entry> Language for negotiation.
143 </entry><entry>none</entry></row>
145 charset</entry><entry> Character set for negotiation.
146 </entry><entry>none</entry></row>
151 If either option <literal>lang</literal> or <literal>charset</literal>
153 <ulink url="http://lcweb.loc.gov/z3950/agency/defns/charneg-3.html">
154 Character Set and Language Negotiation</ulink> is in effect.
157 int ZOOM_connection_error (ZOOM_connection c, const char **cp,
158 const char **addinfo);
161 Use <function>ZOOM_connection_error</function> to check for
162 errors for the last operation(s) performed. The function returns
163 zero if no errors occurred; non-zero otherwise indicating the error.
164 Pointers <parameter>cp</parameter> and <parameter>addinfo</parameter>
165 holds messages for the error and additional-info if passed as
166 non-<literal>NULL</literal>.
168 <sect2><title>Protocol behavior</title>
170 The calls <function>ZOOM_connection_new</function> and
171 <function>ZOOM_connection_connect</function> establishes a TCP/IP
172 connection and sends an Initialize Request to the target if
173 possible. In addition, the calls waits for an Initialize Response
174 from the target and the result is inspected (OK or rejected).
177 If <literal>proxy</literal> is set then the client will establish
178 a TCP/IP connection with the peer as specified by the
179 <literal>proxy</literal> host and the hostname as part of the
180 connect calls will be set as part of the Initialize Request.
181 The proxy server will then "forward" the PDU's transparently
182 to the target behind the proxy.
185 For the authentication parameters, if option <literal>user</literal>
186 is set and both options <literal>group</literal> and
187 <literal>pass</literal> are unset, then Open style
188 authentication is used (Version 2/3) in which case the username
189 is usually followed by a slash, then by a password.
190 If either <literal>group</literal>
191 or <literal>pass</literal> is set then idPass authentication
192 (Version 3 only) is used. If none of the options are set, no
193 authentication parameters are set as part of the Initialize Request
197 When option <literal>async</literal> is 1, it really means that
198 all network operations are postponed (and queued) until the
199 function <literal>ZOOM_event</literal> is invoked. When doing so
200 it doesn't make sense to check for errors after
201 <literal>ZOOM_connection_new</literal> is called since that
202 operation "connecting - and init" is still incomplete and the
203 API cannot tell the outcome (yet).
207 <sect1 id="zoom.query"><title>Queries</title>
209 Query objects represents queries.
212 ZOOM_query ZOOM_query_create(void);
214 void ZOOM_query_destroy(ZOOM_query q);
216 int ZOOM_query_prefix(ZOOM_query q, const char *str);
218 int ZOOM_query_sortby(ZOOM_query q, const char *criteria);
221 Create query objects using <function>ZOOM_query_create</function>
222 and destroy them by calling <function>ZOOM_query_destroy</function>.
223 RPN-queries can be specified in <link linkend="PQF">PQF</link>
224 notation by using the
225 function <function>ZOOM_query_prefix</function>. More
226 query types will be added later, such as
227 <link linkend="CCL">CCL</link> to RPN-mapping, native CCL query,
228 etc. In addition to a search, a sort criteria may be set. Function
229 <function>ZOOM_query_sortby</function> specifies a
230 sort criteria using the same string notation for sort as offered by
231 the <link linkend="sortspec">YAZ client</link>.
233 <sect2><title>Protocol behavior</title>
235 The query object is just an interface for the member Query
236 in the SearchRequest. The sortby-function is an interface to the
237 sortSequence member of the SortRequest.
241 <sect1 id="zoom.resultsets"><title>Result sets</title>
243 The result set object is a container for records returned from
247 ZOOM_resultset ZOOM_connection_search(ZOOM_connection,
250 ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c,
253 void ZOOM_resultset_destroy(ZOOM_resultset r);
256 Function <function>ZOOM_connection_search</function> creates
257 a result set given a connection and query.
258 Destroy a result set by calling
259 <function>ZOOM_resultset_destroy</function>.
260 Simple clients may using PQF only may use function
261 <function>ZOOM_connection_search_pqf</function> in which case
262 creating query objects is not necessary.
265 void ZOOM_resultset_option_set (ZOOM_resultset r,
269 const char *ZOOM_resultset_option_get (ZOOM_resultset r,
272 size_t ZOOM_resultset_size (ZOOM_resultset r);
275 Functions <function>ZOOM_resultset_options_set</function> and
276 <function>ZOOM_resultset_get</function> sets and gets an option
277 for a result set similar to <function>ZOOM_connection_option_get</function>
278 and <function>ZOOM_connection_option_set</function>.
281 The number of hits also called result-count is returned by
282 function <function>ZOOM_resultset_size</function>.
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 schema</entry><entry>Schema for retrieval, such as
320 <literal>Gils-schema</literal>, <literal>Geo-schema</literal>, etc.
321 </entry><entry>none</entry></row>
323 smallSetUpperBound</entry><entry>If hits is less than or equal to this
324 value, then target will return all records using small element set name
325 </entry><entry>0</entry></row>
327 largeSetLowerBound</entry><entry>If hits is greater than this
328 value, the target will return no records.
329 </entry><entry>1</entry></row>
331 mediumSetPresentNumber</entry><entry>This value represents
332 the number of records to be returned as part of a search when when
333 hits is less than or equal to large set lower bound and if hits
334 is greater than small set upper bound.
335 </entry><entry>0</entry></row>
337 smallSetElementSetName</entry><entry>
338 The element set name to be used for small result sets.
339 </entry><entry>none</entry></row>
341 mediumSetElementSetName</entry><entry>
342 The element set name to be for medium-sized result sets.
343 </entry><entry>none</entry></row>
345 databaseName</entry><entry>One or more database names
346 separated by character plus (<literal>+</literal>).
347 </entry><entry>Default</entry></row>
349 setname</entry><entry>Name of Result Set (Result Set ID).
350 If this option isn't set, the ZOOM module will automatically
351 allocate a result set name.
352 </entry><entry>default</entry></row>
357 <title>Protocol behavior</title>
359 The creation of a result set involves at least a SearchRequest
360 - SearchResponse protocol handshake. Following that, if a sort
361 criteria was specified as part of the query, a SortRequest -
362 SortResponse handshake takes place. Note that it is necessary to
363 perform sorting before any retrieval takes place, so no records will
364 be returned from the target as part of the SearchResponse because these
365 would be unsorted. Hence, piggyback is disabled when sort criteria
366 is set. Following Search - and a Possible sort, Retrieval takes
367 place - as one or more Present Requests - Present Response being
371 The API allows for two different modes for retrieval. A high level
372 mode which is somewhat more powerful and a low level one.
373 The low level is "enabled" when the settings
374 <literal>smallSetUpperBound</literal>,
375 <literal>mediumSetPresentNumber</literal> and
376 <literal>largeSetLowerBound</literal> are set. The low level mode
377 thus allows you to precisely set how records are returned as part
378 of a search response as offered by the Z39.50 protocol.
379 Since the client may be retrieving records as part of the
380 search response, this mode doesn't work well if sorting is used.
383 The high-level mode allows you to fetch a range of records from
384 the result set with a given start offset. When you use this mode
385 the client will automatically use piggyback if that is possible
386 with the target and perform one or more present requests as needed.
387 Even if the target returns fewer records as part of a present response
388 because of a record size limit, etc. the client will repeat sending
389 present requests. As an example, if option <literal>start</literal>
390 is 0 (default) and <literal>count</literal> is 4, and
391 <literal>piggyback</literal> is 1 (default) and no sorting criteria
392 is specified, then the client will attempt to retrieve the 4
393 records as part the search response (using piggyback). On the other
394 hand, if either <literal>start</literal> is positive or if
395 a sorting criteria is set, or if <literal>piggyback</literal>
396 is 0, then the client will not perform piggyback but send Present
400 If either of the options <literal>mediumSetElementSetName</literal> and
401 <literal>smallSetElementSetName</literal> are unset, the value
402 of option <literal>elementSetName</literal> is used for piggyback
403 searches. This means that for the high-level mode you only have
404 to specify one elementSetName option rather than three.
408 <sect1 id="zoom.records"><title>Records</title>
410 A record object is a retrieval record on the client side -
411 created from result sets.
414 void ZOOM_resultset_records (ZOOM_resultset r,
416 size_t start, size_t count);
417 ZOOM_record ZOOM_resultset_record (ZOOM_resultset s, size_t pos);
419 const char *ZOOM_record_get (ZOOM_record rec, const char *type,
422 ZOOM_record ZOOM_record_clone (ZOOM_record rec);
424 void ZOOM_record_destroy (ZOOM_record rec);
427 References to temporary records are returned by functions
428 <function>ZOOM_resultset_records</function> or
429 <function>ZOOM_resultset_record</function>.
432 If a persistent reference to a record is desired
433 <function>ZOOM_record_clone</function> should be used.
434 It returns a record reference that should be destroyed
435 by a call to <function>ZOOM_record_destroy</function>.
438 A single record is returned by function
439 <function>ZOOM_resultset_record</function> that takes a
440 position as argument. First record has position zero.
441 If no record could be obtained <literal>NULL</literal> is returned.
444 Function <function>ZOOM_resultset_records</function> retrieves
445 a number of records from a result set. Parameter <literal>start</literal>
446 and <literal>count</literal> specifies the range of records to
447 be returned. Upon completion array
448 <literal>recs[0], ..recs[count-1]</literal>
449 holds record objects for the records. The array of records
450 <literal>recs</literal> should be allocated prior the call
451 <function>ZOOM_resultset_records</function>. Note that for those
452 records that couldn't be retrieved from the target
453 <literal>recs[ ..]</literal> is set to <literal>NULL</literal>.
455 <para id="zoom.record.get">
456 In order to extract information about a single record,
457 <function>ZOOM_record_get</function> is provided. The
458 function returns a pointer to certain record information. The
459 nature (type) of the pointer depends on the parameter,
460 <function>type</function>.
461 In addition, for certain types, the length
462 <literal>len</literal> passed will be set to the size in bytes of
463 the returned information.
465 <varlistentry><term><literal>database</literal></term>
466 <listitem><para>Database of record is returned
467 as a C null-terminated string. Return type
468 <literal>const char *</literal>.
471 <varlistentry><term><literal>syntax</literal></term>
472 <listitem><para>The transfer syntax (OID) of the record is returned
473 as a C null-terminated string. Return type is
474 <literal>const char *</literal>.
477 <varlistentry><term><literal>render</literal></term>
478 <listitem><para>The record is returned in a display friendly
479 format. Upon completion buffer is returned
480 (type <literal>const char *</literal>) and length is stored in
481 <literal>*len</literal>.
484 <varlistentry><term><literal>raw</literal></term>
485 <listitem><para>The record is returned in the internal
486 YAZ specific format. For GRS-1, Explain, and others, the
487 raw data is returned as type
488 <literal>Z_External *</literal> which is just the type for
489 the member <literal>retrievalRecord</literal> in
490 type <literal>NamePlusRecord</literal>.
491 For SUTRS and octet aligned record (including all MARCs) the
492 octet buffer is returned and the length of the buffer.
497 <sect2><title>Protocol behavior</title>
499 The functions <function>ZOOM_resultset_record</function> and
500 <function>ZOOM_resultset_records</function> inspects the client-side
501 record cache. Records not found in cache are fetched using
503 The functions may block (and perform network I/O) - even though option
504 <literal>async</literal> is 1, because they return records objects.
505 (and there's no way to return records objects without retrieving them!).
508 There is a trick, however, in the usage of function
509 <function>ZOOM_resultset_records</function> that allows for
510 delayed retrieval (and makes it non-blocking). By passing
511 a null pointer for <parameter>recs</parameter> you're indicating
512 you're not interested in getting records objects
513 <emphasis>now</emphasis>.
517 <sect1 id="zoom.scan"><title>Scan</title>
519 This section describes an interface for Scan. Scan is not an
520 official part of the ZOOM model yet. The result of a scan operation
521 is the <literal>ZOOM_scanset</literal> which is a set of terms
522 returned by a target.
525 ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c,
526 const char *startterm);
528 size_t ZOOM_scanset_size(ZOOM_scanset scan);
530 const char * ZOOM_scanset_term(ZOOM_scanset scan, size_t pos,
531 int *occ, size_t *len);
534 void ZOOM_scanset_destroy (ZOOM_scanset scan);
536 const char *ZOOM_scanset_option_get (ZOOM_scanset scan,
539 void ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
543 The scan set is created by function
544 <function>ZOOM_connection_scan</function> which performs a scan
545 operation on the connection and start term given.
546 If the operation was successful, the size of the scan set can be
547 retrieved by a call to <function>ZOOM_scanset_size</function>.
548 Like result sets, the items are numbered 0,..size-1.
549 To obtain information about a particular scan term, call function
550 <function>ZOOM_scanset_term</function>. This function takes
551 a scan set offset <literal>pos</literal> and returns a pointer
552 to an actual term or <literal>NULL</literal> if non-present.
553 If present, the <literal>occ</literal> and <literal>len</literal>
554 are set to the number of occurrences and the length
555 of the actual term respectively.
556 A scan set may be freed by a call to function
557 <function>ZOOM_scanset_destroy</function>.
558 Functions <function>ZOOM_scanset_option_get</function> and
559 <function>ZOOM_scanset_option_set</function> retrieves and sets
560 an option respectively.
563 <table frame="top"><title>ZOOM Scan Set Options</title>
565 <colspec colwidth="4*" colname="name"></colspec>
566 <colspec colwidth="7*" colname="description"></colspec>
567 <colspec colwidth="2*" colname="default"></colspec>
570 <entry>Option</entry>
571 <entry>Description</entry>
572 <entry>Default</entry>
577 number</entry><entry>Number of Scan Terms requested in next scan.
578 After scan it holds the actual number of terms returned.
579 </entry><entry>10</entry></row>
581 position</entry><entry>Preferred Position of term in response
582 in next scan; actual position after completion of scan.
583 </entry><entry>1</entry></row>
585 stepSize</entry><entry>Step Size
586 </entry><entry>0</entry></row>
588 scanStatus</entry><entry>An integer indicating the Scan Status
590 </entry><entry>0</entry></row>
596 <sect1 id="zoom.options"><title>Options</title>
598 Most &zoom; objects provide a way to specify options to change behavior.
599 From an implementation point of view a set of options is just like
600 an associative array / hash array, etc.
603 ZOOM_options ZOOM_options_create (void);
605 ZOOM_options ZOOM_options_create_with_parent (ZOOM_options parent);
607 void ZOOM_options_destroy (ZOOM_options opt);
610 const char *ZOOM_options_get (ZOOM_options opt, const char *name);
612 void ZOOM_options_set (ZOOM_options opt, const char *name,
616 typedef const char *(*ZOOM_options_callback)
617 (void *handle, const char *name);
619 ZOOM_options_callback
620 ZOOM_options_set_callback (ZOOM_options opt,
621 ZOOM_options_callback c,
625 <sect1 id="zoom.events"><title>Events</title>
627 If you're developing non-blocking applications, you have to deal
631 int ZOOM_event (int no, ZOOM_connection *cs);
634 The <function>ZOOM_event</function> executes pending events for
635 a number of connections. Supply the number of connections in
636 <literal>no</literal> and an array of connections in
637 <literal>cs</literal> (<literal>cs[0] ... cs[no-1]</literal>).
638 A pending event could be a sending a search, receiving a response,
640 When an event has occurred for one of the connections, this function
641 returns a positive integer <literal>n</literal> denoting that an event
642 occurred for connection <literal>cs[n-1]</literal>.
643 When no events are pending for the connections, a value of zero is
645 To ensure that all outstanding requests are performed call this function
646 repeatedly until zero is returned.
651 <!-- Keep this comment at the end of the file
656 sgml-minimize-attributes:nil
657 sgml-always-quote-attributes:t
660 sgml-parent-document: "yaz.xml"
661 sgml-local-catalogs: nil
662 sgml-namecase-general:t