2025-05-30 16:35:54 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CDatabaseVersionManager
|
| | | {
|
 refactor(db): dedupe the 5x/1s retry loop in FileSystemManager + VersionManager
CDatabaseFileSystemManager's CreateDirectory/CleanDirectory/DeleteFile had
three identical retry loops differing only in which FolderCreate/FolderClean/
FileDelete ran and the noun in the log line - collapsed into one
RetryFileSystemOp(enum, target, verb, caller) private helper, dispatched by
enum rather than a function pointer (MQL5 function pointers to a built-in
with default params is untested territory, not worth it for 3 one-liners).
CDatabaseVersionManager's ReadStoredDbVersion/UpdateStoredDbVersion had the
same retry shape around FileOpen, differing only in the open flags and the
reading/writing noun - collapsed into OpenVersionFileWithRetry(path, flags,
verb).
CDatabaseConnectionManager::OpenDatabase (the 6th instance the finding named)
is the only retry loop in its file - no in-file duplication to fix there, and
sharing it with the other two would need a cross-class free function bound to
DatabaseOpen/FileOpen as function pointers, an untested construct for a
20-line win. Left as-is.
Every Print() message text verified identical at each call site; public
method signatures unchanged, no external caller needed a rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:25:34 -04:00 | | | private:
|
| | | //--- Read/Update both open this FILE_COMMON version file with the same 5-attempt/1s-sleep retry,
|
| | | //--- differing only in the open flags and the "reading"/"writing" noun in the log line.
|
| | | // FILE_SHARE_READ|FILE_SHARE_WRITE required - this file is FILE_COMMON (shared across every
|
| | | // chart instance/symbol), so without share flags a second instance's open can be blocked by
|
| | | // the first's exclusive handle, exhausting these retries and (via the ERROR sentinel below)
|
| | | // potentially triggering a version-mismatch CleanDirectory() that wipes the shared DB folder.
|
| | | int OpenVersionFileWithRetry(string versionFilePath, int openFlags, string verb)
|
2025-05-30 16:35:54 +02:00 | | | {
|
| | | int fileHandle = INVALID_HANDLE; // Initialize to a safe value
|
| | | int attempts = 0;
|
| | | while(attempts < 5)
|
| | | {
|
 refactor(db): dedupe the 5x/1s retry loop in FileSystemManager + VersionManager
CDatabaseFileSystemManager's CreateDirectory/CleanDirectory/DeleteFile had
three identical retry loops differing only in which FolderCreate/FolderClean/
FileDelete ran and the noun in the log line - collapsed into one
RetryFileSystemOp(enum, target, verb, caller) private helper, dispatched by
enum rather than a function pointer (MQL5 function pointers to a built-in
with default params is untested territory, not worth it for 3 one-liners).
CDatabaseVersionManager's ReadStoredDbVersion/UpdateStoredDbVersion had the
same retry shape around FileOpen, differing only in the open flags and the
reading/writing noun - collapsed into OpenVersionFileWithRetry(path, flags,
verb).
CDatabaseConnectionManager::OpenDatabase (the 6th instance the finding named)
is the only retry loop in its file - no in-file duplication to fix there, and
sharing it with the other two would need a cross-class free function bound to
DatabaseOpen/FileOpen as function pointers, an untested construct for a
20-line win. Left as-is.
Every Print() message text verified identical at each call site; public
method signatures unchanged, no external caller needed a rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:25:34 -04:00 | | | fileHandle = FileOpen(versionFilePath, openFlags);
|
2025-05-30 16:35:54 +02:00 | | | if(fileHandle != INVALID_HANDLE)
|
| | | {
|
| | | break; // Success, break out of the loop
|
| | | }
|
 refactor(db): dedupe the 5x/1s retry loop in FileSystemManager + VersionManager
CDatabaseFileSystemManager's CreateDirectory/CleanDirectory/DeleteFile had
three identical retry loops differing only in which FolderCreate/FolderClean/
FileDelete ran and the noun in the log line - collapsed into one
RetryFileSystemOp(enum, target, verb, caller) private helper, dispatched by
enum rather than a function pointer (MQL5 function pointers to a built-in
with default params is untested territory, not worth it for 3 one-liners).
CDatabaseVersionManager's ReadStoredDbVersion/UpdateStoredDbVersion had the
same retry shape around FileOpen, differing only in the open flags and the
reading/writing noun - collapsed into OpenVersionFileWithRetry(path, flags,
verb).
CDatabaseConnectionManager::OpenDatabase (the 6th instance the finding named)
is the only retry loop in its file - no in-file duplication to fix there, and
sharing it with the other two would need a cross-class free function bound to
DatabaseOpen/FileOpen as function pointers, an untested construct for a
20-line win. Left as-is.
Every Print() message text verified identical at each call site; public
method signatures unchanged, no external caller needed a rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:25:34 -04:00 | | | Print("Retry " + IntegerToString(attempts + 1) + " failed to open file for " + verb + ": " + versionFilePath + " (error " + IntegerToString(GetLastError()) + ")");
|
2025-05-30 16:35:54 +02:00 | | | Sleep(1000); // Wait for a second before retrying
|
| | | attempts++;
|
| | | }
|
| | | if(fileHandle == INVALID_HANDLE)
|
 refactor(db): dedupe the 5x/1s retry loop in FileSystemManager + VersionManager
CDatabaseFileSystemManager's CreateDirectory/CleanDirectory/DeleteFile had
three identical retry loops differing only in which FolderCreate/FolderClean/
FileDelete ran and the noun in the log line - collapsed into one
RetryFileSystemOp(enum, target, verb, caller) private helper, dispatched by
enum rather than a function pointer (MQL5 function pointers to a built-in
with default params is untested territory, not worth it for 3 one-liners).
CDatabaseVersionManager's ReadStoredDbVersion/UpdateStoredDbVersion had the
same retry shape around FileOpen, differing only in the open flags and the
reading/writing noun - collapsed into OpenVersionFileWithRetry(path, flags,
verb).
CDatabaseConnectionManager::OpenDatabase (the 6th instance the finding named)
is the only retry loop in its file - no in-file duplication to fix there, and
sharing it with the other two would need a cross-class free function bound to
DatabaseOpen/FileOpen as function pointers, an untested construct for a
20-line win. Left as-is.
Every Print() message text verified identical at each call site; public
method signatures unchanged, no external caller needed a rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:25:34 -04:00 | | | Print("Failed to open file for " + verb + " after retries: " + versionFilePath + " (error " + IntegerToString(GetLastError()) + ")");
|
| | | return fileHandle;
|
| | | }
|
| | |
|
| | | public:
|
| | | string ReadStoredDbVersion(string versionFilePath)
|
| | | {
|
| | | if(!FileIsExist(versionFilePath, FILE_COMMON))
|
| | | return "NA";
|
| | | int fileHandle = OpenVersionFileWithRetry(versionFilePath, FILE_COMMON | FILE_READ | FILE_SHARE_READ | FILE_SHARE_WRITE, "reading");
|
| | | if(fileHandle == INVALID_HANDLE)
|
2025-05-30 16:35:54 +02:00 | | | return "ERROR";
|
| | | string dbVersion = FileReadString(fileHandle);
|
| | | FileClose(fileHandle);
|
| | | return dbVersion;
|
| | | }
|
| | |
|
| | | bool UpdateStoredDbVersion(string versionFilePath, string dbVersion)
|
| | | {
|
 refactor(db): dedupe the 5x/1s retry loop in FileSystemManager + VersionManager
CDatabaseFileSystemManager's CreateDirectory/CleanDirectory/DeleteFile had
three identical retry loops differing only in which FolderCreate/FolderClean/
FileDelete ran and the noun in the log line - collapsed into one
RetryFileSystemOp(enum, target, verb, caller) private helper, dispatched by
enum rather than a function pointer (MQL5 function pointers to a built-in
with default params is untested territory, not worth it for 3 one-liners).
CDatabaseVersionManager's ReadStoredDbVersion/UpdateStoredDbVersion had the
same retry shape around FileOpen, differing only in the open flags and the
reading/writing noun - collapsed into OpenVersionFileWithRetry(path, flags,
verb).
CDatabaseConnectionManager::OpenDatabase (the 6th instance the finding named)
is the only retry loop in its file - no in-file duplication to fix there, and
sharing it with the other two would need a cross-class free function bound to
DatabaseOpen/FileOpen as function pointers, an untested construct for a
20-line win. Left as-is.
Every Print() message text verified identical at each call site; public
method signatures unchanged, no external caller needed a rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:25:34 -04:00 | | | int fileHandle = OpenVersionFileWithRetry(versionFilePath, FILE_COMMON | FILE_WRITE | FILE_SHARE_READ | FILE_SHARE_WRITE, "writing");
|
2025-05-30 16:35:54 +02:00 | | | if(fileHandle == INVALID_HANDLE)
|
| | | return false;
|
| | | FileWriteString(fileHandle, dbVersion);
|
| | | FileClose(fileHandle);
|
| | | return true;
|
| | | }
|
| | | };
|
| | | //+------------------------------------------------------------------+
|