1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-21 19:45:56 +03:00
Roman Nozdrin 4fe9cd64a3
Revert "No boost condition (#2822)" (#2828)
This reverts commit f916e64927cd81569327014f20c4cc0b8aca40ff.
2023-04-22 15:49:50 +03:00

300 lines
7.9 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/***************************************************************************
*
* $Id: filebuffermgr.cpp 699 2008-09-09 19:44:18Z rdempsey $
*
* jrodriguez@calpont.com *
* *
***************************************************************************/
/**
* InitialDBBCSize - the starting number of elements the unordered set used to store disk blocks.
This does not instantiate InitialDBBCSize disk blocks but only the initial size of the unordered_set
**/
#define NDEBUG // Turn off assert macro
#include <cassert>
#include <limits.h>
#include <boost/thread.hpp>
#include "filebuffermgr.h"
using namespace boost;
using namespace std;
#include "stats.h"
extern dbbc::Stats* gPMStatsPtr;
extern bool gPMProfOn;
extern uint32_t gSession;
namespace dbbc
{
FileBufferMgr::FileBufferMgr(const uint32_t numBlcks, const uint32_t blkSz, const uint32_t deleteBlocks)
: fMaxNumBlocks(numBlcks)
, fBlockSz(blkSz)
, fWLock()
, fbSet()
, fbList()
, fCacheSize(0)
, fFBPool()
, aging(false)
, fDeleteBlocks(deleteBlocks)
, fEmptyPoolSlots()
{
fFBPool.reserve(numBlcks);
fEmptyPoolSlots.reserve(deleteBlocks);
}
FileBufferMgr::~FileBufferMgr()
{
flushCache();
}
void FileBufferMgr::flushCache()
{
mutex::scoped_lock lk(fWLock);
fbList.clear();
fbSet.clear();
fFBPool.clear();
fEmptyPoolSlots.clear();
// TODO:: re-init blocks in pool and HWM
}
bool FileBufferMgr::exists(const BRM::LBID_t& lbid, const BRM::VER_t& ver) const
{
const HashObject_t fb = {lbid, ver, 0};
const bool b = exists(fb);
return b;
} // bool FileBufferMgr::exists(const BRM::LBID_t& lbid, const BRM::VER_t& ver) const
FileBuffer* FileBufferMgr::findPtr(const HashObject_t& keyFb)
{
mutex::scoped_lock lk(fWLock);
filebuffer_uset_iter_t it = fbSet.find(keyFb);
if (fbSet.end() != it)
{
FileBuffer* fb = &(fFBPool[it->poolIdx]);
fbList.splice(fbList.begin(), fbList, (fFBPool[it->poolIdx]).listLoc());
return fb;
}
return NULL;
} // end findPtr(const HashObject_t& keyFB)
bool FileBufferMgr::find(const HashObject_t& keyFb, FileBuffer& fb)
{
bool ret = false;
mutex::scoped_lock lk(fWLock);
filebuffer_uset_iter_t it = fbSet.find(keyFb);
if (fbSet.end() != it)
{
fbList.splice(fbList.begin(), fbList, (fFBPool[it->poolIdx]).listLoc());
lk.unlock();
fb = fFBPool[it->poolIdx];
ret = true;
}
return ret;
} // end find(const HashObject_t& keyFB, HashObject_t& fb)
bool FileBufferMgr::find(const HashObject_t& keyFb, void* bufferPtr)
{
bool ret = false;
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(keyFb.lbid, pthread_self(), gSession, 'L');
mutex::scoped_lock lk(fWLock);
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(keyFb.lbid, pthread_self(), gSession, 'M');
filebuffer_uset_iter_t it = fbSet.find(keyFb);
if (fbSet.end() != it)
{
//@bug 669 LRU cache, move block to front of list as last recently used.
fbList.splice(fbList.begin(), fbList, (fFBPool[it->poolIdx]).listLoc());
lk.unlock();
memcpy(bufferPtr, (fFBPool[it->poolIdx]).getData(), 8);
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(keyFb.lbid, pthread_self(), gSession, 'U');
ret = true;
}
return ret;
} // end find(const FileBuffer& keyFB, void* bufferPtr)
bool FileBufferMgr::exists(const HashObject_t& fb) const
{
bool find_bool = false;
mutex::scoped_lock lk(fWLock);
filebuffer_uset_iter_t it = fbSet.find(fb);
if (it != fbSet.end())
{
find_bool = true;
fbList.splice(fbList.begin(), fbList, (fFBPool[it->poolIdx]).listLoc());
}
return find_bool;
}
// default insert operation.
// add a new fb into fbMgr and to fbList
// add to the front and age out from the back
// so add new fbs to the front of the list
//@bug 665: keep filebuffer in a vector. HashObject keeps the index of the filebuffer
const int FileBufferMgr::insert(const BRM::LBID_t lbid, const BRM::VER_t ver, const uint8_t* data)
{
int ret = 0;
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(lbid, pthread_self(), gSession, 'I');
mutex::scoped_lock lk(fWLock);
HashObject_t fbIndex = {lbid, ver, 0};
filebuffer_pair_t pr = fbSet.insert(fbIndex);
if (pr.second)
{
// It was inserted (it wasn't there before)
// Right now we have an invalid cache: we have inserted an entry with a -1 index.
// We need to fix this quickly...
fCacheSize++;
FBData_t fbdata = {lbid, ver};
fbList.push_front(fbdata);
}
else
{
// if it's a duplicate there's nothing to do
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(lbid, pthread_self(), gSession, 'D');
return ret;
}
uint32_t pi = INT_MAX;
if (fCacheSize > maxCacheSize())
{
// If the insert above caused the cache to exceed its max size, find the lru block in
// the cache and use its pool index to store the block data.
FBData_t& fbdata = fbList.back(); // the lru block
HashObject_t lastFB = {fbdata.lbid, fbdata.ver, 0};
filebuffer_uset_iter_t iter = fbSet.find(lastFB); // should be there
idbassert(iter != fbSet.end());
pi = iter->poolIdx;
idbassert(pi < maxCacheSize());
idbassert(pi < fFBPool.size());
/* Why does this iterator return a const HashObject_t? */
HashObject_t& ref = const_cast<HashObject_t&>(*pr.first);
ref.poolIdx = pi;
// replace the lru block with this block
FileBuffer fb(lbid, ver, NULL, 0);
fFBPool[pi] = fb;
fFBPool[pi].setData(data, BLOCK_SIZE);
fbSet.erase(iter);
fbList.pop_back();
fCacheSize--;
depleteCache();
ret = 1;
}
else
{
if (!fEmptyPoolSlots.empty())
{
pi = fEmptyPoolSlots.back();
fEmptyPoolSlots.pop_back();
FileBuffer fb(lbid, ver, NULL, 0);
fFBPool[pi] = fb;
fFBPool[pi].setData(data, 8);
}
else
{
pi = fFBPool.size();
FileBuffer fb(lbid, ver, NULL, 0);
fFBPool.push_back(fb);
fFBPool[pi].setData(data, 8);
}
/* Why does this iterator return a const? */
HashObject_t& ref = const_cast<HashObject_t&>(*pr.first);
ref.poolIdx = pi;
ret = 1;
}
idbassert(pi < fFBPool.size());
fFBPool[pi].listLoc(fbList.begin());
if (gPMProfOn && gPMStatsPtr)
gPMStatsPtr->markEvent(lbid, pthread_self(), gSession, 'J');
idbassert(fCacheSize <= maxCacheSize());
// idbassert(fCacheSize == fbSet.size());
// idbassert(fCacheSize == fbList.size());
return ret;
}
void FileBufferMgr::depleteCache()
{
for (uint32_t i = 0; i < fDeleteBlocks && !fbList.empty(); ++i)
{
FBData_t fbdata(fbList.back()); // the lru block
HashObject_t lastFB = {fbdata.lbid, fbdata.ver, 0};
filebuffer_uset_iter_t iter = fbSet.find(lastFB);
idbassert(iter != fbSet.end());
uint32_t idx = iter->poolIdx;
idbassert(idx < fFBPool.size());
// Save position in FileBuffer pool for reuse.
fEmptyPoolSlots.push_back(idx);
fbSet.erase(iter);
fbList.pop_back();
fCacheSize--;
}
}
ostream& FileBufferMgr::formatLRUList(ostream& os) const
{
filebuffer_list_t::const_iterator iter = fbList.begin();
filebuffer_list_t::const_iterator end = fbList.end();
while (iter != end)
{
os << iter->lbid << '\t' << iter->ver << endl;
++iter;
}
return os;
}
} // namespace dbbc