diff --git a/src/coroutine.cpp b/src/coroutine.cpp index b448f515b0..cc68f3a5bd 100644 --- a/src/coroutine.cpp +++ b/src/coroutine.cpp @@ -967,7 +967,7 @@ bool WaitQueue_c::SuspendAndWaitUntil ( sph::Spinlock_lock& tLock, Worker_c* pAc }); // resumed. Check if deadline is reached - if ( sph::TimeExceeded ( iTimestamp ) ) + if ( sph::TimeExceeded ( iTimestamp ) || sphInterrupted () ) { tLock.lock(); // remove from waiting-queue @@ -976,6 +976,7 @@ bool WaitQueue_c::SuspendAndWaitUntil ( sph::Spinlock_lock& tLock, Worker_c* pAc tLock.unlock(); return false; } + assert ( !w.is_linked () ); return true; } diff --git a/src/searchd.cpp b/src/searchd.cpp index d60c160da6..6c2b179b48 100644 --- a/src/searchd.cpp +++ b/src/searchd.cpp @@ -15637,7 +15637,14 @@ void HandleMysqlOptimize ( RowBuffer_i & tOut, const SqlStmt_t & tStmt ) tTask.m_eVerb = OptimizeTask_t::eManualOptimize; tTask.m_iCutoff = tStmt.m_tQuery.m_iCutoff<=0 ? 0 : tStmt.m_tQuery.m_iCutoff; - RIdx_T ( pIndex )->StartOptimize ( std::move ( tTask ) ); + auto bOptimizeStarted = RIdx_T ( pIndex )->StartOptimize ( std::move ( tTask ) ); + + if ( tStmt.m_tQuery.m_bSync && !bOptimizeStarted ) + { + tOut.Error ( "Can't optimize frozen table" ); + return; + } + if ( tStmt.m_tQuery.m_bSync && !PollOptimizeRunning ( sIndex ) ) tOut.Error ( "RT table went away during waiting" ); else diff --git a/src/sphinxrt.cpp b/src/sphinxrt.cpp index 93b17a7bac..437ddd7114 100644 --- a/src/sphinxrt.cpp +++ b/src/sphinxrt.cpp @@ -1194,13 +1194,17 @@ class SaveState_c // sleep and return false if index's shutdown happened. bool WaitEnabledOrShutdown () const noexcept { - return !m_tValue.Wait ( [&] ( const Value_t& tVal ) { - if ( tVal.m_bShutdown ) - return true; - if ( tVal.m_eValue != States_e::ENABLED ) - return false; - return tVal.m_iDisabledCounter == 0; - }).m_bShutdown; + while (true) { + auto tVal = m_tValue.WaitForMs ( [&] ( const Value_t& tVal ) { + if ( tVal.m_bShutdown ) + return true; + if ( tVal.m_eValue!=States_e::ENABLED ) + return false; + return tVal.m_iDisabledCounter==0; + }, 10000 ); // time doesn't matter, as shutdown abandons all timers + if ( tVal.m_bShutdown || sphInterrupted() || tVal.m_iDisabledCounter==0 ) + return !tVal.m_bShutdown; + } } int GetNumOfLocks() const noexcept @@ -1246,7 +1250,7 @@ class RtIndex_c final : public RtIndex_i, public ISphNoncopyable, public ISphWor bool Truncate ( CSphString & sError, Truncate_e eAction ) final; bool CheckValidateOptimizeParams ( OptimizeTask_t& tTask ) const; bool CheckValidateChunk ( int& iChunk, int iChunks, bool bByOrder ) const; - void StartOptimize ( OptimizeTask_t tTask ) final; + bool StartOptimize ( OptimizeTask_t tTask ) final; int OptimizesRunning() const noexcept final; void Optimize ( OptimizeTask_t tTask ) final; void CheckStartAutoOptimize (); @@ -9872,13 +9876,17 @@ bool RtIndex_c::CheckValidateOptimizeParams ( OptimizeTask_t& tTask ) const } -void RtIndex_c::StartOptimize ( OptimizeTask_t tTask ) +bool RtIndex_c::StartOptimize ( OptimizeTask_t tTask ) { + if ( m_tSaving.GetNumOfLocks ()>0 ) + return false; + Threads::StartJob ( [tTask = std::move ( tTask ), this] () { // want to track optimize only at work auto pDesc = PublishSystemInfo ( "OPTIMIZE" ); Optimize ( std::move ( tTask ) ); } ); + return true; } diff --git a/src/sphinxrt.h b/src/sphinxrt.h index 98c65b7a0b..2b83eed278 100644 --- a/src/sphinxrt.h +++ b/src/sphinxrt.h @@ -149,7 +149,7 @@ class RtIndex_i : public CSphIndexStub virtual bool Truncate ( CSphString & sError, Truncate_e eAction ) = 0; virtual void Optimize ( OptimizeTask_t tTask ) {} - virtual void StartOptimize ( OptimizeTask_t tTask ) {} + virtual bool StartOptimize ( OptimizeTask_t tTask ) { return true; } virtual int OptimizesRunning () const noexcept { return 0; } /// check settings vs current and return back tokenizer and dictionary in case of difference diff --git a/test/test_287/model.bin b/test/test_287/model.bin new file mode 100644 index 0000000000..d173ecb6b6 --- /dev/null +++ b/test/test_287/model.bin @@ -0,0 +1 @@ +a:1:{i:0;a:6:{i:0;a:2:{s:8:"sphinxql";s:25:"drop table if exists test";s:14:"total_affected";i:0;}i:1;a:2:{s:8:"sphinxql";s:17:"create table test";s:14:"total_affected";i:0;}i:2;a:2:{s:8:"sphinxql";s:23:"freeze test like 'fake'";s:10:"total_rows";i:0;}i:3;a:3:{s:8:"sphinxql";s:33:"optimize table test option sync=1";s:5:"errno";i:1064;s:5:"error";s:27:"Can't optimize frozen table";}i:4;a:2:{s:8:"sphinxql";s:13:"unfreeze test";s:14:"total_affected";i:1;}i:5;a:2:{s:8:"sphinxql";s:15:"drop table test";s:14:"total_affected";i:0;}}} \ No newline at end of file diff --git a/test/test_287/test.xml b/test/test_287/test.xml new file mode 100644 index 0000000000..e17a5f59c6 --- /dev/null +++ b/test/test_287/test.xml @@ -0,0 +1,32 @@ + + + +avoid optimize frozen + + + + + + + + +searchd +{ + + data_dir = + binlog_path = +} + + + + + drop table if exists test; + create table test; + freeze test like 'fake'; + optimize table test option sync=1; + unfreeze test; + drop table test; + + + +