1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-27 21:01:50 +03:00

MCOL-4912 This patch introduces Extent Map index to improve EM scaleability

EM scaleability project has two parts: phase1 and phase2.
        This is phase1 that brings EM index to speed up(from O(n) down
        to the speed of boost::unordered_map) EM lookups looking for
        <dbroot, oid, partition> tuple to turn it into LBID,
        e.g. most bulk insertion meta info operations.
        The basis is boost::shared_managed_object where EMIndex is
        stored. Whilst it is not debug-friendly it allows to put a
        nested structs into shmem. EMIndex has 3 tiers. Top down description:
        vector of dbroots, map of oids to partition vectors, partition
        vectors that have EM indices.
        Separate EM methods now queries index before they do EM run.
        EMIndex has a separate shmem file with the fixed id
        MCS-shm-00060001.
This commit is contained in:
Roman Nozdrin
2022-03-30 08:57:05 +00:00
committed by Leonid Fedorov
parent fb3eaabd29
commit 4c26e4f960
25 changed files with 3498 additions and 459 deletions

View File

@ -40,7 +40,15 @@ namespace bi = boost::interprocess;
namespace BRM
{
BRMShmImpl::BRMShmImpl(unsigned key, off_t size, bool readOnly) : fKey(key), fSize(size), fReadOnly(readOnly)
const constexpr uint32_t ShmCreateMaxRetries = 10;
const constexpr unsigned int NapTimer = 500000;
BRMShmImplParent::BRMShmImplParent(unsigned key, off_t size, bool readOnly)
: fKey(key), fSize(size), fReadOnly(readOnly){};
BRMShmImplParent::~BRMShmImplParent(){};
BRMShmImpl::BRMShmImpl(unsigned key, off_t size, bool readOnly) : BRMShmImplParent(key, size, readOnly)
{
string keyName = ShmKeys::keyToName(fKey);
@ -238,5 +246,167 @@ void BRMShmImpl::destroy()
bi::shared_memory_object::remove(oldName.c_str());
}
BRMManagedShmImpl::BRMManagedShmImpl(unsigned key, off_t size, bool readOnly)
: BRMShmImplParent(key, size, readOnly)
{
string keyName = ShmKeys::keyToName(fKey);
off_t curSize = 0;
for (uint32_t tries = 0; fSize == 0 && tries <= ShmCreateMaxRetries; ++tries)
{
try
{
auto* shmSegment = new boost::interprocess::managed_shared_memory(bi::open_only, keyName.c_str());
curSize = shmSegment->get_size();
if (curSize == 0)
{
delete shmSegment;
throw bi::interprocess_exception("shared memory segment size is 0.");
}
else
{
fShmSegment = shmSegment;
fSize = curSize;
return;
}
}
catch (bi::interprocess_exception&)
{
if (tries == ShmCreateMaxRetries)
{
log("BRMManagedShmImpl::BRMManagedShmImpl(): re-creating shared memory segment\
b/c of its size == 0. Re-throw.");
throw;
}
cerr << "BRMManagedShmImpl::BRMManagedShmImpl(): re-creating shared memory segment\
b/c of its size == 0"
<< endl;
usleep(NapTimer);
}
}
try
{
bi::permissions perms;
perms.set_unrestricted();
fShmSegment = new bi::managed_shared_memory(bi::create_only, keyName.c_str(), fSize,
0, // use a default address to map the segment
perms);
// fSize == 0 on any process startup but managed_shared_memory ctor throws
// so control flow doesn't get here.
idbassert(fSize > 0);
}
catch (bi::interprocess_exception& b)
{
if (b.get_error_code() != bi::already_exists_error)
{
ostringstream o;
o << "BRM caught an exception creating a shared memory segment: " << b.what();
log(o.str());
throw;
}
bi::managed_shared_memory* shmSegment = nullptr;
try
{
if (fReadOnly)
shmSegment = new bi::managed_shared_memory(bi::open_read_only, keyName.c_str());
else
shmSegment = new bi::managed_shared_memory(bi::open_only, keyName.c_str());
}
catch (exception& e)
{
ostringstream o;
o << "BRM caught an exception attaching to a shared memory segment (" << keyName << "): " << b.what();
log(o.str());
throw;
}
off_t curSize = shmSegment->get_size();
idbassert(curSize > 0);
idbassert(curSize >= fSize);
fShmSegment = shmSegment;
fSize = curSize;
}
}
int BRMManagedShmImpl::grow(off_t newSize)
{
auto keyName = ShmKeys::keyToName(fKey);
if (newSize > fSize)
{
const auto incSize = newSize - fSize;
if (fShmSegment)
{
// Call destructor to unmap the segment.
delete fShmSegment;
// Grow the segment.
bi::managed_shared_memory::grow(keyName.c_str(), incSize);
// Open only with the assumption ::grow() can be called on read-write shmem.
fShmSegment = new bi::managed_shared_memory(bi::open_only, keyName.c_str());
// Update size.
fSize = newSize;
}
}
return 0;
}
// Dummy method that has no references in the code.
int BRMManagedShmImpl::clear(unsigned newKey, off_t newSize)
{
return 0;
}
// This method calls for all related shmem pointers to be refreshed.
void BRMManagedShmImpl::setReadOnly()
{
if (fReadOnly)
return;
const bool readOnly = true;
remap(readOnly);
fReadOnly = true;
}
void BRMManagedShmImpl::swap(BRMManagedShmImpl& rhs)
{
fShmSegment->swap(*rhs.fShmSegment);
std::swap(fKey, rhs.fKey);
std::swap(fSize, rhs.fSize);
std::swap(fReadOnly, rhs.fReadOnly);
}
// The method was copied from non-managed shmem impl class
// and it has no refences in MCS 6.x code.
void BRMManagedShmImpl::destroy()
{
string keyName = ShmKeys::keyToName(fKey);
try
{
bi::shared_memory_object::remove(keyName.c_str());
}
catch (bi::interprocess_exception& b)
{
std::ostringstream o;
o << "BRMManagedShmImpl::destroy caught an exception removing a managed shared memory segment: "
<< b.what();
log(o.str());
throw;
}
}
void BRMManagedShmImpl::remap(const bool readOnly)
{
delete fShmSegment;
fShmSegment = nullptr;
string keyName = ShmKeys::keyToName(fKey);
if (readOnly)
fShmSegment = new bi::managed_shared_memory(bi::open_read_only, keyName.c_str());
else
fShmSegment = new bi::managed_shared_memory(bi::open_only, keyName.c_str());
}
} // namespace BRM