Skip to content

Commit a668847

Browse files
committed
improved handling of DB connection down
1 parent 350fd13 commit a668847

1 file changed

Lines changed: 83 additions & 56 deletions

File tree

src/InfoLoggerDispatchSQL.cxx

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
// some constants
10-
#define SQL_RETRY_CONNECT 3 // base retry time, will be sleeping up to 10x this value
10+
#define SQL_RETRY_CONNECT 1 // base retry time, will be sleeping up to 10x this value
1111

1212

1313

@@ -37,10 +37,16 @@ class InfoLoggerDispatchSQLImpl {
3737
std::string sql_insert;
3838

3939
unsigned long long insertCount=0; // counter for number of queries executed
40+
unsigned long long msgDroppedCount=0; // counter for number of messages dropped (DB unavailable, etc)
41+
42+
int connectDB(); // function to connect to database
4043
};
4144

4245
void InfoLoggerDispatchSQLImpl::start() {
4346

47+
// log DB params
48+
theLog->info("Using DB %s@%s:%s",theConfig->dbUser.c_str(),theConfig->dbHost.c_str(),theConfig->dbName.c_str());
49+
4450
// init mysql lib
4551
if (mysql_init(&db)==NULL) {
4652
theLog->error("mysql_init() failed");
@@ -82,6 +88,16 @@ void InfoLoggerDispatchSQLImpl::start() {
8288
theLog->error("Failed to initialize db query: error %d",errLine);
8389
}
8490

91+
// try to connect DB
92+
int maxRetry=10;
93+
for (int n=0;n<maxRetry;n++) {
94+
InfoLoggerDispatchSQLImpl::connectDB();
95+
if (dbIsConnected) {
96+
break;
97+
}
98+
sleep(SQL_RETRY_CONNECT);
99+
}
100+
85101
}
86102

87103
InfoLoggerDispatchSQL::InfoLoggerDispatchSQL(ConfigInfoLoggerServer *config, SimpleLog *log): InfoLoggerDispatch(config,log) {
@@ -97,7 +113,8 @@ void InfoLoggerDispatchSQLImpl::stop() {
97113
theLog->info("DB disconnected");
98114
}
99115
mysql_close(&db);
100-
theLog->info("DB thread insert count = %llu",insertCount);
116+
theLog->info("DB thread insert count = %llu, dropped msg count = %llu",insertCount,msgDroppedCount);
117+
101118
}
102119

103120

@@ -116,73 +133,81 @@ int InfoLoggerDispatchSQL::customLoop() {
116133
}
117134

118135

119-
120-
int InfoLoggerDispatchSQLImpl::customLoop() {
121-
122-
if (!dbIsConnected) {
123-
time_t now=time(NULL);
124-
if (now<dbLastConnectTry+SQL_RETRY_CONNECT) {
125-
// wait before reconnecting
126-
return 0;
127-
}
128-
dbLastConnectTry=now;
129-
if (mysql_real_connect(&db,theConfig->dbHost.c_str(),theConfig->dbUser.c_str(),theConfig->dbPassword.c_str(),theConfig->dbName.c_str(),0,NULL,0)) {
130-
theLog->info("DB connected");
131-
dbIsConnected=1;
132-
dbConnectTrials=0;
133-
} else {
134-
if (dbConnectTrials==1) {
135-
theLog->error("DB connection Failed");
136-
}
137-
dbConnectTrials++;
138-
return 0;
139-
}
140-
141-
// create prepared insert statement
142-
stmt=mysql_stmt_init(&db);
143-
if (stmt==NULL) {
144-
theLog->error("mysql_stmt_init() failed: %s",mysql_error(&db));
145-
return -1;
136+
int InfoLoggerDispatchSQLImpl::connectDB() {
137+
if (!dbIsConnected) {
138+
time_t now=time(NULL);
139+
if (now<dbLastConnectTry+SQL_RETRY_CONNECT) {
140+
// wait before reconnecting
141+
return 0;
142+
}
143+
dbLastConnectTry=now;
144+
if (mysql_real_connect(&db,theConfig->dbHost.c_str(),theConfig->dbUser.c_str(),theConfig->dbPassword.c_str(),theConfig->dbName.c_str(),0,NULL,0)) {
145+
theLog->info("DB connected");
146+
dbIsConnected=1;
147+
dbConnectTrials=0;
148+
} else {
149+
if (dbConnectTrials==1) { // the first attempt always fails, hide it
150+
theLog->error("DB connection failed: %s",mysql_error(&db));
146151
}
152+
dbConnectTrials++;
153+
return 0;
154+
}
147155

148-
if (mysql_stmt_prepare(stmt,sql_insert.c_str(),sql_insert.length())) {
149-
theLog->error("mysql_stmt_prepare() failed: %s\n",mysql_error(&db));
150-
return -1;
151-
}
156+
// create prepared insert statement
157+
stmt=mysql_stmt_init(&db);
158+
if (stmt==NULL) {
159+
theLog->error("mysql_stmt_init() failed: %s",mysql_error(&db));
160+
return -1;
161+
}
152162

153-
// bind variables depending on type
154-
memset(bind, 0, sizeof(bind));
155-
int errline=0;
156-
for(int i=0;i<nFields;i++) {
157-
switch (protocols[0].fields[i].type) {
158-
case infoLog_msgField_def_t::ILOG_TYPE_STRING:
159-
bind[i].buffer_type=MYSQL_TYPE_STRING;
160-
break;
161-
case infoLog_msgField_def_t::ILOG_TYPE_INT:
162-
bind[i].buffer_type=MYSQL_TYPE_LONG;
163-
break;
164-
case infoLog_msgField_def_t::ILOG_TYPE_DOUBLE:
165-
bind[i].buffer_type=MYSQL_TYPE_DOUBLE;
166-
break;
167-
default:
168-
theLog->error("undefined field type %d",protocols[0].fields[i].type);
169-
errline=__LINE__;
170-
break;
171-
}
172-
}
173-
if (errline) {
174-
return -1;
163+
if (mysql_stmt_prepare(stmt,sql_insert.c_str(),sql_insert.length())) {
164+
theLog->error("mysql_stmt_prepare() failed: %s\n",mysql_error(&db));
165+
return -1;
166+
}
167+
168+
// bind variables depending on type
169+
memset(bind, 0, sizeof(bind));
170+
int errline=0;
171+
for(int i=0;i<nFields;i++) {
172+
switch (protocols[0].fields[i].type) {
173+
case infoLog_msgField_def_t::ILOG_TYPE_STRING:
174+
bind[i].buffer_type=MYSQL_TYPE_STRING;
175+
break;
176+
case infoLog_msgField_def_t::ILOG_TYPE_INT:
177+
bind[i].buffer_type=MYSQL_TYPE_LONG;
178+
break;
179+
case infoLog_msgField_def_t::ILOG_TYPE_DOUBLE:
180+
bind[i].buffer_type=MYSQL_TYPE_DOUBLE;
181+
break;
182+
default:
183+
theLog->error("undefined field type %d",protocols[0].fields[i].type);
184+
errline=__LINE__;
185+
break;
175186
}
176187
}
188+
if (errline) {
189+
return -1;
190+
}
191+
}
192+
193+
return 0;
194+
}
177195

178196

179-
return 0;
197+
int InfoLoggerDispatchSQLImpl::customLoop() {
198+
199+
return connectDB();
180200
}
181201

182202

183203
int InfoLoggerDispatchSQLImpl::customMessageProcess(std::shared_ptr<InfoLoggerMessageList> lmsg) {
184204
// todo: keep message in queue on error!
185205

206+
if (!dbIsConnected) {
207+
msgDroppedCount++;
208+
return -1;
209+
}
210+
186211
infoLog_msg_t *m;
187212
my_bool param_isnull=1; // boolean telling if a parameter is NULL
188213
my_bool param_isNOTnull=0; // boolean telling if a parameter is not NULL
@@ -232,6 +257,7 @@ int InfoLoggerDispatchSQLImpl::customMessageProcess(std::shared_ptr<InfoLoggerMe
232257
mysql_stmt_close(stmt);
233258
mysql_close(&db);
234259
theLog->info("DB disconnected");
260+
msgDroppedCount++;
235261
return -1;
236262
}
237263

@@ -243,6 +269,7 @@ int InfoLoggerDispatchSQLImpl::customMessageProcess(std::shared_ptr<InfoLoggerMe
243269
theLog->info("DB disconnected");
244270
// retry with new connection - usually it means server was down
245271
dbIsConnected=0;
272+
msgDroppedCount++;
246273
break;
247274
}
248275

0 commit comments

Comments
 (0)