Added include of yaz-util.h
[yaz-moved-to-github.git] / doc / zoom.xml
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>
3   
4   <para>
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.
10   </para>
11   <para>
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
14    became available,
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
20    more
21    are in active development. See the
22    <ulink url="http://zoom.z3950.org/">ZOOM web-site</ulink> for
23    more information.
24   </para>
25
26   <para>
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>
30    directory.
31   </para>
32
33   <para>
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.
42   </para>
43   <para>
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
46    protocol.
47   </para>
48   <sect1 id="zoom.connections"><title>Connections</title>
49    
50    <para>The Connection object is a session with a target.
51    </para>
52    <synopsis>
53    #include &lt;yaz/zoom.h>
54     
55    ZOOM_connection ZOOM_connection_new (const char *host, int portnum);
56     
57    ZOOM_connection ZOOM_connection_create (ZOOM_options options);
58
59    void ZOOM_connection_connect(ZOOM_connection c, const char *host,
60                                  int portnum);
61    void ZOOM_connection_destroy (ZOOM_connection c);
62    </synopsis>
63    <para>
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.
77    </para>
78    <para>
79     Connection objects should be destroyed using the function
80     <function>ZOOM_connection_destroy</function>.
81    </para>
82    <synopsis>
83     void ZOOM_connection_option_set (ZOOM_connection c,
84                                      const char *key,
85                                      const char *val);
86
87     const char *ZOOM_connection_option_get (ZOOM_connection c,
88                                             const char *key);
89    </synopsis>
90    <para>
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>.
96    </para>
97    <table frame="top"><title>ZOOM Connection Options</title>
98     <tgroup cols="3">
99      <colspec colwidth="4*" colname="name"></colspec>
100      <colspec colwidth="7*" colname="description"></colspec>
101      <colspec colwidth="3*" colname="default"></colspec>
102      <thead>
103       <row>
104        <entry>Option</entry>
105        <entry>Description</entry>
106        <entry>Default</entry>
107       </row>
108      </thead>
109      <tbody>
110       <row><entry>
111         implementationName</entry><entry>Name of Your client
112        </entry><entry>none</entry></row>
113       <row><entry>
114         user</entry><entry>Authentication user name
115        </entry><entry>none</entry></row>
116       <row><entry>
117         group</entry><entry>Authentication group name
118        </entry><entry>none</entry></row>
119       <row><entry>
120         pass</entry><entry>Authentication password
121       </entry><entry>none</entry></row>
122       <row><entry>
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>
126       <row><entry>
127         proxy</entry><entry>Proxy host
128        </entry><entry>none</entry></row>
129       <row><entry>
130         async</entry><entry>If true (1) the connection operates in 
131         asynchronous operation which means that all calls are non-blocking
132         except
133         <link linkend="zoom.events"><function>ZOOM_event</function></link>.
134        </entry><entry>0</entry></row>
135       <row><entry>
136         maximumRecordSize</entry><entry> Maximum size of single record.
137        </entry><entry>1 MB</entry></row>
138       <row><entry>
139         preferredMessageSize</entry><entry> Maximum size of multiple records.
140        </entry><entry>1 MB</entry></row>
141       <row><entry>
142         lang</entry><entry> Language for negotiation.
143        </entry><entry>none</entry></row>
144       <row><entry>
145         charset</entry><entry> Character set for negotiation.
146        </entry><entry>none</entry></row>
147      </tbody>
148     </tgroup>
149    </table>
150    <para>
151     If either option <literal>lang</literal> or <literal>charset</literal>
152     is set, then 
153     <ulink url="http://lcweb.loc.gov/z3950/agency/defns/charneg-3.html">
154      Character Set and Language Negotiation</ulink> is in effect.
155    </para>
156    <synopsis>
157      int ZOOM_connection_error (ZOOM_connection c, const char **cp,
158                                  const char **addinfo);
159    </synopsis>
160    <para>
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>.
167    </para>
168    <sect2><title>Protocol behavior</title>
169     <para>
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).
175     </para>
176     <para>
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.
183     </para>
184     <para>
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
194      (obviously).
195     </para>
196     <para>
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).
204     </para>
205     </sect2>
206   </sect1>
207   <sect1 id="zoom.query"><title>Queries</title>
208    <para>
209     Query objects represents queries.
210    </para>
211    <synopsis>
212      ZOOM_query ZOOM_query_create(void);
213
214      void ZOOM_query_destroy(ZOOM_query q);
215
216      int ZOOM_query_prefix(ZOOM_query q, const char *str);
217
218      int ZOOM_query_sortby(ZOOM_query q, const char *criteria);
219    </synopsis>
220    <para>
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>.
232    </para>
233    <sect2><title>Protocol behavior</title>
234     <para>
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.
238     </para>
239    </sect2>
240   </sect1>
241   <sect1 id="zoom.resultsets"><title>Result sets</title>
242    <para>
243     The result set object is a container for records returned from
244     a target.
245    </para>
246    <synopsis>
247      ZOOM_resultset ZOOM_connection_search(ZOOM_connection,
248                                            ZOOM_query q);
249
250      ZOOM_resultset ZOOM_connection_search_pqf(ZOOM_connection c,
251                                                const char *q);
252
253      void ZOOM_resultset_destroy(ZOOM_resultset r);
254    </synopsis>
255    <para>
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.
263    </para>
264    <synopsis>
265      void ZOOM_resultset_option_set (ZOOM_resultset r,
266                                       const char *key,
267                                       const char *val);
268
269      const char *ZOOM_resultset_option_get (ZOOM_resultset r,
270                                              const char *key);
271
272      size_t ZOOM_resultset_size (ZOOM_resultset r);
273    </synopsis>
274    <para>
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>.
279    </para>
280    <para>
281     The number of hits also called result-count is returned by
282     function <function>ZOOM_resultset_size</function>.
283    </para>
284    <table frame="top"><title>ZOOM Result set Options</title>
285     <tgroup cols="3">
286      <colspec colwidth="4*" colname="name"></colspec>
287      <colspec colwidth="7*" colname="description"></colspec>
288      <colspec colwidth="2*" colname="default"></colspec>
289      <thead>
290       <row>
291        <entry>Option</entry>
292        <entry>Description</entry>
293        <entry>Default</entry>
294       </row>
295      </thead>
296      <tbody>
297       <row><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>
301       <row><entry>
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>
306       <row><entry>
307         count</entry><entry>Number of records to be retrieved.
308        </entry><entry>0</entry></row>
309       <row><entry>
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>
314       <row><entry>
315         preferredRecordSyntax</entry><entry>Preferred Syntax, such as
316         <literal>USMARC</literal>, <literal>SUTRS</literal>, etc.
317        </entry><entry>none</entry></row>
318       <row><entry>
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>
322       <row><entry>
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>
326       <row><entry>
327         largeSetLowerBound</entry><entry>If hits is greater than this
328         value, the target will return no records.
329        </entry><entry>1</entry></row>
330       <row><entry>
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>
336       <row><entry>
337         smallSetElementSetName</entry><entry>
338         The element set name to be used for small result sets.
339        </entry><entry>none</entry></row>
340       <row><entry>
341         mediumSetElementSetName</entry><entry>
342         The element set name to be for medium-sized result sets.
343        </entry><entry>none</entry></row>
344       <row><entry>
345         databaseName</entry><entry>One or more database names
346         separated by character plus (<literal>+</literal>).
347        </entry><entry>Default</entry></row>
348       <row><entry>
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>
353      </tbody>
354     </tgroup>
355    </table>
356    <sect2>
357     <title>Protocol behavior</title>
358     <para>
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
368      transferred.
369      </para>
370     <para>
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.
381      </para>
382     <para>
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
397      Requests instead.
398     </para>
399     <para>
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.
405      </para>
406    </sect2>
407   </sect1>
408   <sect1 id="zoom.records"><title>Records</title>
409    <para>
410     A record object is a retrieval record on the client side -
411     created from result sets.
412    </para>
413    <synopsis>
414      void ZOOM_resultset_records (ZOOM_resultset r,
415                                   ZOOM_record *recs,
416                                   size_t start, size_t count);
417      ZOOM_record ZOOM_resultset_record (ZOOM_resultset s, size_t pos);
418
419      const char *ZOOM_record_get (ZOOM_record rec, const char *type,
420                                   size_t *len);
421
422      ZOOM_record ZOOM_record_clone (ZOOM_record rec);
423
424      void ZOOM_record_destroy (ZOOM_record rec);
425    </synopsis>
426    <para>
427     References to temporary records are returned by functions 
428     <function>ZOOM_resultset_records</function> or
429     <function>ZOOM_resultset_record</function>.
430     </para>
431    <para>
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>.
436    </para>
437    <para>
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.
442    </para>
443    <para>
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>.
454    </para>
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.
464     <variablelist>
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>. 
469        </para></listitem>
470       </varlistentry>
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>. 
475        </para></listitem>
476       </varlistentry>
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>.
482        </para></listitem>
483       </varlistentry>
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.
493        </para></listitem>
494       </varlistentry>
495     </variablelist>
496    </para>
497    <sect2><title>Protocol behavior</title>
498     <para>
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
502      Present.
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!).
506      </para>
507     <para>
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>.
514     </para>
515    </sect2>
516   </sect1>
517   <sect1 id="zoom.scan"><title>Scan</title>
518    <para>
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.
523    </para>
524    <synopsis>
525     ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c,
526                                        const char *startterm);
527
528     size_t ZOOM_scanset_size(ZOOM_scanset scan);
529
530     const char * ZOOM_scanset_term(ZOOM_scanset scan, size_t pos,
531                                    int *occ, size_t *len);
532
533
534     void ZOOM_scanset_destroy (ZOOM_scanset scan);
535
536     const char *ZOOM_scanset_option_get (ZOOM_scanset scan,
537                                          const char *key);
538
539     void ZOOM_scanset_option_set (ZOOM_scanset scan, const char *key,
540                                   const char *val);
541     </synopsis>
542    <para>
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.
561    </para>
562    
563    <table frame="top"><title>ZOOM Scan Set Options</title>
564     <tgroup cols="3">
565      <colspec colwidth="4*" colname="name"></colspec>
566      <colspec colwidth="7*" colname="description"></colspec>
567      <colspec colwidth="2*" colname="default"></colspec>
568      <thead>
569       <row>
570        <entry>Option</entry>
571        <entry>Description</entry>
572        <entry>Default</entry>
573       </row>
574      </thead>
575      <tbody>
576       <row><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>
580       <row><entry>
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>
584       <row><entry>
585         stepSize</entry><entry>Step Size
586        </entry><entry>0</entry></row>
587       <row><entry>
588         scanStatus</entry><entry>An integer indicating the Scan Status
589         of last scan.
590        </entry><entry>0</entry></row>
591      </tbody>
592     </tgroup>
593    </table>
594    
595   </sect1>
596   <sect1 id="zoom.options"><title>Options</title>
597    <para>
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.
601    </para>
602    <synopsis>
603      ZOOM_options ZOOM_options_create (void);
604
605      ZOOM_options ZOOM_options_create_with_parent (ZOOM_options parent);
606
607      void ZOOM_options_destroy (ZOOM_options opt);
608    </synopsis>
609    <synopsis>
610      const char *ZOOM_options_get (ZOOM_options opt, const char *name);
611
612      void ZOOM_options_set (ZOOM_options opt, const char *name,
613                             const char *v);
614    </synopsis>
615    <synopsis>
616      typedef const char *(*ZOOM_options_callback)
617                                      (void *handle, const char *name);
618
619      ZOOM_options_callback
620              ZOOM_options_set_callback (ZOOM_options opt,
621                                         ZOOM_options_callback c,
622                                         void *handle);
623    </synopsis>
624   </sect1>
625   <sect1 id="zoom.events"><title>Events</title>
626    <para>
627     If you're developing non-blocking applications, you have to deal 
628     with events.
629    </para>
630    <synopsis>
631     int ZOOM_event (int no, ZOOM_connection *cs);
632    </synopsis>
633    <para>
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,
639     etc.
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
644     returned.
645     To ensure that all outstanding requests are performed call this function
646     repeatedly until zero is returned.
647    </para>
648   </sect1>
649  </chapter>
650  
651  <!-- Keep this comment at the end of the file
652  Local variables:
653  mode: sgml
654  sgml-omittag:t
655  sgml-shorttag:t
656  sgml-minimize-attributes:nil
657  sgml-always-quote-attributes:t
658  sgml-indent-step:1
659  sgml-indent-data:t
660  sgml-parent-document: "yaz.xml"
661  sgml-local-catalogs: nil
662  sgml-namecase-general:t
663  End:
664  -->
665