Protects against time loop calls both externally and internally
This commit is contained in:
parent
27074f9269
commit
e23e1f8cea
15
README.md
15
README.md
@ -12,8 +12,8 @@ A small framework for basic MySQL database operations via MySQL/Connector++
|
|||||||
- Native C++ containers: vector, tuple
|
- Native C++ containers: vector, tuple
|
||||||
- Response object
|
- Response object
|
||||||
- Thread safe
|
- Thread safe
|
||||||
- Exceptions
|
- Exceptions and log error callback
|
||||||
- Can use external periodic maintenance for connection management
|
- Can use external time loop for connection management
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -85,13 +85,16 @@ using namespace marcelb::asynco;
|
|||||||
/**
|
/**
|
||||||
* Init
|
* Init
|
||||||
*/
|
*/
|
||||||
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5, periodical_engine::external);
|
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5, time_loop_type::external);
|
||||||
|
|
||||||
periodic mysql_maintenance ( [&mydb] () {
|
periodic mysql_maintenance ( [&mydb] () {
|
||||||
cout << "IZVRŠAVA SE ENGINE" << endl;
|
|
||||||
mydb.periodic_maintenance();
|
mydb.periodic_maintenance();
|
||||||
}, MYSQL_PERIODIC_INTERNAL_TIME);
|
}, MYSQL_PERIODIC_INTERNAL_TIME);
|
||||||
|
|
||||||
|
mydb.set_on_error( [](const string& error) {
|
||||||
|
cout << error << endl; // print or log
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You can call multiple queries asynchronously
|
* You can call multiple queries asynchronously
|
||||||
*/
|
*/
|
||||||
@ -134,10 +137,6 @@ wait(a2);
|
|||||||
wait(a3);
|
wait(a3);
|
||||||
```
|
```
|
||||||
|
|
||||||
## To do
|
|
||||||
|
|
||||||
- On error, implement virtual/friend function
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include "ctime"
|
||||||
|
|
||||||
#include <mysql_driver.h>
|
#include <mysql_driver.h>
|
||||||
#include <mysql_connection.h>
|
#include <mysql_connection.h>
|
||||||
@ -38,7 +39,7 @@ namespace mysql {
|
|||||||
* external - expects periodic_maintenance() to be run periodically outside the library
|
* external - expects periodic_maintenance() to be run periodically outside the library
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
enum class periodical_engine {
|
enum class time_loop_type {
|
||||||
internal,
|
internal,
|
||||||
external
|
external
|
||||||
};
|
};
|
||||||
@ -103,9 +104,10 @@ class MySQL {
|
|||||||
string path, username, password, database;
|
string path, username, password, database;
|
||||||
uint32_t pool_size;
|
uint32_t pool_size;
|
||||||
uint32_t connect_trys = 3;
|
uint32_t connect_trys = 3;
|
||||||
bool run_engin = true;
|
bool run_tloop = true;
|
||||||
future<void> periodic_engin;
|
future<void> tloop_future;
|
||||||
periodical_engine engine_type;
|
time_loop_type tloop_type;
|
||||||
|
time_t last_loop_time = time(nullptr);
|
||||||
function<void(const string&)> on_error;
|
function<void(const string&)> on_error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +151,13 @@ class MySQL {
|
|||||||
*/
|
*/
|
||||||
void disconnect_pool();
|
void disconnect_pool();
|
||||||
|
|
||||||
public:
|
/**
|
||||||
|
* Internal tloop periodic
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _tloop();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MySQL constructor,
|
* MySQL constructor,
|
||||||
@ -157,7 +165,7 @@ class MySQL {
|
|||||||
* username, password, database name,
|
* username, password, database name,
|
||||||
* and number of active connections (optional)
|
* and number of active connections (optional)
|
||||||
*/
|
*/
|
||||||
MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available = 1, const periodical_engine _engine_type = periodical_engine::internal);
|
MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available = 1, const time_loop_type _engine_type = time_loop_type::internal);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,7 +231,7 @@ class MySQL {
|
|||||||
* please call this function in it for proper operation at a certain time interval.
|
* please call this function in it for proper operation at a certain time interval.
|
||||||
* You can use the default MYSQL_PERIODIC_INTERNAL_TIME
|
* You can use the default MYSQL_PERIODIC_INTERNAL_TIME
|
||||||
*/
|
*/
|
||||||
void periodic_maintenance();
|
void tloop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destruktor
|
* Destruktor
|
||||||
|
125
src/mysql.cpp
125
src/mysql.cpp
@ -1,22 +1,22 @@
|
|||||||
#include "../lib/mysql.hpp"
|
#include "../lib/mysql.hpp"
|
||||||
|
|
||||||
|
|
||||||
marcelb::mysql::MySQL::MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available, const periodical_engine _engine_type) {
|
marcelb::mysql::MySQL::MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available, const time_loop_type _engine_type) {
|
||||||
path = _path;
|
path = _path;
|
||||||
username = _username;
|
username = _username;
|
||||||
password = _password;
|
password = _password;
|
||||||
database = _db;
|
database = _db;
|
||||||
pool_size = _available > 0 ? _available : 1;
|
pool_size = _available > 0 ? _available : 1;
|
||||||
engine_type = _engine_type;
|
tloop_type = _engine_type;
|
||||||
|
|
||||||
drv = get_mysql_driver_instance();
|
drv = get_mysql_driver_instance();
|
||||||
connect_pool();
|
connect_pool();
|
||||||
|
|
||||||
if (engine_type == periodical_engine::internal) {
|
if (tloop_type == time_loop_type::internal) {
|
||||||
periodic_engin = async(launch::async, [&](){
|
tloop_future = async(launch::async, [&](){
|
||||||
while (run_engin) {
|
while (run_tloop) {
|
||||||
usleep(MYSQL_PERIODIC_INTERNAL_TIME*1000);
|
usleep(MYSQL_PERIODIC_INTERNAL_TIME*1000);
|
||||||
periodic_maintenance();
|
_tloop();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
@ -72,7 +72,6 @@ void marcelb::mysql::MySQL::disconnect_pool() {
|
|||||||
|
|
||||||
bool marcelb::mysql::MySQL::disconnect_connection(Connection* connection) {
|
bool marcelb::mysql::MySQL::disconnect_connection(Connection* connection) {
|
||||||
bool status = !connection->isClosed();
|
bool status = !connection->isClosed();
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
try {
|
try {
|
||||||
connection->close();
|
connection->close();
|
||||||
@ -94,66 +93,9 @@ bool marcelb::mysql::MySQL::disconnect_connection(Connection* connection) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void marcelb::mysql::MySQL::_tloop() {
|
||||||
/**
|
for (size_t i = 0; i < pool_size && run_tloop; i++) {
|
||||||
* Broj pokušaja usljed povezivanja s bazom od 1 do unlimited;
|
|
||||||
*/
|
|
||||||
|
|
||||||
void marcelb::mysql::MySQL::set_connect_trys(const uint32_t _trys) {
|
|
||||||
lock_guard<mutex> lock(io);
|
|
||||||
connect_trys = _trys;
|
|
||||||
}
|
|
||||||
|
|
||||||
void marcelb::mysql::MySQL::set_on_error(function<void(const string&)> _on_error) {
|
|
||||||
on_error = _on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
Connection* marcelb::mysql::MySQL::occupy_connection() {
|
|
||||||
unique_lock<mutex> lock(io);
|
|
||||||
while (connection_pool.empty()) {
|
|
||||||
condition.wait(lock);
|
|
||||||
}
|
|
||||||
Connection *connection = connection_pool.front();
|
|
||||||
connection_pool.pop();
|
|
||||||
return connection;
|
|
||||||
|
|
||||||
// while (true) {
|
|
||||||
// while(connection_pool.size()) {
|
|
||||||
// io.lock();
|
|
||||||
// Connection* connection = connection_pool.front();
|
|
||||||
// connection_pool.pop();
|
|
||||||
// if (connection->isValid()) {
|
|
||||||
// io.unlock();
|
|
||||||
// return connection;
|
|
||||||
// }
|
|
||||||
// io.unlock();
|
|
||||||
// }
|
|
||||||
// usleep(1000);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void marcelb::mysql::MySQL::release_connection(Connection* connection) {
|
|
||||||
lock_guard<std::mutex> lock(io);
|
|
||||||
connection_pool.push(connection);
|
|
||||||
condition.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
marcelb::mysql::MySQL::~MySQL() {
|
|
||||||
if (engine_type == periodical_engine::internal) {
|
|
||||||
run_engin = false;
|
|
||||||
periodic_engin.get();
|
|
||||||
} else {
|
|
||||||
run_engin = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect_pool();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void marcelb::mysql::MySQL::periodic_maintenance() {
|
|
||||||
for (size_t i = 0; i < pool_size && run_engin; i++) {
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Connection *conn = occupy_connection();
|
Connection *conn = occupy_connection();
|
||||||
if (conn->isValid()) {
|
if (conn->isValid()) {
|
||||||
release_connection(conn);
|
release_connection(conn);
|
||||||
@ -170,4 +112,55 @@ void marcelb::mysql::MySQL::periodic_maintenance() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
last_loop_time = time(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void marcelb::mysql::MySQL::set_connect_trys(const uint32_t _trys) {
|
||||||
|
// lock_guard<mutex> lock(io);
|
||||||
|
connect_trys = _trys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void marcelb::mysql::MySQL::set_on_error(function<void(const string&)> _on_error) {
|
||||||
|
on_error = _on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection* marcelb::mysql::MySQL::occupy_connection() {
|
||||||
|
if (last_loop_time + (MYSQL_PERIODIC_INTERNAL_TIME/1000)*3 < time(nullptr) && on_error) { // ako je zadnje vrijeme + 3 intervala manje od trenutnog vremena emitiraj grešku
|
||||||
|
on_error("The time loop is not executing properly");
|
||||||
|
}
|
||||||
|
unique_lock<mutex> lock(io);
|
||||||
|
while (connection_pool.empty()) {
|
||||||
|
condition.wait(lock);
|
||||||
|
}
|
||||||
|
Connection *connection = connection_pool.front();
|
||||||
|
connection_pool.pop();
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void marcelb::mysql::MySQL::release_connection(Connection* connection) {
|
||||||
|
lock_guard<std::mutex> lock(io);
|
||||||
|
connection_pool.push(connection);
|
||||||
|
condition.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
marcelb::mysql::MySQL::~MySQL() {
|
||||||
|
if (tloop_type == time_loop_type::internal) {
|
||||||
|
run_tloop = false;
|
||||||
|
tloop_future.get();
|
||||||
|
} else {
|
||||||
|
run_tloop = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect_pool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void marcelb::mysql::MySQL::tloop() {
|
||||||
|
if (tloop_type == time_loop_type::internal) {
|
||||||
|
if (on_error) {
|
||||||
|
on_error("Can't start external call tloop, internal is active!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_tloop();
|
||||||
}
|
}
|
@ -13,17 +13,18 @@ using namespace marcelb::asynco;
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try {
|
try {
|
||||||
// MySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 10, periodical_engine::external);
|
MySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5, time_loop_type::internal);
|
||||||
// MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 10, periodical_engine::external);
|
// MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 10, time_loop_type::external);
|
||||||
MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5);
|
// MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5);
|
||||||
|
|
||||||
mydb.set_on_error( [](const string& error) {
|
mydb.set_on_error( [](const string& error) {
|
||||||
cout << error << endl;
|
cout << error << endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
// periodic mysql_maintenance ( [&mydb] () {
|
periodic mysql_tloop ( [&mydb] () {
|
||||||
// mydb.periodic_maintenance();
|
mydb.tloop();
|
||||||
// }, MYSQL_PERIODIC_INTERNAL_TIME);
|
}, MYSQL_PERIODIC_INTERNAL_TIME);
|
||||||
|
|
||||||
|
|
||||||
sleep(5);
|
sleep(5);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user