New OID database - with public definitions in oid_db.h. Removed old OID
[yaz-moved-to-github.git] / src / zoom-c.c
index 2a9d433..a67405a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.104 2007-01-03 08:42:15 adam Exp $
+ * $Id: zoom-c.c,v 1.123 2007-04-12 13:52:57 adam Exp $
  */
 /**
  * \file zoom-c.c
 #include <yaz/cql.h>
 #include <yaz/ccl.h>
 
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#if HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#endif
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef WIN32
-#if FD_SETSIZE < 512
-#define FD_SETSIZE 512
-#endif
-#include <winsock.h>
-#endif
-
 static int log_api = 0;
 static int log_details = 0;
 
@@ -54,10 +35,27 @@ typedef enum {
     zoom_complete
 } zoom_ret;
 
+static void resultset_destroy(ZOOM_resultset r);
 static zoom_ret ZOOM_connection_send_init(ZOOM_connection c);
 static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out);
 static char *cql2pqf(ZOOM_connection c, const char *cql);
 
+
+/*
+ * This wrapper is just for logging failed lookups.  It would be nicer
+ * if it could cause failure when a lookup fails, but that's hard.
+ */
+static int *zoom_yaz_str_to_z3950oid(ZOOM_connection c,
+                                     int oid_class, const char *str) {
+    int *res = yaz_string_to_oid_odr(yaz_oid_std(), oid_class, str,
+                                     c->odr_out);
+    if (res == 0)
+        yaz_log(YLOG_WARN, "%p OID lookup (%d, '%s') failed",
+                c, (int) oid_class, str);
+    return res;
+}
+
+
 static void initlog(void)
 {
     static int log_level_initialized = 0;
@@ -122,6 +120,21 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
     return event;
 }
 
+static void ZOOM_connection_remove_events(ZOOM_connection c)
+{
+    ZOOM_Event event;
+    while ((event = ZOOM_connection_get_event(c)))
+        ZOOM_Event_destroy(event);
+}
+
+ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c)
+{
+    ZOOM_Event event = c->m_queue_front;
+
+    return event ? event->kind : ZOOM_EVENT_NONE;
+}
+
+void ZOOM_connection_remove_tasks(ZOOM_connection c);
 
 static void set_dset_error(ZOOM_connection c, int error,
                            const char *dset,
@@ -148,11 +161,14 @@ static void set_dset_error(ZOOM_connection c, int error,
     }
     else if (addinfo)
         c->addinfo = xstrdup(addinfo);
-    if (error)
+    if (error != ZOOM_ERROR_NONE)
+    {
         yaz_log(log_api, "%p set_dset_error %s %s:%d %s %s",
                 c, c->host_port ? c->host_port : "<>", dset, error,
                 addinfo ? addinfo : "",
                 addinfo2 ? addinfo2 : "");
+        ZOOM_connection_remove_tasks(c);
+    }
 }
 
 #if YAZ_HAVE_XML2
@@ -163,6 +179,7 @@ static void set_HTTP_error(ZOOM_connection c, int error,
 }
 #endif
 
+
 static void set_ZOOM_error(ZOOM_connection c, int error,
                            const char *addinfo)
 {
@@ -178,6 +195,8 @@ static void clear_error(ZOOM_connection c)
      * or Init Refused are not cleared, because they are not
      * recoverable: doing another search doesn't help.
      */
+
+    ZOOM_connection_remove_events(c);
     switch (c->error)
     {
     case ZOOM_ERROR_CONNECT:
@@ -261,12 +280,12 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
         switch (task->which)
         {
         case ZOOM_TASK_SEARCH:
-            ZOOM_resultset_destroy(task->u.search.resultset);
+            resultset_destroy(task->u.search.resultset);
             xfree(task->u.search.syntax);
             xfree(task->u.search.elementSetName);
             break;
         case ZOOM_TASK_RETRIEVE:
-            ZOOM_resultset_destroy(task->u.retrieve.resultset);
+            resultset_destroy(task->u.retrieve.resultset);
             xfree(task->u.retrieve.syntax);
             xfree(task->u.retrieve.elementSetName);
             break;
@@ -279,7 +298,7 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
             ZOOM_package_destroy(task->u.package);
             break;
         case ZOOM_TASK_SORT:
-            ZOOM_resultset_destroy(task->u.sort.resultset);
+            resultset_destroy(task->u.sort.resultset);
             ZOOM_query_destroy(task->u.sort.q);
             break;
         default:
@@ -318,7 +337,7 @@ ZOOM_API(ZOOM_connection)
 
     c->proto = PROTO_Z3950;
     c->cs = 0;
-    c->mask = 0;
+    ZOOM_connection_set_mask(c, 0);
     c->reconnect_ok = 0;
     c->state = STATE_IDLE;
     c->addinfo = 0;
@@ -375,7 +394,7 @@ static char **set_DatabaseNames(ZOOM_connection con, ZOOM_options options,
     }
     if (!cp)
         cp = "Default";
-    nmem_strsplit(odr->mem, "+", cp,  &databaseNames, num);
+    nmem_strsplit(odr_getmem(odr), "+", cp,  &databaseNames, num);
     return databaseNames;
 }
 
@@ -411,7 +430,7 @@ ZOOM_API(void)
     initlog();
 
     yaz_log(log_api, "%p ZOOM_connection_connect host=%s portnum=%d",
-            c, host, portnum);
+            c, host ? host : "null", portnum);
 
     set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     ZOOM_connection_remove_tasks(c);
@@ -453,15 +472,18 @@ ZOOM_API(void)
     else
         c->lang = 0;
 
-    xfree(c->host_port);
-    if (portnum)
+    if (host)
     {
-        char hostn[128];
-        sprintf(hostn, "%.80s:%d", host, portnum);
-        c->host_port = xstrdup(hostn);
-    }
-    else
-        c->host_port = xstrdup(host);
+        xfree(c->host_port);
+        if (portnum)
+        {
+            char hostn[128];
+            sprintf(hostn, "%.80s:%d", host, portnum);
+            c->host_port = xstrdup(hostn);
+        }
+        else
+            c->host_port = xstrdup(host);
+    }        
 
     {
         /*
@@ -562,7 +584,7 @@ ZOOM_API(int)
     s->query_string = odr_strdup(s->odr, str);
     s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query));
     s->z_query->which = Z_Query_type_1;
-    s->z_query->u.type_1 =  p_query_rpn(s->odr, PROTO_Z3950, str);
+    s->z_query->u.type_1 =  p_query_rpn(s->odr, str);
     if (!s->z_query->u.type_1)
     {
         yaz_log(log_details, "%p ZOOM_query_prefix str=%s failed", s, str);
@@ -653,8 +675,8 @@ ZOOM_API(int)
         WRBUF wr = wrbuf_alloc();
         ccl_pquery(wr, rpn);
         ccl_rpn_delete(rpn);
-        ret = ZOOM_query_prefix(s, wrbuf_buf(wr));
-        wrbuf_free(wr, 1);
+        ret = ZOOM_query_prefix(s, wrbuf_cstr(wr));
+        wrbuf_destroy(wr);
     }
     ccl_qual_rm(&bibset);
     return ret;
@@ -695,6 +717,7 @@ ZOOM_API(void)
     odr_destroy(c->odr_out);
     ZOOM_options_destroy(c->options);
     ZOOM_connection_remove_tasks(c);
+    ZOOM_connection_remove_events(c);
     xfree(c->host_port);
     xfree(c->path);
     xfree(c->proxy);
@@ -831,16 +854,11 @@ ZOOM_API(ZOOM_resultset)
     return r;
 }
 
-/*
- * This is the old result-set sorting API, which is maintained only
- * for the sake of binary compatibility.  There is no reason ever to
- * use this rather than ZOOM_resultset_sort1().
- */
 ZOOM_API(void)
     ZOOM_resultset_sort(ZOOM_resultset r,
-                        const char *sort_type, const char *sort_spec)
+                         const char *sort_type, const char *sort_spec)
 {
-    (void) ZOOM_resultset_sort1(r, sort_type, sort_spec);
+    (void) ZOOM_resultset_sort(r, sort_type, sort_spec);
 }
 
 ZOOM_API(int)
