From 160861551bee5b3e209948801262c80e7b0f0c4a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Wed, 14 Sep 2005 09:47:36 +0000 Subject: [PATCH] Basic DB support. --- org.glite.jp.index/Makefile | 10 +- org.glite.jp.index/src/dbis.c | 294 ++++++++++++++++++++++++++++++++++++++++++ org.glite.jp.index/src/dbis.h | 17 +++ 3 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 org.glite.jp.index/src/dbis.c create mode 100644 org.glite.jp.index/src/dbis.h diff --git a/org.glite.jp.index/Makefile b/org.glite.jp.index/Makefile index 861846c..c82c065 100644 --- a/org.glite.jp.index/Makefile +++ b/org.glite.jp.index/Makefile @@ -48,7 +48,8 @@ ps_prefix:=jpps_ SRCS:= conf.c bones_server.c soap_ops.c soap_ps_calls.c ws_typeref.c db_ops.c\ ${is_prefix}ServerLib.c \ - ${ps_prefix}ClientLib.c ${ps_prefix}C.c + ${ps_prefix}ClientLib.c ${ps_prefix}C.c \ + dbis.c EXA_SRCS:=jpis-test.c ${is_prefix}C.c ${is_prefix}Client.c @@ -83,6 +84,13 @@ ${daemon}: ${OBJS} ${example}: ${EXA_OBJS} ${LINK} -o $@ ${EXA_OBJS} ${GSOAPLIB} ${GLOBUS_LIBS} +test_db.o: dbis.c + ${CC} ${CFLAGS} -DTEST_DBIS -c $< -o $@ + +test_db: test_db.o + ${LINK} -o $@ $+ -lglite_jp_common ${MYSQLIB} ${GLOBUS_LIBS} + + JobProvenanceIS.xh: JobProvenanceIS.wsdl JobProvenanceTypes.wsdl typemap.dat cp ${stagedir}/interface/JobProvenanceTypes.wsdl . ${gsoap_prefix}/bin/wsdl2h -t ${top_srcdir}/src/typemap.dat -c -o $@ $< diff --git a/org.glite.jp.index/src/dbis.c b/org.glite.jp.index/src/dbis.c new file mode 100644 index 0000000..01f9509 --- /dev/null +++ b/org.glite.jp.index/src/dbis.c @@ -0,0 +1,294 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "glite/jp/types.h" +#include "glite/jp/context.h" + +#include "dbis.h" + + +#define DEFAULTCS "jpis/@localhost:jpis1" + +#define JP_ERR(CTX, CODE, DESC) jp_err((CTX), (CODE), (DESC), __FUNCTION__, __LINE__) +#define MY_ERR(CTX) my_err((CTX), __FUNCTION__, __LINE__) +#define MY_ISOK(CTX, RETRY) my_isok((CTX), __FUNCTION__, __LINE__, (RETRY)) + + +struct glite_jpis_db_stmt_s { + glite_jp_context_t ctx; + MYSQL_RES *result; +}; + + +static int jp_err(glite_jp_context_t ctx, int code, const char *desc, const char *source, int line) { + glite_jp_error_t err; + + memset(&err,0,sizeof err); + asprintf(&err.source, "%s:%d", source, line); + err.code = code; + err.desc = strdup(desc); + + return glite_jp_stack_error(ctx,&err); +} + + +static int my_err(glite_jp_context_t ctx, const char *source, int line) { + return jp_err(ctx, EIO, mysql_error((MYSQL *)ctx->dbhandle), source, line); +} + + +/* + * Error handle. + * + * \return -1 failed + * \return 0 retry + * \return 1 OK + */ +static int my_isok(glite_jp_context_t ctx, const char *source, int line, int *retry) { + switch (mysql_errno((MYSQL *) ctx->dbhandle)) { + case 0: + return 1; + break; + case ER_DUP_ENTRY: + jp_err(ctx, EEXIST, mysql_error((MYSQL *) ctx->dbhandle), source, line); + return -1; + break; + case CR_SERVER_LOST: + if (*retry > 0) { + (*retry)--; + return 0; + } else + return -1; + break; + default: + my_err(ctx, source, line); + return -1; + break; + } +} + + +int glite_jpis_db_connect(glite_jp_context_t ctx, const char *cs) { + char *buf = NULL; + char *host,*user,*pw,*db; + char *slash,*at,*colon; + + glite_jp_clear_error(ctx); + + if (!cs) cs = DEFAULTCS; + + if ((ctx->dbhandle = (void *) mysql_init(NULL)) == NULL) + return JP_ERR(ctx, ENOMEM, NULL); + + // TODO: ??? + mysql_options(ctx->dbhandle, MYSQL_READ_DEFAULT_FILE, "my"); + + host = user = pw = db = NULL; + + buf = strdup(cs); + slash = strchr(buf,'/'); + at = strrchr(buf,'@'); + colon = strrchr(buf,':'); + + if (!slash || !at || !colon) { + free(buf); + return JP_ERR(ctx, EINVAL, "Invalid DB connect string"); + } + + *slash = *at = *colon = 0; + host = at+1; + user = buf; + pw = slash+1; + db = colon+1; + + if (!mysql_real_connect((MYSQL *) ctx->dbhandle,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) { + free(buf); + return MY_ERR(ctx); + } + + free(buf); + return 0; +} + + +void glite_jpis_db_close(glite_jp_context_t ctx) { + mysql_close((MYSQL *) ctx->dbhandle); + ctx->dbhandle = NULL; +} + + +int glite_jpis_db_execute(glite_jp_context_t ctx, const char *sql, glite_jpis_db_stmt_t **jpstmt) { + int retry, ret; + va_list ap; + MYSQL_BIND *binds; + void **params; + unsigned long i, nparams; + MYSQL_RES *r; + + glite_jp_clear_error(ctx); + + // execute the SQL command + retry = 1; + do { + mysql_query((MYSQL *)ctx->dbhandle, sql); + ret = MY_ISOK(ctx, &retry); + } while (ret == 0); + if (ret == -1) goto failed; + + // result + r = mysql_store_result((MYSQL *)ctx->dbhandle); + if (mysql_errno((MYSQL *) ctx->dbhandle)) { + MY_ERR(ctx); + goto failed; + } + if (jpstmt) { + *jpstmt = calloc(1, sizeof(glite_jpis_db_stmt_t)); + (*jpstmt)->ctx = ctx; + (*jpstmt)->result = r; + } else mysql_free_result(r); + + return mysql_affected_rows((MYSQL *) ctx->dbhandle); + +failed: + return -1; +} + + +int glite_jpis_db_fetchrow(glite_jpis_db_stmt_t *jpstmt, char ***res, int **lenres) { + MYSQL_ROW row; + glite_jp_context_t ctx; + int i, nr; + unsigned long *len; + unsigned long sumlen; + char *buf; + + ctx = jpstmt->ctx; + glite_jp_clear_error(ctx); + + *res = NULL; + *lenres = NULL; + + if (!jpstmt->result) return 0; + + if (!(row = mysql_fetch_row(jpstmt->result))) { + if (mysql_errno((MYSQL *) ctx->dbhandle)) { + MY_ERR(ctx); + return -1; + } + + return 0; + } + + // find out + nr = mysql_num_fields(jpstmt->result); + len = mysql_fetch_lengths(jpstmt->result); + + // allocate + if (nr) { + sumlen = nr; + for (i = 0; i < nr; i++) sumlen += len[i]; + buf = malloc(sumlen); + } + *res = calloc(nr + 1, sizeof(char *)); + if (lenres) { + if (nr) *lenres = calloc(nr, sizeof(int)); + else *lenres = NULL; + } + + // copy + for (i = 0; i < nr; i++) { + if (lenres) (*lenres)[i] = len[i]; + if (row[i]) { + (*res)[i] = buf; + if (len[i]) memcpy((*res)[i], row[i], len[i]); + ((*res)[i])[len[i]] = '\0'; + buf += (len[i] + 1); + } else (*res)[i] = NULL; + } + res[nr] = NULL; + + return nr; +} + + +void glite_jpis_db_freerow(char **res, int *lenres) { + if (res) { + free(res[0]); + free(res); + free(lenres); + } +} + + +int glite_jpis_db_querycolumns(glite_jpis_db_stmt_t *jpstmt, char **cols) { + int i = 0; + MYSQL_FIELD *f; + + while ((f = mysql_fetch_field(jpstmt->result))) cols[i++] = f->name; + return i == 0; +} + + +void glite_jpis_db_freestmt(glite_jpis_db_stmt_t *jpstmt) { + if (jpstmt->result) mysql_free_result(jpstmt->result); + free(jpstmt); +} + +#ifdef TEST_DBIS +static void print_err(glite_jp_context_t ctx) { + glite_jp_error_t *e; + + e = ctx->error; + while (e) { + printf("%s(%s)\n", e->desc, e->source); + e = e->reason; + } + printf("\n"); +} + + +int main() { + glite_jp_context_t ctx; + glite_jpis_db_stmt_t *jpstmt; + int nr, i; + char **res; + int *lenres; + + glite_jp_init_context(&ctx); + + printf("connecting...\n"); + if (glite_jpis_db_connect(ctx, NULL) != 0) goto fail; + + printf("selecting...\n"); + if ((glite_jpis_db_execute(ctx, "SELECT * FROM feeds", &jpstmt)) == -1) goto fail; + printf("fetching...\n"); + + while ((nr = glite_jpis_db_fetchrow(jpstmt, &res, &lenres)) > 0) { + printf("Result: n=%d, res=%p, lenres=%p\n", nr, res, lenres); + i = 0; + if (res) while(i < nr) {printf("p=%p(%s), len=%d\n", res[i], res[i], lenres[i]);i++;} + printf("freeing...\n"); + glite_jpis_db_freerow(res, lenres); + } + + glite_jpis_db_freestmt(jpstmt); + + printf("closing...\n"); + glite_jpis_db_close(ctx); + glite_jp_free_context(ctx); + return 0; + +fail: + printf("failed\n"); + print_err(ctx); + glite_jp_free_context(ctx); + + return 1; +} +#endif diff --git a/org.glite.jp.index/src/dbis.h b/org.glite.jp.index/src/dbis.h new file mode 100644 index 0000000..99d1ca5 --- /dev/null +++ b/org.glite.jp.index/src/dbis.h @@ -0,0 +1,17 @@ +#ifndef GLITE_JP_IS_DB_H +#define GLITE_JP_IS_DB_H + +#include +#include + +typedef struct glite_jpis_db_stmt_s glite_jpis_db_stmt_t; + +int glite_jpis_db_connect(glite_jp_context_t ctx, const char *cs); +void glite_jpis_db_close(glite_jp_context_t ctx); +int glite_jpis_db_execute(glite_jp_context_t ctx, const char *sql, glite_jpis_db_stmt_t **stmt); +int glite_jpis_db_fetchrow(glite_jpis_db_stmt_t *jpstmt, char ***res, int **lenres); +void glite_jpis_db_freerow(char **res, int *lenres); +int glite_jpis_db_querycolumns(glite_jpis_db_stmt_t *jpstmt, char **cols); +void glite_jpis_db_freestmt(glite_jpis_db_stmt_t *jpstmt); + +#endif -- 1.8.2.3