1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-20 09:07:44 +03:00
2023-03-02 15:59:42 +00:00

457 lines
11 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: we_cache.cpp 33 2006-10-30 13:45:13Z wzhou $
*
******************************************************************************************/
/** @file */
#include <we_cache.h>
using namespace std;
namespace WriteEngine
{
CacheControl* Cache::m_cacheParam = NULL;
FreeBufList* Cache::m_freeList = NULL;
CacheMap* Cache::m_lruList = NULL;
CacheMap* Cache::m_writeList = NULL;
bool Cache::m_useCache = false;
/***********************************************************
* DESCRIPTION:
* Clear all list and free memory
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::clear()
{
CacheMapIt it;
BlockBuffer* block;
size_t i;
// free list
if (m_freeList != NULL)
{
for (i = 0; i < m_freeList->size(); i++)
{
block = m_freeList->at(i);
block->clear();
}
}
// LRU list
if (m_lruList != NULL)
{
for (it = m_lruList->begin(); it != m_lruList->end(); it++)
{
block = it->second;
block->clear();
m_freeList->push_back(block);
}
m_lruList->clear();
}
// Write list
if (m_writeList != NULL)
{
for (it = m_writeList->begin(); it != m_writeList->end(); it++)
{
block = it->second;
block->clear();
m_freeList->push_back(block);
}
m_writeList->clear();
}
}
/***********************************************************
* DESCRIPTION:
* Flush write cache
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::flushCache()
{
bool bHasReadBlock = false;
BlockBuffer* curBuf;
// add lock here
if (m_lruList && m_lruList->size() > 0)
{
bHasReadBlock = true;
for (CacheMapIt it = m_lruList->begin(); it != m_lruList->end(); it++)
{
curBuf = it->second;
curBuf->clear();
m_freeList->push_back(curBuf);
}
m_lruList->clear();
}
// must write to disk first
if (m_writeList && m_writeList->size() > 0)
{
if (!bHasReadBlock)
for (CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++)
{
curBuf = it->second;
curBuf->clear();
m_freeList->push_back(curBuf);
}
else
for (CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++)
{
curBuf = it->second;
(*curBuf).block.dirty = false;
processCacheMap(m_lruList, curBuf, INSERT);
}
m_writeList->clear();
} // end of if( m_writeList->size()
// add unlock here
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Free memory
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::freeMemory()
{
CacheMapIt it;
BlockBuffer* block;
size_t i;
// free list
if (m_freeList != NULL)
{
for (i = 0; i < m_freeList->size(); i++)
{
block = m_freeList->at(i);
block->freeMem();
delete block;
}
m_freeList->clear();
delete m_freeList;
m_freeList = NULL;
}
// LRU list
if (m_lruList != NULL)
{
for (it = m_lruList->begin(); it != m_lruList->end(); it++)
{
block = it->second;
block->freeMem();
delete block;
}
m_lruList->clear();
delete m_lruList;
m_lruList = NULL;
}
// Write list
if (m_writeList != NULL)
{
for (it = m_writeList->begin(); it != m_writeList->end(); it++)
{
block = it->second;
block->freeMem();
delete block;
}
m_writeList->clear();
delete m_writeList;
m_writeList = NULL;
}
// param
if (m_cacheParam != NULL)
{
delete m_cacheParam;
m_cacheParam = NULL;
}
}
/***********************************************************
* DESCRIPTION:
* get a list size
* PARAMETERS:
* listType - List type
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::getListSize(const CacheListType listType)
{
int size = 0;
if (!m_useCache)
return size;
switch (listType)
{
case FREE_LIST: size = m_freeList->size(); break;
case LRU_LIST: size = m_lruList->size(); break;
case WRITE_LIST:
default: size = m_writeList->size(); break;
}
return size;
}
/***********************************************************
* DESCRIPTION:
* Init all parameters and list
* PARAMETERS:
* totalBlock - total blocks
* chkPoint - checkpoint interval
* pctFree - percentage free
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::init(const int totalBlock, const int chkPoint, const int pctFree)
{
BlockBuffer* buffer;
if (m_cacheParam && m_freeList && m_lruList && m_writeList)
return;
m_cacheParam = new CacheControl();
m_cacheParam->totalBlock = totalBlock;
m_cacheParam->checkInterval = chkPoint;
m_cacheParam->pctFree = pctFree;
m_freeList = new FreeBufList();
m_lruList = new CacheMap();
m_writeList = new CacheMap();
for (int i = 0; i < m_cacheParam->totalBlock; i++)
{
buffer = new BlockBuffer();
buffer->init();
m_freeList->push_back(buffer);
}
}
/***********************************************************
* DESCRIPTION:
* Insert a buffer to LRU list
* PARAMETERS:
* cb - Comm Block
* lbid - lbid value
* fbo - fbo
* buf - input buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::insertLRUList(CommBlock& cb, const uint64_t lbid, const uint64_t fbo, const unsigned char* buf)
{
BlockBuffer* buffer;
vector<BlockBuffer*>::iterator it;
if (m_freeList->size() == 0)
return ERR_FREE_LIST_EMPTY;
// make sure flush first if necessary
it = m_freeList->begin();
buffer = *it;
memcpy((*buffer).block.data, buf, BYTE_PER_BLOCK);
(*buffer).listType = LRU_LIST;
(*buffer).block.lbid = lbid;
(*buffer).block.fbo = fbo;
(*buffer).block.dirty = false;
(*buffer).block.hitCount = 1;
(*buffer).cb.file.oid = cb.file.oid;
(*buffer).cb.file.pFile = cb.file.pFile;
RETURN_ON_ERROR(processCacheMap(m_lruList, buffer, INSERT));
m_freeList->erase(it);
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Load cache block
* PARAMETERS:
* key - Cache key
* buf - output buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::loadCacheBlock(const CacheKey& key, unsigned char* buf)
{
BlockBuffer* buffer;
CacheMapIt iter;
iter = m_lruList->find(key);
if (iter != m_lruList->end())
buffer = iter->second;
else
{
iter = m_writeList->find(key);
if (iter != m_writeList->end())
buffer = iter->second;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
memcpy(buf, (*buffer).block.data, BYTE_PER_BLOCK);
(*buffer).block.hitCount++;
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Modify cache block
* PARAMETERS:
* key - Cache key
* buf - output buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::modifyCacheBlock(const CacheKey& key, const unsigned char* buf)
{
BlockBuffer* buffer;
CacheMapIt iter;
iter = m_lruList->find(key);
if (iter != m_lruList->end())
{
buffer = iter->second;
(*buffer).listType = WRITE_LIST;
(*buffer).block.dirty = true;
(*m_writeList)[key] = iter->second;
m_lruList->erase(iter);
}
else
{
iter = m_writeList->find(key);
if (iter != m_writeList->end())
buffer = iter->second;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
memcpy((*buffer).block.data, buf, BYTE_PER_BLOCK);
(*buffer).block.hitCount++;
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Print cache list
* PARAMETERS:
* none
* RETURN:
* none
***********************************************************/
void Cache::printCacheList()
{
BlockBuffer* buffer;
int i = 0;
if (!m_useCache)
return;
cout << "\nFree List has " << m_freeList->size() << " elements" << endl;
cout << "LRU List has " << m_lruList->size() << " elements" << endl;
for (CacheMapIt it = m_lruList->begin(); it != m_lruList->end(); it++)
{
buffer = it->second;
cout << "\t[" << i++ << "] key=" << it->first << " listType=" << buffer->listType
<< " oid=" << (*buffer).cb.file.oid << " fbo=" << (*buffer).block.fbo
<< " dirty=" << (*buffer).block.dirty << " hitCount=" << (*buffer).block.hitCount << endl;
}
i = 0;
cout << "Write List has " << m_writeList->size() << " elements" << endl;
for (CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++)
{
buffer = it->second;
cout << "\t[" << i++ << "] key=" << it->first << " listType=" << buffer->listType
<< " oid=" << (*buffer).cb.file.oid << " fbo=" << (*buffer).block.fbo
<< " dirty=" << (*buffer).block.dirty << " hitCount=" << (*buffer).block.hitCount << endl;
}
}
/***********************************************************
* DESCRIPTION:
* Process a buffer in a cache map
* PARAMETERS:
* buffer - block buffer
* opType - insert or delete
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
int Cache::processCacheMap(CacheMap* map, BlockBuffer* buffer, OpType opType)
{
RETURN_ON_NULL(buffer, ERR_NULL_BLOCK);
CacheMapIt iter;
CacheKey key = getCacheKey(buffer);
iter = map->find(key);
// only handle insert and delete
if (iter == map->end())
{
if (opType == INSERT)
(*map)[key] = buffer;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
else
{
if (opType == INSERT)
return ERR_CACHE_KEY_EXIST;
else
map->erase(iter);
}
return NO_ERROR;
}
} // namespace WriteEngine