Merge branch 'master' of ssh://115.28.86.8:29418/~admin/昆仑_1025
10个文件已修改
11个文件已添加
2个文件已删除
| | |
| | | #include <iostream> |
| | | #include <memory> |
| | | #include <mutex> |
| | | #include <fstream> |
| | | #include <string> |
| | | #include <ctime> |
| | | using namespace std; |
| | | class A { |
| | | #include <mysql_driver.h> |
| | | #include <mysql_connection.h> |
| | | #include <cppconn/statement.h> |
| | | #include <cppconn/resultset.h> |
| | | |
| | | class DatabaseOperator { |
| | | private: |
| | | ofstream logFile; |
| | | A() { |
| | | logFile.open("123.txt", ios::app); |
| | | // ç§ææé 彿° |
| | | DatabaseOperator() { |
| | | try { |
| | | driver = sql::mysql::get_mysql_driver_instance(); |
| | | connection = driver->connect("tcp://127.0.0.1:3306", "username", "password"); |
| | | connection->setSchema("your_database"); |
| | | } catch (sql::SQLException &e) { |
| | | std::cerr << "æ°æ®åºè¿æ¥é误: " << e.what() << std::endl; |
| | | } |
| | | } |
| | | ~A() { |
| | | logFile.close(); |
| | | } |
| | | A(const A &t){} |
| | | A& operator=(const A &t){} |
| | | static A* volatile s_obj; |
| | | static mutex g_mutex; |
| | | |
| | | static DatabaseOperator* instance; |
| | | static std::mutex mutex; |
| | | sql::Driver* driver; |
| | | std::unique_ptr<sql::Connection> connection; |
| | | |
| | | public: |
| | | static A* getInstance() { |
| | | if (s_obj == nullptr) { |
| | | lock_guard<mutex> guard(g_mutex); |
| | | if (s_obj == nullptr) { |
| | | s_obj = new A; |
| | | } |
| | | // è·ååä¾å®ä¾ |
| | | static DatabaseOperator* getInstance() { |
| | | std::lock_guard<std::mutex> lock(mutex); |
| | | if (instance == nullptr) { |
| | | instance = new DatabaseOperator(); |
| | | } |
| | | return s_obj; |
| | | return instance; |
| | | } |
| | | void write(const string& level, const string& description, const string& time) { |
| | | logFile << "[" << level << "] " << "[" << time << "] " << description << endl; |
| | | } |
| | | void release() { |
| | | if (s_obj) { |
| | | delete s_obj; |
| | | s_obj = nullptr; |
| | | |
| | | // æ§è¡æ¥è¯¢æä½ï¼ç¤ºä¾ï¼ |
| | | sql::ResultSet* query(const std::string& sql) { |
| | | try { |
| | | std::unique_ptr<sql::Statement> stmt(connection->createStatement()); |
| | | return stmt->executeQuery(sql); |
| | | } catch (sql::SQLException &e) { |
| | | std::cerr << "æ¥è¯¢é误: " << e.what() << std::endl; |
| | | } |
| | | return nullptr; |
| | | } |
| | | }; |
| | | |
| | | A* volatile A::s_obj = nullptr; |
| | | mutex A::g_mutex; |
| | | |
| | | int main() { |
| | | A* a1 = A::getInstance(); |
| | | A* a2 = A::getInstance(); |
| | | if (a1 == a2) { |
| | | cout << "å便å" << endl; |
| | | } |
| | | else { |
| | | cout << "åä¾å¤±è´¥" << endl; |
| | | } |
| | | time_t now = time(nullptr); |
| | | char buffer[80]; |
| | | struct tm timeinfo; |
| | | localtime_s(&timeinfo, &now); |
| | | strftime(buffer, 80, "%Y - %m - %d %H:%M:%S", &timeinfo); |
| | | string timeStr(buffer); |
| | | a1->write("1", "æ¥å¿", timeStr); |
| | | a1->release(); |
| | | return 0; |
| | | } |
| | | std::mutex DatabaseOperator::mutex; |
| | | DatabaseOperator* DatabaseOperator::instance = nullptr; |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | # æ°æ®åºè¿æ¥åæ° |
| | | DB_USER="your_username" |
| | | DB_PASS="your_password" |
| | | DB_NAME="your_database_name" |
| | | BACKUP_DIR="/path/to/backup/directory" |
| | | |
| | | # è·åå½åæ¥æï¼ç¨äºæä»¶å |
| | | DATE=$(date +%Y%m%d%H%M%S) |
| | | |
| | | # å¤ä»½æä»¶å |
| | | BACKUP_FILE="${BACKUP_DIR}/backup_${DATE}.sql" |
| | | |
| | | # å建å¤ä»½ç®å½ï¼å¦æä¸åå¨ï¼ |
| | | mkdir -p $BACKUP_DIR |
| | | |
| | | # 使ç¨mysqldumpè¿è¡æ°æ®åºå¤ä»½ |
| | | mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE |
| | | |
| | | if [ $? -eq 0 ]; then |
| | | echo "æ°æ®åºå¤ä»½æåï¼$BACKUP_FILE" |
| | | else |
| | | echo "æ°æ®åºå¤ä»½å¤±è´¥" |
| | | fi |
| | | |
| | | # æ·»å 宿¶ä»»å¡ï¼ä½¿ç¨crontab -eæ¥ç¼è¾å®æ¶ä»»å¡ï¼ |
| | | # ä¾å¦ï¼æ¯å¤©åæ¨2ç¹æ§è¡å¤ä»½ |
| | | # 0 2 * * * /path/to/this/script.sh |
New file |
| | |
| | | #include <iostream> |
| | | #include <list> |
| | | #include <mutex> |
| | | #include <condition_variable> |
| | | #include <mysql_driver.h> |
| | | #include <mysql_connection.h> |
| | | #include <cppconn/statement.h> |
| | | #include <cppconn/resultset.h> |
| | | |
| | | class SQLConnectionPool { |
| | | private: |
| | | SQLConnectionPool(int minConns, int maxConns) : |
| | | minConnections(minConns), maxConnections(maxConns), currentConnections(0) {} |
| | | |
| | | static SQLConnectionPool* instance; |
| | | static std::mutex mutex; |
| | | std::condition_variable cv; |
| | | int minConnections; |
| | | int maxConnections; |
| | | int currentConnections; |
| | | std::list<std::unique_ptr<sql::Connection>> connections; |
| | | |
| | | // å建ä¸ä¸ªæ°çæ°æ®åºè¿æ¥ |
| | | std::unique_ptr<sql::Connection> createConnection() { |
| | | try { |
| | | sql::Driver* driver = sql::mysql::get_mysql_driver_instance(); |
| | | std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "username", "password")); |
| | | conn->setSchema("your_database"); |
| | | return conn; |
| | | } catch (sql::SQLException &e) { |
| | | std::cerr << "åå»ºè¿æ¥é误: " << e.what() << std::endl; |
| | | return nullptr; |
| | | } |
| | | } |
| | | |
| | | public: |
| | | // è·ååä¾å®ä¾ |
| | | static SQLConnectionPool* getInstance(int minConns, int maxConns) { |
| | | std::lock_guard<std::mutex> lock(mutex); |
| | | if (instance == nullptr) { |
| | | instance = new SQLConnectionPool(minConns, maxConns); |
| | | instance->initializePool(); |
| | | } |
| | | return instance; |
| | | } |
| | | |
| | | // åå§åè¿æ¥æ± |
| | | void initializePool() { |
| | | for (int i = 0; i < minConnections; ++i) { |
| | | std::unique_ptr<sql::Connection> conn = createConnection(); |
| | | if (conn) { |
| | | connections.push_back(std::move(conn)); |
| | | currentConnections++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // è·åæ°æ®åºè¿æ¥ |
| | | std::unique_ptr<sql::Connection> getConnection() { |
| | | std::unique_lock<std::mutex> lock(mutex); |
| | | while (connections.empty() && currentConnections >= maxConnections) { |
| | | cv.wait(lock); |
| | | } |
| | | |
| | | std::unique_ptr<sql::Connection> conn; |
| | | if (!connections.empty()) { |
| | | conn = std::move(connections.front()); |
| | | connections.pop_front(); |
| | | } else if (currentConnections < maxConnections) { |
| | | conn = createConnection(); |
| | | if (conn) { |
| | | currentConnections++; |
| | | } |
| | | } |
| | | return conn; |
| | | } |
| | | |
| | | // å½è¿æ°æ®åºè¿æ¥ |
| | | void releaseConnection(std::unique_ptr<sql::Connection>& conn) { |
| | | std::lock_guard<std::mutex> lock(mutex); |
| | | if (currentConnections > minConnections) { |
| | | currentConnections--; |
| | | } else { |
| | | connections.push_back(std::move(conn)); |
| | | } |
| | | cv.notify_one(); |
| | | } |
| | | }; |
| | | |
| | | std::mutex SQLConnectionPool::mutex; |
| | | SQLConnectionPool* SQLConnectionPool::instance = nullptr; |
| | |
| | | https://blog.csdn.net/qq_28245087/article/details/131453274 |
| | | 1 .使ç¨åæ°åæ¥è¯¢ |
| | | 使ç¨åæ°åæ¥è¯¢å¯ä»¥é²æ¢SQL注å
¥æ»å»ï¼å¹¶æé«ä»£ç çå¯è¯»æ§åå¯ç»´æ¤æ§ãå¨Javaä¸ï¼å¯ä»¥ä½¿ç¨PreparedStatementæ¥å®ç°åæ°åæ¥è¯¢ã |
| | | 2. è¾å
¥éªè¯åè¿æ»¤ |
| | | è¾å
¥éªè¯åè¿æ»¤æ¯ä¸ç§ç¨äºç¡®ä¿ç¨æ·è¾å
¥æ°æ®çå®å
¨æ§åæææ§çææ¯ãå®å¯ä»¥é²æ¢æ¶æè¾å
¥åéè¯¯æ°æ®å¯¼è´çå®å
¨æ¼æ´ååºç¨ç¨åºé误ã |
| | | 3. 使ç¨åå¨è¿ç¨ |
| | | åå¨è¿ç¨æ¯ä¸ç»é¢å®ä¹çSQLè¯å¥éåï¼å¯ä»¥å¨æ°æ®åºä¸è¿è¡é夿§å夿æ§çæä½ãå®ä»¬å¯ä»¥æ¥ååæ°ï¼å¹¶ä¸å¯ä»¥å¨æ°æ®åºä¸è¿è¡éå¤ä½¿ç¨ã |
| | | 4.æå°æéåå |
| | | æå°æéå忝ä¸ç§å®å
¨æ§ååï¼æçæ¯ä¸ºäºä¿æ¤æææ°æ®åç³»ç»èµæºï¼ç¨æ·åºè¯¥è¢«æäºæå°å¿
éçæéãè¿æå³çç¨æ·åªè½è®¿é®åæ§è¡ä»ä»¬å·¥ä½æéçæ°æ®åºå¯¹è±¡åæä½ï¼è䏿¯æ¥æå¯¹æ´ä¸ªæ°æ®åºçå®å
¨è®¿é®æéã |
| | | ä½¿ç¨æå°æéååå¯ä»¥åå°æ½å¨çå®å
¨é£é©åæ°æ®æ³é²çå¯è½æ§ãéè¿éå¶ç¨æ·çæéï¼å¯ä»¥é²æ¢ä»ä»¬å¯¹æ°æ®åºä¸çæææ°æ®è¿è¡æªç»ææç访é®ãä¿®æ¹æå é¤ã |
| | | 5. 使ç¨ORMæ¡æ¶ |
| | | ORMï¼å¯¹è±¡å
³ç³»æ å°ï¼æ¡æ¶æ¯ä¸ç§å°å¯¹è±¡æ¨¡ååå
³ç³»æ°æ®åºä¹é´è¿è¡æ å°çææ¯ãå®å
许å¼å人å使ç¨é¢åå¯¹è±¡çæ¹å¼æä½æ°æ®åºï¼èä¸éè¦ç¼åç¹ççSQLè¯å¥ãORMæ¡æ¶å°æ°æ®åºè¡¨æ å°ä¸ºå¯¹è±¡ï¼å°è¡¨çè¡æ å°ä¸ºå¯¹è±¡ç屿§ï¼å°è¡¨ä¹é´çå
³ç³»æ å°ä¸ºå¯¹è±¡ä¹é´çå
³èã |
| | | ORMæ¡æ¶çä¼ç¹å
æ¬æé«å¼åæçãåå°ä»£ç éãç®åæ°æ®åºæä½ãæä¾å¯¹è±¡çº§å«çæ¥è¯¢åæä¹
åçã |
| | | 6. 使ç¨åå¤è¯å¥ |
| | | åå¤è¯å¥ï¼Prepared Statementï¼æ¯ä¸ç§é¢ç¼è¯çSQLè¯å¥ï¼å®å
许å¼å人åå°åæ°åæ¥è¯¢åéå°æ°æ®åºï¼å¹¶å¨æ§è¡æ¶æä¾åæ°å¼ãåå¤è¯å¥å¯ä»¥æé«æ°æ®åºæä½çæ§è½åå®å
¨æ§ï¼åæ¶è¿è½é²æ¢SQL注å
¥æ»å»ã |
| | | 7.使ç¨å®å
¨çæ°æ®åºè¿æ¥ |
| | | 使ç¨å®å
¨çæ°æ®åºè¿æ¥æ¯é常éè¦çï¼å¯ä»¥ä¿æ¤æ°æ®åºå
åæ¶ææ»å»åæ°æ®æ³é²ã |
| | | 使ç¨SSL/TLSå å¯ï¼éè¿ä½¿ç¨SSL/TLSå å¯ï¼å¯ä»¥ç¡®ä¿æ°æ®åºè¿æ¥å¨ä¼ è¾è¿ç¨ä¸çæ°æ®å®å
¨ã |
| | | 8.é¿å
å¨ææ¼æ¥SQLè¯å¥ |
| | | é¿å
å¨ææ¼æ¥SQLè¯å¥æ¯ä¸ºäºé²æ¢SQL注å
¥æ»å»åæé«ä»£ç çå¯è¯»æ§åå¯ç»´æ¤æ§ã |
| | | 9.使ç¨é²ç«å¢åå
¥ä¾µæ£æµç³»ç» |
| | | 使ç¨é²ç«å¢åå
¥ä¾µæ£æµç³»ç»æ¯ä¸ºäºä¿æ¤è®¡ç®æºç½ç»å
åæªç»ææç访é®åæ¶ææ»å»ã |
| | | 10.å®ææ´æ°åç»´æ¤æ°æ®åºè½¯ä»¶ |
| | | å®ææ´æ°åç»´æ¤æ°æ®åºè½¯ä»¶æ¯é常éè¦çï¼ä»¥ç¡®ä¿æ°æ®åºçå®å
¨æ§ãæ§è½ååè½çç¨³å®æ§ã以䏿¯ä¸äºè¯´æåè§£éï¼ä»¥å使ç¨Java代ç ç¤ºä¾æ¥å®ç°æ°æ®åºè½¯ä»¶çå®ææ´æ°åç»´æ¤ï¼ |
| | | #include <iostream> |
| | | #include <mysql_driver.h> |
| | | #include <mysql_connection.h> |
| | | #include <cppconn/statement.h> |
| | | #include <cppconn/prepared_statement.h> |
| | | #include <cppconn/resultset.h> |
| | | #include <string> |
| | | #include <regex> |
| | | |
| | | å®ææ´æ°ï¼ |
| | | å®ææ´æ°æ°æ®åºè½¯ä»¶æ¯ä¸ºäºè·åææ°çå®å
¨è¡¥ä¸ãåè½æ¹è¿åæ§è½ä¼åãæ°æ®åºä¾åºåé常ä¼å叿´æ°çæ¬ï¼ä»¥ä¿®å¤å·²ç¥çæ¼æ´åé®é¢ãæ´æ°æ°æ®åºè½¯ä»¶å¯ä»¥æé«æ°æ®åºçå®å
¨æ§ï¼å¹¶ç¡®ä¿æ°æ®åºä¸ææ°çææ¯åæ åä¿æä¸è´ã |
| | | ç»´æ¤ä»»å¡ï¼ |
| | | æ°æ®åºè½¯ä»¶çç»´æ¤ä»»å¡å
æ¬å¤ä»½åæ¢å¤ãç´¢å¼ä¼åãç»è®¡ä¿¡æ¯æ´æ°ã空é´ç®¡çãæ¥å¿ç®¡ççãè¿äºä»»å¡æå©äºæé«æ°æ®åºçæ§è½ãå¯ç¨æ§åå¯é æ§ã |
| | | class DatabaseUtils { |
| | | public: |
| | | // è¿æ¥æ°æ®åº |
| | | static sql::Connection* connect() { |
| | | try { |
| | | sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance(); |
| | | sql::Connection* con = driver->connect("tcp://127.0.0.1:3306", "mayi", "123456"); |
| | | con->setSchema("your_database"); |
| | | return con; |
| | | } catch (sql::SQLException& e) { |
| | | std::cerr << "æ°æ®åºè¿æ¥é误: " << e.what() << std::endl; |
| | | return nullptr; |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥SQLè¯å¥æ¯å¦å卿½å¨æ³¨å
¥é£é©ï¼ç®åæ£åæ ¡éªï¼ |
| | | static bool isSafeSQL(const std::string& sql) { |
| | | // ç®åçæ£å表达å¼ï¼é²æ¢å¸¸è§ç注å
¥å
³é®è¯ |
| | | std::regex injectionRegex("(drop|delete|update|insert|select\\s+\\*\\s+from)", std::regex_constants::icase); |
| | | return!std::regex_search(sql, injectionRegex); |
| | | } |
| | | |
| | | // 使ç¨åæ°åæ¥è¯¢æ§è¡SQLè¯å¥ |
| | | static sql::ResultSet* executeSafeQuery(sql::Connection* con, const std::string& sql, const std::vector<std::string>& params) { |
| | | try { |
| | | sql::PreparedStatement* pstmt = con->prepareStatement(sql); |
| | | for (size_t i = 0; i < params.size(); ++i) { |
| | | pstmt->setString(i + 1, params[i]); |
| | | } |
| | | return pstmt->executeQuery(); |
| | | } catch (sql::SQLException& e) { |
| | | std::cerr << "æ¥è¯¢æ§è¡é误: " << e.what() << std::endl; |
| | | return nullptr; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | int main() { |
| | | sql::Connection* con = DatabaseUtils::connect(); |
| | | if (con) { |
| | | std::string sql = "SELECT * FROM your_table WHERE column_name =?"; |
| | | std::vector<std::string> params = {"test_value"}; |
| | | if (DatabaseUtils::isSafeSQL(sql)) { |
| | | sql::ResultSet* res = DatabaseUtils::executeSafeQuery(con, sql, params); |
| | | if (res) { |
| | | while (res->next()) { |
| | | // å¤çç»æ |
| | | std::cout << res->getString(1) << std::endl; |
| | | } |
| | | delete res; |
| | | } |
| | | } else { |
| | | std::cerr << "æ½å¨çSQL注å
¥é£é©" << std::endl; |
| | | } |
| | | delete con; |
| | | } |
| | | return 0; |
| | | } |
New file |
| | |
| | | { |
| | | "configurations": [ |
| | | { |
| | | "name": "windows-gcc-x64", |
| | | "includePath": [ |
| | | "${workspaceFolder}/**" |
| | | ], |
| | | "compilerPath": "gcc", |
| | | "cStandard": "${default}", |
| | | "cppStandard": "${default}", |
| | | "intelliSenseMode": "windows-gcc-x64", |
| | | "compilerArgs": [ |
| | | "" |
| | | ] |
| | | } |
| | | ], |
| | | "version": 4 |
| | | } |
New file |
| | |
| | | { |
| | | "version": "0.2.0", |
| | | "configurations": [ |
| | | { |
| | | "name": "C/C++ Runner: Debug Session", |
| | | "type": "cppdbg", |
| | | "request": "launch", |
| | | "args": [], |
| | | "stopAtEntry": false, |
| | | "externalConsole": true, |
| | | "cwd": "d:/git_1026/æä»_1025/Server/马丽è/code/log", |
| | | "program": "d:/git_1026/æä»_1025/Server/马丽è/code/log/build/Debug/outDebug", |
| | | "MIMode": "gdb", |
| | | "miDebuggerPath": "gdb", |
| | | "setupCommands": [ |
| | | { |
| | | "description": "Enable pretty-printing for gdb", |
| | | "text": "-enable-pretty-printing", |
| | | "ignoreFailures": true |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
New file |
| | |
| | | { |
| | | "C_Cpp_Runner.cCompilerPath": "gcc", |
| | | "C_Cpp_Runner.cppCompilerPath": "g++", |
| | | "C_Cpp_Runner.debuggerPath": "gdb", |
| | | "C_Cpp_Runner.cStandard": "", |
| | | "C_Cpp_Runner.cppStandard": "", |
| | | "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat", |
| | | "C_Cpp_Runner.useMsvc": false, |
| | | "C_Cpp_Runner.warnings": [ |
| | | "-Wall", |
| | | "-Wextra", |
| | | "-Wpedantic", |
| | | "-Wshadow", |
| | | "-Wformat=2", |
| | | "-Wcast-align", |
| | | "-Wconversion", |
| | | "-Wsign-conversion", |
| | | "-Wnull-dereference" |
| | | ], |
| | | "C_Cpp_Runner.msvcWarnings": [ |
| | | "/W4", |
| | | "/permissive-", |
| | | "/w14242", |
| | | "/w14287", |
| | | "/w14296", |
| | | "/w14311", |
| | | "/w14826", |
| | | "/w44062", |
| | | "/w44242", |
| | | "/w14905", |
| | | "/w14906", |
| | | "/w14263", |
| | | "/w44265", |
| | | "/w14928" |
| | | ], |
| | | "C_Cpp_Runner.enableWarnings": true, |
| | | "C_Cpp_Runner.warningsAsError": false, |
| | | "C_Cpp_Runner.compilerArgs": [], |
| | | "C_Cpp_Runner.linkerArgs": [], |
| | | "C_Cpp_Runner.includePaths": [], |
| | | "C_Cpp_Runner.includeSearch": [ |
| | | "*", |
| | | "**/*" |
| | | ], |
| | | "C_Cpp_Runner.excludeSearch": [ |
| | | "**/build", |
| | | "**/build/**", |
| | | "**/.*", |
| | | "**/.*/**", |
| | | "**/.vscode", |
| | | "**/.vscode/**" |
| | | ], |
| | | "C_Cpp_Runner.useAddressSanitizer": false, |
| | | "C_Cpp_Runner.useUndefinedSanitizer": false, |
| | | "C_Cpp_Runner.useLeakSanitizer": false, |
| | | "C_Cpp_Runner.showCompilationTime": false, |
| | | "C_Cpp_Runner.useLinkTimeOptimization": false, |
| | | "C_Cpp_Runner.msvcSecureNoWarnings": false |
| | | } |
New file |
| | |
| | | |
| | | 忥/弿¥æ¥å¿ç³»ç» |
| | | =============== |
| | | 忥/弿¥æ¥å¿ç³»ç»ä¸»è¦æ¶åäºä¸¤ä¸ªæ¨¡åï¼ä¸ä¸ªæ¯æ¥å¿æ¨¡åï¼ä¸ä¸ªæ¯é»å¡é忍¡å,å
¶ä¸å å
¥é»å¡é忍¡åä¸»è¦æ¯è§£å³å¼æ¥åå
¥æ¥å¿ååå¤. |
| | | > * èªå®ä¹é»å¡éå |
| | | > * å便¨¡å¼å建æ¥å¿ |
| | | > * 忥æ¥å¿ |
| | | > * 弿¥æ¥å¿ |
| | | > * å®ç°æå¤©ãè¶
è¡åç±» |
New file |
| | |
| | | /************************************************************* |
| | | *å¾ªç¯æ°ç»å®ç°çé»å¡éåï¼m_back = (m_back + 1) % m_max_size; |
| | | *线ç¨å®å
¨ï¼æ¯ä¸ªæä½åé½è¦å
å äºæ¥éï¼æä½å®åï¼åè§£é |
| | | **************************************************************/ |
| | | |
| | | #ifndef BLOCK_QUEUE_H |
| | | #define BLOCK_QUEUE_H |
| | | |
| | | #include <iostream> |
| | | #include <stdlib.h> |
| | | #include <pthread.h> |
| | | #include <sys/time.h> |
| | | #include "../lock/locker.h" |
| | | using namespace std; |
| | | |
| | | template <class T> |
| | | class block_queue |
| | | { |
| | | public: |
| | | block_queue(int max_size = 1000) |
| | | { |
| | | if (max_size <= 0) |
| | | { |
| | | exit(-1); |
| | | } |
| | | |
| | | m_max_size = max_size; |
| | | m_array = new T[max_size]; |
| | | m_size = 0; |
| | | m_front = -1; |
| | | m_back = -1; |
| | | } |
| | | |
| | | void clear() |
| | | { |
| | | m_mutex.lock(); |
| | | m_size = 0; |
| | | m_front = -1; |
| | | m_back = -1; |
| | | m_mutex.unlock(); |
| | | } |
| | | |
| | | ~block_queue() |
| | | { |
| | | m_mutex.lock(); |
| | | if (m_array != NULL) |
| | | delete [] m_array; |
| | | |
| | | m_mutex.unlock(); |
| | | } |
| | | //夿é忝妿»¡äº |
| | | bool full() |
| | | { |
| | | m_mutex.lock(); |
| | | if (m_size >= m_max_size) |
| | | { |
| | | |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | //夿é忝å¦ä¸ºç©º |
| | | bool empty() |
| | | { |
| | | m_mutex.lock(); |
| | | if (0 == m_size) |
| | | { |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | //è¿åéé¦å
ç´ |
| | | bool front(T &value) |
| | | { |
| | | m_mutex.lock(); |
| | | if (0 == m_size) |
| | | { |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | value = m_array[m_front]; |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | //è¿åéå°¾å
ç´ |
| | | bool back(T &value) |
| | | { |
| | | m_mutex.lock(); |
| | | if (0 == m_size) |
| | | { |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | value = m_array[m_back]; |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | |
| | | int size() |
| | | { |
| | | int tmp = 0; |
| | | |
| | | m_mutex.lock(); |
| | | tmp = m_size; |
| | | |
| | | m_mutex.unlock(); |
| | | return tmp; |
| | | } |
| | | |
| | | int max_size() |
| | | { |
| | | int tmp = 0; |
| | | |
| | | m_mutex.lock(); |
| | | tmp = m_max_size; |
| | | |
| | | m_mutex.unlock(); |
| | | return tmp; |
| | | } |
| | | //å¾éåæ·»å å
ç´ ï¼éè¦å°ææä½¿ç¨éåç线ç¨å
å¤é |
| | | //彿å
ç´ pushè¿éå,ç¸å½äºç产è
ç产äºä¸ä¸ªå
ç´ |
| | | //è¥å½å没æçº¿ç¨çå¾
æ¡ä»¶åé,åå¤éæ æä¹ |
| | | bool push(const T &item) |
| | | { |
| | | |
| | | m_mutex.lock(); |
| | | if (m_size >= m_max_size) |
| | | { |
| | | |
| | | m_cond.broadcast(); |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | |
| | | m_back = (m_back + 1) % m_max_size; |
| | | m_array[m_back] = item; |
| | | |
| | | m_size++; |
| | | |
| | | m_cond.broadcast(); |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | //popæ¶,妿å½åéåæ²¡æå
ç´ ,å°ä¼çå¾
æ¡ä»¶åé |
| | | bool pop(T &item) |
| | | { |
| | | |
| | | m_mutex.lock(); |
| | | while (m_size <= 0) |
| | | { |
| | | |
| | | if (!m_cond.wait(m_mutex.get())) |
| | | { |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | m_front = (m_front + 1) % m_max_size; |
| | | item = m_array[m_front]; |
| | | m_size--; |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | |
| | | //å¢å äºè¶
æ¶å¤ç |
| | | bool pop(T &item, int ms_timeout) |
| | | { |
| | | struct timespec t = {0, 0}; |
| | | struct timeval now = {0, 0}; |
| | | gettimeofday(&now, NULL); |
| | | m_mutex.lock(); |
| | | if (m_size <= 0) |
| | | { |
| | | t.tv_sec = now.tv_sec + ms_timeout / 1000; |
| | | t.tv_nsec = (ms_timeout % 1000) * 1000; |
| | | if (!m_cond.timewait(m_mutex.get(), t)) |
| | | { |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | if (m_size <= 0) |
| | | { |
| | | m_mutex.unlock(); |
| | | return false; |
| | | } |
| | | |
| | | m_front = (m_front + 1) % m_max_size; |
| | | item = m_array[m_front]; |
| | | m_size--; |
| | | m_mutex.unlock(); |
| | | return true; |
| | | } |
| | | |
| | | private: |
| | | locker m_mutex; |
| | | cond m_cond; |
| | | |
| | | T *m_array; |
| | | int m_size; |
| | | int m_max_size; |
| | | int m_front; |
| | | int m_back; |
| | | }; |
| | | |
| | | #endif |
New file |
| | |
| | | #include <string.h> |
| | | #include <time.h> |
| | | #include <sys/time.h> |
| | | #include <stdarg.h> |
| | | #include "log.h" |
| | | #include <pthread.h> |
| | | using namespace std; |
| | | |
| | | Log::Log() |
| | | { |
| | | m_count = 0; |
| | | m_is_async = false; |
| | | } |
| | | |
| | | Log::~Log() |
| | | { |
| | | if (m_fp != NULL) |
| | | { |
| | | fclose(m_fp); |
| | | } |
| | | } |
| | | //弿¥éè¦è®¾ç½®é»å¡éåçé¿åº¦ï¼åæ¥ä¸éè¦è®¾ç½® |
| | | bool Log::init(const char *file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size) |
| | | { |
| | | //å¦æè®¾ç½®äºmax_queue_size,åè®¾ç½®ä¸ºå¼æ¥ |
| | | if (max_queue_size >= 1) |
| | | { |
| | | m_is_async = true; |
| | | m_log_queue = new block_queue<string>(max_queue_size); |
| | | pthread_t tid; |
| | | //flush_log_thread为åè°å½æ°,è¿é表示å建线ç¨å¼æ¥åæ¥å¿ |
| | | pthread_create(&tid, NULL, flush_log_thread, NULL); |
| | | } |
| | | |
| | | m_close_log = close_log; |
| | | m_log_buf_size = log_buf_size; |
| | | m_buf = new char[m_log_buf_size]; |
| | | memset(m_buf, '\0', m_log_buf_size); |
| | | m_split_lines = split_lines; |
| | | |
| | | time_t t = time(NULL); |
| | | struct tm *sys_tm = localtime(&t); |
| | | struct tm my_tm = *sys_tm; |
| | | |
| | | |
| | | const char *p = strrchr(file_name, '/'); |
| | | char log_full_name[256] = {0}; |
| | | |
| | | if (p == NULL) |
| | | { |
| | | snprintf(log_full_name, 255, "%d_%02d_%02d_%s", my_tm.tm_year + 1900, my_tm.tm_mon + 1, my_tm.tm_mday, file_name); |
| | | } |
| | | else |
| | | { |
| | | strcpy(log_name, p + 1); |
| | | strncpy(dir_name, file_name, p - file_name + 1); |
| | | snprintf(log_full_name, 255, "%s%d_%02d_%02d_%s", dir_name, my_tm.tm_year + 1900, my_tm.tm_mon + 1, my_tm.tm_mday, log_name); |
| | | } |
| | | |
| | | m_today = my_tm.tm_mday; |
| | | |
| | | m_fp = fopen(log_full_name, "a"); |
| | | if (m_fp == NULL) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | void Log::write_log(int level, const char *format, ...) |
| | | { |
| | | struct timeval now = {0, 0}; |
| | | gettimeofday(&now, NULL); |
| | | time_t t = now.tv_sec; |
| | | struct tm *sys_tm = localtime(&t); |
| | | struct tm my_tm = *sys_tm; |
| | | char s[16] = {0}; |
| | | switch (level) |
| | | { |
| | | case 0: |
| | | strcpy(s, "[debug]:"); |
| | | break; |
| | | case 1: |
| | | strcpy(s, "[info]:"); |
| | | break; |
| | | case 2: |
| | | strcpy(s, "[warn]:"); |
| | | break; |
| | | case 3: |
| | | strcpy(s, "[erro]:"); |
| | | break; |
| | | default: |
| | | strcpy(s, "[info]:"); |
| | | break; |
| | | } |
| | | //åå
¥ä¸ä¸ªlogï¼å¯¹m_count++, m_split_linesæå¤§è¡æ° |
| | | m_mutex.lock(); |
| | | m_count++; |
| | | |
| | | if (m_today != my_tm.tm_mday || m_count % m_split_lines == 0) //everyday log |
| | | { |
| | | |
| | | char new_log[256] = {0}; |
| | | fflush(m_fp); |
| | | fclose(m_fp); |
| | | char tail[16] = {0}; |
| | | |
| | | snprintf(tail, 16, "%d_%02d_%02d_", my_tm.tm_year + 1900, my_tm.tm_mon + 1, my_tm.tm_mday); |
| | | |
| | | if (m_today != my_tm.tm_mday) |
| | | { |
| | | snprintf(new_log, 255, "%s%s%s", dir_name, tail, log_name); |
| | | m_today = my_tm.tm_mday; |
| | | m_count = 0; |
| | | } |
| | | else |
| | | { |
| | | snprintf(new_log, 255, "%s%s%s.%lld", dir_name, tail, log_name, m_count / m_split_lines); |
| | | } |
| | | m_fp = fopen(new_log, "a"); |
| | | } |
| | | |
| | | m_mutex.unlock(); |
| | | |
| | | va_list valst; |
| | | va_start(valst, format); |
| | | |
| | | string log_str; |
| | | m_mutex.lock(); |
| | | |
| | | //åå
¥çå
·ä½æ¶é´å
å®¹æ ¼å¼ |
| | | int n = snprintf(m_buf, 48, "%d-%02d-%02d %02d:%02d:%02d.%06ld %s ", |
| | | my_tm.tm_year + 1900, my_tm.tm_mon + 1, my_tm.tm_mday, |
| | | my_tm.tm_hour, my_tm.tm_min, my_tm.tm_sec, now.tv_usec, s); |
| | | |
| | | int m = vsnprintf(m_buf + n, m_log_buf_size - n - 1, format, valst); |
| | | m_buf[n + m] = '\n'; |
| | | m_buf[n + m + 1] = '\0'; |
| | | log_str = m_buf; |
| | | |
| | | m_mutex.unlock(); |
| | | |
| | | if (m_is_async && !m_log_queue->full()) |
| | | { |
| | | m_log_queue->push(log_str); |
| | | } |
| | | else |
| | | { |
| | | m_mutex.lock(); |
| | | fputs(log_str.c_str(), m_fp); |
| | | m_mutex.unlock(); |
| | | } |
| | | |
| | | va_end(valst); |
| | | } |
| | | |
| | | void Log::flush(void) |
| | | { |
| | | m_mutex.lock(); |
| | | //强å¶å·æ°åå
¥æµç¼å²åº |
| | | fflush(m_fp); |
| | | m_mutex.unlock(); |
| | | } |
New file |
| | |
| | | #ifndef LOG_H |
| | | #define LOG_H |
| | | |
| | | #include <stdio.h> |
| | | #include <iostream> |
| | | #include <string> |
| | | #include <stdarg.h> |
| | | #include <pthread.h> |
| | | #include "block_queue.h" |
| | | |
| | | using namespace std; |
| | | |
| | | class Log |
| | | { |
| | | public: |
| | | //C++11以å,使ç¨å±é¨åéææ±ä¸ç¨å é |
| | | static Log *get_instance() |
| | | { |
| | | static Log instance; |
| | | return &instance; |
| | | } |
| | | |
| | | static void *flush_log_thread(void *args) |
| | | { |
| | | Log::get_instance()->async_write_log(); |
| | | } |
| | | //å¯éæ©çåæ°ææ¥å¿æä»¶ãæ¥å¿ç¼å²åºå¤§å°ãæå¤§è¡æ°ä»¥åæé¿æ¥å¿æ¡éå |
| | | bool init(const char *file_name, int close_log, int log_buf_size = 8192, int split_lines = 5000000, int max_queue_size = 0); |
| | | |
| | | void write_log(int level, const char *format, ...); |
| | | |
| | | void flush(void); |
| | | |
| | | private: |
| | | Log(); |
| | | virtual ~Log(); |
| | | void *async_write_log() |
| | | { |
| | | string single_log; |
| | | //ä»é»å¡éåä¸ååºä¸ä¸ªæ¥å¿stringï¼åå
¥æä»¶ |
| | | while (m_log_queue->pop(single_log)) |
| | | { |
| | | m_mutex.lock(); |
| | | fputs(single_log.c_str(), m_fp); |
| | | m_mutex.unlock(); |
| | | } |
| | | } |
| | | |
| | | private: |
| | | char dir_name[128]; //è·¯å¾å |
| | | char log_name[128]; //logæä»¶å |
| | | int m_split_lines; //æ¥å¿æå¤§è¡æ° |
| | | int m_log_buf_size; //æ¥å¿ç¼å²åºå¤§å° |
| | | long long m_count; //æ¥å¿è¡æ°è®°å½ |
| | | int m_today; //å 为æå¤©åç±»,è®°å½å½åæ¶é´æ¯é£ä¸å¤© |
| | | FILE *m_fp; //æå¼logçæä»¶æé |
| | | char *m_buf; |
| | | block_queue<string> *m_log_queue; //é»å¡éå |
| | | bool m_is_async; //æ¯å¦åæ¥æ å¿ä½ |
| | | locker m_mutex; |
| | | int m_close_log; //å
³éæ¥å¿ |
| | | }; |
| | | |
| | | #define LOG_DEBUG(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(0, format, ##__VA_ARGS__); Log::get_instance()->flush();} |
| | | #define LOG_INFO(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(1, format, ##__VA_ARGS__); Log::get_instance()->flush();} |
| | | #define LOG_WARN(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(2, format, ##__VA_ARGS__); Log::get_instance()->flush();} |
| | | #define LOG_ERROR(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(3, format, ##__VA_ARGS__); Log::get_instance()->flush();} |
| | | |
| | | #endif |