当前位置:网站首页>Database connection pool: Code Directory
Database connection pool: Code Directory
2022-06-22 15:05:00 【_ Soren】
Preface
of MySQL Database programming 、 Multithreaded programming 、 Thread mutual exclusion and synchronous communication operation 、 Intelligent pointer 、 Design patterns 、 Containers, etc. these technologies are C++ Language level can be realized directly , Therefore, the project is selected directly in windows On the platform 【virtual studio 2022】 Development .
List of articles
The header file
public.h
#pragma once
#include<iostream>
#define LOG(str) \ std::cout << __FILE__ << ":" << __LINE__ << " " << \ __TIMESTAMP__ << " : " << str << std::endl;
Connection.h
// Realization MySQL Operation of database
#include <mysql.h>
#include <string>
#include <ctime>
using namespace std;
// Database operation class
class Connection
{
public:
// Initialize database connection
Connection();
// Release database connection resources
~Connection();
// Connect to database
bool connect(string ip,
unsigned short port,
string user,
string password,
string dbname);
// update operation insert、delete、update
bool update(string sql);
// Query operation select
MYSQL_RES* query(string sql);
// Refresh the starting idle time of the connection
void refreshAliveTime();
// Return to the time of survival
clock_t getAliveTime() const;
private:
MYSQL* _conn; // Represents and MySQL Server A connection of
clock_t _aliveTime; // Record the survival time after entering the idle state
};
CommonConnectionPool.h
#pragma once
// Implement the connection pool function module
#include<iostream>
#include<string>
#include<queue>
#include<mutex>
#include<atomic>
#include<thread>
#include<memory>
#include<functional>
#include<condition_variable>
#include "Connection.h"
using namespace std;
class ConnectionPool
{
public:
// Get connection pool object instance Static
static ConnectionPool* getConnectionPool();
// Provide an interface to the outside , Provide an idle connection
shared_ptr<Connection> getConnection();
private:
ConnectionPool(); // The singleton pattern Constructor privatization
bool loadConfigFile(); // Load profile
// Producer thread function , Responsible for the production of new connections
void produceConnectionTask();
// Recycling thread functions , Responsible for recycling redundant idle connections
void scannerConnectionTask();
string _ip; // MySQL Of IP Address
unsigned short _port; // MySQL Port number
string _username; // MySQL Login user name of
string _password; // MySQL Login password for
string _dbname; // Database name
int _initSize; // The initial number of connections to the connection pool
int _maxSize; // The maximum number of connections in the connection pool
int _maxIdleTime; // The maximum waiting time of the connection pool
int _connectionTimeOut; // The timeout for the connection pool to obtain connections
queue<Connection*> _connectionQue; // Storage MySQL Connected queue
mutex _queueMutex; // Maintain thread safe mutexes for connection queues
atomic_int _connectionCnt; // Record the... Created by the connection connection Total connections for , No more than _maxSize
condition_variable cv; // Connect the communication between the production thread and the consumption thread
};
Source file
Connection.cpp
#include <mysql.h>
#include <string>
#include "Connection.h"
#include "public.h"
using namespace std;
// Initialize database connection
Connection::Connection()
{
_conn = mysql_init(nullptr);
}
// Release database connection resources
Connection::~Connection()
{
if (_conn != nullptr)
mysql_close(_conn);
}
// Connect to database
bool Connection::connect(string ip, unsigned short port, string user,
string password, string dbname)
{
MYSQL* p = mysql_real_connect(_conn, ip.c_str(), user.c_str(),
password.c_str(), dbname.c_str(), port, nullptr, 0);
return p != nullptr;
}
// update operation insert、delete、update
bool Connection::update(string sql)
{
if (mysql_query(_conn, sql.c_str()))
{
LOG(" Update failed :" + sql);
return false;
}
return true;
}
// Query operation select
MYSQL_RES* Connection::query(string sql)
{
if (mysql_query(_conn, sql.c_str()))
{
LOG(" The query fails :" + sql);
return nullptr;
}
return mysql_use_result(_conn);
}
// Refresh the starting idle time of the connection
void Connection::refreshAliveTime()
{
_aliveTime = clock();
}
// Return to the time of survival
clock_t Connection::getAliveTime() const
{
return clock() - _aliveTime;
}
mysql.ini
# Configuration file of database connection pool
ip=127.0.0.1
port=3306
username=root
password=123456
dbname=chat
initSize=10
maxSize=1024
# The maximum idle time is seconds by default
maxIdleTime=60
# Connection timeout , In milliseconds
connectionTimeOut=100
CommonConnectionPool.cpp
#include "CommonConnectionPool.h"
#include "public.h"
// Thread safe lazy singleton mode function interface
ConnectionPool* ConnectionPool::getConnectionPool()
{
// Static local variables , Compiler automatic lock and unlock
static ConnectionPool pool;
return& pool;
}
// Load configuration items from the configuration file
bool ConnectionPool::loadConfigFile()
{
FILE* pf = fopen("mysql.ini", "r");
if (pf == nullptr)
{
LOG("mysql.ini file is not exist!");
return false;
}
while (!feof(pf))
{
char line[1024] = {
0 };
fgets(line, 1024, pf);
string str = line;
int idx = str.find('=', 0);
if (-1 == idx) // Invalid configuration
{
continue;
}
int endidx = str.find('\n', idx);
string key = str.substr(0, idx);
string value = str.substr(idx + 1, endidx - idx - 1);
if (key == "ip")
{
_ip = value;
}
else if (key == "port")
{
_port = atoi(value.c_str());
}
else if (key == "username")
{
_username = value;
}
else if (key == "password")
{
_password = value;
}
else if (key == "dbname")
{
_dbname = value;
}
else if (key == "initSize")
{
_initSize = atoi(value.c_str());
}
else if (key == "maxSize")
{
_maxSize = atoi(value.c_str());
}
else if (key == "maxIdleTime")
{
_maxIdleTime = atoi(value.c_str());
}
else if (key == "connectionTimeOut")
{
_connectionTimeOut = atoi(value.c_str());
}
}
return true;
}
// Constructor for connection pool
ConnectionPool::ConnectionPool()
{
// 1. Load configuration items
if (!loadConfigFile())
{
return;
}
// 2. Create initial quantity connection
for (int i = 0; i < _initSize; ++i)
{
Connection* p = new Connection();
p->connect(_ip, _port, _username, _password, _dbname);
p->refreshAliveTime(); // Refresh the start time of idle
_connectionQue.push(p);
_connectionCnt++;
}
// 3. Start a new thread as the producer thread
thread produce(std::bind( & ConnectionPool::produceConnectionTask, this));
produce.detach(); // The guardian thread ( Detaching threads )
// 4. Start a new thread , Scan over maxIdleTime Of free connections , Recycle excess connections
thread scanner(std::bind(&ConnectionPool::scannerConnectionTask, this));
scanner.detach();
}
// producer : Running on a separate thread , Responsible for production connection
void ConnectionPool::produceConnectionTask()
{
// loop ( Keep listening )
for (; ;)
{
unique_lock<mutex> lock(_queueMutex);
while (!_connectionQue.empty())
{
cv.wait(lock); // The queue is not empty , The production thread enters the waiting queue for the condition variable
}
// The number of connections has not reached the maximum , Continue creating new connections
if (_connectionCnt < _maxSize)
{
Connection* p = new Connection();
p->connect(_ip, _port, _username, _password, _dbname);
p->refreshAliveTime(); // Refresh the start time of idle
_connectionQue.push(p);
_connectionCnt++;
}
// Wake up all threads in the waiting queue
cv.notify_all(); // Notify consumer thread , You can consume and connect
}
}
// Provide an interface to the outside , Provide an idle connection
shared_ptr<Connection> ConnectionPool::getConnection()
{
unique_lock<mutex> lock(_queueMutex);
while (_connectionQue.empty())
{
// Not directly sleep
// When I wake up after a timeout, I find that it is still empty , Just go back to nullptr
if (cv_status::timeout == cv.wait_for(lock, std::chrono::milliseconds(_connectionTimeOut)))
{
if (_connectionQue.empty())
{
LOG(" Getting idle connection timed out ... Failed to get connection !");
return nullptr;
}
}
}
/* because shared_ptr At the time of deconstruction , Will be able to Connection Resource Direct delete fall , Equivalent to calling Connection Destructor of ,Connection I was close It fell off , So you need to customize how smart pointers release resources , Instead, return the resource to the queue */
shared_ptr<Connection> sp(_connectionQue.front(),
[&](Connection* pcon) {
// This is called in the server application thread. , Thread safety needs to be considered
unique_lock<mutex> lock(_queueMutex);
pcon->refreshAliveTime(); // Refresh the start time of idle
_connectionQue.push(pcon);
});
_connectionQue.pop();
// Consume the last one in the queue Connection, The producer thread is notified of the production connection
cv.notify_all();
return sp;
}
// Scan over maxIdleTime Of free connections , Recycle excess connections
void ConnectionPool::scannerConnectionTask()
{
for (; ;)
{
// adopt sleep Simulate the timing effect
this_thread::sleep_for(std::chrono::seconds(_maxIdleTime));
// Scan the entire queue , Release more than connections
unique_lock<mutex> lock(_queueMutex);
while (_connectionCnt > _initSize)
{
Connection* p = _connectionQue.front();
if (p->getAliveTime() >= (_maxIdleTime * 1000))
{
_connectionQue.pop();
_connectionCnt--;
delete p; // call ~Connection();
}
else
{
break; // The connection of the team head does not exceed _maxIdleTime, There must be none in the back
}
}
}
}
边栏推荐
- 拜登簽署兩項旨在加强政府網絡安全的新法案
- What are strong and weak symbols in embedded systems?
- 【Pr】基础流程
- RealNetworks vs. Microsoft: the battle in the early streaming media industry
- Error: unable to find a match: lrzsz
- C generic method
- Using pictures to locate app elements sikulix
- CSAPP之详解Labs
- [Zhejiang University] information sharing of the first and second postgraduate entrance examinations
- Keil simulation and VSPD
猜你喜欢

