You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
fix(brm): This refactors shmem RWLocks operations for EM, EMIndex and FreeList so that re-map operation always takes shmem lock in Exclusive mode
--------- Co-authored-by: Roman Nozdrin <rnozdrin@mariadb.com>
This commit is contained in:
@ -1901,43 +1901,54 @@ void ExtentMap::save(const string& filename)
|
|||||||
releaseEMEntryTable(READ);
|
releaseEMEntryTable(READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This routine takes shmem RWLock in appropriate mode.
|
||||||
|
MSTEntry* ExtentMap::_getTableLock(const OPS op, std::atomic<bool>& lockedState, const int table)
|
||||||
|
{
|
||||||
|
if (op == READ)
|
||||||
|
{
|
||||||
|
return fMST.getTable_read(table);
|
||||||
|
}
|
||||||
|
// WRITE/NONE op
|
||||||
|
auto result = fMST.getTable_write(table);
|
||||||
|
lockedState = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine upgrades shmem RWlock mode if needed.
|
||||||
|
void ExtentMap::_getTableLockUpgradeIfNeeded(const OPS op, std::atomic<bool>& lockedState, const int table)
|
||||||
|
{
|
||||||
|
if (op == READ)
|
||||||
|
{
|
||||||
|
fMST.getTable_upgrade(table);
|
||||||
|
lockedState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine downgrades shmem RWlock if it was previously upgraded.
|
||||||
|
void ExtentMap::_getTableLockDowngradeIfNeeded(const OPS op, std::atomic<bool>& lockedState, const int table)
|
||||||
|
{
|
||||||
|
if (op == READ)
|
||||||
|
{
|
||||||
|
// Look releaseEMEntryTable() for the explanation why lockedState is set before the lock is downgraded.
|
||||||
|
lockedState = false;
|
||||||
|
fMST.getTable_downgrade(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* always returns holding the EM lock, and with the EM seg mapped */
|
/* always returns holding the EM lock, and with the EM seg mapped */
|
||||||
void ExtentMap::grabEMEntryTable(OPS op)
|
void ExtentMap::grabEMEntryTable(OPS op)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lk(mutex);
|
boost::mutex::scoped_lock lk(mutex);
|
||||||
|
|
||||||
if (op == READ)
|
fEMRBTreeShminfo = _getTableLock(op, emLocked, MasterSegmentTable::EMTable);
|
||||||
{
|
|
||||||
fEMRBTreeShminfo = fMST.getTable_read(MasterSegmentTable::EMTable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fEMRBTreeShminfo = fMST.getTable_write(MasterSegmentTable::EMTable);
|
|
||||||
emLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fPExtMapRBTreeImpl || fPExtMapRBTreeImpl->key() != (uint32_t)fEMRBTreeShminfo->tableShmkey)
|
if (!fPExtMapRBTreeImpl || fPExtMapRBTreeImpl->key() != (uint32_t)fEMRBTreeShminfo->tableShmkey)
|
||||||
{
|
{
|
||||||
|
_getTableLockUpgradeIfNeeded(op, emLocked, MasterSegmentTable::EMTable);
|
||||||
|
|
||||||
if (fEMRBTreeShminfo->allocdSize == 0)
|
if (fEMRBTreeShminfo->allocdSize == 0)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
growEMShmseg();
|
||||||
{
|
|
||||||
fMST.getTable_upgrade(MasterSegmentTable::EMTable);
|
|
||||||
emLocked = true;
|
|
||||||
|
|
||||||
if (fEMRBTreeShminfo->allocdSize == 0)
|
|
||||||
{
|
|
||||||
growEMShmseg();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has to be done holding the write lock.
|
|
||||||
emLocked = false;
|
|
||||||
fMST.getTable_downgrade(MasterSegmentTable::EMTable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
growEMShmseg();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1951,6 +1962,8 @@ void ExtentMap::grabEMEntryTable(OPS op)
|
|||||||
throw runtime_error("ExtentMap cannot create RBTree in shared memory segment");
|
throw runtime_error("ExtentMap cannot create RBTree in shared memory segment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getTableLockDowngradeIfNeeded(op, emLocked, MasterSegmentTable::EMTable);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1961,21 +1974,14 @@ void ExtentMap::grabEMEntryTable(OPS op)
|
|||||||
/* always returns holding the FL lock */
|
/* always returns holding the FL lock */
|
||||||
void ExtentMap::grabFreeList(OPS op)
|
void ExtentMap::grabFreeList(OPS op)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lk(mutex, boost::defer_lock);
|
boost::mutex::scoped_lock lk(mutex);
|
||||||
|
|
||||||
if (op == READ)
|
fFLShminfo = _getTableLock(op, flLocked, MasterSegmentTable::EMFreeList);
|
||||||
{
|
|
||||||
fFLShminfo = fMST.getTable_read(MasterSegmentTable::EMFreeList);
|
|
||||||
lk.lock();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fFLShminfo = fMST.getTable_write(MasterSegmentTable::EMFreeList);
|
|
||||||
flLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fPFreeListImpl || fPFreeListImpl->key() != (unsigned)fFLShminfo->tableShmkey)
|
if (!fPFreeListImpl || fPFreeListImpl->key() != (unsigned)fFLShminfo->tableShmkey)
|
||||||
{
|
{
|
||||||
|
_getTableLockUpgradeIfNeeded(op, flLocked, MasterSegmentTable::EMFreeList);
|
||||||
|
|
||||||
if (fFreeList != nullptr)
|
if (fFreeList != nullptr)
|
||||||
{
|
{
|
||||||
fFreeList = nullptr;
|
fFreeList = nullptr;
|
||||||
@ -1983,20 +1989,7 @@ void ExtentMap::grabFreeList(OPS op)
|
|||||||
|
|
||||||
if (fFLShminfo->allocdSize == 0)
|
if (fFLShminfo->allocdSize == 0)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
growFLShmseg();
|
||||||
{
|
|
||||||
lk.unlock();
|
|
||||||
fMST.getTable_upgrade(MasterSegmentTable::EMFreeList);
|
|
||||||
flLocked = true;
|
|
||||||
|
|
||||||
if (fFLShminfo->allocdSize == 0)
|
|
||||||
growFLShmseg();
|
|
||||||
|
|
||||||
flLocked = false; // has to be done holding the write lock
|
|
||||||
fMST.getTable_downgrade(MasterSegmentTable::EMFreeList);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
growFLShmseg();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2013,17 +2006,12 @@ void ExtentMap::grabFreeList(OPS op)
|
|||||||
log_errno("ExtentMap::grabFreeList(): shmat");
|
log_errno("ExtentMap::grabFreeList(): shmat");
|
||||||
throw runtime_error("ExtentMap::grabFreeList(): shmat failed. Check the error log.");
|
throw runtime_error("ExtentMap::grabFreeList(): shmat failed. Check the error log.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == READ)
|
|
||||||
lk.unlock();
|
|
||||||
}
|
}
|
||||||
|
_getTableLockDowngradeIfNeeded(op, flLocked, MasterSegmentTable::EMFreeList);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fFreeList = fPFreeListImpl->get();
|
fFreeList = fPFreeListImpl->get();
|
||||||
|
|
||||||
if (op == READ)
|
|
||||||
lk.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2031,36 +2019,20 @@ void ExtentMap::grabEMIndex(OPS op)
|
|||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lk(emIndexMutex);
|
boost::mutex::scoped_lock lk(emIndexMutex);
|
||||||
|
|
||||||
if (op == READ)
|
fEMIndexShminfo = _getTableLock(op, emIndexLocked, MasterSegmentTable::EMIndex);
|
||||||
|
|
||||||
|
if (fPExtMapIndexImpl_ && (fPExtMapIndexImpl_->getShmemImplSize() == (unsigned)fEMIndexShminfo->allocdSize))
|
||||||
{
|
{
|
||||||
fEMIndexShminfo = fMST.getTable_read(MasterSegmentTable::EMIndex);
|
return;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fEMIndexShminfo = fMST.getTable_write(MasterSegmentTable::EMIndex);
|
|
||||||
emIndexLocked = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getTableLockUpgradeIfNeeded(op, emIndexLocked, MasterSegmentTable::EMIndex);
|
||||||
|
|
||||||
if (!fPExtMapIndexImpl_)
|
if (!fPExtMapIndexImpl_)
|
||||||
{
|
{
|
||||||
if (fEMIndexShminfo->allocdSize == 0)
|
if (fEMIndexShminfo->allocdSize == 0)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
growEMIndexShmseg();
|
||||||
{
|
|
||||||
fMST.getTable_upgrade(MasterSegmentTable::EMIndex);
|
|
||||||
emIndexLocked = true;
|
|
||||||
|
|
||||||
// Checking race conditions
|
|
||||||
if (fEMIndexShminfo->allocdSize == 0)
|
|
||||||
growEMIndexShmseg();
|
|
||||||
|
|
||||||
emIndexLocked = false;
|
|
||||||
fMST.getTable_downgrade(MasterSegmentTable::EMIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
growEMIndexShmseg();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2079,13 +2051,14 @@ void ExtentMap::grabEMIndex(OPS op)
|
|||||||
fPExtMapIndexImpl_ =
|
fPExtMapIndexImpl_ =
|
||||||
ExtentMapIndexImpl::makeExtentMapIndexImpl(getInitialEMIndexShmkey(), fEMIndexShminfo->allocdSize);
|
ExtentMapIndexImpl::makeExtentMapIndexImpl(getInitialEMIndexShmkey(), fEMIndexShminfo->allocdSize);
|
||||||
}
|
}
|
||||||
|
_getTableLockDowngradeIfNeeded(op, emIndexLocked, MasterSegmentTable::EMIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtentMap::releaseEMEntryTable(OPS op)
|
void ExtentMap::_releaseTable(const OPS op, std::atomic<bool>& lockedState, const int table)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
if (op == READ)
|
||||||
{
|
{
|
||||||
fMST.releaseTable_read(MasterSegmentTable::EMTable);
|
fMST.releaseTable_read(table);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2094,33 +2067,24 @@ void ExtentMap::releaseEMEntryTable(OPS op)
|
|||||||
// here will fail is if the underlying semaphore doesn't exist anymore
|
// here will fail is if the underlying semaphore doesn't exist anymore
|
||||||
// or there is a locking logic error somewhere else. Either way,
|
// or there is a locking logic error somewhere else. Either way,
|
||||||
// declaring the EM unlocked here is OK. Same with all similar assignments.
|
// declaring the EM unlocked here is OK. Same with all similar assignments.
|
||||||
emLocked = false;
|
lockedState = false;
|
||||||
fMST.releaseTable_write(MasterSegmentTable::EMTable);
|
fMST.releaseTable_write(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtentMap::releaseEMEntryTable(OPS op)
|
||||||
|
{
|
||||||
|
_releaseTable(op, emLocked, MasterSegmentTable::EMTable);
|
||||||
|
}
|
||||||
|
|
||||||
void ExtentMap::releaseFreeList(OPS op)
|
void ExtentMap::releaseFreeList(OPS op)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
_releaseTable(op, flLocked, MasterSegmentTable::EMFreeList);
|
||||||
fMST.releaseTable_read(MasterSegmentTable::EMFreeList);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flLocked = false;
|
|
||||||
fMST.releaseTable_write(MasterSegmentTable::EMFreeList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtentMap::releaseEMIndex(OPS op)
|
void ExtentMap::releaseEMIndex(OPS op)
|
||||||
{
|
{
|
||||||
if (op == READ)
|
_releaseTable(op, emIndexLocked, MasterSegmentTable::EMIndex);
|
||||||
{
|
|
||||||
fMST.releaseTable_read(MasterSegmentTable::EMIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
emIndexLocked = false;
|
|
||||||
fMST.releaseTable_write(MasterSegmentTable::EMIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key_t ExtentMap::chooseEMShmkey()
|
key_t ExtentMap::chooseEMShmkey()
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#include <tr1/unordered_map>
|
#include <tr1/unordered_map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
//#define NDEBUG
|
// #define NDEBUG
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <boost/functional/hash.hpp> //boost::hash
|
#include <boost/functional/hash.hpp> //boost::hash
|
||||||
#include <boost/interprocess/allocators/allocator.hpp>
|
#include <boost/interprocess/allocators/allocator.hpp>
|
||||||
@ -1175,6 +1175,11 @@ class ExtentMap : public Undoable
|
|||||||
|
|
||||||
int _markInvalid(const LBID_t lbid, const execplan::CalpontSystemCatalog::ColDataType colDataType);
|
int _markInvalid(const LBID_t lbid, const execplan::CalpontSystemCatalog::ColDataType colDataType);
|
||||||
|
|
||||||
|
MSTEntry* _getTableLock(const OPS op, std::atomic<bool>& lockedState, const int table);
|
||||||
|
void _getTableLockUpgradeIfNeeded(const OPS op, std::atomic<bool>& lockedState, const int table);
|
||||||
|
void _getTableLockDowngradeIfNeeded(const OPS op, std::atomic<bool>& lockedState, const int table);
|
||||||
|
void _releaseTable(const OPS op, std::atomic<bool>& lockedState, const int table);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void load(T* in);
|
void load(T* in);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user