@@ -901,11 +919,11 @@ ZOOM_API(void)
         for (rc = r->record_hash[i]; rc; rc = rc->next)
         {
             if (rc->rec.wrbuf_marc)
-                wrbuf_free(rc->rec.wrbuf_marc, 1);
+                wrbuf_destroy(rc->rec.wrbuf_marc);
             if (rc->rec.wrbuf_iconv)
-                wrbuf_free(rc->rec.wrbuf_iconv, 1);
+                wrbuf_destroy(rc->rec.wrbuf_iconv);
             if (rc->rec.wrbuf_opac)
-                wrbuf_free(rc->rec.wrbuf_opac, 1);
+                wrbuf_destroy(rc->rec.wrbuf_opac);
         }
         r->record_hash[i] = 0;
     }
@@ -914,6 +932,11 @@ ZOOM_API(void)
 ZOOM_API(void)
     ZOOM_resultset_destroy(ZOOM_resultset r)
 {
+    resultset_destroy(r);
+}
+
+static void resultset_destroy(ZOOM_resultset r)
+{
     if (!r)
         return;
     (r->refcount)--;
@@ -960,18 +983,24 @@ static void do_close(ZOOM_connection c)
     if (c->cs)
         cs_close(c->cs);
     c->cs = 0;
-    c->mask = 0;
+    ZOOM_connection_set_mask(c, 0);
     c->state = STATE_IDLE;
 }
 
 static int ZOOM_test_reconnect(ZOOM_connection c)
 {
+    ZOOM_Event event;
+
     if (!c->reconnect_ok)
         return 0;
     do_close(c);
     c->reconnect_ok = 0;
     c->tasks->running = 0;
     ZOOM_connection_insert_task(c, ZOOM_TASK_CONNECT);
+
+    event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
+    ZOOM_connection_put_event(c, event);
+
     return 1;
 }
 
@@ -1115,7 +1144,7 @@ static zoom_ret do_connect(ZOOM_connection c)
                 /* no init request for SRW .. */
                 assert(c->tasks->which == ZOOM_TASK_CONNECT);
                 ZOOM_connection_remove_task(c);
-                c->mask = 0;
+                ZOOM_connection_set_mask(c, 0);
                 ZOOM_connection_exec_task(c);
             }
             c->state = STATE_ESTABLISHED;
@@ -1123,12 +1152,13 @@ static zoom_ret do_connect(ZOOM_connection c)
         }
         else if (ret > 0)
         {
-            c->state = STATE_CONNECTING; 
-            c->mask = ZOOM_SELECT_EXCEPT;
+            int mask = ZOOM_SELECT_EXCEPT;
             if (c->cs->io_pending & CS_WANT_WRITE)
-                c->mask += ZOOM_SELECT_WRITE;
+                mask += ZOOM_SELECT_WRITE;
             if (c->cs->io_pending & CS_WANT_READ)
-                c->mask += ZOOM_SELECT_READ;
+                mask += ZOOM_SELECT_READ;
+            ZOOM_connection_set_mask(c, mask);
+            c->state = STATE_CONNECTING; 
             return zoom_pending;
         }
     }
@@ -1137,31 +1167,17 @@ static zoom_ret do_connect(ZOOM_connection c)
     return zoom_complete;
 }
 
