From 5415289d73ebc28de89499afa62b1f765566b1ab Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Mon, 30 Jan 2006 20:01:57 +0000 Subject: [PATCH] Get the JP IS client to almost finished state. Hack for usability of gsoap 270 in JP IS client interface: - direct using JP IS WSDL for client XML query file - it compiles with both gsoap 270 and 276b now Enabled the compilation of glite-jpis-client. --- org.glite.jp.index/Makefile | 22 +- org.glite.jp.index/examples/jpis-client.c | 436 +++++++++++++++++++++++++----- org.glite.jp.index/src/soap_ops.c | 4 + org.glite.jp.index/src/soap_ps_calls.c | 6 +- org.glite.jp.index/src/typemap.dat | 2 +- 5 files changed, 389 insertions(+), 81 deletions(-) diff --git a/org.glite.jp.index/Makefile b/org.glite.jp.index/Makefile index 10571c8..fa55b27 100644 --- a/org.glite.jp.index/Makefile +++ b/org.glite.jp.index/Makefile @@ -47,8 +47,7 @@ INSTALL:=libtool --mode=install install daemon:=glite-jp-indexd -# glite-jpis-client not compiled -examples:=glite-jpis-test +examples:=glite-jpis-test glite-jpis-client is_prefix:=jpis_ is_client_prefix:=jpis_client_ ps_prefix:=jpps_ @@ -60,7 +59,8 @@ SRCS:= conf.c bones_server.c soap_ops.c soap_ps_calls.c \ EXA_TEST_SRCS:=jpis-test.c ${is_prefix}C.c ${is_prefix}Client.c context.c db_ops.c conf.c EXA_DB_SRCS:=jpis-db-internal.c db_ops.c conf.c context.c -EXA_CLIENT_SRCS:=jpis-client.c ${is_client_prefix}C.c +EXA_CLIENT_SRCS:=jpis-client.c ${is_client_prefix}C.c ${is_client_prefix}Client.c +# ${is_prefix}C.c OBJS:=${SRCS:.c=.o} EXA_TEST_OBJS:=${EXA_TEST_SRCS:.c=.o} @@ -99,24 +99,24 @@ JobProvenancePS.xh: %.xh: %.wsdl JobProvenanceTypes.wsdl typemap.dat ${gsoap_bin_prefix}/wsdl2h -t ${top_srcdir}/src/typemap.dat -c -o $@ $< rm -f JobProvenanceTypes.wsdl -JobProvenanceISClient.xh: typemap.dat JobProvenanceISClient.xsd JobProvenanceIS.wsdl - cp ${stagedir}/interface/JobProvenance{Types.xsd,Types.wsdl,IS.wsdl} . - ${gsoap_bin_prefix}/wsdl2h -t ${top_srcdir}/src/typemap.dat -c -o $@ JobProvenanceIS.wsdl ${top_srcdir}/src/JobProvenanceISClient.xsd - rm -f JobProvenance{Types.xsd,Types.wsdl,IS.wsdl} +#JobProvenanceISClient.xh: typemap.dat JobProvenanceISClient.xsd JobProvenanceIS.wsdl +# cp ${stagedir}/interface/JobProvenance{Types.xsd,Types.wsdl,IS.wsdl} . +# ${gsoap_bin_prefix}/wsdl2h -t ${top_srcdir}/src/typemap.dat -c -o $@ JobProvenanceIS.wsdl ${top_srcdir}/src/JobProvenanceISClient.xsd +# rm -f JobProvenance{Types.xsd,Types.wsdl,IS.wsdl} ${is_prefix}ClientLib.c ${is_prefix}Client.c \ ${is_prefix}Server.c ${is_prefix}ServerLib.c \ ${is_prefix}C.c ${is_prefix}H.h ${is_prefix}_Stub.h: JobProvenanceIS.xh - ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${is_prefix} JobProvenanceIS.xh + ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${is_prefix} $< ${is_client_prefix}ClientLib.c ${is_client_prefix}Client.c \ ${is_client_prefix}Server.c ${is_client_prefix}ServerLib.c \ -${is_client_prefix}C.c ${is_client_prefix}H.h ${is_client_prefix}_Stub.h: JobProvenanceISClient.xh - ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${is_client_prefix} JobProvenanceISClient.xh +${is_client_prefix}C.c ${is_client_prefix}H.h ${is_client_prefix}_Stub.h: JobProvenanceIS.xh + ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${is_client_prefix} $< ${ps_prefix}Client.c ${ps_prefix}ClientLib.c \ ${ps_prefix}C.c ${ps_prefix}H.h ${ps_prefix}_Stub.h: JobProvenancePS.xh - ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${ps_prefix} JobProvenancePS.xh + ${gsoap_bin_prefix}/soapcpp2 -n -w -c -p ${ps_prefix} $< #env_C.c env_Server.c: diff --git a/org.glite.jp.index/examples/jpis-client.c b/org.glite.jp.index/examples/jpis-client.c index ea35d50..1e1930e 100644 --- a/org.glite.jp.index/examples/jpis-client.c +++ b/org.glite.jp.index/examples/jpis-client.c @@ -1,20 +1,111 @@ +#include +#include +#include +#include #include + #include +#include -/* workaround namespace symbol naming */ -#define jpis_client__namespaces namespaces +#include "soap_version.h" #include "jpis_client_.nsmap" +/* 'jpisclient' as future namespace */ +#define _jpisclient__QueryJobs _jpelem__QueryJobs +#define soap_default__jpisclient__QueryJobs soap_default__jpelem__QueryJobs +#define soap_get__jpisclient__QueryJobs soap_get__jpelem__QueryJobs +#define soap_put__jpisclient__QueryJobs soap_put__jpelem__QueryJobs +#define soap_serialize__jpisclient__QueryJobs soap_serialize__jpelem__QueryJobs + +#define DEFAULT_JPIS "http://localhost:8902" + + +/* namespaces[] not used here but needed to prevent linker to complain... */ +SOAP_NMAC struct Namespace namespaces[] = { + {NULL, NULL, NULL, NULL}, +}; + static struct option opts[] = { - {"host", 1, NULL, 'h'}, + {"index-server", required_argument, NULL, 'i'}, + {"example-file", optional_argument, NULL, 'e'}, + {"query-file", optional_argument, NULL, 'q'}, + {"test-file", optional_argument, NULL, 't'}, {NULL, 0, NULL, 0} }; -static const char *get_opt_string = "h:"; +static const char *get_opt_string = "i:q:e:t:"; + +#define NUMBER_OP 6 +struct { + enum jptype__queryOp op; + const char *name; +} operations[] = { + {jptype__queryOp__EQUAL, "=="}, + {jptype__queryOp__UNEQUAL, "<>"}, + {jptype__queryOp__LESS, "<"}, + {jptype__queryOp__GREATER, ">"}, + {jptype__queryOp__WITHIN, "in"}, + {jptype__queryOp__EXISTS, "exists"}, + {0, "unknown"} +}; + + +/* + * set the value + */ +static void value_set(struct soap *soap, struct jptype__stringOrBlob **value, const char *str) { +#if GSOAP_VERSION >= 20706 + *value = soap_malloc(soap, sizeof(*value)); + (*value)->__union_1 = SOAP_UNION_jptype__union_1_string; + (*value)->union_1.string = soap_strdup(soap, str); +#else + *value = soap_malloc(soap, sizeof(*value)); + (*value)->string = soap_strdup(soap, str); + (*value)->blob = NULL; +#endif +} -#if USE_DUMP -void query_example_fill(struct soap *soap, struct _jpisclient__QueryJobs *in) { +/* + * print the query data in the soap structre + */ +static void value_print(FILE *out, const struct jptype__stringOrBlob *value) { + int i, size, maxsize; + unsigned char *ptr; + + if (value) { +#if GSOAP_VERSION >= 20706 + if (value->__union_1 == SOAP_UNION_jptype__union_1_string) { + fprintf(out, "%s", value->union_1.string); + } else if (value->__union_1 == SOAP_UNION_jptype__union_1_blob) { + fprintf(out, "BLOB("); + ptr = value->union_1.blob->__ptr; + size = value->union_1.blob->__size; +#else + if (value->string) fprintf(out, "%s", value->string); + else if (value->blob) { + fprintf(out, "BLOB("); + ptr = value->blob->__ptr; + size = value->blob->__size; +#endif + maxsize = 10; + if (ptr) { + maxsize = size < 10 ? size : 10; + for (i = 0; i < maxsize; i++) fprintf(out, "%02X ", ptr[i]); + if (maxsize < size) fprintf(out, "..."); + } else fprintf(out, "NULL"); + fprintf(out, ")"); + } + } else { + fprintf(out, "-"); + } +} + + +/* + * fill the query soap structure with some example data + */ +static void query_example_fill(struct soap *soap, struct _jpisclient__QueryJobs *in) { struct jptype__indexQuery *cond; struct jptype__indexQueryRecord *rec; @@ -35,18 +126,14 @@ void query_example_fill(struct soap *soap, struct _jpisclient__QueryJobs *in) { rec = soap_malloc(soap, sizeof(*rec)); memset(rec, 0, sizeof(*rec)); rec->op = jptype__queryOp__EQUAL; - rec->value = soap_malloc(soap, sizeof(*(rec->value))); - rec->value->string = soap_strdup(soap, "Done"); - rec->value->blob = NULL; + value_set(soap, &rec->value, "Done"); cond->record[0] = rec; // OR equal to Ready rec = soap_malloc(soap, sizeof(*rec)); memset(rec, 0, sizeof(*rec)); rec->op = jptype__queryOp__EQUAL; - rec->value = soap_malloc(soap, sizeof(*(rec->value))); - rec->value->string = soap_strdup(soap, "Ready"); - rec->value->blob = NULL; + value_set(soap, &rec->value, "Ready"); cond->record[1] = rec; in->conditions[0] = cond; @@ -64,9 +151,7 @@ void query_example_fill(struct soap *soap, struct _jpisclient__QueryJobs *in) { rec = soap_malloc(soap, sizeof(*rec)); memset(rec, 0, sizeof(*rec)); rec->op = jptype__queryOp__UNEQUAL; - rec->value = soap_malloc(soap, sizeof(*(rec->value))); - rec->value->string = soap_strdup(soap, "God"); - rec->value->blob = NULL; + value_set(soap, &rec->value, "God"); cond->record[0] = rec; in->conditions[1] = cond; @@ -84,45 +169,43 @@ void query_example_fill(struct soap *soap, struct _jpisclient__QueryJobs *in) { } -void query_example_free(struct soap *soap, struct _jpisclient__QueryJobs *in) { +/* + * print info from the query soap structure + */ +static void query_print(FILE *out, const struct _jpisclient__QueryJobs *in) { struct jptype__indexQueryRecord *rec; - int i, j; + int i, j, k; + fprintf(out, "Conditions:\n"); for (i = 0; i < in->__sizeconditions; i++) { - if (in->conditions[i]->attr) soap_dealloc(soap, in->conditions[i]->attr); + fprintf(out, "\t%s\n", in->conditions[i]->attr); for (j = 0; j < in->conditions[i]->__sizerecord; j++) { rec = in->conditions[i]->record[j]; + for (k = 0; k <= NUMBER_OP; k++) + if (operations[k].op == rec->op) break; + fprintf(out, "\t\t%s", operations[k].name); if (rec->value) { - if (rec->value->string) soap_dealloc(soap, rec->value->string); - if (rec->value->blob) soap_dealloc(soap, rec->value->blob); - soap_dealloc(soap, rec->value); + fprintf(out, " "); + value_print(out, rec->value); + } + if (rec->value2) { + if (!rec->value) fprintf(out, "-"); + fprintf(out, " "); + value_print(out, rec->value2); } - soap_dealloc(soap, in->conditions[i]->record[j]); + fprintf(out, "\n"); } - soap_dealloc(soap, in->conditions[i]); } + fprintf(out, "Attributes:\n"); for (i = 0; i < in->__sizeattributes; i++) - soap_dealloc(soap, in->attributes[i]); + fprintf(out, "\t%s\n", in->attributes[i]); } -void query_example_dump(struct soap *soap, int fd) { - struct _jpisclient__QueryJobs qj; - - memset(&qj, 0, sizeof(qj)); - - soap->sendfd = fd; - soap_begin(soap); - query_example_fill(soap, &qj); - soap_begin_send(soap); - soap_serialize__jpisclient__QueryJobs(soap, &qj); - soap_put__jpisclient__QueryJobs(soap, &qj, "queryJobs", "indexQuery"); - soap_end_send(soap); - soap_end(soap); -} -#endif - -int query_recv(struct soap *soap, int fd, struct _jpisclient__QueryJobs *qj) { +/* + * read the XML query + */ +static int query_recv(struct soap *soap, int fd, struct _jpisclient__QueryJobs *qj) { memset(qj, 0, sizeof(*qj)); soap->recvfd = fd; @@ -140,52 +223,269 @@ int query_recv(struct soap *soap, int fd, struct _jpisclient__QueryJobs *qj) { } -static void usage(const char *name) { - fprintf(stderr, "Usage: %s [-h JPIS:PORT]\n", name); +/* + * dump the XML query + */ +static int query_dump(struct soap *soap, int fd, struct _jpisclient__QueryJobs *qj) { + int retval; + + soap->sendfd = fd; + soap_begin_send(soap); + soap_serialize__jpisclient__QueryJobs(soap, qj); + retval = soap_put__jpisclient__QueryJobs(soap, qj, "queryJobs", "indexQuery"); + soap_end_send(soap); + + return retval; +} + + +/* + * dump the XML query with the example data + */ +static int query_example_dump(struct soap *soap, int fd) { + struct _jpisclient__QueryJobs qj; + int retval; + + memset(&qj, 0, sizeof(qj)); + + soap_begin(soap); + query_example_fill(soap, &qj); + retval = query_dump(soap, fd, &qj); + soap_end(soap); + + return retval; +} + + +/* + * help screen + */ +static void usage(const char *prog_name) { + fprintf(stderr, "Usage: %s OPTIONS\n", prog_name); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h|--help\n"); + fprintf(stderr, " -i|--index-server JPIS:PORT (default: " DEFAULT_JPIS ")\n"); + fprintf(stderr, " -q|--query-file IN_FILE.XML\n"); + fprintf(stderr, " -t|--test-file IN_FILE.XML\n"); + fprintf(stderr, " -e|--example-file OUT_FILE.XML\n"); +} + + +/* + * process the result after calling soap + */ +static int check_fault(struct soap *soap, int err) { + struct SOAP_ENV__Detail *detail; + struct jptype__genericFault *f; + char *reason,indent[200] = " "; + + switch(err) { + case SOAP_OK: fputs("OK", stderr); + putc('\n', stderr); + break; + case SOAP_FAULT: + case SOAP_SVR_FAULT: + if (soap->version == 2) { + detail = soap->fault->SOAP_ENV__Detail; +#if GSOAP_VERSION >= 20706 + reason = soap->fault->SOAP_ENV__Reason->SOAP_ENV__Text; +#else + reason = soap->fault->SOAP_ENV__Reason; +#endif + } + else { + detail = soap->fault->detail; + reason = soap->fault->faultstring; + } + fputs(reason, stderr); + putc('\n', stderr); + assert(detail->__type == SOAP_TYPE__genericFault); +#if GSOAP_VERSION >= 20700 + f = ((struct _genericFault *) detail->fault) +#else + f = ((struct _genericFault *) detail->value) +#endif + -> jpelem__genericFault; + + while (f) { + fprintf(stderr,"%s%s: %s (%s)\n",indent, + f->source,f->text,f->description); + f = f->reason; + strcat(indent," "); + } + return -1; + + default: soap_print_fault(soap,stderr); + return -1; + } + return 0; +} + + +/* + * print the data returned from JP IS + */ +static void queryJobsResponse_print(FILE *out, const struct _jpelem__QueryJobsResponse *in) { + struct jptype__attrValue *attr; + int i, j; + + fprintf(out, "Result %d jobs:\n", in->__sizejobs); + for (j=0; j__sizejobs; j++) { + fprintf(out, "\tjobid = %s, owner = %s\n", in->jobs[j]->jobid, in->jobs[j]->owner); + for (i=0; ijobs[j]->__sizeattributes; i++) { + attr = in->jobs[j]->attributes[i]; + fprintf(out, "\t\t%s\n", attr->name); + fprintf(out, "\t\t\tvalue = "); + value_print(out, attr->value); + fprintf(out, "\n"); + fprintf(out, "\t\t\torigin = %d, %s\n", attr->origin, attr->originDetail); + fprintf(out, "\t\t\ttime = %s", ctime(&attr->timestamp)); + } + } } int main(int argc, char * const argv[]) { struct soap soap; struct _jpisclient__QueryJobs qj; - char *query_file = NULL; - const char *name = NULL; - int opt; - + char *server, *example_file, *query_file, *test_file; + const char *prog_name; + int retval, opt, example_fd, query_fd, test_fd; + + prog_name = server = NULL; + example_file = query_file = test_file = NULL; + query_fd = example_fd = test_fd = -1; + retval = 1; + + /* + * Soap with registered plugin can't be used for reading XML. + * For communications with JP IS glite_gsplugin needs to be registered yet. + */ soap_init(&soap); + soap_set_namespaces(&soap, jpis_client__namespaces); #ifdef SOAP_XML_INDENT soap_omode(&soap, SOAP_XML_INDENT); #endif -#ifdef USE_DUMP - query_example_dump(&soap, 1); -#endif - - /* arguments */ - name = strrchr(argv[0], '/'); - if (name) name++; - else name = argv[0]; + /* program name */ + prog_name = strrchr(argv[0], '/'); + if (prog_name) prog_name++; + else prog_name = argv[0]; + /* handle arguments */ while ((opt = getopt_long(argc, argv, get_opt_string, opts, NULL)) != EOF) switch (opt) { - case 'h': free(query_file); query_file = strdup(optarg); break; + case 'i': + free(server); + server = strdup(optarg); + break; + case 'e': + free(example_file); + example_file = strdup(optarg); + break; + case 'q': + free(query_file); + query_file = strdup(optarg); + break; + case 't': + free(test_file); + test_file = strdup(optarg); + break; default: - usage(name); - return 1; + usage(prog_name); + goto cleanup; } if (optind < argc) { - usage(name); - return 1; + usage(prog_name); + goto cleanup; + } + if (!server) server = strdup(DEFAULT_JPIS); + + /* prepare steps according to the arguments */ + if (query_file) { + if (strcmp(query_file, "-") == 0) query_fd = STDIN_FILENO; + else if ((query_fd = open(query_file, 0)) < 0) { + fprintf(stderr, "error opening %s: %s\n", query_file, strerror(errno)); + goto cleanup; + } + free(query_file); + query_file = NULL; + } + if (example_file) { + if (strcmp(example_file, "-") == 0) example_fd = STDOUT_FILENO; + else if ((example_fd = creat(example_file, S_IREAD | S_IWRITE | S_IRGRP)) < 0) { + fprintf(stderr, "error creating %s: %s\n", example_file, strerror(errno)); + goto cleanup; + } + free(example_file); + example_file = NULL; + } + if (test_file) { + if (strcmp(test_file, "-") == 0) example_fd = STDOUT_FILENO; + else if ((test_fd = open(test_file, 0)) < 0) { + fprintf(stderr, "error opening %s: %s\n", test_file, strerror(errno)); + goto cleanup; + } + free(test_file); + test_file = NULL; } - soap_begin(&soap); - if (query_recv(&soap, 0, &qj) != 0) { - printf("chyba\n"); - } else { - printf("qj.attributes[0] = %s\n", qj.attributes[0]); + /* the dump action */ + if (example_fd >= 0) { + if (query_example_dump(&soap, example_fd) != 0) { + fprintf(stderr, "Error dumping example query XML.\n"); + } } - soap_end(&soap); /* free decoded data */ - soap_done(&soap); + /* the test XML file action */ + if (test_fd >= 0) { + soap_begin(&soap); + if (query_recv(&soap, test_fd, &qj) != 0) { + fprintf(stderr, "test: Error getting query XML\n"); + } else { + query_print(stdout, &qj); + } + soap_end(&soap); + } - return 0; + /* query action */ + if (query_fd >= 0) { + struct _jpelem__QueryJobs in; + struct _jpelem__QueryJobsResponse out; + int ret; + + soap_begin(&soap); + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + /* + * Right way would be copy data from client query structure to IS query + * structure. Just ugly retype to client here. + */ + if (query_recv(&soap, query_fd, (struct _jpisclient__QueryJobs *)&in) != 0) { + fprintf(stderr, "test: Error getting query XML\n"); + } else { + fprintf(stderr, "query: using JPIS %s\n\n", server); + query_print(stderr, &in); + fprintf(stderr, "\n"); + soap_register_plugin(&soap, glite_gsplugin); + ret = check_fault(&soap, soap_call___jpsrv__QueryJobs(&soap, server, "", &in, &out)); + if (ret == 0) { + queryJobsResponse_print(stderr, &out); + } else goto cleanup; + } + soap_end(&soap); + } + + retval = 0; + +cleanup: + soap_done(&soap); + if (example_fd > STDERR_FILENO) close(example_fd); + if (query_fd > STDERR_FILENO) close(query_fd); + if (test_fd > STDERR_FILENO) close(test_fd); + free(server); + free(example_file); + free(query_file); + free(test_file); + + return retval; } diff --git a/org.glite.jp.index/src/soap_ops.c b/org.glite.jp.index/src/soap_ops.c index baa60b2..32fc6bf 100644 --- a/org.glite.jp.index/src/soap_ops.c +++ b/org.glite.jp.index/src/soap_ops.c @@ -22,6 +22,10 @@ // XXX: 2 is only for debugging, replace with e.g. 100 #define JOBIDS_STRIDE 2 // how often realloc matched jobids result +#if GSOAP_VERSION >= 20706 +#define false_ xsd__boolean__false_ +#endif + /*------------------*/ /* Helper functions */ /*------------------*/ diff --git a/org.glite.jp.index/src/soap_ps_calls.c b/org.glite.jp.index/src/soap_ps_calls.c index b879efa..ddd899b 100644 --- a/org.glite.jp.index/src/soap_ps_calls.c +++ b/org.glite.jp.index/src/soap_ps_calls.c @@ -73,7 +73,11 @@ static int check_fault(struct soap *soap,int err) { case SOAP_SVR_FAULT: if (soap->version == 2) { detail = soap->fault->SOAP_ENV__Detail; +#if GSOAP_VERSION >= 20706 + reason = soap->fault->SOAP_ENV__Reason->SOAP_ENV__Text; +#else reason = soap->fault->SOAP_ENV__Reason; +#endif } else { detail = soap->fault->detail; @@ -82,7 +86,7 @@ static int check_fault(struct soap *soap,int err) { fputs(reason,stderr); putc('\n',stderr); assert(detail->__type == SOAP_TYPE__genericFault); -#if GSOAP_VERSION >=20700 +#if GSOAP_VERSION >= 20700 f = ((struct _genericFault *) detail->fault) #else f = ((struct _genericFault *) detail->value) diff --git a/org.glite.jp.index/src/typemap.dat b/org.glite.jp.index/src/typemap.dat index e86b875..18321cc 100644 --- a/org.glite.jp.index/src/typemap.dat +++ b/org.glite.jp.index/src/typemap.dat @@ -1,4 +1,4 @@ jpsrv = http://glite.org/wsdl/services/jp jptype = http://glite.org/wsdl/types/jp jpelem = http://glite.org/wsdl/elements/jp -jpisclient = http://glite.org/xsd/types/jpisclient +#jpisclient = http://glite.org/xsd/types/jpisclient -- 1.8.2.3