|
|
|
@ -1,15 +1,16 @@ |
|
|
|
|
#include "../lib/mysql.hpp" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
marcelb::mysql::MySQL::MySQL(const string _path, const string _username, const string _password, const string _db, const uint _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 periodical_engine _engine_type) { |
|
|
|
|
path = _path; |
|
|
|
|
username = _username; |
|
|
|
|
password = _password; |
|
|
|
|
db = _db; |
|
|
|
|
available = _available > 0 ? _available : 1; |
|
|
|
|
database = _db; |
|
|
|
|
pool_size = _available > 0 ? _available : 1; |
|
|
|
|
engine_type = _engine_type; |
|
|
|
|
|
|
|
|
|
drv = get_mysql_driver_instance(); |
|
|
|
|
connect_pool(); |
|
|
|
|
|
|
|
|
|
if (engine_type == periodical_engine::internal) { |
|
|
|
|
periodic_engin = async(launch::async, [&](){ |
|
|
|
@ -23,51 +24,58 @@ marcelb::mysql::MySQL::MySQL(const string _path, const string _username, const s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Connection* marcelb::mysql::MySQL::create_con() { |
|
|
|
|
uint trys = 0; |
|
|
|
|
Connection* marcelb::mysql::MySQL::create_connection() { |
|
|
|
|
uint32_t trys = 0; |
|
|
|
|
bool status = true; |
|
|
|
|
Connection* new_con = NULL; |
|
|
|
|
|
|
|
|
|
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) { |
|
|
|
|
while (connect_trys == unlimited ? status : (trys <= connect_trys && status)) { |
|
|
|
|
try { |
|
|
|
|
Connection* con_can = drv->connect(path, username, password); |
|
|
|
|
con_can->setSchema(database); |
|
|
|
|
status = !con_can->isValid(); |
|
|
|
|
if (!status) { |
|
|
|
|
new_con = con_can; |
|
|
|
|
} |
|
|
|
|
else if (!con_can->isClosed()) { |
|
|
|
|
disconnect_one(con_can); |
|
|
|
|
disconnect_connection(con_can); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
catch (const SQLException &error) { |
|
|
|
|
cout << error.what() << endl; |
|
|
|
|
// on_error -- ako se ikad impelementira pozovi ga ovdje!
|
|
|
|
|
usleep(reconnectSleep); |
|
|
|
|
reconTrys == unlimited ? trys : trys++; |
|
|
|
|
connect_trys == unlimited ? trys : trys++; |
|
|
|
|
}
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return new_con; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool marcelb::mysql::MySQL::disconnect() { |
|
|
|
|
io.lock(); |
|
|
|
|
bool status = true; |
|
|
|
|
|
|
|
|
|
for (uint i=0; i<con.size(); i++) { |
|
|
|
|
status = disconnect_one(con[i]) ; |
|
|
|
|
void marcelb::mysql::MySQL::connect_pool() { |
|
|
|
|
lock_guard<mutex> lock(io); |
|
|
|
|
for (uint32_t i=0; i<pool_size; i++) { |
|
|
|
|
Connection* connection = create_connection(); |
|
|
|
|
connection_pool.push(connection); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
io.unlock(); |
|
|
|
|
return status; |
|
|
|
|
void marcelb::mysql::MySQL::disconnect_pool() { |
|
|
|
|
lock_guard<mutex> lock(io); |
|
|
|
|
for (uint32_t i=0; i<connection_pool.size(); i++) { |
|
|
|
|
Connection* connection = connection_pool.front(); |
|
|
|
|
connection_pool.pop(); |
|
|
|
|
disconnect_connection(connection) ; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool marcelb::mysql::MySQL::disconnect_one(Connection* con_ptr) { |
|
|
|
|
bool status = !con_ptr->isClosed(); |
|
|
|
|
bool marcelb::mysql::MySQL::disconnect_connection(Connection* connection) { |
|
|
|
|
bool status = !connection->isClosed(); |
|
|
|
|
|
|
|
|
|
if (status) { |
|
|
|
|
try { |
|
|
|
|
con_ptr->close(); |
|
|
|
|
status = !con_ptr->isClosed(); |
|
|
|
|
connection->close(); |
|
|
|
|
status = !connection->isClosed(); |
|
|
|
|
}
|
|
|
|
|
catch (const SQLException &error) { |
|
|
|
|
cout << error.what() << endl; |
|
|
|
@ -79,58 +87,48 @@ bool marcelb::mysql::MySQL::disconnect_one(Connection* con_ptr) { |
|
|
|
|
status = false; // već je zatvorena
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
delete con_ptr; |
|
|
|
|
delete connection; |
|
|
|
|
return status; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool marcelb::mysql::MySQL::open_one(Connection* con_ptr) { |
|
|
|
|
bool status = true; // ako true greška je
|
|
|
|
|
uint trys = 0; |
|
|
|
|
|
|
|
|
|
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) { |
|
|
|
|
try { |
|
|
|
|
if (con_ptr->isValid()) { |
|
|
|
|
con_ptr->setSchema(db); |
|
|
|
|
status = false; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
catch (const SQLException &error) { |
|
|
|
|
cout << error.what() << endl; |
|
|
|
|
usleep(reconnectSleep); |
|
|
|
|
reconTrys == unlimited ? trys : trys++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return status; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Broj pokušaja usljed povezivanja s bazom od 1 do unlimited; |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
void marcelb::mysql::MySQL::reconnectTrys(const uint _trys) { |
|
|
|
|
io.lock(); |
|
|
|
|
reconTrys = _trys; |
|
|
|
|
io.unlock(); |
|
|
|
|
void marcelb::mysql::MySQL::set_connect_trys(const uint32_t _trys) { |
|
|
|
|
lock_guard<mutex> lock(io); |
|
|
|
|
connect_trys = _trys; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Connection* marcelb::mysql::MySQL::shift_con() { |
|
|
|
|
while (true) { |
|
|
|
|
while(con.size()) { |
|
|
|
|
io.lock(); |
|
|
|
|
Connection* con_ptr = con[0]; |
|
|
|
|
con.pop_front(); |
|
|
|
|
if (con_ptr->isValid()) { |
|
|
|
|
io.unlock(); |
|
|
|
|
return con_ptr; |
|
|
|
|
}
|
|
|
|
|
io.unlock(); |
|
|
|
|
} |
|
|
|
|
usleep(1000); |
|
|
|
|
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() { |
|
|
|
@ -138,38 +136,26 @@ marcelb::mysql::MySQL::~MySQL() { |
|
|
|
|
run_engin = false; |
|
|
|
|
periodic_engin.get(); |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
// ne bi bilo loše ubiti periodic nekako?!
|
|
|
|
|
// iako disconnecta može periodic connect napraviti!!!
|
|
|
|
|
run_engin = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
disconnect(); |
|
|
|
|
disconnect_pool(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void marcelb::mysql::MySQL::periodic_maintenance() { |
|
|
|
|
while (available>con.size() && run_engin) { |
|
|
|
|
try { |
|
|
|
|
Connection* new_con_ptr = create_con(); |
|
|
|
|
if (!db.empty()) { |
|
|
|
|
if (open_one(new_con_ptr)) { |
|
|
|
|
throw string("[ERROR] Unable to open database " + db); |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < pool_size && run_engin; i++) { |
|
|
|
|
Connection *conn = occupy_connection(); |
|
|
|
|
if (conn->isValid()) { |
|
|
|
|
release_connection(conn); |
|
|
|
|
} else { |
|
|
|
|
if (!conn->isClosed()){ |
|
|
|
|
conn->close(); |
|
|
|
|
} |
|
|
|
|
io.lock(); |
|
|
|
|
con.push_back(new_con_ptr);
|
|
|
|
|
io.unlock(); |
|
|
|
|
} catch (const SQLException except) { |
|
|
|
|
cout << except.what() << endl; |
|
|
|
|
} catch (const string except) { |
|
|
|
|
cout << except << endl; |
|
|
|
|
}
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i=0; i<con.size() && run_engin; i++) { |
|
|
|
|
if (!con[i]->isValid()) { |
|
|
|
|
io.lock(); |
|
|
|
|
con.erase(con.begin()+i); |
|
|
|
|
io.unlock(); |
|
|
|
|
i--; |
|
|
|
|
Connection *n_conn = create_connection(); |
|
|
|
|
release_connection(n_conn); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |