From 828d139af2da35f881e2f2516f33c73c5e3a07a9 Mon Sep 17 00:00:00 2001 From: Stas Klinov Date: Thu, 17 Aug 2023 17:25:41 +0200 Subject: [PATCH] added replay of the empty binlog files with the old binlog versions; fixed Github#1364 --- src/binlog.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/binlog.cpp b/src/binlog.cpp index d054b74b7f..d980be25cd 100644 --- a/src/binlog.cpp +++ b/src/binlog.cpp @@ -151,6 +151,7 @@ class Binlog_c : public ISphNoncopyable bool m_bDisabled = true; bool m_bConfigless = false; DWORD m_uReplayFlags = 0; + bool m_bWrongVersion = false; int m_iRestartSize = 268435456; // binlog size restart threshold, 256M @@ -169,7 +170,7 @@ class Binlog_c : public ISphNoncopyable bool ReplayTxn ( Binlog::Blop_e eOp, int iBinlog, BinlogReader_c & tReader ) const; bool ReplayUpdateAttributes ( int iBinlog, BinlogReader_c & tReader ) const; bool ReplayIndexAdd ( int iBinlog, const SmallStringHash_T & hIndexes, BinlogReader_c & tReader ) const; - bool ReplayCacheAdd ( int iBinlog, BinlogReader_c & tReader ) const; + bool ReplayCacheAdd ( int iBinlog, DWORD uVersion, BinlogReader_c & tReader ) const; bool IsBinlogWritable ( int64_t * pTID = nullptr ); static bool CheckCrc ( const char * sOp, const CSphString & sIndex, int64_t iTID, int64_t iTxnPos, BinlogReader_c & tReader ) ; @@ -663,11 +664,10 @@ void Binlog_c::LoadMeta () return; // ok, so there is actual recovery data - // let's require that exact version and bitness, then - if ( uVersion!=BINLOG_VERSION ) - sphDie ( "binlog meta file %s is v.%d, binary is v.%d; recovery requires previous binary version", - sMeta.cstr(), uVersion, BINLOG_VERSION ); + // could be wrong version of the empty binlog + m_bWrongVersion = ( uVersion!=BINLOG_VERSION ); + // let's require that bitness if ( !bLoaded64bit ) sphDie ( "tables with 32-bit docids are no longer supported; recovery requires previous binary version" ); @@ -878,11 +878,11 @@ int Binlog_c::ReplayBinlog ( const SmallStringHash_T & hIndexes, int } DWORD uVersion = tReader.GetDword(); - if ( uVersion!=BINLOG_VERSION || tReader.GetErrorFlag() ) - { - Log ( REPLAY_IGNORE_TRX_ERROR, "binlog: log %s is v.%d, binary is v.%d; recovery requires previous binary version", sLog.cstr(), uVersion, BINLOG_VERSION ); - return -1; - } + if ( tReader.GetErrorFlag() ) + sphWarning ( "binlog: log io error at pos=" INT64_FMT ": %s", tReader.GetPos(), sError.cstr() ); + + // could replay empty binlog of the old version + m_bWrongVersion = ( uVersion!=BINLOG_VERSION ); ///////////// // do replay @@ -920,6 +920,12 @@ int Binlog_c::ReplayBinlog ( const SmallStringHash_T & hIndexes, int bReplayOK = false; break; } + if ( m_bWrongVersion && uOp!=ADD_CACHE ) + { + Log ( REPLAY_IGNORE_TRX_ERROR, "binlog: log %s is v.%d, binary is v.%d; recovery requires previous binary version", sLog.cstr(), uVersion, BINLOG_VERSION ); + bReplayOK = false; + break; + } // FIXME! blop might be OK but skipped (eg. index that is no longer) switch ( uOp ) @@ -936,7 +942,7 @@ int Binlog_c::ReplayBinlog ( const SmallStringHash_T & hIndexes, int break; } bHaveCacheOp = true; - bReplayOK = ReplayCacheAdd ( iBinlog, tReader ); + bReplayOK = ReplayCacheAdd ( iBinlog, uVersion, tReader ); break; case UPDATE_ATTRS: @@ -1056,7 +1062,7 @@ bool Binlog_c::ReplayIndexAdd ( int iBinlog, const SmallStringHash_T return true; } -bool Binlog_c::ReplayCacheAdd ( int iBinlog, BinlogReader_c & tReader ) const +bool Binlog_c::ReplayCacheAdd ( int iBinlog, DWORD uVersion, BinlogReader_c & tReader ) const { const int64_t iTxnPos = tReader.GetPos(); BinlogFileDesc_t & tLog = m_dLogFiles[iBinlog]; @@ -1064,6 +1070,11 @@ bool Binlog_c::ReplayCacheAdd ( int iBinlog, BinlogReader_c & tReader ) const // load data CSphVector dCache; dCache.Resize ( (int) tReader.UnzipOffset() ); // FIXME! sanity check + if ( m_bWrongVersion && dCache.GetLength() ) + { + Log ( REPLAY_IGNORE_TRX_ERROR, "binlog: log %s is v.%d, binary is v.%d; recovery requires previous binary version", tReader.GetFilename().cstr(), uVersion, BINLOG_VERSION ); + return false; + } ARRAY_FOREACH ( i, dCache ) { dCache[i].m_sName = tReader.GetString();