📜 ⬆️ ⬇️

Asynchronous requests to MySQL on the API (libmysqlclient)

So it turns out that now I am working on the scheduler for MySQL connections. And here recently it was necessary to poke around in the documentation / blogs, etc. So I decided to share with the community how to implement asynchronous requests to the MySQL server in C ++ using the API and the library libmysqlclient.



To start programming with the MySQL API, we need the mysql.h header file.
And the library libmysqlclient. For deb-like OS, all this can be put like this:
sudo apt-get install libmysqlclient-dev libmysqlclient 

')
To the compiler we specify the following:
-L / path / to / mysqliclientlib / -lmysqlclient

If you write code in Qt Creator, you can add the following in the project file (you may have a different path):
Libs + = -l / usr / lib / mysql -lmysqlclient

We have almost everything ready to work with MySQL in C ++.
We determine: asynchronous requests - several parallel requests to the database without the use of threads (thread). Using the mysql_real_query function, this is impossible to achieve, i.e. the program will wait for the result (response) from the server.

Among other things, I use the libevent library to catch events. You can put it like this:
 sudo apt-get install libevent-dev libevent 


Specify the compiler:
LIBS + = -L / usr / lib / mysql -lmysqlclient -L / usr / lib / -lele
Header file:
#include <event.h>

Everything, everything is ready. Getting started. So we write a class that will send requests asynchronously. I have this class contains more methods - I will focus only on those that have a reference to the topic.

 class CBalanceMySQL { private: //    //    unsigned int thread_count; //    std::vector<MYSQL*> v; //  std::vector<event*> events; //  std::vector<std::string> queries; struct event_base *evbase; //   ,      //     pFunc p_func; //      void run(); public: // constructor CBalanceMySQL(); // destructor ~CBalanceMySQL(); //      //     void setThreadCount(int); //    bool ConnectAllThreads(); //        bool setSuccessFunc(void(*)(int, short, void*)); }; 


In the class constructor (or somewhere else), we initialize the event base:
 this->evbase = event_base_new(); 


Next, we will need to establish connections with the server and “remember” them. We run in a loop for a given number of requests and save the connections in the vector v.
 bool CBalanceMySQL::ConnectAllThreads() { for (uint i = 0; i < this->thread_count; i++) { MYSQL *m; m = mysql_init(NULL); if (!mysql_real_connect(m, this->host, this->user, this->password, NULL, this->port, NULL, 0)) { std::cout << mysql_error(m); return 0; } else { this->v.push_back(m); } } return 1; } 


It remains to execute the requests we need for these connections:
 void CBalanceMySQL::run() { for (uint i = 0; i < this->v.size(); i++) { //  struct event *ev; //     std::string q = this->queries.at(i); //    MYSQL *m = this->v.at(i); //   mysql_send_query(m, q.c_str() , strlen(q.c_str())); ev = new event; //   //   -      p_func event_set(ev, m->net.fd, EV_READ, this->p_func, m); event_base_set(this->evbase, ev); event_add(ev, NULL); events.push_back(ev); } //         while (0 == event_base_loop(this->evbase, 0)); } 


This is almost all. It remains to clean up for yourself:

 for (uint i = 0; i < v.size(); i++) { mysql_close(this->v.at(i)); } for (uint i = 0; i < events.size(); i++) { delete(this->events.at(i)); } event_base_free(this->evbase); 


And the last - the function of processing the result of the request. It looks like:

 static void read_result(int fd, short event, void *_userdata) { MYSQL *m = (MYSQL*)_userdata; if (0 == mysql_read_query_result(m)) { MYSQL_RES *res = mysql_store_result(m); MYSQL_ROW row = mysql_fetch_row(res); //     SELECT COUNT(*) FROM information_schema.processlist,      cout << "cnt for net.fd = " << fd << " is " << row[0] << endl; mysql_free_result(res); } } 


That's all. I hope someone will come in handy.
ps not to kick much - in C ++ is not a guru.

Source: https://habr.com/ru/post/144918/


All Articles