--- 1.8.4 2001/XX/XX
+Scan for ZOOM API. New object ZOOM_scanset. New functions
+ZOOM_connection_scan, ZOOM_scanset_size, ZOOM_scanset_term and
+ZOOM_scanset_destroy.
+
+New ZOOM function, ZOOM_connection_last_event, that returns type
+of last event (such as "receive data", "send data", "apdu received",
+etc.
+
New ZOOM option, schema, that specifies shema OID for retrieval.
New CCL feature. Qualifiers can be aliases for one or more
/*
* Public header for ZOOM C.
- * $Id: zoom.h,v 1.7 2001-11-18 21:14:23 adam Exp $
+ * $Id: zoom.h,v 1.8 2001-12-30 22:21:11 adam Exp $
*/
#include <yaz/yconfig.h>
typedef struct ZOOM_resultset_p *ZOOM_resultset;
typedef struct ZOOM_task_p *ZOOM_task;
typedef struct ZOOM_record_p *ZOOM_record;
+typedef struct ZOOM_scanset_p *ZOOM_scanset;
/* ----------------------------------------------------------- */
/* connections */
#define ZOOM_ERROR_INTERNAL 10006
#define ZOOM_ERROR_TIMEOUT 10007
+ZOOM_EXPORT
+int ZOOM_connection_last_event(ZOOM_connection cs);
+
+#define ZOOM_EVENT_NONE 0
+#define ZOOM_EVENT_CONNECT 1
+#define ZOOM_EVENT_SEND_DATA 2
+#define ZOOM_EVENT_RECV_DATA 3
+#define ZOOM_EVENT_TIMEOUT 4
+#define ZOOM_EVENT_UNKNOWN 5
+#define ZOOM_EVENT_SEND_APDU 6
+#define ZOOM_EVENT_RECV_APDU 7
+
/* ----------------------------------------------------------- */
/* result sets */
/* retrieve records */
ZOOM_EXPORT
void ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs,
- size_t start, size_t count);
+ size_t start, size_t count);
/* return record object at pos. Returns 0 if unavailable */
ZOOM_EXPORT
ZOOM_record ZOOM_record_clone (ZOOM_record srec);
/* ----------------------------------------------------------- */
-/* searches */
+/* queries */
/* create search object */
ZOOM_EXPORT
int ZOOM_query_sortby(ZOOM_query s, const char *criteria);
/* ----------------------------------------------------------- */
+/* scan */
+ZOOM_EXPORT
+ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c, const char *startterm);
+
+ZOOM_EXPORT
+const char * ZOOM_scanset_term(ZOOM_scanset scan, size_t no, int *occ, size_t *len);
+
+ZOOM_EXPORT
+size_t ZOOM_scanset_size(ZOOM_scanset scan);
+
+ZOOM_EXPORT
+void ZOOM_scanset_destroy (ZOOM_scanset scan);
+/* ----------------------------------------------------------- */
/* options */
typedef const char *(*ZOOM_options_callback)(void *handle, const char *name);
/* poll for events on a number of connections. Returns positive
integer if event occurred ; zero if none occurred and no more
events are pending. The positive integer specifies the
- connection for which the event occurred. There's no way to get
- the details yet, sigh. */
+ connection for which the event occurred. */
ZOOM_EXPORT
int ZOOM_event (int no, ZOOM_connection *cs);
# makefile.mak - makefile for MS NMAKE
-# $Id: makefile,v 1.30 2001-10-28 23:28:26 adam Exp $
+# $Id: makefile,v 1.31 2001-12-30 22:21:11 adam Exp $
#
# Programmed by
# HL: Heikki Levanto, Index Data
ZOOMTST5=$(BINDIR)\zoomtst5.exe
ZOOMTST6=$(BINDIR)\zoomtst6.exe
ZOOMTST7=$(BINDIR)\zoomtst7.exe
-
+ZOOMTST8=$(BINDIR)\zoomtst8.exe
# shortcut names defined here
dll : $(DLL)
client: $(CLIENT)
ztest: $(ZTEST)
+
zoomsh: $(ZOOMSH) $(ZOOMTST1) $(ZOOMTST2) $(ZOOMTST3) \
- $(ZOOMTST4) $(ZOOMTST5) $(ZOOMTST6) $(ZOOMTST7)
+ $(ZOOMTST4) $(ZOOMTST5) $(ZOOMTST6) $(ZOOMTST7) $(ZOOMTST8)
+
yaz_date_h: $(YAZ_DATE_H)
###########################################################
$(OBJDIR)\zoomtst6.obj
YAZ_ZOOMTST7_OBJS = \
$(OBJDIR)\zoomtst7.obj
+YAZ_ZOOMTST8_OBJS = \
+ $(OBJDIR)\zoomtst8.obj
YAZ_SERVER_OBJS= \
"$(OBJDIR)\eventl.obj" \
/out:$(ZOOMTST7)
<<
+$(ZOOMTST8) : "$(BINDIR)" $(YAZ_ZOOMTST8_OBJS)
+ @echo Linking $(ZOOMTST8)
+ $(LINK) @<<
+ $(LNKOPT)
+ $(ZOOMSH_LINK_OPTIONS)
+ $(LINK_LIBS)
+ $(IMPLIB)
+ $(YAZ_ZOOMTST8_OBJS)
+ /pdb:"$(LIBDIR)\zoomtst8.pdb"
+ /map:"$(LIBDIR)\zoomtst8.map"
+ /out:$(ZOOMTST8)
+<<
+
$(ZTEST) : "$(BINDIR)" $(ZTEST_OBJS) $(DLL)
@echo Linking the ztest $(ZTEST)
$(LINK) @<<
dirs: $(OBJDIR) $(WINDIR) $(LIBDIR) $(BINDIR) $(TMPDIR)
$(OBJDIR) $(WINDIR) $(LIBDIR) $(BINDIR) $(TMPDIR):
- if not exist "$@/$(NUL)" mkdir "$@"
+ if not exist "$@/$(NUL)" mkdir "$@"
###########################################################
###########################################################
#
# $Log: makefile,v $
-# Revision 1.30 2001-10-28 23:28:26 adam
+# Revision 1.31 2001-12-30 22:21:11 adam
+# Scan for ZOOM.
+#
+# Revision 1.30 2001/10/28 23:28:26 adam
# Enable CCL-to-RPN for YAZ client on WIN32.
#
# Revision 1.29 2001/10/25 12:46:07 adam
-## $Id: Makefile.am,v 1.1 2001-10-23 21:00:20 adam Exp $
+## $Id: Makefile.am,v 1.2 2001-12-30 22:21:11 adam Exp $
## Copyright (C) 2001, Index Data
INCLUDES = -I$(top_srcdir)/include
zoomtst5_LDADD = $(zoomlibs)
zoomtst6_LDADD = $(zoomlibs)
zoomtst7_LDADD = $(zoomlibs)
+zoomtst8_LDADD = $(zoomlibs)
-noinst_PROGRAMS = zoomtst1 zoomtst2 zoomtst3 zoomtst4 zoomtst5 zoomtst6 zoomtst7
+noinst_PROGRAMS = zoomtst1 zoomtst2 zoomtst3 zoomtst4 zoomtst5 zoomtst6 zoomtst7 zoomtst8
bin_PROGRAMS = zoomsh
zoomtst1_SOURCES = zoomtst1.c
zoomtst5_SOURCES = zoomtst5.c
zoomtst6_SOURCES = zoomtst6.c
zoomtst7_SOURCES = zoomtst7.c
+zoomtst8_SOURCES = zoomtst8.c
zoomsh_SOURCES = zoomsh.c
/*
- * $Id: zoom-c.c,v 1.14 2001-11-30 08:24:06 adam Exp $
+ * $Id: zoom-c.c,v 1.15 2001-12-30 22:21:11 adam Exp $
*
* ZOOM layer for C, connections, result sets, queries.
*/
}
else
c->m_queue_back = 0;
+ c->last_event = event->kind;
return event;
}
break;
case ZOOM_TASK_CONNECT:
break;
+ case ZOOM_TASK_SCAN:
+ ZOOM_scanset_destroy (task->u.scan.scan);
+ break;
default:
assert (0);
}
c->async = 0;
c->support_named_resultsets = 0;
+ c->last_event = ZOOM_EVENT_NONE;
c->m_queue_front = 0;
c->m_queue_back = 0;
/* set database names. Take local databases (if set); otherwise
take databases given in ZURL (if set); otherwise use Default */
-static char **set_DatabaseNames (ZOOM_connection con, int *num)
+static char **set_DatabaseNames (ZOOM_connection con, ZOOM_options options,
+ int *num)
{
char **databaseNames;
const char *c;
int no = 2;
- const char *cp = ZOOM_options_get (con->options, "databaseName");
+ const char *cp = ZOOM_options_get (options, "databaseName");
if (!cp || !*cp)
{
do_close (c);
return -1;
}
+
return 0;
}
static int send_APDU (ZOOM_connection c, Z_APDU *a)
{
+ ZOOM_Event event;
assert (a);
if (encode_APDU(c, a, c->odr_out))
return -1;
c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0);
+ event = ZOOM_Event_create (ZOOM_EVENT_SEND_APDU);
+ ZOOM_connection_put_event (c, event);
odr_reset(c->odr_out);
do_write (c);
return 0;
search_req->query = r->r_query;
search_req->databaseNames =
- set_DatabaseNames (c, &search_req->num_databaseNames);
+ set_DatabaseNames (c, r->options, &search_req->num_databaseNames);
/* get syntax (no need to provide unless piggyback is in effect) */
syntax = ZOOM_options_get (r->options, "preferredRecordSyntax");
response_diag (c, res->diagnostics[0]);
}
+static int scan_response (ZOOM_connection c, Z_ScanResponse *res)
+{
+ NMEM nmem = odr_extract_mem (c->odr_in);
+ ZOOM_scanset scan;
+
+ if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
+ return 0;
+ scan = c->tasks->u.scan.scan;
+
+ if (res->entries && res->entries->nonsurrogateDiagnostics)
+ response_diag(c, res->entries->nonsurrogateDiagnostics[0]);
+ scan->scan_response = res;
+ nmem_transfer (scan->odr->mem, nmem);
+ nmem_destroy (nmem);
+}
+
static int send_sort (ZOOM_connection c)
{
ZOOM_resultset resultset;
return 1;
}
+ZOOM_scanset ZOOM_connection_scan (ZOOM_connection c, const char *start)
+{
+ ZOOM_scanset scan = xmalloc (sizeof(*scan));
+
+ scan->connection = c;
+ scan->odr = odr_createmem (ODR_DECODE);
+ scan->options = ZOOM_options_create_with_parent (c->options);
+ scan->refcount = 1;
+ scan->scan_response = 0;
+
+ if ((scan->termListAndStartPoint =
+ p_query_scan(scan->odr, PROTO_Z3950, &scan->attributeSet,
+ start)))
+ {
+ ZOOM_task task = ZOOM_connection_add_task (c, ZOOM_TASK_SCAN);
+ task->u.scan.scan = scan;
+
+ (scan->refcount)++;
+ if (!c->async)
+ {
+ while (ZOOM_event (1, &c))
+ ;
+ }
+ }
+ return scan;
+}
+
+void ZOOM_scanset_destroy (ZOOM_scanset scan)
+{
+ if (!scan)
+ return;
+ (scan->refcount)--;
+ if (scan->refcount == 0)
+ {
+ odr_destroy (scan->odr);
+
+ ZOOM_options_destroy (scan->options);
+ xfree (scan);
+ }
+}
+
+int send_scan (ZOOM_connection c)
+{
+ ZOOM_scanset scan;
+ Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_scanRequest);
+ Z_ScanRequest *req = apdu->u.scanRequest;
+ if (!c->tasks)
+ return 0;
+ assert (c->tasks->which == ZOOM_TASK_SCAN);
+ scan = c->tasks->u.scan.scan;
+
+ req->termListAndStartPoint = scan->termListAndStartPoint;
+ req->attributeSet = scan->attributeSet;
+
+ *req->numberOfTermsRequested =
+ ZOOM_options_get_int(scan->options, "number", 10);
+
+ req->preferredPositionInResponse =
+ odr_intdup (c->odr_out,
+ ZOOM_options_get_int(scan->options, "position", 1));
+
+ req->stepSize =
+ odr_intdup (c->odr_out,
+ ZOOM_options_get_int(scan->options, "stepSize", 0));
+
+ req->databaseNames = set_DatabaseNames (c, scan->options,
+ &req->num_databaseNames);
+
+ send_APDU (c, apdu);
+
+ return 1;
+}
+
+size_t ZOOM_scanset_size (ZOOM_scanset scan)
+{
+ if (!scan || !scan->scan_response || !scan->scan_response->entries)
+ return 0;
+ return scan->scan_response->entries->num_entries;
+}
+
+const char *ZOOM_scanset_term (ZOOM_scanset scan, size_t i, int *occ, size_t *len)
+{
+ const char *term = 0;
+ size_t noent = ZOOM_scanset_size (scan);
+ Z_ScanResponse *res = scan->scan_response;
+
+ *len = 0;
+ *occ = 0;
+ if (i >= noent)
+ return 0;
+ if (res->entries->entries[i]->which == Z_Entry_termInfo)
+ {
+ Z_TermInfo *t = res->entries->entries[i]->u.termInfo;
+
+ if (t->term->which == Z_Term_general)
+ {
+ term = t->term->u.general->buf;
+ *len = t->term->u.general->len;
+ }
+ *occ = t->globalOccurrences ? *t->globalOccurrences : 0;
+ }
+ return term;
+}
+
static int ZOOM_connection_exec_task (ZOOM_connection c)
{
ZOOM_task task = c->tasks;
case ZOOM_TASK_CONNECT:
if (do_connect(c))
return 1;
+ break;
+ case ZOOM_TASK_SCAN:
+ if (send_scan(c))
+ return 1;
}
ZOOM_connection_remove_task (c);
return 0;
c->cookie_in = 0;
if (cookie)
c->cookie_in = xstrdup(cookie);
- if (ODR_MASK_GET(initrs->options, Z_Options_namedResultSets))
+ if (ODR_MASK_GET(initrs->options, Z_Options_namedResultSets) &&
+ ODR_MASK_GET(initrs->protocolVersion, Z_ProtocolVersion_3))
c->support_named_resultsets = 1;
if (c->tasks)
{
sort_response (c, apdu->u.sortResponse);
if (!send_present (c))
ZOOM_connection_remove_task (c);
+ break;
+ case Z_APDU_scanResponse:
+ scan_response (c, apdu->u.scanResponse);
+ ZOOM_connection_remove_task (c);
}
}
{
int r;
Z_APDU *apdu;
+ ZOOM_Event event;
+
+ event = ZOOM_Event_create (ZOOM_EVENT_RECV_DATA);
+ ZOOM_connection_put_event (c, event);
r = cs_get (c->cs, &c->buf_in, &c->len_in);
if (r == 1)
}
else
{
+ ZOOM_Event event;
odr_reset (c->odr_in);
odr_setbuf (c->odr_in, c->buf_in, r, 0);
+ event = ZOOM_Event_create (ZOOM_EVENT_RECV_APDU);
+ ZOOM_connection_put_event (c, event);
if (!z_APDU (c->odr_in, &apdu, 0, 0))
{
c->error = ZOOM_ERROR_DECODE;
static int do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
{
int r;
+ ZOOM_Event event;
+ event = ZOOM_Event_create(ZOOM_EVENT_SEND_DATA);
+ ZOOM_connection_put_event (c, event);
+
if ((r=cs_put (c->cs, buf_out, len_out)) < 0)
{
if (c->state == STATE_CONNECTING)
int ZOOM_connection_do_io(ZOOM_connection c, int mask)
{
- ZOOM_Event event;
+ ZOOM_Event event = 0;
#if 0
int r = cs_look(c->cs);
yaz_log (LOG_LOG, "ZOOM_connection_do_io c=%p mask=%d cs_look=%d",
if (r == CS_NONE)
{
+ event = ZOOM_Event_create (ZOOM_EVENT_IO_CONNECT);
c->error = ZOOM_ERROR_CONNECT;
do_close (c);
+ ZOOM_connection_put_event (c, event);
}
else if (r == CS_CONNECT)
{
+ event = ZOOM_Event_create (ZOOM_EVENT_IO_CONNECT);
yaz_log (LOG_LOG, "calling rcvconnect");
if (cs_rcvconnect (c->cs) < 0)
{
c->error = ZOOM_ERROR_CONNECT;
do_close (c);
+ ZOOM_connection_put_event (c, event);
}
else
+ {
+ ZOOM_connection_put_event (c, event);
ZOOM_connection_send_init (c);
+ }
}
else
{
yaz_log (LOG_DEBUG, "ZOOM_connection_do_io c=%p mask=%d", c, mask);
if (c->state == STATE_CONNECTING)
{
+ event = ZOOM_Event_create (ZOOM_EVENT_CONNECT);
if (mask & ZOOM_SELECT_WRITE)
+ {
+ ZOOM_connection_put_event (c, event);
ZOOM_connection_send_init (c);
+ }
else
{
c->error = ZOOM_ERROR_CONNECT;
do_close (c);
+ ZOOM_connection_put_event (c, event);
}
}
else if (c->state == STATE_ESTABLISHED)
}
else
{
+ event = ZOOM_Event_create (ZOOM_EVENT_UNKNOWN);
+ ZOOM_connection_put_event (c, event);
c->error = ZOOM_ERROR_INTERNAL;
do_close (c);
}
#endif
- event = ZOOM_Event_create (1);
- ZOOM_connection_put_event (c, event);
return 1;
}
+int ZOOM_connection_last_event(ZOOM_connection cs)
+{
+ if (!cs)
+ return ZOOM_EVENT_NONE;
+ return cs->last_event;
+}
int ZOOM_event (int no, ZOOM_connection *cs)
{
for (i = 0; i<no; i++)
{
ZOOM_connection c = cs[i];
+ ZOOM_Event event;
if (c && ZOOM_connection_exec_task (c))
- return i+1;
+ {
+ if ((event = ZOOM_connection_get_event(c)))
+ {
+ ZOOM_Event_destroy (event);
+ return i+1;
+ }
+ }
}
#if HAVE_SYS_POLL_H
}
else if (r == 0 && c->mask)
{
- ZOOM_Event event = ZOOM_Event_create(0);
+ ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
/* timeout and this connection was waiting */
c->error = ZOOM_ERROR_TIMEOUT;
do_close (c);
}
if (r == 0 && c->mask)
{
- ZOOM_Event event = ZOOM_Event_create(0);
+ ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_IO_TIMEOUT);
/* timeout and this connection was waiting */
c->error = ZOOM_ERROR_TIMEOUT;
do_close (c);
/*
* Private C header for ZOOM C.
- * $Id: zoom-p.h,v 1.7 2001-11-28 23:00:19 adam Exp $
+ * $Id: zoom-p.h,v 1.8 2001-12-30 22:21:11 adam Exp $
*/
#include <yaz/proto.h>
#include <yaz/comstack.h>
#include <yaz/wrbuf.h>
#include <yaz/zoom.h>
+#include <yaz/sortspec.h>
typedef struct ZOOM_Event_p *ZOOM_Event;
char *cookie_in;
int async;
int support_named_resultsets;
+ int last_event;
ZOOM_task tasks;
ZOOM_options options;
ZOOM_resultset resultsets;
ZOOM_record_cache next;
};
+struct ZOOM_scanset_p {
+ int refcount;
+ ODR odr;
+ ZOOM_options options;
+ ZOOM_connection connection;
+ Z_AttributesPlusTerm *termListAndStartPoint;
+ Z_AttributeSetId *attributeSet;
+ Z_ScanResponse *scan_response;
+};
+
struct ZOOM_task_p {
int running;
int which;
int count;
} retrieve;
#define ZOOM_TASK_CONNECT 3
+#define ZOOM_TASK_SCAN 4
+ struct {
+ ZOOM_scanset scan;
+ } scan;
} u;
ZOOM_task next;
};
};
-#ifndef YAZ_DATE
-COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp);
-Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class, const char *str);
-Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg);
-#else
-#include <yaz/sortspec.h>
-#endif
/*
- * $Id: zoomtst3.c,v 1.4 2001-11-18 21:14:23 adam Exp $
+ * $Id: zoomtst3.c,v 1.5 2001-12-30 22:21:11 adam Exp $
*
* Asynchronous multi-target client doing search and piggyback retrieval
*/
r[i] = ZOOM_connection_search_pqf (z[i], argv[argc-1]);
/* network I/O. pass number of connections and array of connections */
- while (ZOOM_event (no, z))
- ;
+ while ((i = ZOOM_event (no, z)))
+ {
+ printf ("no = %d event = %d\n", i-1,
+ ZOOM_connection_last_event(z[i-1]));
+ }
/* no more to be done. Inspect results */
for (i = 0; i<no; i++)
/*
- * $Id: zoomtst5.c,v 1.6 2001-11-18 21:14:23 adam Exp $
+ * $Id: zoomtst5.c,v 1.7 2001-12-30 22:21:11 adam Exp $
*
* Asynchronous multi-target client doing search, sort and present
*/
int pos;
printf ("%s: %d hits\n", ZOOM_connection_option_get(z[i], "host"),
ZOOM_resultset_size(r[i]));
- /* go through all records at target */
+ /* go through first 20 records at target */
for (pos = 0; pos < 20; pos++)
{
ZOOM_record rec;
/*
- * $Id: zoomtst7.c,v 1.7 2001-11-18 21:14:23 adam Exp $
+ * $Id: zoomtst7.c,v 1.8 2001-12-30 22:21:11 adam Exp $
*
* API test..
*/
for (i = 0; i<10; i++)
{
char host[40];
+
printf ("session %2d", i);
sprintf (host, "localhost:9999/%d", i);
z = ZOOM_connection_create (o);
for (; j < 10; j++)
ZOOM_resultset_destroy (r[j]);
printf ("10 searches, 20 presents done\n");
+
}
-
+
for (i = 0; i<1; i++)
{
ZOOM_query q = ZOOM_query_create ();
while (ZOOM_event (1, &z))
;
}
+
+
ZOOM_connection_destroy (z);
for (j = 0; j < 10; j++)
ZOOM_query_destroy (q);
printf ("10 searches, 10 ignored presents done\n");
}
+
+
+ for (i = 0; i<1; i++)
+ {
+ char host[40];
+ ZOOM_scanset scan = 0;
+
+ printf ("session %2d", i);
+ sprintf (host, "localhost:9999/%d", i);
+ z = ZOOM_connection_create (o);
+ ZOOM_connection_connect (z, host, 0);
+
+ scan = ZOOM_connection_scan (z, "@attr 1=4 a");
+ if (block > 0)
+ while (ZOOM_event (1, &z))
+ ;
+ printf (" scan size = %d\n", ZOOM_scanset_size(scan));
+ for (j = 0; j<ZOOM_scanset_size (scan); j++)
+ {
+ int occur, len;
+ const char *term;
+ term = ZOOM_scanset_term (scan, j, &occur, &len);
+ if (term)
+ printf ("%d %.*s %d\n", j, len, term, occur);
+
+ }
+ ZOOM_scanset_destroy (scan);
+ ZOOM_connection_destroy (z);
+ }
+
}
ZOOM_options_destroy (o);
xmalloc_trav("");
--- /dev/null
+/*
+ * $Id: zoomtst8.c,v 1.1 2001-12-30 22:21:11 adam Exp $
+ *
+ * Asynchronous multi-target client doing scan
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <yaz/nmem.h>
+#include <yaz/xmalloc.h>
+#include <yaz/zoom.h>
+
+int main(int argc, char **argv)
+{
+ int i;
+ int no = argc-2;
+ ZOOM_connection z[500]; /* allow at most 500 connections */
+ ZOOM_scanset s[500]; /* and scan sets .. */
+ ZOOM_options o = ZOOM_options_create ();
+
+ if (argc < 3)
+ {
+ fprintf (stderr, "usage:\n%s target1 target2 ... targetN scan\n",
+ *argv);
+ exit (1);
+ }
+ if (no > 500)
+ no = 500;
+
+ /* async mode */
+ ZOOM_options_set (o, "async", "1");
+
+ /* connect to all */
+ for (i = 0; i<no; i++)
+ {
+ /* create connection - pass options (they are the same for all) */
+ z[i] = ZOOM_connection_create (o);
+
+ /* connect and init */
+ ZOOM_connection_connect (z[i], argv[1+i], 0);
+ }
+ /* search all */
+ for (i = 0; i<no; i++)
+ s[i] = ZOOM_connection_scan (z[i], argv[argc-1]);
+
+ /* network I/O. pass number of connections and array of connections */
+ while (ZOOM_event (no, z))
+ ;
+
+ for (i = 0; i<no; i++)
+ {
+ int error;
+ const char *errmsg, *addinfo;
+ if ((error = ZOOM_connection_error(z[i], &errmsg, &addinfo)))
+ fprintf (stderr, "%s error: %s (%d) %s\n",
+ ZOOM_connection_option_get(z[i], "host"),
+ errmsg, error, addinfo);
+ else
+ {
+ int j;
+ printf ("%s\n", ZOOM_connection_option_get(z[i], "host"));
+ for (j = 0; j<ZOOM_scanset_size (s[i]); j++)
+ {
+ int occur, len;
+ const char *term;
+ term = ZOOM_scanset_term (s[i], j, &occur, &len);
+ if (term)
+ printf ("%d %.*s %d\n", j, len, term, occur);
+
+ }
+ }
+ }
+
+ /* destroy and exit */
+ for (i = 0; i<no; i++)
+ {
+ ZOOM_scanset_destroy (s[i]);
+ ZOOM_connection_destroy (z[i]);
+ }
+ ZOOM_options_destroy(o);
+ exit (0);
+}