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