Update of /cvsroot/monetdb/pathfinder/runtime
In directory sc8-pr-cvs16:/tmp/cvs-serv2946

Modified Files:
        pathfinder.mx xrpc_client.mx xrpc_server.mx 
Log Message:
- Better error handling: create a buffer to store MIL error messages.
  When xquery_method() returns the vague error message "xquery_method:
  error during execution", copy the real MIL errors from the buffer into
  the SOAP Fault message.

- Upon receiving the response message for an updating RPC call,
  check if it contains a SOAP Fault message and handle it accordingly.



Index: xrpc_client.mx
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/xrpc_client.mx,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- xrpc_client.mx      17 Apr 2007 13:37:52 -0000      1.29
+++ xrpc_client.mx      18 Apr 2007 19:50:26 -0000      1.30
@@ -150,7 +150,10 @@
                 fault_text_pre := 
pre_prop.ord_select(fault_text_pre).reverse().fetch(0);
                 fault_text_pre := pre_prop.fetch(int(fault_text_pre)+1);
             var fault_text     := prop_text.fetch(fault_text_pre);
-            ERROR("SOAP Fault Code  : %s\nSOAP Fault Reason: %s\n", 
fault_value, fault_text);
+            ERROR("Remote execution failed.\n" +
+                  "SOAP Fault Code: %s\n" +
+                  "SOAP Fault Reason:\n%s\n",
+                  fault_value, fault_text);
         }
     }
 
@@ -638,28 +641,6 @@
 }
 
 /**
- * NOTE: this function is not used any more, as of Dec 06, 2006
- * @return cont-kind, or
- *         GDK_int_min by error
- */
-/*
-static int
-getContKind(BAT *itemBat, BAT *kindBat, int offset)
-{
-    BUN bres;
-    oid index  = *(oid*)BUNhead(itemBat, BUNptr(itemBat, offset));
-
-    BUNfndVOID(bres, kindBat, &index);
-    if(!bres){
-        GDKerror("getContKind: could not find BUN with head value "
-                "[EMAIL PROTECTED]", index);
-        return GDK_int_min;
-    }
-    return *(int*) BUNtail(kindBat, bres);
-}
-*/
-
-/**
  * @return WS BAT, or
  *         NULL by error
  */
@@ -741,6 +722,46 @@
     return ret;
 }
 
+static void
+handle_soap_fault_msg(char *errmsg)
+{
+    char *strptr, *strptr2;
+
+    strptr = strstr(errmsg, "<env:Value");
+    if(!strptr) {
+        GDKerror("handle_soap_fault_msg: SOAP Fault message not "
+                 "well-formed: could not find \"<env:Value\".\n%s\n",
+                 errmsg);
+    }
+    strptr = strchr(strptr, '>'); assert(strptr);
+    strptr2 = strstr(++strptr, "</env:Value>");
+    if( (!strptr) || (!strptr2) ) {
+        GDKerror("handle_soap_fault_msg: SOAP Fault message not "
+                 "well-formed at \"<env:Value>.\n%s\n", errmsg);
+        return;
+    }
+    strptr2[0] = '\0';
+    GDKerror("SOAP Fault Code  : %s\n", strptr);
+    strptr2[0] = '<';
+
+    strptr = strstr(strptr2+12, "<env:Text");
+    if(!strptr) {
+        GDKerror("handle_soap_fault_msg: SOAP Fault message not "
+                 "well-formed: could not find \"<env:Text\".\n%s\n",
+                 errmsg);
+        return;
+    }
+    strptr = strchr(strptr, '>') + 1;
+    strptr2 = strstr(strptr, "</env:Text>");
+    if( (!strptr) || (!strptr2) ) {
+        GDKerror("handle_soap_fault_msg: SOAP Fault message not "
+                 "well-formed at \"<env:Text>\".\n%s\n", errmsg);
+        return;
+    }
+    strptr2[0] = '\0';
+    GDKerror("SOAP Fault Reason:\n%s\n", strptr);
+}
+
 /**
  * try to receive the response message and shred it into shredBAT
  * Returns shredBAT, or
@@ -753,30 +774,28 @@
              int updCall,
              lng *time_xrpcClntDeSeria)
 {
-    char *strptr = NULL, *ptr = NULL;
+    char *strptr = NULL;
     int ret;
     stream *in;
     BAT *shredBAT;
 
-    in = socket_rastream(sock, "http_receive");
-    if(!in){
+    if( !(in = socket_rastream(sock, "http_receive")) ){
         GDKerror("response2bat: failed to create socket_rastream\n");
         return NULL;
     }
 
     b->pos = 0;
     errno = 0;
-    ret = stream_readline(in, b->buf, 1024);
-    if (ret < 0) {
-        GDKerror("response2bat: failed to receive response from %s: %s\n",
-                dst, errno?strerror(errno):".");
+    if( !(ret = stream_readline(in, b->buf, 1024)) ){
+        GDKerror("response2bat: failed to receive response from %s", dst);
+        if(errno) GDKerror(": %s", strerror(errno));
+        GDKerror(".\n");
         stream_close(in); stream_destroy(in);
         return NULL;
     }
 
-    strptr = strchr(b->buf, ' ');
-    if (!strptr) {
-        GDKerror("response2bat: invalid response from %s\n%s\n",
+    if( !(strptr = strchr(b->buf, ' ')) ){
+        GDKerror("response2bat: invalid response from %s:\n%s\n",
                 dst, b->buf);
         stream_close(in); stream_destroy(in);
         return NULL;
@@ -785,55 +804,22 @@
     if (strncmp(++strptr, "200", 3) != 0) {
         b->buf[ret] = '\0';
         GDKerror("HTTP Error Code  : %s\n", b->buf + 9);
-        strptr = b->buf + b->pos + 1;
-        do{ /* receive the whole error message */
+
+        b->pos = 0;
+        do{ /* read the SOAP Fault message */
             errno = 0;
             ret = stream_read(in, (b->buf + b->pos), 1, (b->len - b->pos));
-            b->pos += ret;
+            if (ret > 0) b->pos += ret;
         } while (ret > 0);
         if (ret < 0) {
-            GDKerror("response2bat: failed to receive response from %s: %s\n",
-                    dst, errno?strerror(errno):".");
-            stream_close(in); stream_destroy(in);
+            GDKerror("response2bat: failed to receive response from %s",
+                    dst);
+            if(errno) GDKerror(": %s", strerror(errno));
+            GDKerror(".\n");
             return NULL;
         }
         b->buf[b->pos] = 0;