-int z3950_connection_socket(ZOOM_connection c)
-{
-    if (c->cs)
-        return cs_fileno(c->cs);
-    return -1;
-}
-
-int z3950_connection_mask(ZOOM_connection c)
-{
-    if (c->cs)
-        return c->mask;
-    return 0;
-}
-
 static void otherInfo_attach(ZOOM_connection c, Z_APDU *a, ODR out)
 {
     int i;
     for (i = 0; i<200; i++)
     {
         size_t len;
+        int *oid;
         Z_OtherInformation **oi;
         char buf[80];
         const char *val;
         const char *cp;
-        int oidval;
 
         sprintf(buf, "otherInfo%d", i);
         val = ZOOM_options_get(c->options, buf);
@@ -1175,12 +1191,14 @@ static void otherInfo_attach(ZOOM_connection c, Z_APDU *a, ODR out)
             len = sizeof(buf)-1;
         memcpy(buf, val, len);
         buf[len] = '\0';
-        oidval = oid_getvalbyname(buf);
-        if (oidval == VAL_NONE)
+        
+        oid = yaz_string_to_oid_odr(yaz_oid_std(), CLASS_USERINFO,
+                                    buf, out);
+        if (!oid)
             continue;
         
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, oidval, 1, cp+1);
+        yaz_oi_set_string_oid(oi, out, oid, 1, cp+1);
     }
 }
 
@@ -1189,15 +1207,19 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
     assert(a);
     if (c->cookie_out)
     {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_COOKIE);
         Z_OtherInformation **oi;
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, VAL_COOKIE, 1, c->cookie_out);
+        yaz_oi_set_string_oid(oi, out, oid, 1, c->cookie_out);
     }
     if (c->client_IP)
     {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_CLIENT_IP);
         Z_OtherInformation **oi;
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, VAL_CLIENT_IP, 1, c->client_IP);
+        yaz_oi_set_string_oid(oi, out, oid, 1, c->client_IP);
     }
     otherInfo_attach(c, a, out);
     if (!z_APDU(out, &a, 0, 0))
@@ -1276,7 +1298,7 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
                     odr_prepend(c->odr_out, "ZOOM-C",
                                 ireq->implementationName));
     
-    version = odr_strdup(c->odr_out, "$Revision: 1.104 $");
+    version = odr_strdup(c->odr_out, "$Revision: 1.123 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     ireq->implementationVersion = 
@@ -1334,8 +1356,12 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
         ireq->idAuthentication = auth;
     }
     if (c->proxy)
-        yaz_oi_set_string_oidval(&ireq->otherInfo, c->odr_out,
-                                 VAL_PROXY, 1, c->host_port);
+    {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_CLIENT_IP);
+        yaz_oi_set_string_oid(&ireq->otherInfo, c->odr_out,
+                              oid, 1, c->host_port);
+    }
     if (c->charset || c->lang)
     {
         Z_OtherInformation **oi;
@@ -1578,7 +1604,7 @@ static zoom_ret ZOOM_connection_send_search(ZOOM_connection c)
     }
     if (syntax)
         search_req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
     
     if (!r->setname)
     {
@@ -1631,7 +1657,8 @@ static void response_default_diag(ZOOM_connection c, Z_DefaultDiagFormat *r)
     xfree(c->addinfo);
     c->addinfo = 0;
     set_dset_error(c, *r->condition,
-                   yaz_z3950oid_to_str(r->diagnosticSetId, &oclass),
+                   yaz_oid_to_string(yaz_oid_std(), 
+                                     r->diagnosticSetId, &oclass),
                    addinfo, 0);
 }
 
@@ -1706,11 +1733,11 @@ ZOOM_API(void)
     if (!rec)
         return;
     if (rec->wrbuf_marc)
-        wrbuf_free(rec->wrbuf_marc, 1);
+        wrbuf_destroy(rec->wrbuf_marc);
     if (rec->wrbuf_iconv)
-        wrbuf_free(rec->wrbuf_iconv, 1);
+        wrbuf_destroy(rec->wrbuf_iconv);
     if (rec->wrbuf_opac)
-        wrbuf_free(rec->wrbuf_opac, 1);
+        wrbuf_destroy(rec->wrbuf_opac);
     odr_destroy(rec->odr);
     xfree(rec);
 }
@@ -1763,7 +1790,7 @@ static const char *marc_iconv_return(ZOOM_record rec, int marc_type,
             yaz_iconv_close(cd);
         if (len)
             *len = wrbuf_len(rec->wrbuf_marc);
-        return wrbuf_buf(rec->wrbuf_marc);
+        return wrbuf_cstr(rec->wrbuf_marc);
     }
     yaz_marc_destroy(mt);
     if (cd)
@@ -1781,6 +1808,7 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
 
     *from = '\0';
     strcpy(to, "UTF-8");
+
     if (record_charset && *record_charset)
     {
         /* Use "from,to" or just "from" */
@@ -1802,32 +1830,15 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
 
     if (*from && *to && (cd = yaz_iconv_open(to, from)))
     {
-        char outbuf[12];
-        size_t inbytesleft = sz;
-        const char *inp = buf;
-        
         if (!rec->wrbuf_iconv)
             rec->wrbuf_iconv = wrbuf_alloc();
 
         wrbuf_rewind(rec->wrbuf_iconv);
 
-        while (inbytesleft)
-        {
-            size_t outbytesleft = sizeof(outbuf);
-            char *outp = outbuf;
-            size_t r = yaz_iconv(cd, (char**) &inp,
-                                 &inbytesleft, 
-                                 &outp, &outbytesleft);
-            if (r == (size_t) (-1))
-            {
-                int e = yaz_iconv_error(cd);
-                if (e != YAZ_ICONV_E2BIG)
-                    break;
-            }
-            wrbuf_write(rec->wrbuf_iconv, outbuf, outp - outbuf);
-        }
-        wrbuf_puts(rec->wrbuf_iconv, "");
-        buf = wrbuf_buf(rec->wrbuf_iconv);
+        wrbuf_iconv_write(rec->wrbuf_iconv, cd, buf, sz);
+        wrbuf_iconv_reset(rec->wrbuf_iconv, cd);
+
+        buf = wrbuf_cstr(rec->wrbuf_iconv);
         sz = wrbuf_len(rec->wrbuf_iconv);
         yaz_iconv_close(cd);
     }
@@ -1867,7 +1878,9 @@ ZOOM_API(int)
                 break;
             }
             if (diagset)
