1#ifndef ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
2#define ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
3
4#include <atomic>
5#include <base/tl/threading.h>
6#include <memory>
7#include <vector>
8
9class IDbConnection;
10
11struct ISqlResult
12{
13 // using atomic_bool to indicate completed sql query since usage_count
14 // from shard_ptr isn't safe in multithreaded environment
15 // the main thread must only access the remaining result data if set to true
16 std::atomic_bool m_Completed{false};
17 // indicate whether the thread indicated a successful completion (returned true)
18 bool m_Success = false;
19
20 virtual ~ISqlResult() = default;
21};
22
23struct ISqlData
24{
25 ISqlData(std::shared_ptr<ISqlResult> pResult) :
26 m_pResult(std::move(pResult))
27 {
28 }
29 virtual ~ISqlData() = default;
30
31 mutable std::shared_ptr<ISqlResult> m_pResult;
32};
33
34enum Write
35{
36 // write everything into the backup db first
37 BACKUP_FIRST,
38 // now try to write it into remote db
39 NORMAL,
40 // succeeded writing -> remove copy from backup
41 NORMAL_SUCCEEDED,
42 // failed writing -> notify about failure
43 NORMAL_FAILED,
44};
45
46class IConsole;
47
48struct CMysqlConfig
49{
50 char m_aDatabase[64];
51 char m_aPrefix[64];
52 char m_aUser[64];
53 char m_aPass[64];
54 char m_aIp[64];
55 char m_aBindaddr[128];
56 int m_Port;
57 bool m_Setup;
58};
59
60class CDbConnectionPool
61{
62public:
63 CDbConnectionPool();
64 ~CDbConnectionPool();
65 CDbConnectionPool &operator=(const CDbConnectionPool &) = delete;
66
67 // Returns false on success.
68 typedef bool (*FRead)(IDbConnection *, const ISqlData *, char *pError, int ErrorSize);
69 typedef bool (*FWrite)(IDbConnection *, const ISqlData *, Write, char *pError, int ErrorSize);
70
71 enum Mode
72 {
73 READ,
74 WRITE,
75 WRITE_BACKUP,
76 NUM_MODES,
77 };
78
79 void Print(IConsole *pConsole, Mode DatabaseMode);
80
81 void RegisterSqliteDatabase(Mode DatabaseMode, const char FileName[64]);
82 void RegisterMysqlDatabase(Mode DatabaseMode, const CMysqlConfig *pMysqlConfig);
83
84 void Execute(
85 FRead pFunc,
86 std::unique_ptr<const ISqlData> pSqlRequestData,
87 const char *pName);
88 // writes to WRITE_BACKUP first and removes it from there when successfully
89 // executed on WRITE server
90 void ExecuteWrite(
91 FWrite pFunc,
92 std::unique_ptr<const ISqlData> pSqlRequestData,
93 const char *pName);
94
95 void OnShutdown();
96
97 friend class CWorker;
98 friend class CBackup;
99
100private:
101 static bool ExecSqlFunc(IDbConnection *pConnection, struct CSqlExecData *pData, Write w);
102
103 // Only the main thread accesses this variable. It points to the index,
104 // where the next query is added to the queue.
105 int m_InsertIdx = 0;
106
107 bool m_Shutdown = false;
108
109 struct CSharedData
110 {
111 // Used as signal that shutdown is in progress from main thread to
112 // speed up the queries by discarding read queries and writing to
113 // the sqlite file instead of the remote mysql server.
114 // The worker thread signals the main thread that all queries are
115 // processed by setting this variable to false again.
116 std::atomic_bool m_Shutdown{false};
117 // Queries go first to the backup thread. This semaphore signals about
118 // new queries.
119 CSemaphore m_NumBackup;
120 // When the backup thread processed the query, it signals the main
121 // thread with this semaphore about the new query
122 CSemaphore m_NumWorker;
123
124 // spsc queue with additional backup worker to look at queries first.
125 std::unique_ptr<struct CSqlExecData> m_aQueries[512];
126 };
127
128 std::shared_ptr<CSharedData> m_pShared;
129 void *m_pWorkerThread = nullptr;
130 void *m_pBackupThread = nullptr;
131};
132
133#endif // ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
134