1#ifndef ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
2#define ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
3
4#include <base/sphore.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
47struct CMysqlConfig
48{
49 char m_aDatabase[64];
50 char m_aPrefix[64];
51 char m_aUser[64];
52 char m_aPass[64];
53 char m_aIp[64];
54 char m_aBindaddr[128];
55 int m_Port;
56 bool m_Setup;
57};
58
59class CDbConnectionPool
60{
61public:
62 CDbConnectionPool();
63 ~CDbConnectionPool();
64 CDbConnectionPool &operator=(const CDbConnectionPool &) = delete;
65
66 // Returns false on success.
67 typedef bool (*FRead)(IDbConnection *, const ISqlData *, char *pError, int ErrorSize);
68 typedef bool (*FWrite)(IDbConnection *, const ISqlData *, Write, char *pError, int ErrorSize);
69
70 enum Mode
71 {
72 READ,
73 WRITE,
74 WRITE_BACKUP,
75 NUM_MODES,
76 };
77
78 void Print(Mode DatabaseMode);
79
80 void RegisterSqliteDatabase(Mode DatabaseMode, const char aFilename[64]);
81 void RegisterMysqlDatabase(Mode DatabaseMode, const CMysqlConfig *pMysqlConfig);
82
83 void Execute(
84 FRead pFunc,
85 std::unique_ptr<const ISqlData> pSqlRequestData,
86 const char *pName);
87 // writes to WRITE_BACKUP first and removes it from there when successfully
88 // executed on WRITE server
89 void ExecuteWrite(
90 FWrite pFunc,
91 std::unique_ptr<const ISqlData> pSqlRequestData,
92 const char *pName);
93
94 void OnShutdown();
95
96 friend class CWorker;
97 friend class CBackup;
98
99private:
100 static bool ExecSqlFunc(IDbConnection *pConnection, struct CSqlExecData *pData, Write w);
101
102 // Only the main thread accesses this variable. It points to the index,
103 // where the next query is added to the queue.
104 int m_InsertIdx = 0;
105
106 bool m_Shutdown = false;
107
108 struct CSharedData
109 {
110 // Used as signal that shutdown is in progress from main thread to
111 // speed up the queries by discarding read queries and writing to
112 // the sqlite file instead of the remote mysql server.
113 // The worker thread signals the main thread that all queries are
114 // processed by setting this variable to false again.
115 std::atomic_bool m_Shutdown{false};
116 // Queries go first to the backup thread. This semaphore signals about
117 // new queries.
118 CSemaphore m_NumBackup;
119 // When the backup thread processed the query, it signals the main
120 // thread with this semaphore about the new query
121 CSemaphore m_NumWorker;
122
123 // spsc queue with additional backup worker to look at queries first.
124 std::unique_ptr<struct CSqlExecData> m_aQueries[512];
125 };
126
127 std::shared_ptr<CSharedData> m_pShared;
128 void *m_pWorkerThread = nullptr;
129 void *m_pBackupThread = nullptr;
130};
131
132#endif // ENGINE_SERVER_DATABASES_CONNECTION_POOL_H
133