-                *diagset = yaz_z3950oid_to_str(ddf->diagnosticSetId, &oclass);
+                *diagset =
+                    yaz_oid_to_string(yaz_oid_std(),
+                                      ddf->diagnosticSetId, &oclass);
         }
         else
         {
@@ -1951,9 +1964,7 @@ ZOOM_API(const char *)
         if (npr->which == Z_NamePlusRecord_databaseRecord)
         {
             Z_External *r = (Z_External *) npr->u.databaseRecord;
-            oident *ent = oid_getentbyoid(r->direct_reference);
-            if (ent)
-                desc = ent->desc;
+            desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0);
         }
         if (!desc)
             desc = "none";
@@ -1968,7 +1979,7 @@ ZOOM_API(const char *)
     if (!strcmp(type, "render"))
     {
         Z_External *r = (Z_External *) npr->u.databaseRecord;
-        oident *ent = oid_getentbyoid(r->direct_reference);
+        const int *oid = r->direct_reference;
 
         /* render bibliographic record .. */
         if (r->which == Z_External_OPAC)
@@ -1976,7 +1987,7 @@ ZOOM_API(const char *)
             r = r->u.opac->bibliographicRecord;
             if (!r)
                 return 0;
-            ent = oid_getentbyoid(r->direct_reference);
+            oid = r->direct_reference;
         }
         if (r->which == Z_External_sutrs)
             return record_iconv_return(rec, len,
@@ -1985,18 +1996,9 @@ ZOOM_API(const char *)
                                        charset);
         else if (r->which == Z_External_octet)
         {
-            const char *ret_buf;
-            switch (ent->value)
+            if (yaz_oid_is_iso2709(oid))
             {
-            case VAL_SOIF:
-            case VAL_HTML:
-            case VAL_SUTRS:
-                break;
-            case VAL_TEXT_XML:
-            case VAL_APPLICATION_XML:
-                break;
-            default:
-                ret_buf = marc_iconv_return(
+                const char *ret_buf = marc_iconv_return(
                     rec, YAZ_MARC_LINE, len,
                     (const char *) r->u.octet_aligned->buf,
                     r->u.octet_aligned->len,
@@ -2025,7 +2027,7 @@ ZOOM_API(const char *)
     else if (!strcmp(type, "xml"))
     {
         Z_External *r = (Z_External *) npr->u.databaseRecord;
-        oident *ent = oid_getentbyoid(r->direct_reference);
+        const int *oid = r->direct_reference;
 
         /* render bibliographic record .. */
         if (r->which == Z_External_OPAC)
@@ -2033,7 +2035,7 @@ ZOOM_API(const char *)
             r = r->u.opac->bibliographicRecord;
             if (!r)
                 return 0;
-            ent = oid_getentbyoid(r->direct_reference);
+            oid = r->direct_reference;
         }
         
         if (r->which == Z_External_sutrs)
@@ -2043,20 +2045,10 @@ ZOOM_API(const char *)
                                        charset);
         else if (r->which == Z_External_octet)
         {
-            const char *ret_buf;
             int marc_decode_type = YAZ_MARC_MARCXML;
-
-            switch (ent->value)
+            if (yaz_oid_is_iso2709(oid))
             {
-            case VAL_SOIF:
-            case VAL_HTML:
-            case VAL_SUTRS:
-                break;
-            case VAL_TEXT_XML:
-            case VAL_APPLICATION_XML:
-                break;
-            default:
-                ret_buf = marc_iconv_return(
+                const char *ret_buf = marc_iconv_return(
                     rec, marc_decode_type, len,
                     (const char *) r->u.octet_aligned->buf,
                     r->u.octet_aligned->len,
@@ -2273,7 +2265,7 @@ static void handle_records(ZOOM_connection c, Z_Records *sr,
                     resultset, *start, *count);
 
             /* transfer our response to search_nmem .. we need it later */
-            nmem_transfer(resultset->odr->mem, nmem);
+            nmem_transfer(odr_getmem(resultset->odr), nmem);
             nmem_destroy(nmem);
             if (present_phase && p->num_records == 0)
             {
@@ -2418,6 +2410,16 @@ static void handle_search_response(ZOOM_connection c, Z_SearchResponse *sr)
 
     resultset = c->tasks->u.search.resultset;
 
+    if (sr->resultSetStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "resultSetStatus",
+                             *sr->resultSetStatus);
+    }
+    if (sr->presentStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "presentStatus",
+                             *sr->presentStatus);
+    }
     handle_searchResult(c, resultset, sr->additionalSearchInfo);
 
     resultset->size = *sr->resultCount;
@@ -2442,7 +2444,7 @@ static int scan_response(ZOOM_connection c, Z_ScanResponse *res)
     if (res->entries && res->entries->nonsurrogateDiagnostics)
         response_diag(c, res->entries->nonsurrogateDiagnostics[0]);
     scan->scan_response = res;
-    nmem_transfer(scan->odr->mem, nmem);
+    nmem_transfer(odr_getmem(scan->odr), nmem);
     if (res->stepSize)
         ZOOM_options_set_int(scan->options, "stepSize", *res->stepSize);
     if (res->positionOfTerm)
@@ -2563,7 +2565,7 @@ static zoom_ret send_present(ZOOM_connection c)
 
     if (syntax && *syntax)
         req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
 
     if (resultset->schema && *resultset->schema)
     {
@@ -2583,14 +2585,14 @@ static zoom_ret send_present(ZOOM_connection c)
 
         compo->u.complex->generic->which = Z_Schema_oid;
         compo->u.complex->generic->schema.oid = (Odr_oid *)
-            yaz_str_to_z3950oid (c->odr_out, CLASS_SCHEMA, resultset->schema);
+            zoom_yaz_str_to_z3950oid (c, CLASS_SCHEMA, resultset->schema);
 
         if (!compo->u.complex->generic->schema.oid)
         {
             /* OID wasn't a schema! Try record syntax instead. */
 
             compo->u.complex->generic->schema.oid = (Odr_oid *)
-                yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, resultset->schema);
+                zoom_yaz_str_to_z3950oid (c, CLASS_RECSYN, resultset->schema);
         }
         if (elementSetName && *elementSetName)
         {
@@ -2847,7 +2849,7 @@ ZOOM_API(void)
     ZOOM_options_set(scan->options, key, val);
 }
 
-static Z_APDU *create_es_package(ZOOM_package p, int type)
+static Z_APDU *create_es_package(ZOOM_package p, const char *type)
 {
     const char *str;
     Z_APDU *apdu = zget_APDU(p->odr_out, Z_APDU_extendedServicesRequest);
@@ -2857,14 +2859,14 @@ static Z_APDU *create_es_package(ZOOM_package p, int type)
     
     str = ZOOM_options_get(p->options, "package-name");
     if (str && *str)
-        req->packageName = nmem_strdup(p->odr_out->mem, str);
+        req->packageName = odr_strdup(p->odr_out, str);
     
     str = ZOOM_options_get(p->options, "user-id");
     if (str)
-        req->userId = nmem_strdup(p->odr_out->mem, str);
+        req->userId = odr_strdup(p->odr_out, str);
     
-    req->packageType = yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                              type);
+    req->packageType = yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                             type, p->odr_out);
 
     str = ZOOM_options_get(p->options, "function");
     if (str)
@@ -2908,16 +2910,14 @@ static Z_External *encode_ill_request(ZOOM_package p)
     }
     else
     {
-        oident oid;
         int illRequest_size = 0;
         char *illRequest_buf = odr_getbuf(out, &illRequest_size, 0);
                 
-        oid.proto = PROTO_GENERAL;
-        oid.oclass = CLASS_GENERAL;
-        oid.value = VAL_ISO_ILL_1;
-                
         r = (Z_External *) odr_malloc(out, sizeof(*r));
-        r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); 
+        r->direct_reference = yaz_string_to_oid_odr(yaz_oid_std(),
+                                                    CLASS_GENERAL,
+                                                    OID_STR_ILL_1,
+                                                    out);
         r->indirect_reference = 0;
         r->descriptor = 0;
         r->which = Z_External_single;
@@ -2948,15 +2948,15 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
         
     str = ZOOM_options_get(p->options, "contact-name");
     req->u.esRequest->toKeep->contact->name = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     str = ZOOM_options_get(p->options, "contact-phone");
     req->u.esRequest->toKeep->contact->phone = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     str = ZOOM_options_get(p->options, "contact-email");
     req->u.esRequest->toKeep->contact->email = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     req->u.esRequest->toKeep->addlBilling = 0;
         
@@ -2976,7 +2976,7 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
             odr_malloc(p->odr_out, sizeof(Z_IOResultSetItem));
 
         req->u.esRequest->notToKeep->resultSetItem->resultSetId =
-            nmem_strdup(p->odr_out->mem, str);
+            odr_strdup(p->odr_out, str);
         req->u.esRequest->notToKeep->resultSetItem->item =
             (int *) odr_malloc(p->odr_out, sizeof(int));
         
@@ -2984,7 +2984,17 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
         *req->u.esRequest->notToKeep->resultSetItem->item =
             (str ? atoi(str) : 1);
     }
-    req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
+
+    str = ZOOM_options_get(p->options, "doc");
+    if (str)
+    {
+        const int *oid = yaz_string_to_oid(yaz_oid_std(),
+                                           CLASS_RECSYN, OID_STR_XML);
+        req->u.esRequest->notToKeep->itemRequest =
+            z_ext_record_oid(p->odr_out, oid, str, strlen(str));
+    }
+    else
+        req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
     
     return req;
 }
@@ -2993,7 +3003,7 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
                              Z_ESAdminOriginPartToKeep **toKeepP,
                              Z_ESAdminOriginPartNotToKeep **notToKeepP)
 {
-    Z_APDU *apdu = create_es_package(p, VAL_ADMINSERVICE);
+    Z_APDU *apdu = create_es_package(p, OID_STR_ADMIN);
     if (apdu)
     {
         Z_ESAdminOriginPartToKeep  *toKeep;
@@ -3007,8 +3017,8 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
             first_db = db[0];
             
         r->direct_reference =
-            yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                   VAL_ADMINSERVICE);
+            yaz_string_to_oid_odr(yaz_oid_std(),
+                                  CLASS_EXTSERV, OID_STR_ADMIN, p->odr_out);
         r->descriptor = 0;
         r->indirect_reference = 0;
         r->which = Z_External_ESAdmin;
@@ -3043,7 +3053,7 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
 
 static Z_APDU *create_xmlupdate_package(ZOOM_package p)
 {
-    Z_APDU *apdu = create_es_package(p, VAL_XMLES);
+    Z_APDU *apdu = create_es_package(p, OID_STR_XMLES);
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
     Z_External *ext = (Z_External *) odr_malloc(p->odr_out, sizeof(*ext));
     const char *doc = ZOOM_options_get(p->options, "doc");
@@ -3074,19 +3084,26 @@ static Z_APDU *create_update_package(ZOOM_package p)
     const char *recordIdNumber = ZOOM_options_get(p->options, "recordIdNumber");
     const char *record_buf = ZOOM_options_get(p->options, "record");
     const char *syntax_str = ZOOM_options_get(p->options, "syntax");
-    int syntax_oid = VAL_NONE;
     int action_no = -1;
-    
-    if (syntax_str)
-        syntax_oid = oid_getvalbyname(syntax_str);
+    int *syntax_oid = 0;
+
+    if (!syntax_str)
+        syntax_str = "xml";
     if (!record_buf)
     {
         record_buf = "void";
-        syntax_oid = VAL_SUTRS;
+        syntax_str = "SUTRS";
     }
-    if (syntax_oid == VAL_NONE)
-        syntax_oid = VAL_TEXT_XML;
-    
+
+    if (syntax_str)
+    {
+        syntax_oid = yaz_string_to_oid_odr(yaz_oid_std(),
+                                           CLASS_RECSYN, syntax_str,
+                                           p->odr_out);
+    }
+    if (!syntax_oid)
+        return 0;
+
     if (num_db > 0)
         first_db = db[0];
     
@@ -3106,7 +3123,7 @@ static Z_APDU *create_update_package(ZOOM_package p)
     else
         return 0;
 
-    apdu = create_es_package(p, VAL_DBUPDATE);
+    apdu = create_es_package(p, OID_STR_EXT_UPDATE);
     if (apdu)
     {
         Z_IUOriginPartToKeep *toKeep;
@@ -3115,10 +3132,11 @@ static Z_APDU *create_update_package(ZOOM_package p)
             odr_malloc(p->odr_out, sizeof(*r));
         
         apdu->u.extendedServicesRequest->taskSpecificParameters = r;
+
         
         r->direct_reference =
-            yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                   VAL_DBUPDATE);
+            yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                  OID_STR_EXT_UPDATE, p->odr_out);
         r->descriptor = 0;
         r->which = Z_External_update;
         r->indirect_reference = 0;
@@ -3166,8 +3184,8 @@ static Z_APDU *create_update_package(ZOOM_package p)
         notToKeep->elements[0]->supplementalId = 0;
         notToKeep->elements[0]->correlationInfo = 0;
         notToKeep->elements[0]->record =
-            z_ext_record(p->odr_out, syntax_oid,
-                         record_buf, strlen(record_buf));
+            z_ext_record_oid(p->odr_out, syntax_oid,
+                             record_buf, strlen(record_buf));
     }
     if (0 && apdu)
     {
@@ -3192,14 +3210,14 @@ ZOOM_API(void)
     p->buf_out = 0;
     if (!strcmp(type, "itemorder"))
     {
-        apdu = create_es_package(p, VAL_ITEMORDER);
+        apdu = create_es_package(p, OID_STR_ITEMORDER);
         if (apdu)
         {
             Z_External *r = (Z_External *) odr_malloc(p->odr_out, sizeof(*r));
             
             r->direct_reference =
-                yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                       VAL_ITEMORDER);
+                yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                      OID_STR_ITEMORDER, p->odr_out);
             r->descriptor = 0;
             r->which = Z_External_itemOrder;
             r->indirect_reference = 0;
@@ -3452,7 +3470,7 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu)
 {
     Z_InitResponse *initrs;
     
-    c->mask = 0;
+    ZOOM_connection_set_mask(c, 0);
     yaz_log(log_details, "%p recv_apdu apdu->which=%d", c, apdu->which);
     switch(apdu->which)
     {
@@ -3493,9 +3511,12 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu)
         }
         else
         {
+            const int *oid = yaz_string_to_oid(yaz_oid_std(),
+                                               CLASS_USERINFO,
+                                               OID_STR_COOKIE);
             char *cookie =
-                yaz_oi_get_string_oidval(&apdu->u.initResponse->otherInfo,
-                                         VAL_COOKIE, 1, 0);
+                yaz_oi_get_string_oid(&apdu->u.initResponse->otherInfo,
+                                      oid, 1, 0);
             xfree(c->cookie_in);
             c->cookie_in = 0;
             if (cookie)
@@ -3643,7 +3664,8 @@ static void handle_srw_response(ZOOM_connection c,
             odr_malloc(c->odr_in, sizeof(Z_External));
         npr->u.databaseRecord->descriptor = 0;
         npr->u.databaseRecord->direct_reference =
-            yaz_oidval_to_z3950oid(c->odr_in, CLASS_RECSYN, VAL_TEXT_XML);
+            yaz_string_to_oid_odr(yaz_oid_std(), CLASS_RECSYN, OID_STR_XML,
+                                  c->odr_in);
         npr->u.databaseRecord->which = Z_External_octet;
 
         npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
@@ -3669,7 +3691,7 @@ static void handle_srw_response(ZOOM_connection c,
         }
     }
     nmem = odr_extract_mem(c->odr_in);
-    nmem_transfer(resultset->odr->mem, nmem);
+    nmem_transfer(odr_getmem(resultset->odr), nmem);
     nmem_destroy(nmem);
 }
 #endif
@@ -3682,7 +3704,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
                                                     "Content-Type");
     const char *connection_head = z_HTTP_header_lookup(hres->headers,
                                                        "Connection");