Common real machine debugging plug-ins for unity commercial games

【浙江大学】考研初试复试资料分享

Simulation Keil et vspd

Those confusing user state & kernel state

What is the value of a website? Why build an independent station

Live broadcast goes to sea | domestic live broadcast room produces explosive products again. How can "roll out" win the world

C # WinForm photo album function, picture zooming, dragging, preview Pagination

轻松上手Fluentd,结合 Rainbond 插件市场,日志收集更快捷

After reading this article, I will teach you to play with the penetration test target vulnhub - drivetingblues-5

PowerPoint 教程,如何在 PowerPoint 中添加水印?
随机推荐
一文彻底弄懂建造者模式(Builder)
Fight, programmer chapter 43 kill one man in ten steps
Madcap flare 2022, documentation in language or format
Sikulix select the picture of relative position (advanced version)
推动制造业高效增长,用友U9 cloud不断精进背后的密码
Common real machine debugging plug-ins for unity commercial games
网络安全的五大特点有哪些?五大属性是什么?
Thoroughly understand the builder mode (builder)
Mobile learning notes of u++ programming
Struggle, programmer -- Chapter 46 this situation can be recalled, but it was at a loss at that time
扩散模型又杀疯了!这一次被攻占的领域是...
Groovy list operation
How to compare the size of two dates in unity and C #
那些没考上大学的人,后来过的怎样
11 method reference and constructor application
拜登签署两项旨在加强政府网络安全的新法案
Those confusing user state & kernel state
Unity's rich text color sets the color to be fully transparent
机器学习之随机森林
No wonder the postgraduate entrance examination is so hot. These are the "hidden benefits" of Postgraduates!