Skip to content
Permalink
Browse files

fixed RT and percolate indexes rotate of config settings and index ro…

…tation and reload; fixed #675

tighten g_tRotateConfigMutex to prevent deadlock between CheckRotate and RotationThreadFunc->PreallocNewIndex
fixed index hash replace of existed index; added regression to gtest
  • Loading branch information...
tomatolog committed Feb 20, 2019
1 parent a84d540 commit 8af810111b8e2f87bc9f378172eff1ab9725c7e7
Showing with 67 additions and 19 deletions.
  1. +19 −0 src/gtests_searchdaemon.cpp
  2. +47 −19 src/searchd.cpp
  3. +1 −0 src/searchdaemon.h
@@ -562,6 +562,25 @@ TEST ( T_IndexHash, served_hash_and_getter )
ASSERT_EQ ( pFoo->GetRefcount (), 1 ) << "we're the only owner now";
}


TEST ( T_IndexHash, served_hash_add_or_replace )
{
auto pHash = new GuardedHash_c;
ServedDesc_t tDesc;

// crash of AddOrReplace after Delete
ServedIndex_c * pIdx1 = new ServedIndex_c ( tDesc );
ServedIndex_c * pIdx2 = new ServedIndex_c ( tDesc );
ASSERT_TRUE ( pHash->AddUniq ( pIdx1, "idx1" ) );

// case itself
ASSERT_TRUE ( pHash->Delete ( "idx1" ) );
pHash->AddOrReplace ( pIdx2, "idx1" );

// cleanup
ASSERT_TRUE ( pHash->Delete ( "idx1" ) );
}

TEST ( T_IndexHash, ensure_right_refcounting )
{
auto pHash = new GuardedHash_c;
@@ -962,12 +962,16 @@ bool GuardedHash_c::AddUniq ( ISphRefcountedMT * pValue, const CSphString &tKey
void GuardedHash_c::AddOrReplace ( ISphRefcountedMT * pValue, const CSphString &tKey )
{
ScWL_t hHashWLock { m_tIndexesRWLock };
// add new unique
ISphRefcountedMT * &pVal = m_hIndexes.AddUnique ( tKey );
ISphRefcountedMT * pExisted = pVal;
pVal = pValue;
if ( pExisted!=pValue )
SafeRelease ( pExisted );
// can not use AddUnique as new inserted item has no values
ISphRefcountedMT ** ppEntry = m_hIndexes ( tKey );
if ( ppEntry )
{
SafeRelease ( *ppEntry );
(*ppEntry) = pValue;
} else
{
Verify ( m_hIndexes.Add ( pValue, tKey ) );
}
}

// check if hash contains an entry
ThreadSystem_t tThdSystemDesc ( "ROTATION" );

CSphString sIndex;
bool bMutable = false;
{
ServedIndexRefPtr_c pIndex ( nullptr );
// scope for g_pDisabledIndexes
sIndex = it.GetName ();
pIndex = it.Get();
}
assert ( g_pLocalIndexes->Contains ( sIndex ) );

if ( pIndex ) // that is rt/percolate. Plain locals has just name and nullptr index
{
ServedDescRPtr_c tLocked ( pIndex );
// FIXME!!! RT and percolate can not rotate along with replicator adding indexes
if ( tLocked->IsMutable () )
continue;
{
ServedDescRPtr_c tLocked ( pIndex );
bMutable = tLocked->IsMutable ();
// cluster indexes got managed by different path
if ( tLocked->IsCluster() )
continue;
}

// prealloc RT and percolate here
if ( bMutable )
{
ServedDescWPtr_c wLocked ( pIndex );
if ( PreallocNewIndex ( *wLocked, sIndex.cstr() ) )
{
wLocked->m_bOnlyNew = false;
g_pLocalIndexes->AddOrReplace ( pIndex, sIndex );
pIndex->AddRef ();
} else
{
g_pLocalIndexes->DeleteIfNull ( sIndex );
}
}
}
}

CSphString sError;
if ( !RotateIndexMT ( sIndex, sError ) )
sphWarning ( "%s", sError.cstr () );
if ( !bMutable )
{
CSphString sError;
if ( !RotateIndexMT ( sIndex, sError ) )
sphWarning ( "%s", sError.cstr () );
}

g_pDistIndexes->Delete ( sIndex ); // postponed delete of same-named distributed (if any)
g_pDisabledIndexes->Delete ( sIndex );
SmallStringHash_T<bool> dLocalToDelete;
for ( RLockedServedIt_c it ( g_pLocalIndexes ); it.Next (); )
{
// skip JSON indexes - no need to delete them
// skip JSON indexes or indexes belong to cluster - no need to manage them
ServedDescRPtr_c pServed ( it.Get() );
if ( pServed && pServed->m_bJson )
if ( pServed && pServed->IsCluster() )
continue;

dLocalToDelete.Add ( true, it.GetName() );
// fixme! disabled hash protected by g_bInRotate exclusion,
// what about more explicit protection?
g_pDisabledIndexes->ReleaseAndClear ();
ScWL_t dRotateConfigMutexWlocked { g_tRotateConfigMutex };
if ( CheckConfigChanges () )
ReloadIndexSettings ( g_pCfg );
{
ScWL_t dRotateConfigMutexWlocked { g_tRotateConfigMutex };
if ( CheckConfigChanges () )
ReloadIndexSettings ( g_pCfg );
}

// special pass for 'simple' rotation (i.e. *.new to current)
for ( RLockedServedIt_c it ( g_pLocalIndexes ); it.Next (); )

if ( !g_bSeamlessRotate )
{
ScRL_t tRotateConfigMutex { g_tRotateConfigMutex };
for ( RLockedServedIt_c it ( g_pDisabledIndexes ); it.Next(); )
{
auto pIndex = it.Get();
@@ -674,6 +674,7 @@ struct ServedDesc_t
CSphString m_sCluster;

inline bool IsMutable () const { return m_eType==IndexType_e::RT || m_eType==IndexType_e::PERCOLATE; }
bool IsCluster () const { return m_bJson || !m_sCluster.IsEmpty(); }
virtual ~ServedDesc_t ();
};

0 comments on commit 8af8101

Please sign in to comment.
You can’t perform that action at this time.