-    c->mask = 0;
+    ZOOM_connection_set_mask(c, 0);
     yaz_log(log_details, "%p handle_http", c);
 
     if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
@@ -3754,11 +3776,7 @@ static int do_read(ZOOM_connection c)
         return 0;
     if (r <= 0)
     {
-        if (ZOOM_test_reconnect(c))
-        {
-            yaz_log(log_details, "%p do_read reconnect read", c);
-        }
-        else
+        if (!ZOOM_test_reconnect(c))
         {
             set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
             do_close(c);
@@ -3826,17 +3844,18 @@ static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out)
     }
     else if (r == 1)
     {    
-        c->mask = ZOOM_SELECT_EXCEPT;
+        int mask = ZOOM_SELECT_EXCEPT;
         if (c->cs->io_pending & CS_WANT_WRITE)
-            c->mask += ZOOM_SELECT_WRITE;
+            mask += ZOOM_SELECT_WRITE;
         if (c->cs->io_pending & CS_WANT_READ)
-            c->mask += ZOOM_SELECT_READ;
+            mask += ZOOM_SELECT_READ;
+        ZOOM_connection_set_mask(c, mask);
         yaz_log(log_details, "%p do_write_ex write incomplete mask=%d",
                 c, c->mask);
     }
     else
     {
-        c->mask = ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT;
+        ZOOM_connection_set_mask(c, ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT);
         yaz_log(log_details, "%p do_write_ex write complete mask=%d",
                 c, c->mask);
     }
