Rob, (Nick)I have been looking a little more at the issue of returning meaningful error messages back to apache - i didn't like my previous mail's hijacking of apache as a solution - though it should provide an idea of what is going on. So now the implementation looks like. Rob, sorry - this should be a better way of doing exactly what my previous mail suggested - (caveat - I have built these, but not run them - the production machine is live)! However, we now have kept httpd separate from apr and so we don't need to mess with the includes and so on.
In srclib/apr-util/dbd/apr_dbd_mysql.c - rewrite dbd_mysql_check_conn, around line 740
--------------static apr_status_t dbd_mysql_check_conn(apr_pool_t *pool, apr_dbd_t *handle) {
unsigned int mysql_err_num = mysql_ping(handle->conn); if (mysql_err_num == 0) { return APR_SUCCESS; } else {return APR_OS_START_USERERR + mysql_err_num; /* we could also remove the CR_MIN_ERROR offset... */
} } --------------Also in srclib/apr-util/dbd/apr_dbd_mysql.c - rewrite dbd_mysql_error, around line 240
-------------- static const char *dbd_mysql_error(apr_dbd_t *sql, int n) { const char *mysql_error_msg_string = mysql_error(sql->conn); if (mysql_error_msg_string != NULL) { return mysql_error_msg_string; } else { switch (n) { case 0: return mysql_error_msg_string;case CR_COMMANDS_OUT_OF_SYNC: return "mysql error COMMANDS_OUT_OF_SYNC"; case CR_SERVER_GONE_ERROR: return "mysql error SERVER_GONE_ERROR";
case CR_UNKNOWN_ERROR: return "mysql error UNKNOWN_ERROR ";/* add a whole load of other mysql errors here see mysql file errmsg.h */
default: return "unspecified mysql error"; } } } --------------So we need to change return value of the apr_dbd_open function in srclib/apr-util/dbd/apr_dbd.c line 170. - The API is open regarding errors (lucky us) so rather than blanking the error out with a GEN, we can return rv
Change: if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { apr_dbd_close(driver, *handle); return APR_EGENERAL; } To: -------------- if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { apr_dbd_close(driver, *handle); return rv; } --------------And finally we can change mod_dbd.c (modules/database/mod_dbd.c) around line 288
--------------if (rec->driver == NULL) { ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,"DBD: mod_dbd received a NULL when calling apr_dbd_get_driver for %s",svr->name); } rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec- >handle); if (rec->driver == NULL) { ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,"DBD: mod_dbd received a NULL when calling apr_dbd_get_driver for %s",svr->name); } rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec- >handle);
switch (rv) { case APR_SUCCESS: {ap_log_perror(APLOG_MARK, APLOG_DEBUG, rv, rec->pool, "DBD: % s driver is successfully opened and connected", svr->name);
} break; case APR_ENOTIMPL: {ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, "DBD: Can't connect to %s Not Implemented.", svr->name);
return APR_ENOTIMPL; } break; default: {const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv - APR_OS_START_USERERR); ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,"DBD: Can't connect to %s - ", svr->name, (errmsg ? errmsg : "no reason given"));
return APR_EGENERAL; } break; } --------------Nick, in modules/database/mod_dbd.c, just before we call apr_dbd_open is there any reason why not to check that rec->driver is not NULL ? The previous error management code only evaluates return values, and it seems possible to me that apr_dbd_get_driver can actually return a NULL driver without returning an error code to match. I am unsure as to whether or not the (rec->driver == NULL) test line is redundant.
Another challenge is how to pass the error result from mysql_ping (called in dbd_mysql_check_conn) over to dbd_mysql_error. I am not impressed with merely discarding it!! As the error is internal to mysql, it doesn't feel correct to be returned by apr_dbd_open, but we do have APR_OS_START_USERERR so I used that - is there a better way? Now we are handling any messages correctly, through the apr_dbd_error function, and we know that rec->driver is not null.
Of course the code above does a good deal more than merely deal with connection issues - it demonstrates how to use mysql error reporting from mod_dbd in a consistent manner. The significant change is making use of the mysql error numbers and returning them in APR_OS_START_USERERR space.
Hoping these mails are helping someone! -b --------------------------------------------------------------------- The official User-To-User support forum of the Apache HTTP Server Project. See <URL:http://httpd.apache.org/userslist.html> for more info. To unsubscribe, e-mail: users-unsubscribe@xxxxxxxxxxxxxxxx " from the digest: users-digest-unsubscribe@xxxxxxxxxxxxxxxx For additional commands, e-mail: users-help@xxxxxxxxxxxxxxxx