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