@@ -4014,11 +4033,12 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask)
                 "cs_rcvconnect returned %d", c, ret);
         if (ret == 1)
         {
-            c->mask = ZOOM_SELECT_EXCEPT;
+            int mask = ZOOM_SELECT_EXCEPT;
             if (c->cs->io_pending & CS_WANT_WRITE)
-                c->mask += ZOOM_SELECT_WRITE;
+                mask += ZOOM_SELECT_WRITE;
             if (c->cs->io_pending & CS_WANT_READ)
-                c->mask += ZOOM_SELECT_READ;
+                mask += ZOOM_SELECT_READ;
+            ZOOM_connection_set_mask(c, mask);
         }
         else if (ret == 0)
         {
@@ -4032,7 +4052,7 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask)
                 /* no init request for SRW .. */
                 assert(c->tasks->which == ZOOM_TASK_CONNECT);
                 ZOOM_connection_remove_task(c);
-                c->mask = 0;
+                ZOOM_connection_set_mask(c, 0);
                 ZOOM_connection_exec_task(c);
             }
             c->state = STATE_ESTABLISHED;
@@ -4047,12 +4067,7 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask)
     {
         if (mask & ZOOM_SELECT_EXCEPT)
         {
-            if (ZOOM_test_reconnect(c))
-            {
-                event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
-                ZOOM_connection_put_event(c, event);
-            }
-            else
+            if (!ZOOM_test_reconnect(c))
             {
                 set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
                 do_close(c);
@@ -4074,217 +4089,13 @@ ZOOM_API(int)
     return cs->last_event;
 }
 
-ZOOM_API(int)
-    ZOOM_event(int no, ZOOM_connection *cs)
-{
-    int timeout = 30;      /* default timeout in seconds */
-    int timeout_set = 0;   /* whether it was overriden at all */
-#if HAVE_SYS_POLL_H
-    struct pollfd pollfds[1024];
-    ZOOM_connection poll_cs[1024];
-#else
-    struct timeval tv;
-    fd_set input, output, except;
-#endif
-    int i, r, nfds;
-    int max_fd = 0;
-
-    yaz_log(log_details, "ZOOM_event(no=%d,cs=%p)", no, cs);
-    
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        ZOOM_Event event;
-
-#if 0
-        if (c)
-            ZOOM_connection_show_tasks(c);
-#endif
-
-        if (c && (event = ZOOM_connection_get_event(c)))
-        {
-            ZOOM_Event_destroy(event);
-            return i+1;
-        }
-    }
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        if (c)
-        {
-            ZOOM_Event event;
-            ZOOM_connection_exec_task(c);
-            if ((event = ZOOM_connection_get_event(c)))
-            {
-                ZOOM_Event_destroy(event);
-                return i+1;
-            }
-        }
-    }
-#if HAVE_SYS_POLL_H
 
-#else
-    FD_ZERO(&input);
-    FD_ZERO(&output);
-    FD_ZERO(&except);
-#endif
-    nfds = 0;
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        int fd, mask;
-        int this_timeout;
-        
-        if (!c)
-            continue;
-        fd = z3950_connection_socket(c);
-        mask = z3950_connection_mask(c);
-
-        if (fd == -1)
-            continue;
-        if (max_fd < fd)
-            max_fd = fd;
-        
-        /* -1 is used for indefinite timeout (no timeout), so -2 here. */
-        this_timeout = ZOOM_options_get_int(c->options, "timeout", -2);
-        if (this_timeout != -2)
-        {
-            /* ensure the minimum timeout is used */
-            if (!timeout_set)
-                timeout = this_timeout;
-            else if (this_timeout != -1 && this_timeout < timeout)
-                timeout = this_timeout;
-            timeout_set = 1;
-        }               
-#if HAVE_SYS_POLL_H
-        if (mask)
-        {
-            short poll_events = 0;
-
-            if (mask & ZOOM_SELECT_READ)
-                poll_events += POLLIN;
-            if (mask & ZOOM_SELECT_WRITE)
-                poll_events += POLLOUT;
-            if (mask & ZOOM_SELECT_EXCEPT)
-                poll_events += POLLERR;
-            pollfds[nfds].fd = fd;
-            pollfds[nfds].events = poll_events;
-            pollfds[nfds].revents = 0;
-            poll_cs[nfds] = c;
-            nfds++;
-        }
-#else
-        if (mask & ZOOM_SELECT_READ)
-        {
-            FD_SET(fd, &input);
-            nfds++;
-        }
-        if (mask & ZOOM_SELECT_WRITE)
-        {
-            FD_SET(fd, &output);
-            nfds++;
-        }
-        if (mask & ZOOM_SELECT_EXCEPT)
-        {
-            FD_SET(fd, &except);
-            nfds++;
-        }
-#endif
-    }
-    if (!nfds)
-        return 0;
-
-#if HAVE_SYS_POLL_H
-    while ((r = poll(pollfds, nfds,
-         (timeout == -1 ? -1 : timeout * 1000))) < 0
-          && errno == EINTR)
-    {
-        ;
-    }
-    if (r < 0)
-        yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event: poll");
-    for (i = 0; i<nfds; i++)
-    {
-        ZOOM_connection c = poll_cs[i];
-        if (r && c->mask)
-        {
-            int mask = 0;
-            if (pollfds[i].revents & POLLIN)
-                mask += ZOOM_SELECT_READ;
-            if (pollfds[i].revents & POLLOUT)
-                mask += ZOOM_SELECT_WRITE;
-            if (pollfds[i].revents & POLLERR)
-                mask += ZOOM_SELECT_EXCEPT;
-            if (mask)
-                ZOOM_connection_do_io(c, mask);
-        }
-        else if (r == 0 && c->mask)
-        {
-            ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
-            /* timeout and this connection was waiting */
-            set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0);
-            do_close(c);
-            ZOOM_connection_put_event(c, event);
-        }
-    }
-#else
-    tv.tv_sec = timeout;
-    tv.tv_usec = 0;
-
-    while ((r = select(max_fd+1, &input, &output, &except,
-                       (timeout == -1 ? 0 : &tv))) < 0 && errno == EINTR)
-    {
-        ;
-    }
-    if (r < 0)
-        yaz_log(YLOG_WARN|YLOG_ERRNO, "ZOOM_event: select");
-
-    r = select(max_fd+1, &input, &output, &except, (timeout == -1 ? 0 : &tv));
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        int fd, mask;
-
-        if (!c)
-            continue;
-        fd = z3950_connection_socket(c);
-        mask = 0;
-        if (r && c->mask)
-        {
-            /* no timeout and real socket */
-            if (FD_ISSET(fd, &input))
-                mask += ZOOM_SELECT_READ;
-            if (FD_ISSET(fd, &output))
-                mask += ZOOM_SELECT_WRITE;
-            if (FD_ISSET(fd, &except))
-                mask += ZOOM_SELECT_EXCEPT;
-            if (mask)
-                ZOOM_connection_do_io(c, mask);
-        }
-        if (r == 0 && c->mask)
-        {
-            ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
-            /* timeout and this connection was waiting */
-            set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0);
-            do_close(c);
-            ZOOM_connection_put_event(c, event);
-        }
-    }
-#endif
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        ZOOM_Event event;
-        if (c && (event = ZOOM_connection_get_event(c)))
-        {
-            ZOOM_Event_destroy(event);
-            return i+1;
-        }
-    }
-    return 0;
+static void cql2pqf_wrbuf_puts(const char *buf, void *client_data)
+{
+    WRBUF wrbuf = client_data;
+    wrbuf_puts(wrbuf, buf);
 }
 
