1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
2017-10-26 17:18:17 +01:00

471 lines
12 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;
#ifdef _MSC_VER
__declspec(dllexport)
#endif
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
***********************************************************/
const 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
***********************************************************/
const 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
***********************************************************/
const 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
***********************************************************/
const 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
***********************************************************/
const 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
***********************************************************/
const 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;
}
} //end of namespace