Warrior_EA/Database/DatabaseConnectionManager.mqh
AnimateDread d7eea325fb refactor(ai): extract Layer.mqh and deduplicate AI config
- Moves CLayer neuron construction to AI/Impl/Layer.mqh to keep Network.mqh clean
- Unifies four previously duplicated architecture initialisation blocks (MLP/CONV/LSTM/HYBRID) into a single shared function
- Eliminates risk of behavioural drift where one architecture missed a setter, causing mismatched feature sets or targets
2026-08-01 11:27:28 -04:00

127 lines
4.5 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
#include "..\\System\\PrintVerbose.mqh"
class CDatabaseConnectionManager
{
private:
bool m_transactionActive;
int m_databaseHandle;
string m_dbPath;
bool m_verboseMode;
public:
CDatabaseConnectionManager(bool verbose = false)
{
m_transactionActive = false;
m_verboseMode = verbose;
m_databaseHandle = INVALID_HANDLE;
}
bool Init(string path)
{
m_dbPath = path;
return (true);
}
int GetDatabaseHandle()
{
return m_databaseHandle;
}
bool OpenDatabase()
{
if(m_databaseHandle != INVALID_HANDLE)
{
if(m_verboseMode)
PrintVerbose("Database is already open.");
return true;
}
int attempts = 0;
while(attempts < 5)
{
m_databaseHandle = DatabaseOpen(m_dbPath, DATABASE_OPEN_COMMON | DATABASE_OPEN_CREATE | DATABASE_OPEN_READWRITE);
if(m_databaseHandle != INVALID_HANDLE)
{
return true;
}
Print("Attempt " + IntegerToString(attempts + 1) + " failed to open database.");
Sleep(1000); // Wait for a second before retrying
attempts++;
}
Print("Database open failed after retries.");
return false;
}
bool CloseDatabase()
{
if(m_databaseHandle != INVALID_HANDLE)
{
DatabaseClose(m_databaseHandle);
m_databaseHandle = INVALID_HANDLE;
}
//--- MUST clear this with the handle. DatabaseClose() finalises whatever transaction was open, so
//--- leaving the flag set left the object claiming an active transaction against a handle that no
//--- longer exists: the next TransactionCommit()/Rollback() would sail past its own
//--- !m_transactionActive early-return and call the API on INVALID_HANDLE.
m_transactionActive = false;
return(true);
}
//--- Every transaction call below validates the handle first. OpenDatabase() returns false after its
//--- retries are exhausted, but a caller that ignores that return would otherwise pass INVALID_HANDLE
//--- straight into the DatabaseTransaction* API, whose failure then reads as "the transaction failed"
//--- rather than "there is no database" - two very different faults to chase in a log.
bool TransactionBegin()
{
if(m_databaseHandle == INVALID_HANDLE)
{
Print("TransactionBegin: no open database (handle is INVALID_HANDLE) - did OpenDatabase() fail?");
return(false);
}
if(!DatabaseTransactionBegin(m_databaseHandle))
{
Print("DatabaseTransactionBegin failed.");
return(false);
}
else
m_transactionActive = true;
return(true);
}
bool TransactionCommit()
{
if(!m_transactionActive)
return(true);
if(m_databaseHandle == INVALID_HANDLE)
{
Print("TransactionCommit: database handle is INVALID_HANDLE - dropping the pending transaction.");
m_transactionActive = false;
return(false);
}
if(!DatabaseTransactionCommit(m_databaseHandle))
{
Print("DatabaseTransactionCommit failed. Reverting changes...");
TransactionRollback();
m_transactionActive = false;
return(false);
}
m_transactionActive = false;
return(true);
}
bool TransactionRollback()
{
if(!m_transactionActive)
return(true);
if(m_databaseHandle == INVALID_HANDLE)
{
Print("TransactionRollback: database handle is INVALID_HANDLE - dropping the pending transaction.");
m_transactionActive = false;
return(false);
}
if(!DatabaseTransactionRollback(m_databaseHandle))
{
Print("DatabaseTransactionRollback failed.");
return(false);
}
m_transactionActive = false;
return(true);
}
};
//+------------------------------------------------------------------+