|
@@ -15,7 +15,10 @@
|
|
|
#include <string.h>// strlen/strnlen/memcpy/memset
|
|
|
#include <stdlib.h>// strtoul
|
|
|
|
|
|
+void ra_mysql_error_handler(unsigned int ecode);
|
|
|
|
|
|
+int mysql_reconnect_type;
|
|
|
+unsigned int mysql_reconnect_count;
|
|
|
|
|
|
/// Sql handle
|
|
|
struct Sql
|
|
@@ -74,7 +77,7 @@ Sql* Sql_Malloc(void)
|
|
|
self->lengths = NULL;
|
|
|
self->result = NULL;
|
|
|
self->keepalive = INVALID_TIMER;
|
|
|
-
|
|
|
+ self->handle.reconnect = 1;
|
|
|
return self;
|
|
|
}
|
|
|
|
|
@@ -266,12 +269,14 @@ int Sql_QueryV(Sql* self, const char* query, va_list args)
|
|
|
if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_error(&self->handle));
|
|
|
+ ra_mysql_error_handler(mysql_errno(&self->handle));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
self->result = mysql_store_result(&self->handle);
|
|
|
if( mysql_errno(&self->handle) != 0 )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_error(&self->handle));
|
|
|
+ ra_mysql_error_handler(mysql_errno(&self->handle));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
return SQL_SUCCESS;
|
|
@@ -291,12 +296,14 @@ int Sql_QueryStr(Sql* self, const char* query)
|
|
|
if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_error(&self->handle));
|
|
|
+ ra_mysql_error_handler(mysql_errno(&self->handle));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
self->result = mysql_store_result(&self->handle);
|
|
|
if( mysql_errno(&self->handle) != 0 )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_error(&self->handle));
|
|
|
+ ra_mysql_error_handler(mysql_errno(&self->handle));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
return SQL_SUCCESS;
|
|
@@ -639,6 +646,7 @@ int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args)
|
|
|
if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
|
|
|
+ ra_mysql_error_handler(mysql_stmt_errno(self->stmt));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
self->bind_params = false;
|
|
@@ -660,6 +668,7 @@ int SqlStmt_PrepareStr(SqlStmt* self, const char* query)
|
|
|
if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
|
|
|
+ ra_mysql_error_handler(mysql_stmt_errno(self->stmt));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
self->bind_params = false;
|
|
@@ -721,12 +730,14 @@ int SqlStmt_Execute(SqlStmt* self)
|
|
|
mysql_stmt_execute(self->stmt) )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
|
|
|
+ ra_mysql_error_handler(mysql_stmt_errno(self->stmt));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
self->bind_columns = false;
|
|
|
if( mysql_stmt_store_result(self->stmt) )// store all the data
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
|
|
|
+ ra_mysql_error_handler(mysql_stmt_errno(self->stmt));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
|
|
@@ -868,6 +879,7 @@ int SqlStmt_NextRow(SqlStmt* self)
|
|
|
if( err )
|
|
|
{
|
|
|
ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
|
|
|
+ ra_mysql_error_handler(mysql_stmt_errno(self->stmt));
|
|
|
return SQL_ERROR;
|
|
|
}
|
|
|
|
|
@@ -946,3 +958,67 @@ void SqlStmt_Free(SqlStmt* self)
|
|
|
aFree(self);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/// Receives MySQL error codes during runtime (not on first-time-connects).
|
|
|
+void ra_mysql_error_handler(unsigned int ecode) {
|
|
|
+ static unsigned int retry = 1;
|
|
|
+ switch( ecode ) {
|
|
|
+ case 2003:// Can't connect to MySQL (this error only happens here when failing to reconnect)
|
|
|
+ if( mysql_reconnect_type == 1 ) {
|
|
|
+ if( ++retry > mysql_reconnect_count ) {
|
|
|
+ ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Sql_inter_server_read(const char* cfgName, bool first) {
|
|
|
+ int i;
|
|
|
+ char line[1024], w1[1024], w2[1024];
|
|
|
+ FILE* fp;
|
|
|
+
|
|
|
+ fp = fopen(cfgName, "r");
|
|
|
+ if(fp == NULL) {
|
|
|
+ if( first ) {
|
|
|
+ ShowFatalError("File not found: %s\n", cfgName);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ } else
|
|
|
+ ShowError("File not found: %s\n", cfgName);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ while(fgets(line, sizeof(line), fp)) {
|
|
|
+ i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2);
|
|
|
+ if(i != 2)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if(!strcmpi(w1,"mysql_reconnect_type")) {
|
|
|
+ mysql_reconnect_type = atoi(w2);
|
|
|
+ switch( mysql_reconnect_type ) {
|
|
|
+ case 1:
|
|
|
+ case 2:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type);
|
|
|
+ mysql_reconnect_type = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if(!strcmpi(w1,"mysql_reconnect_count")) {
|
|
|
+ mysql_reconnect_count = atoi(w2);
|
|
|
+ if( mysql_reconnect_count < 1 )
|
|
|
+ mysql_reconnect_count = 1;
|
|
|
+ } else if(!strcmpi(w1,"import"))
|
|
|
+ Sql_inter_server_read(w2,false);
|
|
|
+ }
|
|
|
+ fclose(fp);
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+void Sql_Init(void) {
|
|
|
+ Sql_inter_server_read("conf/inter_athena.conf",true);
|
|
|
+}
|