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
4245void 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
87103InfoLoggerDispatchSQL::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
183203int 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