From a7b1bfa4c5304d864d02187824ea1998ee53e59d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 3 Jun 2016 09:53:10 +0000 Subject: refactoring my API --- src/my/my.c | 202 +++++++++++++----------------- src/my/my_result_helper.c | 310 +++++++++++++++++++++++++++------------------- 2 files changed, 273 insertions(+), 239 deletions(-) (limited to 'src/my') diff --git a/src/my/my.c b/src/my/my.c index 54b2a49b0..1d78a08cf 100644 --- a/src/my/my.c +++ b/src/my/my.c @@ -35,7 +35,7 @@ * @param mc mysql context * @param sh handle to SELECT statment * @param params parameters to the statement - * @return + * @return #GNUNET_YES if we can prepare all statement #GNUNET_SYSERR if we can't prepare all statement */ @@ -98,37 +98,24 @@ GNUNET_MY_exec_prepared (struct GNUNET_MYSQL_Context *mc, /** - * Extract results from a query result according - * to the given specification. If colums are NULL, - * the destination is not modified, and #GNUNET_NO is returned4 + * Extract results from a query result according to the given + * specification. Always fetches the next row. * * - * @param result - * @param row, the row from the result to extract - * @param result specificatio to extract for + * @param sh statement that returned results + * @param rs specification to extract for * @return - #GNUNET_YES if all results could be extracted - #GNUNET_NO if at least one result was NULL - #GNUNET_SYSERR if a result was invalid -*/ + * #GNUNET_YES if all results could be extracted + * #GNUNET_NO if there is no more data in the result set + * #GNUNET_SYSERR if a result was invalid + */ int GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh, - struct GNUNET_MY_QueryParam *qp, - struct GNUNET_MY_ResultSpec *rs, - int row) + struct GNUNET_MY_ResultSpec *rs) { - MYSQL_BIND *result; - - int num_fields; - MYSQL_FIELD *fields; - MYSQL_RES *res; - + unsigned int num_fields; unsigned int i; - unsigned int j; - int had_null = GNUNET_NO; int ret; - - result = NULL; MYSQL_STMT *stmt; stmt = GNUNET_MYSQL_statement_get_stmt (NULL /* FIXME */, sh); @@ -141,115 +128,104 @@ GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh, return GNUNET_SYSERR; } + num_fields = 0; + for (i=0;NULL != rs[i].conv;i++) + num_fields += rs[i].num_fields; - num_fields = mysql_stmt_field_count (stmt); - res = mysql_stmt_result_metadata (stmt); - fields = mysql_fetch_fields (res); - - int int_data[num_fields]; - long int long_data[num_fields]; - short short_data[num_fields]; - char str_data[STRING_SIZE]; - int error[num_fields]; - - result = (MYSQL_BIND *)malloc (sizeof (MYSQL_BIND)*num_fields); - if(!result) + if (mysql_stmt_field_count (stmt) != num_fields) { - fprintf(stderr, "Error to allocate output buffers\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Number of fields missmatch between SQL result and result specification\n"); return GNUNET_SYSERR; } - memset(result, 0, sizeof (MYSQL_BIND) * num_fields); - -/** INITIALISER LE MYSQL_BIND ****/ - - for(i = 0 ; i< num_fields ;i++) { - result[i].buffer_type = fields[i].type; - result[i].is_null = 0; - result[i].error = &error[i]; + MYSQL_BIND result[num_fields]; + unsigned int field_off; - switch (fields[i].type) + memset (result, 0, sizeof (MYSQL_BIND) * num_fields); + field_off = 0; + for (i=0;NULL != rs[i].conv;i++) { - case MYSQL_TYPE_LONG: - result[i].buffer = &(int_data[i]); - result[i].buffer_length = sizeof (int_data); - break; - - case MYSQL_TYPE_LONGLONG: - result[i].buffer = &(long_data[i]); - result[i].buffer_length = sizeof (long_data); - break; - - case MYSQL_TYPE_STRING: - result[i].buffer = (char *)str_data; - result[i].buffer_length = sizeof (str_data); - break; - - case MYSQL_TYPE_SHORT: - result[i].buffer = &(short_data[i]); - result[i].buffer_length = sizeof (short_data); - break; - - default: - fprintf(stderr, "Failed : wrong type : %d!\n", fields[i].type); - } - } + struct GNUNET_MY_ResultSpec *rp = &rs[i]; - if (mysql_stmt_bind_result(stmt, result)) - { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", + if (GNUNET_OK != + rp->pre_conv (rp->cls, + rp, + stmt, + field_off, + &result[field_off])) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Pre-conversion for MySQL result failed at offset %u\n", + i); + GNUNET_MY_cleanup_result (rs); + return GNUNET_SYSERR; + } + field_off += rp->num_fields; + } + if (mysql_stmt_bind_result (stmt, result)) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, + "my", _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_result", __FILE__, __LINE__, mysql_stmt_error (stmt)); return GNUNET_SYSERR; - } - - /*** FAILED HERE ***/ - if (mysql_stmt_fetch (stmt)) - { - for(j = 0 ; j < num_fields ;j++) - { - fprintf(stderr, "Error Bind [%d] : %d\n", j, error[j]); } - - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", - _("`%s' failed at %s:%d with error: %s\n"), - "mysql_stmt_fetch", __FILE__, __LINE__, + ret = mysql_stmt_fetch (stmt); + if (MYSQL_NO_DATA == ret) + return GNUNET_NO; + if (0 != ret) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, + "my", + _("mysql_stmt_fetch failed at %s:%d with error: %s\n"), + __FILE__, __LINE__, mysql_stmt_error (stmt)); - return GNUNET_SYSERR; - } - -/* - while (1) - { - mysql_stmt_fetch (stmt); - - for (i = 0 ; NULL != rs[i].conv ; i++) + return GNUNET_SYSERR; + } + field_off = 0; + for (i=0;NULL != rs[i].conv;i++) { - struct GNUNET_MY_ResultSpec *spec; - - spec = &rs[i]; - ret = spec->conv (spec->conv_cls, - spec, - result); - - if (GNUNET_SYSERR == ret) - { - return GNUNET_SYSERR; - } - - if (NULL != spec->result_size) - *spec->result_size = spec->dst_size; + struct GNUNET_MY_ResultSpec *rp = &rs[i]; + + if (NULL != rp->post_conv) + if (GNUNET_OK != + rp->post_conv (rp->cls, + rp, + stmt, + field_off, + &result[field_off])) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Post-conversion for MySQL result failed at offset %u\n", + i); + GNUNET_MY_cleanup_result (rs); + return GNUNET_SYSERR; + } + field_off += rp->num_fields; } } + return GNUNET_OK; +} - if (GNUNET_YES == had_null) - return GNUNET_NO; -*/ - free (result); - return GNUNET_OK; +/** + * Free all memory that was allocated in @a rs during + * #GNUNET_MY_extract_result(). + * + * @param rs reult specification to clean up + */ +void +GNUNET_MY_cleanup_result (struct GNUNET_PQ_ResultSpec *rs) +{ + unsigned int i; + + for (i=0;NULL != rs[i].conv;i++) + rs[i].cleaner (rs[i].cls, + &rs[i]); } + /* end of my.c */ diff --git a/src/my/my_result_helper.c b/src/my/my_result_helper.c index a5c39913c..108edb62d 100644 --- a/src/my/my_result_helper.c +++ b/src/my/my_result_helper.c @@ -21,116 +21,166 @@ #include "gnunet_my_lib.h" /** - * extract data from a Mysql database @a result at row @a row - * - * @param cls closure - * @param qp data about the query - * @param result mysql result - * @return - * #GNUNET_OK if all results could be extracted - * #GNUNET_SYSERR if a result was invalid - */ - + * extract data from a Mysql database @a result at row @a row + * + * @param cls closure + * @param qp data about the query + * @param result mysql result + * @return + * #GNUNET_OK if all results could be extracted + * #GNUNET_SYSERR if a result was invalid + */ static int -extract_varsize_blob (void *cls, - struct GNUNET_MY_ResultSpec *rs, - MYSQL_BIND *results) +pre_extract_varsize_blob (void *cls, + struct GNUNET_MY_ResultSpec *rs, + MYSQL_BIND *results) { - size_t len; - void *idst; - char * res; + results[0].buffer = NULL; + results[0].buffer_length = 0; + results[0].length = &rs->mysql_bind_output_length; + return GNUNET_OK; +} - if (results->is_null) + +/** + * extract data from a Mysql database @a result at row @a row + * + * @param cls closure + * @param[in,out] rs + * @param stmt the mysql statement that is being run + * @param column the column that is being processed + * @param[out] results + * @return + * #GNUNET_OK if all results could be extracted + * #GNUNET_SYSERR if a result was invalid + */ +static int +post_extract_varsize_blob (void *cls, + struct GNUNET_MY_ResultSpec *rs, + MYSQL_STMT *stmt, + unsigned int column, + MYSQL_BIND *results) +{ + void *buf; + size_t size; + + size = (size_t) rs->mysql_bind_output_length; + if (rs->mysql_bind_output_length != size) + return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */ + buf = GNUNET_malloc (size); + results[0].buffer = buf; + results[0].buffer_length = size; + if (0 != + mysql_stmt_fetch_column (stmt, + results, + column, + 0)) { + GNUNET_free (buf); return GNUNET_SYSERR; } + *(void **) rs->dst = buf; + *rs->result_size = size; + return GNUNET_OK; +} - len = results->buffer_length; - res = results->buffer; - - GNUNET_assert (NULL != res); - - rs->dst_size = len; - - idst = GNUNET_malloc (len); - *(void **)rs->dst = idst; - - memcpy (idst, - res, - len); - return GNUNET_OK; +/** + * extract data from a Mysql database @a result at row @a row + * + * @param cls closure + * @param[in,out] rs + */ +static void +cleanup_varsize_blob (void *cls, + struct GNUNET_MY_ResultSpec *rs) +{ + void *ptr; + + ptr = * (void **) rs->dst; + if (NULL == ptr) + return; + GNUNET_free (ptr); + *(void **) rs->dst = NULL; + *rs->result_size = 0; } + /** - * Variable-size result expected - * - * @param[out] dst where to store the result, allocated - * @param[out] sptr where to store the size of @a dst - * @return array entru for the result specification to use - */ + * Variable-size result expected + * + * @param[out] dst where to store the result, allocated + * @param[out] sptr where to store the size of @a dst + * @return array entru for the result specification to use + */ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_variable_size (void **dst, size_t *ptr_size) { - struct GNUNET_MY_ResultSpec res = + struct GNUNET_MY_ResultSpec res = { - &extract_varsize_blob, - NULL, - (void *)(dst), - 0, - ptr_size + .pre_conv = &pre_extract_varsize_blob, + .post_conv = &post_extract_varsize_blob, + .cleaner = &cleanup_varsize_blob, + .dst = (void *)(dst), + .result_size = ptr_size, + .num_fields = 1 }; return res; } + /** - * Extract data from a Mysql database @a result at row @a row - * - * @param cls closure - * @param result where to extract data from - * @param int row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in] dst_size desired size, never NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_OK if all results could be extracted - * #GNUNET_SYSERR if a result was invalid(non-existing field or NULL) - * - */ + * Extract data from a Mysql database @a result at row @a row + * + * @param cls closure + * @param result where to extract data from + * @param int row to extract data from + * @param fname name (or prefix) of the fields to extract from + * @param[in] dst_size desired size, never NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_OK if all results could be extracted + * #GNUNET_SYSERR if a result was invalid(non-existing field or NULL) + */ static int -extract_fixed_blob (void *cls, - struct GNUNET_MY_ResultSpec *rs, - MYSQL_BIND *results) +pre_extract_fixed_blob (void *cls, + struct GNUNET_MY_ResultSpec *rs, + MYSQL_BIND *results) { - size_t len; - const char *res; + results[0].buffer = rs->dst; + results[0].buffer_length = rs->dst_size; + results[0].length = &rs->mysql_bind_output_length; + return GNUNET_OK; +} - if (results->is_null) - { - return GNUNET_SYSERR; - } - len = results->buffer_length; - if (rs->dst_size != len) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Results has wrong size (got %u, expected %u)\n", - (unsigned int)len, - (unsigned int)rs->dst_size); +/** + * Check size of extracted fixed size data from a Mysql database @a + * result at row @a row + * + * @param cls closure + * @param result where to extract data from + * @param int row to extract data from + * @param fname name (or prefix) of the fields to extract from + * @param[in] dst_size desired size, never NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_OK if all results could be extracted + * #GNUNET_SYSERR if a result was invalid(non-existing field or NULL) + */ +static int +post_extract_fixed_blob (void *cls, + struct GNUNET_MY_ResultSpec *rs, + MYSQL_BIND *results) +{ + if (rs->dst_size != rs->mysql_bind_output_length) return GNUNET_SYSERR; - } - - res = results->buffer; - - GNUNET_assert (NULL != res); - memcpy (rs->dst, - res, - len); - return GNUNET_OK; } + + /** * Fixed-size result expected. * @@ -143,15 +193,15 @@ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_fixed_size (void *ptr, size_t ptr_size) { - struct GNUNET_MY_ResultSpec res = - { - &extract_fixed_blob, - NULL, - (void *)(ptr), - ptr_size, - NULL + struct GNUNET_MY_ResultSpec res = + { + .pre_conv = &pre_extract_fixed_blob, + .post_conv = &post_extract_fixed_blob, + .dst = (void *)(ptr), + .dst_size = ptr_size, + .num_fields = 1 }; - + return res; } @@ -175,7 +225,7 @@ extract_rsa_public_key (void *cls, { struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst; - + size_t len; const char *res; @@ -215,7 +265,8 @@ GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa) NULL, (void *) rsa, 0, - NULL + NULL, + 1 }; return res; @@ -273,13 +324,14 @@ extract_rsa_signature (void *cls, struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) { - struct GNUNET_MY_ResultSpec res = + struct GNUNET_MY_ResultSpec res = { &extract_rsa_signature, NULL, (void *)sig, 0, - NULL + NULL, + 1 }; return res; } @@ -326,13 +378,15 @@ extract_string (void * cls, return GNUNET_SYSERR; } return GNUNET_OK; -} +} + + /** - * 0- terminated string exprected. - * - * @param[out] dst where to store the result, allocated - * @return array entry for the result specification to use - */ + * 0- terminated string exprected. + * + * @param[out] dst where to store the result, allocated + * @return array entry for the result specification to use + */ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_string (char **dst) { @@ -341,17 +395,19 @@ GNUNET_MY_result_spec_string (char **dst) NULL, (void *) dst, 0, - NULL + NULL, + 1 }; return res; } + /** - * Absolute time expected - * - * @param name name of the field in the table - * @param[out] at where to store the result - * @return array entry for the result specification to use + * Absolute time expected + * + * @param name name of the field in the table + * @param[out] at where to store the result + * @return array entry for the result specification to use */ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) @@ -359,6 +415,7 @@ GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) return GNUNET_MY_result_spec_uint64 (&at->abs_value_us); } + /** * Absolute time in network byte order expected * @@ -368,11 +425,12 @@ GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at) { - struct GNUNET_MY_ResultSpec res = + struct GNUNET_MY_ResultSpec res = GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__); - return res; + return res; } + /** * Extract data from a Postgres database @a result at row @a row. * @@ -390,7 +448,7 @@ static int extract_uint16 (void *cls, struct GNUNET_MY_ResultSpec *rs, MYSQL_BIND *results) -{ +{ uint16_t *udst = rs->dst; const uint16_t *res; @@ -412,12 +470,13 @@ extract_uint16 (void *cls, return GNUNET_OK; } + /** - * uint16_t expected - * - * @param[out] u16 where to store the result - * @return array entry for the result specification to use - */ + * uint16_t expected + * + * @param[out] u16 where to store the result + * @return array entry for the result specification to use + */ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_uint16 (uint16_t *u16) { @@ -426,7 +485,8 @@ GNUNET_MY_result_spec_uint16 (uint16_t *u16) NULL, (void *) u16, sizeof (*u16), - NULL + NULL, + 1 }; return res; } @@ -467,7 +527,7 @@ extract_uint32 (void *cls, res = (uint32_t *)results->buffer; *udst = ntohl (*res); - + return GNUNET_OK; } @@ -485,7 +545,8 @@ GNUNET_MY_result_spec_uint32 (uint32_t *u32) NULL, (void *) u32, sizeof (*u32), - NULL + NULL, + 1 }; return res; } @@ -511,10 +572,8 @@ extract_uint64 (void *cls, uint64_t *udst = rs->dst; const uint64_t *res; - if (results->is_null) - { - return GNUNET_SYSERR; - } + results[0].buffer = &rs->dst; + results[0].buffer_length = 42; GNUNET_assert (NULL != rs->dst); if (sizeof (uint64_t) != rs->dst_size) @@ -540,13 +599,12 @@ struct GNUNET_MY_ResultSpec GNUNET_MY_result_spec_uint64 (uint64_t *u64) { struct GNUNET_MY_ResultSpec res = { - &extract_uint64, - NULL, - (void *) u64, - sizeof (*u64), - NULL + .pre_conv = &extract_uint64, + .dst = (void *) u64, + .dst_size = sizeof (*u64), + .num_fields = 1 }; return res; } -/* end of pq_result_helper.c */ \ No newline at end of file +/* end of pq_result_helper.c */ -- cgit v1.2.3