diff --git a/src/common/os/guid.h b/src/common/os/guid.h index 9c79cdd5331..3097f7ad3d8 100644 --- a/src/common/os/guid.h +++ b/src/common/os/guid.h @@ -51,8 +51,7 @@ static_assert(sizeof(UUID) == 16, "Guid size mismatch"); namespace Firebird { -const int GUID_BUFF_SIZE = 39; -const int GUID_BODY_SIZE = 36; +constexpr int GUID_BUFF_SIZE = 39; void GenerateRandomBytes(void* buffer, FB_SIZE_T size); @@ -65,8 +64,10 @@ void GenerateGuid(UUID* guid); class Guid { // Some versions of MSVC cannot recognize hh specifier but MSVC 2015 has it - static constexpr const char* GUID_FORMAT = - "{%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}"; +#define GUID_FORMAT_BASE "%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX" + static constexpr const char* GUID_FORMAT = "{" GUID_FORMAT_BASE "}"; + static constexpr const char* GUID_FORMAT_WITHOUT_BRACKETS = GUID_FORMAT_BASE; +#undef GUID_FORMAT_BASE static constexpr int GUID_FORMAT_ARGS = 11; Guid() @@ -121,25 +122,25 @@ class Guid memcpy(&m_data, buffer, SIZE); } - void toString(char* buffer) const + void toString(char* buffer, bool withBrackets = true) const { - sprintf(buffer, GUID_FORMAT, + sprintf(buffer, withBrackets ? GUID_FORMAT : GUID_FORMAT_WITHOUT_BRACKETS, m_data.Data1, m_data.Data2, m_data.Data3, m_data.Data4[0], m_data.Data4[1], m_data.Data4[2], m_data.Data4[3], m_data.Data4[4], m_data.Data4[5], m_data.Data4[6], m_data.Data4[7]); } - Firebird::string toString() const + Firebird::string toString(bool withBrackets = true) const { Firebird::string result; - toString(result.getBuffer(GUID_BUFF_SIZE - 1)); + toString(result.getBuffer(GUID_BUFF_SIZE - (withBrackets ? 1 : 3)), withBrackets); return result; } - Firebird::PathName toPathName() const + Firebird::PathName toPathName(bool withBrackets = true) const { Firebird::PathName result; - toString(result.getBuffer(GUID_BUFF_SIZE - 1)); + toString(result.getBuffer(GUID_BUFF_SIZE - (withBrackets ? 1 : 3)), withBrackets); return result; } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 84deafb4179..8d5d249be18 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -3116,6 +3116,8 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch if (attachment2) { allow_overwrite = attachment2->getHandle()->locksmith(tdbb, DROP_DATABASE); + if (allow_overwrite) + REPL_journal_cleanup(attachment2->getHandle()->att_database); attachment2->detach(user_status); } else @@ -3604,6 +3606,9 @@ void JAttachment::internalDropDatabase(CheckStatusWrapper* user_status) throw; } + // Unlink active replication segments + REPL_journal_cleanup(dbb); + // Unlink attachment from database release_attachment(tdbb, attachment, &threadGuard); att = NULL; diff --git a/src/jrd/replication/ChangeLog.cpp b/src/jrd/replication/ChangeLog.cpp index f446ea84a76..04e4d648280 100644 --- a/src/jrd/replication/ChangeLog.cpp +++ b/src/jrd/replication/ChangeLog.cpp @@ -73,7 +73,7 @@ namespace const unsigned COPY_BLOCK_SIZE = 64 * 1024; // 64 KB - const char* FILENAME_PATTERN = "%s.journal-%09" UQUADFORMAT; + const char* FILENAME_PATTERN = "%s_%s.journal-%09" UQUADFORMAT; const char* FILENAME_WILDCARD = "$(filename)"; const char* PATHNAME_WILDCARD = "$(pathname)"; @@ -885,6 +885,26 @@ void ChangeLog::bgArchiver() } } +void ChangeLog::cleanup() +{ + LockGuard guard(this); + + while (m_segments.hasData()) + { + const auto segment = m_segments.pop(); + + if (segment->getState() == SEGMENT_STATE_USED && segment->hasData()) + segment->setState(SEGMENT_STATE_FULL); + + if (segment->getState() == SEGMENT_STATE_FULL) + archiveSegment(segment); + + const PathName filename = segment->getPathName(); + segment->release(); + unlink(filename.c_str()); + } +} + void ChangeLog::initSegments() { clearSegments(); @@ -939,7 +959,7 @@ ChangeLog::Segment* ChangeLog::createSegment() const auto sequence = state->sequence + 1; PathName filename; - filename.printf(FILENAME_PATTERN, m_config->filePrefix.c_str(), sequence); + filename.printf(FILENAME_PATTERN, m_config->filePrefix.c_str(), m_guid.toString(false).c_str(), sequence); filename = m_config->journalDirectory + filename; const auto fd = os_utils::openCreateSharedFile(filename.c_str(), O_EXCL | O_BINARY); @@ -989,7 +1009,7 @@ ChangeLog::Segment* ChangeLog::reuseSegment(ChangeLog::Segment* segment) // Attempt to rename the backing file PathName newname; - newname.printf(FILENAME_PATTERN, m_config->filePrefix.c_str(), sequence); + newname.printf(FILENAME_PATTERN, m_config->filePrefix.c_str(), m_guid.toString(false).c_str(), sequence); newname = m_config->journalDirectory + newname; // If renaming fails, then we just create a new file. diff --git a/src/jrd/replication/ChangeLog.h b/src/jrd/replication/ChangeLog.h index 6bd7ec18d16..dd86c708fc1 100644 --- a/src/jrd/replication/ChangeLog.h +++ b/src/jrd/replication/ChangeLog.h @@ -213,6 +213,7 @@ namespace Replication FB_UINT64 write(ULONG length, const UCHAR* data, bool sync); void bgArchiver(); + void cleanup(); private: void initSharedFile(); diff --git a/src/jrd/replication/Manager.h b/src/jrd/replication/Manager.h index ed6f6b26e54..7e618b52ff0 100644 --- a/src/jrd/replication/Manager.h +++ b/src/jrd/replication/Manager.h @@ -88,6 +88,12 @@ namespace Replication m_changeLog->forceSwitch(); } + void journalCleanup() + { + if (m_changeLog) + m_changeLog->cleanup(); + } + const Replication::Config* getConfig() const { return m_config; diff --git a/src/jrd/replication/Publisher.cpp b/src/jrd/replication/Publisher.cpp index 2ff27076245..9315537c770 100644 --- a/src/jrd/replication/Publisher.cpp +++ b/src/jrd/replication/Publisher.cpp @@ -707,3 +707,9 @@ void REPL_journal_switch(thread_db* tdbb) replMgr->forceJournalSwitch(); } + +void REPL_journal_cleanup(Database* dbb) +{ + if (const auto replMgr = dbb->replManager(true)) + replMgr->journalCleanup(); +} diff --git a/src/jrd/replication/Publisher.h b/src/jrd/replication/Publisher.h index 547d86de6cb..7fee6ceee1c 100644 --- a/src/jrd/replication/Publisher.h +++ b/src/jrd/replication/Publisher.h @@ -27,6 +27,7 @@ namespace Jrd { class thread_db; class jrd_tra; + class Database; class Savepoint; struct record_param; } @@ -47,5 +48,6 @@ void REPL_gen_id(Jrd::thread_db* tdbb, SLONG genId, SINT64 value); void REPL_exec_sql(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction, const Firebird::string& sql, const Firebird::ObjectsArray& schemaSearchPath); void REPL_journal_switch(Jrd::thread_db* tdbb); +void REPL_journal_cleanup(Jrd::Database* dbb); #endif // JRD_REPLICATION_PUBLISHER_H