-
-        strptr = strstr(strptr, "<env:Value");
-        if(!strptr) {
-            GDKerror("response2bat: SOAP Fault message not well-formed: "
-                     "could not find \"<env:Value\".\n");
-            stream_close(in); stream_destroy(in);
-            return NULL;
-        }
-        strptr = strchr(strptr, '>') + 1;
-        ptr = strstr(strptr, "</env:Value>");
-        if( (!strptr) || (!ptr) ) {
-            GDKerror("response2bat: SOAP Fault message not well-formed: "
-                     "could not find \"</env:Value>\".\n");
-            stream_close(in); stream_destroy(in);
-            return NULL;
-        }
-        ptr[0] = '\0';
-        GDKerror("SOAP Fault Code  : %s\n", strptr);
-
-        strptr = strstr(ptr+12, "<env:Text");
-        if(!strptr) {
-            GDKerror("response2bat: SOAP Fault message not well-formed: "
-                     "could not find \"<env:Text\".\n");
-            stream_close(in); stream_destroy(in);
-            return NULL;
-        }
-        strptr = strchr(strptr, '>') + 1;
-        ptr = strstr(strptr, "</env:Text>");
-        if( (!strptr) || (!ptr) ) {
-            GDKerror("response2bat: SOAP Fault message not well-formed: "
-                     "could not find \"</env:Text>\".\n");
-            stream_close(in); stream_destroy(in);
-            return NULL;
-        }
-        ptr[0] = '\0';
-        GDKerror("SOAP Fault Reason: %s\n", strptr);
+        handle_soap_fault_msg(b->buf);
         stream_close(in); stream_destroy(in);
         return NULL;
     }
@@ -846,8 +832,10 @@
             ret = 0; /* end-of-HTTP-header found */
     } while (ret > 0);
     if (ret < 0) {
-        GDKerror("response2bat: failed to receive response from %s: %s\n",
-                dst, errno?strerror(errno):".");
+        GDKerror("response2bat: failed to receive response from %s",
+                dst);
+        if(errno) GDKerror(": %s", strerror(errno));
+        GDKerror(".\n");
         stream_close(in); stream_destroy(in);
         return NULL;
     }
@@ -861,23 +849,34 @@
     }
 
     if (updCall) {
-        *time_xrpcClntDeSeria = GDKusec() - *time_xrpcClntDeSeria;
+        b->pos = 0;
+        do{ /* Check for error message */
+            errno = 0;
+            ret = stream_read(in, (b->buf + b->pos), 1, (b->len - b->pos));
+            if (ret > 0) b->pos += ret;
+        } while (ret > 0);
+        b->buf[b->pos] = 0;
         stream_close(in); stream_destroy(in);
-        return shredBAT;
+
+        if(b->pos == 0){ /* no error message => operation succeeded */
+            *time_xrpcClntDeSeria = GDKusec() - *time_xrpcClntDeSeria;
+            return shredBAT;
+        } else {
+            handle_soap_fault_msg(b->buf);
+            BBPreclaim(shredBAT);
+            return NULL;
+        }
     }
 
     if(shred(shredBAT, NULL, NULL, in, 0, NULL, NULL, NULL) ==GDK_FAIL) {
-        GDKerror("most probably, the XRPC response contains some MIL "
-                "error message\n");
-        if(BBPreclaim(shredBAT) == -1){
-            GDKerror("response2bat: failed to destroy \"shredBAT\"!");
-        }
+        GDKerror("response2bat: invalid XRPC response received\n");
+        BBPreclaim(shredBAT);
         stream_close(in); stream_destroy(in);
         return NULL;
     }