-
 /*
  * Returns an xmalloc()d string containing RPN that corresponds to the
  * CQL passed in.  On error, sets the Connection object's error state
@@ -4295,10 +4106,9 @@ static char *cql2pqf(ZOOM_connection c, const char *cql)
 {
     CQL_parser parser;
     int error;
-    struct cql_node *node;
     const char *cqlfile;
-    static cql_transform_t trans;
-    char pqfbuf[512];
+    cql_transform_t trans;
+    char *result = 0;
 
     parser = cql_parser_create();
     if ((error = cql_parser_string(parser, cql)) != 0) {
@@ -4307,42 +4117,127 @@ static char *cql2pqf(ZOOM_connection c, const char *cql)
         return 0;
     }
 
-    node = cql_parser_result(parser);
-    /* ### Do not call cql_parser_destroy() yet: it destroys `node'! */
-
     cqlfile = ZOOM_connection_option_get(c, "cqlfile");
-    if (cqlfile == 0) {
-        cql_parser_destroy(parser);
-        cql_node_destroy(node);
+    if (cqlfile == 0) 
+    {
         set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file");
-        return 0;
     }
-
-    if ((trans = cql_transform_open_fname(cqlfile)) == 0) {
+    else if ((trans = cql_transform_open_fname(cqlfile)) == 0) 
+    {
         char buf[512];        
-        cql_parser_destroy(parser);
-        cql_node_destroy(node);
         sprintf(buf, "can't open CQL transform file '%.200s': %.200s",
                 cqlfile, strerror(errno));
         set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
-        return 0;
     }
-
-    error = cql_transform_buf(trans, node, pqfbuf, sizeof pqfbuf);
-    cql_parser_destroy(parser);
-    cql_node_destroy(node);
-    if (error != 0) {
-        char buf[512];
-        const char *addinfo;
-        error = cql_transform_error(trans, &addinfo);
+    else 
+    {
+        WRBUF wrbuf_result = wrbuf_alloc();
+        error = cql_transform(trans, cql_parser_result(parser),
+                              cql2pqf_wrbuf_puts, wrbuf_result);
+        if (error != 0) {
+            char buf[512];
+            const char *addinfo;
+            error = cql_transform_error(trans, &addinfo);
+            sprintf(buf, "%.200s (addinfo=%.200s)", 
+                    cql_strerror(error), addinfo);
+            set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
+        }
+        else
+        {
+            result = xstrdup(wrbuf_cstr(wrbuf_result));
+        }
         cql_transform_close(trans);
-        sprintf(buf, "%.200s (addinfo=%.200s)", cql_strerror(error), addinfo);
-        set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
+        wrbuf_destroy(wrbuf_result);
+    }
+    cql_parser_destroy(parser);
+    return result;
+}
+
+ZOOM_API(int) ZOOM_connection_fire_event_timeout(ZOOM_connection c)
+{
+    if (c->mask)
+    {
+        ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
+        /* timeout and this connection was waiting */
+        set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0);
+        do_close(c);
+        ZOOM_connection_put_event(c, event);
+    }
+    return 0;
+}
+
+ZOOM_API(int)
+    ZOOM_connection_process(ZOOM_connection c)
+{
+    ZOOM_Event event;
+    if (!c)
         return 0;
+
+    event = ZOOM_connection_get_event(c);
+    if (event)
+    {
+        ZOOM_Event_destroy(event);
+        return 1;
+    }
+    ZOOM_connection_exec_task(c);
+    event = ZOOM_connection_get_event(c);
+    if (event)
+    {
+        ZOOM_Event_destroy(event);
+        return 1;
     }
+    return 0;
+}
 
-    cql_transform_close(trans);
-    return xstrdup(pqfbuf);
+ZOOM_API(int)
+    ZOOM_event_nonblock(int no, ZOOM_connection *cs)
+{
+    int i;
+
+    yaz_log(log_details, "ZOOM_process_event(no=%d,cs=%p)", no, cs);
+    
+    for (i = 0; i<no; i++)
+    {
+        ZOOM_connection c = cs[i];
+
+        if (c && ZOOM_connection_process(c))
+            return i+1;
+    }
+    return 0;
+}
+
+ZOOM_API(int) ZOOM_connection_fire_event_socket(ZOOM_connection c, int mask)
+{
+    if (c->mask && mask)
+        ZOOM_connection_do_io(c, mask);
+    return 0;
+}
+
+ZOOM_API(int) ZOOM_connection_get_socket(ZOOM_connection c)
+{
+    if (c->cs)
+        return cs_fileno(c->cs);
+    return -1;
+}
+
+ZOOM_API(int) ZOOM_connection_set_mask(ZOOM_connection c, int mask)
+{
+    c->mask = mask;
+    if (!c->cs)
+        return -1; 
+    return 0;
+}
+
+ZOOM_API(int) ZOOM_connection_get_mask(ZOOM_connection c)
+{
+    if (c->cs)
+        return c->mask;
+    return 0;
+}
+
+ZOOM_API(int) ZOOM_connection_get_timeout(ZOOM_connection c)
+{
+    return ZOOM_options_get_int(c->options, "timeout", 30);
 }
 
 /*