implemented >, < and within operations on index
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Mon, 2 Apr 2007 10:45:45 +0000 (10:45 +0000)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Mon, 2 Apr 2007 10:45:45 +0000 (10:45 +0000)
added test for WITHIN on query operation
testing w/o distractions from running JPPS (w/o feeds)
cosmetic changes in tests

org.glite.jp.index/Makefile
org.glite.jp.index/config/glite-jpis-test-config.xml [new file with mode: 0644]
org.glite.jp.index/examples/jpis-client.c
org.glite.jp.index/examples/query-tests/exists_query.out
org.glite.jp.index/examples/query-tests/run-test.sh
org.glite.jp.index/examples/query-tests/within_query.in [new file with mode: 0644]
org.glite.jp.index/examples/query-tests/within_query.out [new file with mode: 0644]
org.glite.jp.index/src/soap_ops.c

index b7c028c..b43cc0a 100644 (file)
@@ -49,7 +49,7 @@ INSTALL:=libtool --mode=install install
 daemon:=glite-jp-indexd
 examples:=glite-jpis-test glite-jpis-client
 test:=run-test.sh
-test_files:=dump1.sql simple_query.in simple_query.out complex_query.in complex_query.out authz.out jobid_query.in jobid_query.out origin_query.in origin_query.out exists_query.in exists_query.out
+test_files:=dump1.sql simple_query.in simple_query.out complex_query.in complex_query.out authz.out jobid_query.in jobid_query.out origin_query.in origin_query.out exists_query.in exists_query.out within_query.in within_query.out
 
 MANS1:=glite-jpis-client.1
 MANS8:=glite-jp-indexd.8
@@ -169,6 +169,7 @@ install:
        ${INSTALL} -m 755 ${top_srcdir}/config/startup ${PREFIX}/etc/init.d/glite-jp-indexd
        ${INSTALL} -m 755 ${top_srcdir}/config/glite-jp-index-dbsetup.sql ${PREFIX}/etc
        ${INSTALL} -m 755 ${top_srcdir}/config/glite-jpis-config.xml ${PREFIX}/etc
+       ${INSTALL} -m 755 ${top_srcdir}/config/glite-jpis-test-config.xml ${PREFIX}/etc
        ${INSTALL} -m 644 ${top_srcdir}/doc/README ${HTMLS} ${PREFIX}/share/doc/${package}-${version}
        ${INSTALL} -m 644 ${MANS1} ${PREFIX}/share/man/man1
        ${INSTALL} -m 644 ${MANS8} ${PREFIX}/share/man/man8
diff --git a/org.glite.jp.index/config/glite-jpis-test-config.xml b/org.glite.jp.index/config/glite-jpis-test-config.xml
new file mode 100644 (file)
index 0000000..b81b342
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jpelem:ServerConfiguration xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jptype="http://glite.org/wsdl/types/jp" xmlns:jpsrv="http://glite.org/wsdl/services/jp" xmlns:jpelem="http://glite.org/wsdl/elements/jp">
+       
+       <!-- List of attributes IS want to receive from PS's -->
+       <attrs>http://egee.cesnet.cz/en/Schema/JP/System:owner</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/JP/System:jobId</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/JP/System:regtime</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:user</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:aTag</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:eNodes</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:RB</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:CE</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:UIHost</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:CPUTime</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:NProc</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatus</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatusDate</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:retryCount</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:jobType</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:nsubjobs</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:lastStatusHistory</attrs>
+       <attrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:fullStatusHistory</attrs>
+
+
+       <!-- List of attributes IS will index -->
+       <indexedAttrs>http://egee.cesnet.cz/en/Schema/JP/System:owner</indexedAttrs>
+       <indexedAttrs>http://egee.cesnet.cz/en/Schema/JP/System:jobId</indexedAttrs>
+       <indexedAttrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:user</indexedAttrs>
+       <indexedAttrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:CE</indexedAttrs>
+       <indexedAttrs>http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatus</indexedAttrs>
+
+       <!-- List of type plugins -->
+       <plugins></plugins>
+</jpelem:ServerConfiguration>
index 50c7875..e7cbff0 100644 (file)
@@ -55,8 +55,8 @@ struct {
        {jptype__queryOp__UNEQUAL, "<>"},
        {jptype__queryOp__LESS, "<"},
        {jptype__queryOp__GREATER, ">"},
-       {jptype__queryOp__WITHIN, "in"},
-       {jptype__queryOp__EXISTS, "exists"},
+       {jptype__queryOp__WITHIN, "WITHIN"},
+       {jptype__queryOp__EXISTS, "EXISTS"},
        {0, "unknown"}
 };
 