+
     /* Stop timing Client DeSerialisation */
     *time_xrpcClntDeSeria = GDKusec() - *time_xrpcClntDeSeria;
-
     stream_close(in); stream_destroy(in);
     return shredBAT;
 }

Index: pathfinder.mx
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/pathfinder.mx,v
retrieving revision 1.342
retrieving revision 1.343
diff -u -d -r1.342 -r1.343
--- pathfinder.mx       18 Apr 2007 17:41:37 -0000      1.342
+++ pathfinder.mx       18 Apr 2007 19:50:25 -0000      1.343
@@ -4544,7 +4544,7 @@
                 c = xquery_types[t].loc;
 
                if (xquery_types[t].monet_tpe == TYPE_str) {
-                    /* we no longer do fancy strTostr for strings; just copied 
as-is */
+            /* we no longer do fancy strTostr for strings; just copied as-is */
                    char *t, *s = argval[l];
                    int len = strlen(s)*2;
                    if (len >= ctx->vallen) {
@@ -5854,11 +5854,10 @@
     if (err == NULL) { 
         err = xquery_function_call(ctx, usec, ns, method, argc, itercnt, 
argcnt, argtpe, argval, shredBAT);
         if (err == (char*) -1) err = "xquery_method: function could not be 
resolved.\n";
-        else if (err == xquery_nondescriptive_error) err = 
xquery_function_error;
+        else if (err == xquery_function_error) err = 
xquery_nondescriptive_error;
     }
 
     time_xrpcServApp = GDKusec() - time_xrpcServApp;
-
     if (flags&1){
         /* print timing ourselves */
         fprintf(stdout, "\n"

Index: xrpc_server.mx
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/runtime/xrpc_server.mx,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- xrpc_server.mx      18 Apr 2007 11:36:42 -0000      1.36
+++ xrpc_server.mx      18 Apr 2007 19:50:26 -0000      1.37
@@ -234,39 +234,51 @@
 BAT* xrpc_trusted = NULL;
 BAT* xrpc_admin = NULL;
 
-#define clean_up(argcnt, argtpe, argval, iterc, nr_args) {          \
-    lng i = 0;                                                      \
-                                                                    \
-    if(argcnt){                                                     \
-        for(i = 0; i < iterc; i++) GDKfree(argcnt[i]);              \
-        GDKfree(argcnt);                                            \
-    }                                                               \
-    if(argtpe){                                                     \
-        for(i = 0; i < nr_args; i++) GDKfree(argtpe[i]);            \
-        GDKfree(argtpe);                                            \
-    }                                                               \
-    if(argval){                                                     \
-        for(i = 0; i < nr_args; i++) GDKfree(argval[i]);            \
-        GDKfree(argval);                                            \
-    }                                                               \
+static INLINE void
+clean_up(lng **argcnt,
+         char **argtpe,
+         char **argval,
+         lng iterc,
+         lng nr_args)
+{
+    lng i = 0;
+
+    if(argcnt){
+        for(i = 0; i < iterc; i++) GDKfree(argcnt[i]);
+        GDKfree(argcnt);
+    }
+    if(argtpe){
+        for(i = 0; i < nr_args; i++) GDKfree(argtpe[i]);
+        GDKfree(argtpe);
+    }
+    if(argval){
+        for(i = 0; i < nr_args; i++) GDKfree(argval[i]);
+        GDKfree(argval);
+    }
 }
 
-#define send_err(out, header, http_err, soap_err, err_reason) {     \
-    if (header)                                                     \
-        stream_printf(out, "HTTP/1.1 %s\r\n"                        \
-                "Content-type: text/xml; charset=\"utf-8\"\r\n\r\n",\
-                http_err);                                          \
-    stream_printf(out,                                              \
-            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"          \
-            "<env:Envelope xmlns:env=\"%s\">"                       \
-            "<env:Body>"                                            \
-            "<env:Fault>"                                           \
-            "<env:Code><env:Value>%s</env:Value></env:Code>"        \
-            "<env:Reason>"                                          \
-            "<env:Text xml:lang=\"en\">%s</env:Text>"               \
-            "</env:Reason>"                                         \
-            "</env:Fault></env:Body></env:Envelope>",               \
-            SOAP_NS, soap_err, err_reason);                         \
+static INLINE void
+send_err(stream *out,
+         int header,
+         char *http_err,
+         char *soap_err,
+         char *err_reason)
+{
+    if (header)
+        stream_printf(out, "HTTP/1.1 %s\r\n"
+                "Content-type: text/xml; charset=\"utf-8\"\r\n\r\n",
+                http_err);
+    stream_printf(out,
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+            "<env:Envelope xmlns:env=\"%s\">"
+            "<env:Body>"
+            "<env:Fault>"
+            "<env:Code><env:Value>%s</env:Value></env:Code>"
+            "<env:Reason>"
+            "<env:Text xml:lang=\"en\">%s</env:Text>"
+            "</env:Reason>"
+            "</env:Fault></env:Body></env:Envelope>",
+            SOAP_NS, soap_err, err_reason);
 }
 
 /**
@@ -937,6 +949,8 @@
           str *argval,
           BAT *shredBAT)
 {
+       char errbuf[GDKMAXERRLEN], *errbuf_bak = GDKerrbuf;
+
     /* Possible values of serializeMode:
      * 0: xml-noheader-xrpc
      *    This is the normal serialize mode used for XRPC calls
@@ -953,14 +967,22 @@
     stream_printf(mc->c->fdout, "HTTP/1.1 200 OK\r\n"
             "Content-type: text/xml; "
             "charset=\"utf-8\"\r\n\r\n");
+
+       *errbuf = 0;
+       GDKsetbuf(errbuf);
     char *err = xquery_method(mc, serializeMode, module, location,
                               method, argc, iterc, argcnt, argtpe,
                               argval, shredBAT);
     if (err) {
+        if(err == ((char*)-1)) {
+            err = strstr(errbuf, "first error was:"); assert(err);
+            err = strstr(err, "!ERROR"); assert(err);
+        }
         send_err(mc->c->fdout, 0, "", "env:Sender", err);
         return GDK_FAIL;
     }
     stream_flush(mc->c->fdout);
+       GDKsetbuf(errbuf_bak);
 
     return GDK_SUCCEED;
 }
@@ -1095,6 +1117,7 @@
     int ret = GDK_FAIL;
     lng **argcnt = NULL;
 
+    lng time_xrpcServDeSeria = GDKusec();
     /* we don't always have the second '/' */
     if(uri[0] == '/') uri++;
     if(uri[0] == '\0'){
@@ -1145,17 +1168,26 @@
 
         str argtpe[2] = { "xs:string", "xs:document" };
         str argval[2] = { uri , "0" };
-        ret = execQuery(mc, 2, MXQ_ADMIN, location, method, 2, 1,
+        time_xrpcServDeSeria = GDKusec() - time_xrpcServDeSeria;
+
+        ret = execQuery(mc, 2|timing, MXQ_ADMIN, location, method, 2, 1,
                 argcnt, argtpe, argval, shredBAT);
         BBPreclaim(shredBAT);
     } else { /* GET/DELETE */
         str argtpe[1] = { "xs:string" };
         str argval[1] = { uri };
+        time_xrpcServDeSeria = GDKusec() - time_xrpcServDeSeria;
 
-        ret = execQuery(mc, 2, MXQ_ADMIN, location, method, 1, 1,
+        ret = execQuery(mc, 2|timing, MXQ_ADMIN, location, method, 1, 1,
                 argcnt, argtpe, argval, NULL);
     }
 
+    if (timing && ret != GDK_FAIL) {
+        fprintf(stdout,
+                "XRPC_Server_DeSerialisation:   %lld microsec\n",
+                time_xrpcServDeSeria);
+    }
+
     GDKfree(argcnt[0]);
     GDKfree(argcnt);
     return ret;
@@ -1179,7 +1211,7 @@
     }
 
     /* clean up */
-    mc->engine = xquery_client_engine; 
+    mc->engine = xquery_client_engine;
     xquery_client_end(mc, NULL);
     shttpd_finish(arg);
 }
@@ -1223,14 +1255,15 @@
     char *s;
     
     if (rpcd_running) {
-        stream_printf(GDKout, "\nRPC receiver already running\n");
+        stream_printf(GDKout,
+                "\nRPC receiver already running (on port %d)\n",
+                xrpc_port);
         return GDK_SUCCEED;
     }
 
     xrpc_port = *port;
     rpcd_running = 1;
 
-
     /* find 'datadir' (often datadir = <prefix>/share), otherwise use
      * "/usr/share", hence, httpd serves out <datadir>/MonetDB/xrpc */
     if( !(s = GDKgetenv("datadir")) ){
@@ -1269,7 +1302,6 @@
     return GDK_SUCCEED;
 }
 
-
 void xrpc_epilogue(void)
 {
     shttpd_fini();      /* Shut down the HTTP server. */


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins

Reply via email to