@@ -227,7 +227,7 @@ static void query_print(FILE *out, const struct _jpisclient__QueryJobs *in) {
                        }
                        if (rec->value2) {
                                if (!rec->value) fprintf(out, "-");
-                               fprintf(out, " ");
+                               fprintf(out, " AND ");
                                value_print(out, rec->value2);
                        }
                        fprintf(out, "\n");
index 04f2c48..2fbebf3 100644 (file)
@@ -3,7 +3,7 @@ query: using JPIS http://localhost:10000
 Conditions:
        http://egee.cesnet.cz/en/Schema/LB/Attributes:CE
                origin IS ANY
-               value exists
+               value EXISTS
 Attributes:
        http://egee.cesnet.cz/en/Schema/JP/System:owner
        http://egee.cesnet.cz/en/Schema/JP/System:jobId
index ad2e381..9c0335a 100755 (executable)
@@ -6,6 +6,8 @@
 # requires running mysql
 #
 
+LC_ALL=C
+
 usage() {
 cat <<EOF
 
@@ -18,6 +20,8 @@ cat <<EOF
    GLITE_HOST_KEY..................path to host key
    GLITE_JPIS_TEST_PIDFILE.........pidfile (default \`pwd\`/glite-jp-indexd.pid)
    GLITE_JPIS_TEST_LOGFILE.........logfile (default \`pwd\`/glite-jp-indexd.log)
+   GLITE_JPIS_TEST_CONFIG..........config file (default \$GLITE_LOCATION/etc/
+                                   glite-jpis-test-config.xml)
    GLITE_JPIS_TEST_PORT............index server port
    GLITE_JPIS_TEST_DB..............connection string 
                                    (default jpis/@localhost:jpis1test,
@@ -63,7 +67,7 @@ init() {
        GLITE_JPIS_TEST_PORT=${GLITE_JPIS_TEST_PORT:-"10000"}
        GLITE_JPIS_TEST_PIDFILE=${GLITE_JPIS_TEST_PIDFILE:-"/tmp/glite-jp-indexd.pid"}
        GLITE_JPIS_TEST_LOGFILE=${GLITE_JPIS_TEST_LOGFILE:-"/tmp/glite-jp-indexd.log"}
-       GLITE_JPIS_TEST_CONFIG=${GLITE_JPIS_TEST_CONFIG:-"$GLITE_LOCATION/etc/glite-jpis-config.xml"}
+       GLITE_JPIS_TEST_CONFIG=${GLITE_JPIS_TEST_CONFIG:-"$GLITE_LOCATION/etc/glite-jpis-test-config.xml"}
 
        if [ -z "$GLITE_JPIS_TEST_DB" ]; then
                GLITE_JPIS_TEST_DB="jpis/@localhost:jpis1test"
@@ -90,8 +94,6 @@ create_db() {
 import_db() {
        # import database
        echo -n "D"
-       # delay (if JP IS downloads something...)
-       sleep 1
        cat $1 | sed "s/jpis1test/$DB_NAME/" | mysql -u $DB_USER -h $DB_HOST
        if [ x"$?" != x"0" ]; then
                echo "FAILED to import database."
@@ -130,11 +132,14 @@ run_is() {
                drop_db;
                exit 1
        fi
-       if [ ! -s "${GLITE_JPIS_TEST_PIDFILE}" ]; then
-               sleep 1
-       fi
+       i=0
+       while [ ! -s "${GLITE_JPIS_TEST_PIDFILE}" -a $i -lt 20 ]; do
+               sleep 0.1
+               i=$(($i+1))
+       done
        if [ ! -s "${GLITE_JPIS_TEST_PIDFILE}" ]; then
                echo "Can't startup index server."
+               kill_is;
                drop_db;
                exit 1
        fi
@@ -143,11 +148,17 @@ run_is() {
        ret=1
        i=0
        while [ x"$ret" != x"0" -a $i -lt 20 ]; do
-               LC_ALL=C netstat -tap 2>/dev/null | grep "\<$GLITE_JPIS_TEST_PORT\>" > /dev/null
+               netstat -tap 2>/dev/null | grep "\<$GLITE_JPIS_TEST_PORT\>" > /dev/null
                ret=$?
                i=$(($i+1))
-               LC_ALL=C sleep 0.1
+               sleep 0.1
        done
+       if [ x"$ret" != x"0" ]; then
+               echo "Index server not started."
+               kill_is;
+               drop_db;
+               exit 1;
+       fi
        echo -n "S "
 }
 
@@ -252,7 +263,7 @@ run_test_query $GLITE_LOCATION/examples/query-tests/simple_query.in $GLITE_LOCAT
 drop_db;
 kill_is;
 
-echo -n "Query jobId test........... "
+echo -n "Query jobId test..... "
 create_db;
 run_is "-n";
 import_db $GLITE_LOCATION/examples/query-tests/dump1.sql;
@@ -260,7 +271,7 @@ run_test_query $GLITE_LOCATION/examples/query-tests/jobid_query.in $GLITE_LOCATI
 drop_db;
 kill_is;
 
-echo -n "Origin test........... "
+echo -n "Origin test.......... "
 create_db;
 run_is "-n";
 import_db $GLITE_LOCATION/examples/query-tests/dump1.sql;
@@ -268,10 +279,18 @@ run_test_query $GLITE_LOCATION/examples/query-tests/origin_query.in $GLITE_LOCAT
 drop_db;
 kill_is;
 
-echo -n "EXISTS operation test........... "
+echo -n "EXISTS test.......... "
 create_db;
 run_is "-n";
 import_db $GLITE_LOCATION/examples/query-tests/dump1.sql;
 run_test_query $GLITE_LOCATION/examples/query-tests/exists_query.in $GLITE_LOCATION/examples/query-tests/exists_query.out;
 drop_db;
 kill_is;
+
+echo -n "WITHIN test.......... "
+create_db;
+run_is "-n";
+import_db $GLITE_LOCATION/examples/query-tests/dump1.sql;
+run_test_query $GLITE_LOCATION/examples/query-tests/within_query.in $GLITE_LOCATION/examples/query-tests/exists_query.out;
+drop_db;
+kill_is;
diff --git a/org.glite.jp.index/examples/query-tests/within_query.in b/org.glite.jp.index/examples/query-tests/within_query.in
new file mode 100644 (file)
index 0000000..99d5a51
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jpisclient:QueryJobs xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jptype="http://glite.org/wsdl/types/jp" xmlns:jpsrv="http://glite.org/wsdl/services/jp" xmlns:jpelem="http://glite.org/wsdl/elements/jp" xmlns:jpisclient="http://glite.org/xsd/types/jpisclient">
+
+       <conditions>
+               <attr>http://egee.cesnet.cz/en/Schema/LB/Attributes:CE</attr>
+               <record>
+                       <op>WITHIN</op>
+                       <value><string>VOCA</string></value>
+                       <value2><string>VOCI</string></value2>
+               </record>
+       </conditions>
+
+       <attributes>http://egee.cesnet.cz/en/Schema/JP/System:owner</attributes>
+       <attributes>http://egee.cesnet.cz/en/Schema/JP/System:jobId</attributes>
+       <attributes>http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatus</attributes>
+       <attributes>http://egee.cesnet.cz/en/Schema/LB/Attributes:user</attributes>
+       <attributes>http://egee.cesnet.cz/en/Schema/LB/Attributes:CE</attributes>
+
+</jpisclient:QueryJobs>
diff --git a/org.glite.jp.index/examples/query-tests/within_query.out b/org.glite.jp.index/examples/query-tests/within_query.out
new file mode 100644 (file)
index 0000000..c1d7251
--- /dev/null
@@ -0,0 +1,28 @@
+query: using JPIS http://localhost:12002
+
+Conditions:
+       http://egee.cesnet.cz/en/Schema/LB/Attributes:CE
+               origin IS ANY
+               value WITHIN VOCA AND VOCI
+Attributes:
+       http://egee.cesnet.cz/en/Schema/JP/System:owner
+       http://egee.cesnet.cz/en/Schema/JP/System:jobId
+       http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatus
+       http://egee.cesnet.cz/en/Schema/LB/Attributes:user
+       http://egee.cesnet.cz/en/Schema/LB/Attributes:CE
+
+OK
+Result 1 jobs:
+       jobid = https://localhost:7846/pokus1, owner = /O=CESNET/O=Masaryk University/CN=Milos Mulac
+               http://egee.cesnet.cz/en/Schema/LB/Attributes:finalStatus
+                       value = Done
+                       origin = FILE (no detail)
+                       time = Thu Jan  1 02:00:01 1970
+               http://egee.cesnet.cz/en/Schema/LB/Attributes:user
+                       value = CertSubj
+                       origin = FILE (no detail)
+                       time = Thu Jan  1 02:00:01 1970
+               http://egee.cesnet.cz/en/Schema/LB/Attributes:CE
+                       value = VOCE
+                       origin = FILE (no detail)
+                       time = Thu Jan  1 02:00:01 1970
index 354d26b..000082d 100644 (file)
@@ -189,6 +189,16 @@ static int get_op(const enum jptype__queryOp in, char **out)
                case  GLITE_JP_QUERYOP_UNEQUAL:
                        qop = strdup("!=");
                        break;
+// FIXME: has index the same metrics?
+               case  GLITE_JP_QUERYOP_GREATER:
+                       qop = strdup(">");
+                       break;
+               case  GLITE_JP_QUERYOP_LESS:
+                       qop = strdup("<");
+                       break;
+               case  GLITE_JP_QUERYOP_WITHIN:
+                       qop = strdup("BETWEEN");
+                       break;
                default:
                        // unsupported query operator
                        return(1);
@@ -200,10 +210,61 @@ static int get_op(const enum jptype__queryOp in, char **out)
 }
 
 
+static char *get_sql_stringvalue(glite_jpis_context_t ctx, struct jptype__stringOrBlob *value) {
+       if (!value) return NULL;
+       if (!GSOAP_ISSTRING(value)) return NULL;
+       return GSOAP_STRING(value);
+}
+
+
+static int get_sql_indexvalue(char **sql, struct soap *soap, glite_jpis_context_t ctx, struct jptype__indexQuery *condition, struct jptype__stringOrBlob *value) {
+       glite_jp_attrval_t attr;
+
+       *sql = NULL;
+       if (!value) return 0;
+       memset(&attr, 0, sizeof attr);
+       attr.name = condition->attr;
+       if (GSOAP_ISSTRING(value)) {
+               attr.value = GSOAP_STRING(value);
+               attr.binary = 0;
+       } else if (GSOAP_ISBLOB(value)) {
+               attr.value = GSOAP_BLOB(value)->__ptr;
+               attr.size = GSOAP_BLOB(value)->__size;
+               attr.binary = 1;
+       } else return 0;
+       glite_jpis_SoapToAttrOrig(soap, condition->origin, &(attr.origin));
+
+       *sql = glite_jp_attrval_to_db_index(ctx->jpctx, &attr, 255);
+       return 0;
+}
+
+
+static int get_sql_cond(char **sql, const char *attr_md5, enum jptype__queryOp op, char *value, char *value2) {
+       char *s, *qop, *column;
+
+       *sql = NULL;
+       if (get_op(op, &qop) != 0) return 0;
+       if (attr_md5) trio_asprintf(&column, "attr_%|Ss.value", attr_md5);
+       else asprintf(&column, "jobs.dg_jobid");
+       trio_asprintf(sql, "%s %s \"%|Ss\"", column, qop, value);
+       free(column);
+       free(qop);
+       if (op == jptype__queryOp__WITHIN) {
+               if (!value) {
+                       free(*sql);
+                       *sql = NULL;
+                       return EINVAL;
+               }
+               trio_asprintf(&s, "%s AND \"%|Ss\"", *sql, value2);
+               free(*sql); *sql = s;
+       }
+       return 0;
+}
+
+
 static char *get_sql_or(struct soap *soap, glite_jpis_context_t ctx, struct jptype__indexQuery *condition, const char *attr_md5) {
        struct jptype__indexQueryRecord *record;
-       glite_jp_attrval_t      attr;
-       char *qop, *sql, *s;
+       char *sql, *cond, *s = NULL, *value, *value2;
        int j;
 
        sql = strdup("");
@@ -212,34 +273,30 @@ static char *get_sql_or(struct soap *soap, glite_jpis_context_t ctx, struct jpty
                if (record->op == jptype__queryOp__EXISTS) {
                        /* no additional conditions needed when existing is enough */
                } else {
-                       if (get_op(record->op, &qop)) return NULL;
-
-                       memset(&attr, 0, sizeof(attr));
-                       attr.name = condition->attr;
-                       if (GSOAP_ISSTRING(record->value)) {
-                               attr.value = GSOAP_STRING(record->value);
-                               attr.binary = 0;
-                       } else {
-                               attr.value = GSOAP_BLOB(record->value)->__ptr;
-                               attr.size = GSOAP_BLOB(record->value)->__size;
-                               attr.binary = 1;
-                       }
-                       glite_jpis_SoapToAttrOrig(soap,
-                               condition->origin, &(attr.origin));
                        if (strcmp(condition->attr, GLITE_JP_ATTR_JOBID) == 0) {
-                               trio_asprintf(&s,"%s%sjobs.dg_jobid %s \"%|Ss\"",
-                                       sql, (sql[0] ? " OR " : ""), qop, attr.value);
+                               value = get_sql_stringvalue(ctx, record->value);
+                               if (!value) goto err;
+                               value2 = get_sql_stringvalue(ctx, record->value2);
+                               if (get_sql_cond(&cond, attr_md5, record->op, value, value2) != 0) goto err;
                        } else {
-                               trio_asprintf(&s,"%s%sattr_%|Ss.value %s \"%|Ss\"",
-                                       sql, (sql[0] ? " OR " : ""), attr_md5, qop,
-                                       glite_jp_attrval_to_db_index(ctx->jpctx, &attr, 255));
+                               get_sql_indexvalue(&value, soap, ctx, condition, record->value);
+                               get_sql_indexvalue(&value2, soap, ctx, condition, record->value2);
+                               get_sql_cond(&cond, attr_md5, record->op, value, value2);
+                               free(value);
+                               free(value2);
+                               if (!cond) goto err;
                        }
-                       free(qop);
+                       trio_asprintf(&s,"%s%s%s", sql, (sql[0] ? " OR " : ""), cond);
+                       free(cond);
                        free(sql); sql = s;
                }
        }
 
        return sql;
+err:
+       free(sql);
+       free(s);
+       return NULL;
 }
 
 
@@ -250,7 +307,7 @@ static int get_jobids(struct soap *soap, glite_jpis_context_t ctx, struct _jpele
                                *qwhere = NULL, *query = NULL, *res[2], 
                                **jids = NULL, **pss = NULL, **attr_tables = NULL;
        int                     i, ret;
-       glite_jp_db_stmt_t      stmt;
+       glite_jp_db_stmt_t      stmt = NULL;
        glite_jp_attr_orig_t    orig;
 
        
@@ -277,8 +334,8 @@ static int get_jobids(struct soap *soap, glite_jpis_context_t ctx, struct _jpele
                                trio_asprintf(&qb, "");
 
                        /* select given records in attr_ table */
-                       trio_asprintf(&qa,"%s%s jobs.jobid = attr_%|Ss.jobid",
-                               (i ? "AND" : ""), qb, attr_md5);
+                       trio_asprintf(&qa,"%s%sjobs.jobid = attr_%|Ss.jobid",
+                               (i ? "AND " : ""), qb, attr_md5);
 
                        free(qb);
                }
@@ -292,7 +349,7 @@ static int get_jobids(struct soap *soap, glite_jpis_context_t ctx, struct _jpele
                }
                free(qor);
 
-               trio_asprintf(&qb,"%s %s", qwhere, qa);
+               trio_asprintf(&qb,"%s%s%s", qwhere, qa[0] ? " " : "", qa);
                free(qa); qwhere = qb; qb = NULL; qa = NULL;
                free(attr_md5);
        }
@@ -308,7 +365,7 @@ static int get_jobids(struct soap *soap, glite_jpis_context_t ctx, struct _jpele
                trio_asprintf(&query, "SELECT DISTINCT dg_jobid,ps FROM jobs%s WHERE%s", qa, qwhere);
        }
        else {
-               trio_asprintf(&query, "SELECT DISTINCT dg_jobid,ps FROM jobs,users%s WHERE (jobs.ownerid = users.userid AND users.cert_subj='%s') AND %s", qa, ctx->jpctx->peer, qwhere);
+               trio_asprintf(&query, "SELECT DISTINCT dg_jobid,ps FROM jobs,users%s WHERE (jobs.ownerid = users.userid AND users.cert_subj='%s') AND%s", qa, ctx->jpctx->peer, qwhere);
        }
        printf("Incomming QUERY:\n %s\n", query);
        free(qwhere);