TarsCloud_TarsCpp/util/src/tc_multi_hashmap.cpp
2020-02-07 13:50:04 +08:00

3949 lines
111 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "util/tc_multi_hashmap.h"
#include "util/tc_pack.h"
#include "util/tc_common.h"
namespace tars
{
int TC_Multi_HashMap::FailureRecover::_iRefCount = 0;
bool TC_Multi_HashMap::MainKey::next()
{
_iHead = getHeadPtr()->_iNext;
_pHead = _pMap->getAbsolute(_iHead);
return _iHead != 0;
}
bool TC_Multi_HashMap::MainKey::prev()
{
_iHead = getHeadPtr()->_iPrev;
_pHead = _pMap->getAbsolute(_iHead);
return _iHead != 0;
}
void TC_Multi_HashMap::MainKey::deallocate()
{
if(HASNEXTCHUNK())
{
// 释放所有chunk
deallocate(getHeadPtr()->_iNextChunk);
}
// 释放主key头
vector<uint32_t> v;
v.push_back(_iHead);
_pMap->_pDataAllocator->deallocateMemChunk(v);
}
void TC_Multi_HashMap::MainKey::deallocate(uint32_t iChunk)
{
vector<uint32_t> v;
v.push_back(iChunk);
tagChunkHead *pChunk = getChunkHead(iChunk);
//获取所有后续的chunk地址
while(true)
{
if(pChunk->_bNextChunk)
{
v.push_back(pChunk->_iNextChunk);
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
break;
}
}
// 空间全部释放掉
_pMap->_pDataAllocator->deallocateMemChunk(v);
}
void TC_Multi_HashMap::MainKey::makeNew(uint32_t iIndex, uint32_t iAllocSize)
{
getHeadPtr()->_iSize = iAllocSize;
getHeadPtr()->_iIndex = iIndex;
getHeadPtr()->_iAddr = 0;
getHeadPtr()->_iNext = 0;
getHeadPtr()->_iPrev = 0;
getHeadPtr()->_iGetNext = 0;
getHeadPtr()->_iGetPrev = 0;
getHeadPtr()->_iDataLen = 0;
SETNEXTCHUNK(false);
SETFULLDATA(false);
_pMap->incMainKeyListCount(iIndex);
// 挂到主key链上
if(_pMap->itemMainKey(iIndex)->_iMainKeyAddr == 0)
{
//当前hash桶没有元素
_pMap->saveValue(&_pMap->itemMainKey(iIndex)->_iMainKeyAddr, _iHead);
_pMap->saveValue(&getHeadPtr()->_iNext, (uint32_t)0);
_pMap->saveValue(&getHeadPtr()->_iPrev, (uint32_t)0);
}
else
{
//当前hash桶有元素, 挂在桶开头
_pMap->saveValue(&getHeadPtr(_pMap->itemMainKey(iIndex)->_iMainKeyAddr)->_iPrev, _iHead);
_pMap->saveValue(&getHeadPtr()->_iNext, _pMap->itemMainKey(iIndex)->_iMainKeyAddr);
_pMap->saveValue(&_pMap->itemMainKey(iIndex)->_iMainKeyAddr, _iHead);
_pMap->saveValue(&getHeadPtr()->_iPrev, (uint32_t)0);
}
//挂在Get链表头部
if(_pMap->_pHead->_iGetHead == 0)
{
assert(_pMap->_pHead->_iGetTail == 0);
_pMap->saveValue(&_pMap->_pHead->_iGetHead, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iGetTail, _iHead);
}
else
{
assert(_pMap->_pHead->_iGetTail != 0);
_pMap->saveValue(&getHeadPtr()->_iGetNext, _pMap->_pHead->_iGetHead);
_pMap->saveValue(&getHeadPtr(_pMap->_pHead->_iGetHead)->_iGetPrev, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iGetHead, _iHead);
}
}
int TC_Multi_HashMap::MainKey::erase(vector<Value> &vtData)
{
//////////////////修改备份数据链表/////////////
if(_pMap->_pHead->_iBackupTail == _iHead)
{
_pMap->saveValue(&_pMap->_pHead->_iBackupTail, getHeadPtr()->_iGetPrev);
}
////////////////////修改Get链表的数据//////////
//
{
bool bHead = (_pMap->_pHead->_iGetHead == _iHead);
bool bTail = (_pMap->_pHead->_iGetTail == _iHead);
if(!bHead)
{
if(bTail)
{
assert(getHeadPtr()->_iGetNext == 0);
//是尾部, 尾部指针指向上一个元素
_pMap->saveValue(&_pMap->_pHead->_iGetTail, getHeadPtr()->_iGetPrev);
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iGetPrev)->_iGetNext, (uint32_t)0);
}
else
{
//不是头部也不是尾部
assert(getHeadPtr()->_iGetNext != 0);
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iGetPrev)->_iGetNext, getHeadPtr()->_iGetNext);
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iGetNext)->_iGetPrev, getHeadPtr()->_iGetPrev);
}
}
else
{
if(bTail)
{
assert(getHeadPtr()->_iGetNext == 0);
assert(getHeadPtr()->_iGetPrev == 0);
//头部也是尾部, 指针都设置为0
_pMap->saveValue(&_pMap->_pHead->_iGetHead, (uint32_t)0);
_pMap->saveValue(&_pMap->_pHead->_iGetTail, (uint32_t)0);
}
else
{
//头部不是尾部, 头部指针指向下一个元素
assert(getHeadPtr()->_iGetNext != 0);
_pMap->saveValue(&_pMap->_pHead->_iGetHead, getHeadPtr()->_iGetNext);
//下一个元素上指针为0
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iGetNext)->_iGetPrev, (uint32_t)0);
}
}
}
///////////////////删除主key下的所有block/////////////////////////////
string mk;
int ret = get(mk);
if(ret != TC_Multi_HashMap::RT_OK)
{
// todo, 这里出错会有大问题,前面的修改都应该取消
return ret;
}
while(getHeadPtr()->_iAddr != 0)
{
Block block(_pMap, getHeadPtr()->_iAddr);
Value value;
value._mkey = mk;
int ret = block.getBlockData(value._data);
if(ret == TC_Multi_HashMap::RT_OK)
{
vtData.push_back(value);
}
block.erase();
}
///////////////////从主key链表中去掉///////////
//
//上一个主key指向下一个主key
if(getHeadPtr()->_iPrev != 0)
{
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iPrev)->_iNext, getHeadPtr()->_iNext);
}
//下一个主key指向上一个
if(getHeadPtr()->_iNext != 0)
{
_pMap->saveValue(&getHeadPtr(getHeadPtr()->_iNext)->_iPrev, getHeadPtr()->_iPrev);
}
//////////////////如果是hash头部, 需要修改hash索引数据指针//////
//
_pMap->delMainKeyListCount(getHeadPtr()->_iIndex);
if(getHeadPtr()->_iPrev == 0)
{
//如果是hash桶的头部, 则还需要处理
TC_Multi_HashMap::tagMainKeyHashItem *pItem = _pMap->itemMainKey(getHeadPtr()->_iIndex);
assert(pItem->_iMainKeyAddr == _iHead);
if(pItem->_iMainKeyAddr == _iHead)
{
_pMap->saveValue(&pItem->_iMainKeyAddr, getHeadPtr()->_iNext);
}
}
// 手工置空一些参数使在数据恢复区建立记录以便crash后恢复
_pMap->saveValue(&getHeadPtr()->_iSize, (uint32_t)0);
_pMap->saveValue(&getHeadPtr()->_iIndex, (uint32_t)0);
_pMap->saveValue(&getHeadPtr()->_iBitset, (uint8_t)0);
_pMap->saveValue(&getHeadPtr()->_iDataLen, (uint32_t)0);
// 归还内存前先确认上述修改,因为内存被释放后是不能恢复的
// 即使后面的内存释放失败也不会造成数据的破坏
_pMap->doUpdate();
//归还到内存中
deallocate();
return RT_OK;
}
void TC_Multi_HashMap::MainKey::refreshGetList()
{
assert(_pMap->_pHead->_iGetHead != 0);
assert(_pMap->_pHead->_iGetTail != 0);
// 本身已经在头部,不需要处理
if(_pMap->_pHead->_iGetHead == _iHead)
{
return;
}
uint32_t iPrev = getHeadPtr()->_iGetPrev;
uint32_t iNext = getHeadPtr()->_iGetNext;
assert(iPrev != 0);
//是正在备份的数据
if(_pMap->_pHead->_iBackupTail == _iHead)
{
_pMap->saveValue(&_pMap->_pHead->_iBackupTail, iPrev);
}
//挂在链表头部
_pMap->saveValue(&getHeadPtr()->_iGetNext, _pMap->_pHead->_iGetHead);
_pMap->saveValue(&getHeadPtr(_pMap->_pHead->_iGetHead)->_iGetPrev, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iGetHead, _iHead);
_pMap->saveValue(&getHeadPtr()->_iGetPrev, (uint32_t)0);
//上一个元素的Next指针指向下一个元素
_pMap->saveValue(&getHeadPtr(iPrev)->_iGetNext, iNext);
//下一个元素的Prev指向上一个元素
if (iNext != 0)
{
_pMap->saveValue(&getHeadPtr(iNext)->_iGetPrev, iPrev);
}
else
{
//改变尾部指针
assert(_pMap->_pHead->_iGetTail == _iHead);
_pMap->saveValue(&_pMap->_pHead->_iGetTail, iPrev);
}
}
int TC_Multi_HashMap::MainKey::allocate(uint32_t iDataLen, vector<TC_Multi_HashMap::Value> &vtData)
{
uint32_t fn = 0;
//一个块的真正的数据容量
fn = getHeadPtr()->_iSize - sizeof(tagMainKeyHead);
if(fn >= iDataLen)
{
//一个chunk就可以了, 后续的chunk都要释放掉
if(HASNEXTCHUNK())
{
uint32_t iNextChunk = getHeadPtr()->_iNextChunk;
//先修改自己的区块
_pMap->saveValue(&getHeadPtr()->_iBitset, NEXTCHUNK_BIT, false);
_pMap->saveValue(&getHeadPtr()->_iDataLen, (uint32_t)0);
//修改成功后再释放区块, 从而保证, 不会core的时候导致整个内存块不可用
deallocate(iNextChunk);
}
return TC_Multi_HashMap::RT_OK;
}
//计算还需要多少长度
fn = iDataLen - fn;
if(HASNEXTCHUNK())
{
tagChunkHead *pChunk = getChunkHead(getHeadPtr()->_iNextChunk);
while(true)
{
if(fn <= (pChunk->_iSize - sizeof(tagChunkHead)))
{
//已经不需要chunk了, 释放多余的chunk
if(pChunk->_bNextChunk)
{
uint32_t iNextChunk = pChunk->_iNextChunk;
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
//一旦异常core, 最坏的情况就是少了可用的区块, 但是整个内存结构还是可用的
deallocate(iNextChunk);
}
return TC_Multi_HashMap::RT_OK;
}
//计算, 还需要多少长度
fn -= pChunk->_iSize - sizeof(tagChunkHead);
if(pChunk->_bNextChunk)
{
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
//没有后续chunk了, 需要新分配fn的空间
vector<uint32_t> chunks;
int ret = allocateChunk(fn, chunks, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
//没有内存可以分配
return ret;
}
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)true);
_pMap->saveValue(&pChunk->_iNextChunk, chunks[0]);
//chunk指向分配的第一个chunk
pChunk = getChunkHead(chunks[0]);
//修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
//连接每个chunk
return joinChunk(pChunk, chunks);
}
}
}
else
{
//没有后续chunk了, 需要新分配fn空间
vector<uint32_t> chunks;
int ret = allocateChunk(fn, chunks, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
//没有内存可以分配
return ret;
}
_pMap->saveValue(&getHeadPtr()->_iBitset, NEXTCHUNK_BIT, true);
_pMap->saveValue(&getHeadPtr()->_iNextChunk, chunks[0]);
//chunk指向分配的第一个chunk
tagChunkHead *pChunk = getChunkHead(chunks[0]);
//修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
//连接每个chunk
return joinChunk(pChunk, chunks);
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::MainKey::joinChunk(tagChunkHead *pChunk, const vector<uint32_t>& chunks)
{
for (size_t i = 0; i < chunks.size(); ++i)
{
if (i == chunks.size() - 1)
{
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
return TC_Multi_HashMap::RT_OK;
}
else
{
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)true);
_pMap->saveValue(&pChunk->_iNextChunk, chunks[i+1]);
pChunk = getChunkHead(chunks[i+1]);
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
}
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::MainKey::allocateChunk(uint32_t fn, vector<uint32_t> &chunks, vector<TC_Multi_HashMap::Value> &vtData)
{
assert(fn > 0);
while(true)
{
uint32_t iAllocSize = fn;
// 分配空间
// 分配过程中可能会淘汰数据第一个参数是当前的主key头地址不能被淘汰
uint32_t t = _pMap->_pDataAllocator->allocateChunk(_iHead, iAllocSize, vtData);
if (t == 0)
{
//没有内存可以分配了, 先把分配的归还
_pMap->_pDataAllocator->deallocateMemChunk(chunks);
chunks.clear();
return TC_Multi_HashMap::RT_NO_MEMORY;
}
//设置分配的数据块的大小
getChunkHead(t)->_iSize = iAllocSize;
chunks.push_back(t);
//分配够了
if(fn <= (iAllocSize - sizeof(tagChunkHead)))
{
break;
}
//还需要多少空间
fn -= iAllocSize - sizeof(tagChunkHead);
}
return TC_Multi_HashMap::RT_OK;
}
uint32_t TC_Multi_HashMap::MainKey::getDataLen()
{
uint32_t n = 0;
if(!HASNEXTCHUNK())
{
// 只有一个chunk
n += getHeadPtr()->_iDataLen;
return n;
}
//当前块的大小
n += getHeadPtr()->_iSize - sizeof(tagMainKeyHead);
tagChunkHead *pChunk = getChunkHead(getHeadPtr()->_iNextChunk);
while (true)
{
if(pChunk->_bNextChunk)
{
//当前块的大小
n += pChunk->_iSize - sizeof(tagChunkHead);
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
// 最后一个chunk
n += pChunk->_iDataLen;
break;
}
}
return n;
}
int TC_Multi_HashMap::MainKey::get(void *pData, uint32_t &iDataLen)
{
if(!HASNEXTCHUNK())
{
// 没有下一个chunk, 一个chunk就可以装下数据了
iDataLen = min(getHeadPtr()->_iDataLen, iDataLen);
memcpy(pData, getHeadPtr()->_cData, iDataLen);
return TC_Multi_HashMap::RT_OK;
}
else
{
uint32_t iUseSize = getHeadPtr()->_iSize - sizeof(tagMainKeyHead);
uint32_t iCopyLen = min(iUseSize, iDataLen);
// 先copy第一个chunk的数据
memcpy(pData, getHeadPtr()->_cData, iCopyLen);
if (iDataLen < iUseSize)
{
return TC_Multi_HashMap::RT_NOTALL_ERR; // copy数据不完全
}
// 已经copy长度
uint32_t iHasLen = iCopyLen;
// 最大剩余长度
uint32_t iLeftLen = iDataLen - iCopyLen;
// copy后面所有的chunk中的数据
tagChunkHead *pChunk = getChunkHead(getHeadPtr()->_iNextChunk);
while(iHasLen < iDataLen)
{
iUseSize = pChunk->_iSize - sizeof(tagChunkHead);
if(!pChunk->_bNextChunk)
{
uint32_t iCopyLen = min(pChunk->_iDataLen, iLeftLen);
memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
iDataLen = iHasLen + iCopyLen;
if(iLeftLen < pChunk->_iDataLen)
{
return TC_Multi_HashMap::RT_NOTALL_ERR; // copy不完全
}
return TC_Multi_HashMap::RT_OK;
}
else
{
uint32_t iCopyLen = min(iUseSize, iLeftLen);
memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
if (iLeftLen <= iUseSize)
{
iDataLen = iHasLen + iCopyLen;
return TC_Multi_HashMap::RT_NOTALL_ERR; // copy不完全
}
iHasLen += iCopyLen;
iLeftLen -= iCopyLen;
pChunk = getChunkHead(pChunk->_iNextChunk);
}
}
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::MainKey::get(string &mk)
{
// 获取数据长度
uint32_t iLen = getDataLen();
char *cData = new char[iLen];
uint32_t iGetLen = iLen;
int ret = get(cData, iGetLen);
if(ret == TC_Multi_HashMap::RT_OK)
{
// 解码成string
mk.assign(cData, iGetLen);
}
delete[] cData;
return ret;
}
int TC_Multi_HashMap::MainKey::set(const void *pData, uint32_t iDataLen, vector<TC_Multi_HashMap::Value> &vtData)
{
// 首先分配刚刚够的长度, 不能多一个chunk, 也不能少一个chunk
// allocate会判断当前chunk的长度是否满足iDataLen少了就加chunk多了就释放chunk
int ret = allocate(iDataLen, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
// 第一个chunk的有效长度
uint32_t iUseSize = getHeadPtr()->_iSize - sizeof(tagMainKeyHead);
if(!HASNEXTCHUNK())
{
// 没有下一个chunk, 一个chunk就可以装下数据了
// 先copy数据, 再复制数据长度
memcpy(getHeadPtr()->_cData, (char*)pData, iDataLen);
getHeadPtr()->_iDataLen = iDataLen;
}
else
{
// copy到当前的chunk中
memcpy(getHeadPtr()->_cData, (char*)pData, iUseSize);
// 剩余程度
uint32_t iLeftLen = iDataLen - iUseSize;
uint32_t iCopyLen = iUseSize;
tagChunkHead *pChunk = getChunkHead(getHeadPtr()->_iNextChunk);
while(true)
{
// 计算chunk的可用大小
iUseSize = pChunk->_iSize - sizeof(tagChunkHead);
if(!pChunk->_bNextChunk)
{
assert(iUseSize >= iLeftLen);
// copy到当前的chunk中
memcpy(pChunk->_cData, (char*)pData + iCopyLen, iLeftLen);
// 最后一个chunk, 才有数据长度, 先copy数据再赋值长度
pChunk->_iDataLen = iLeftLen;
iCopyLen += iLeftLen;
iLeftLen -= iLeftLen;
break;
}
else
{
// copy到当前的chunk中
memcpy(pChunk->_cData, (char*)pData + iCopyLen, iUseSize);
iCopyLen += iUseSize;
iLeftLen -= iUseSize;
pChunk = getChunkHead(pChunk->_iNextChunk);
}
}
assert(iLeftLen == 0);
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::Block::getBlockData(TC_Multi_HashMap::BlockData &data)
{
data._dirty = isDirty();
data._synct = getSyncTime();
data._iVersion = getVersion();
string s;
int ret = get(s);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
try
{
// block保存的数据中第一部分为除主key外的联合主键
TC_PackOut po(s.c_str(), s.length());
po >> data._key;
// 如果不是只有Key
if(!isOnlyKey())
{
// 第二部分为数据值
po >> data._value;
}
else
{
return TC_Multi_HashMap::RT_ONLY_KEY;
}
}
catch(exception &ex)
{
ret = TC_Multi_HashMap::RT_DECODE_ERR;
}
return ret;
}
uint32_t TC_Multi_HashMap::Block::getLastBlockHead(bool bUKList)
{
uint32_t iHead = _iHead;
if(bUKList)
{
// 获取当前联合主键block链上的最后一个block
while(getBlockHead(iHead)->_iUKBlockNext != 0)
{
iHead = getBlockHead(iHead)->_iUKBlockNext;
}
}
else
{
// 获取当前主key block链上的最后一个block
while(getBlockHead(iHead)->_iMKBlockNext != 0)
{
iHead = getBlockHead(iHead)->_iMKBlockNext;
}
}
return iHead;
}
int TC_Multi_HashMap::Block::get(void *pData, uint32_t &iDataLen)
{
if(!HASNEXTCHUNK())
{
// 没有下一个chunk, 一个chunk就可以装下数据了
memcpy(pData, getBlockHead()->_cData, min(getBlockHead()->_iDataLen, iDataLen));
iDataLen = getBlockHead()->_iDataLen;
return TC_Multi_HashMap::RT_OK;
}
else
{
// 第一个chunk的有效空间长度
uint32_t iUseSize = getBlockHead()->_iSize - sizeof(tagBlockHead);
uint32_t iCopyLen = min(iUseSize, iDataLen);
// copy第一个chunk中的数据
memcpy(pData, getBlockHead()->_cData, iCopyLen);
if (iDataLen < iUseSize)
{
// 外部提供的缓冲区长度不够
return TC_Multi_HashMap::RT_NOTALL_ERR; //copy数据不完全
}
// 已经copy长度
uint32_t iHasLen = iCopyLen;
// 最大剩余长度
uint32_t iLeftLen = iDataLen - iCopyLen;
tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
while(iHasLen < iDataLen)
{
iUseSize = pChunk->_iSize - sizeof(tagChunkHead);
if(!pChunk->_bNextChunk)
{
// 最后一个chunk
uint32_t iCopyLen = min(pChunk->_iDataLen, iLeftLen);
memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
iDataLen = iHasLen + iCopyLen;
if(iLeftLen < pChunk->_iDataLen)
{
return TC_Multi_HashMap::RT_NOTALL_ERR; // copy不完全
}
return TC_Multi_HashMap::RT_OK;
}
else
{
uint32_t iCopyLen = min(iUseSize, iLeftLen);
// copy当前的chunk
memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
if (iLeftLen <= iUseSize)
{
iDataLen = iHasLen + iCopyLen;
return TC_Multi_HashMap::RT_NOTALL_ERR; // copy不完全
}
// copy当前chunk完全
iHasLen += iCopyLen;
iLeftLen -= iCopyLen;
pChunk = getChunkHead(pChunk->_iNextChunk);
}
}
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::Block::get(string &s)
{
uint32_t iLen = getDataLen();
char *cData = new char[iLen];
uint32_t iGetLen = iLen;
int ret = get(cData, iGetLen);
if(ret == TC_Multi_HashMap::RT_OK)
{
s.assign(cData, iGetLen);
}
delete[] cData;
return ret;
}
int TC_Multi_HashMap::Block::set(const void *pData, uint32_t iDataLen, bool bOnlyKey,
uint8_t iVersion, vector<TC_Multi_HashMap::Value> &vtData)
{
// version为0表示外部不关心数据版本onlykey时也不需要关注数据版本
if(iVersion != 0 && !isOnlyKey() && getBlockHead()->_iVersion != iVersion)
{
// 数据版本不匹配
return TC_Multi_HashMap::RT_DATA_VER_MISMATCH;
}
// 首先分配刚刚够的长度, 不能多一个chunk, 也不能少一个chunk
// allocate会判断当前chunk的长度是否满足iDataLen少了就加chunk多了就释放chunk
int ret = allocate(iDataLen, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
if(bOnlyKey)
{
// 原始数据是脏数据
if(isDirty())
{
_pMap->delDirtyCount();
}
// 数据被修改, 设置为脏数据
SETDIRTY(false);
// 原始数据不是OnlyKey数据
if(!isOnlyKey())
{
_pMap->incOnlyKeyCount();
}
}
else
{
//原始数据不是脏数据
if(!isDirty())
{
_pMap->incDirtyCount();
}
//数据被修改, 设置为脏数据
SETDIRTY(true);
//原始数据是OnlyKey数据
if(isOnlyKey())
{
_pMap->delOnlyKeyCount();
}
// 递增数据版本
iVersion = getBlockHead()->_iVersion;
iVersion ++;
if(iVersion == 0)
{
// 0是保留版本有效版本范围是1-255
iVersion = 1;
}
getBlockHead()->_iVersion = iVersion;
}
//设置是否只有Key
SETONLYKEY(bOnlyKey);
// 第一个chunk的有效空间大小
uint32_t iUseSize = getBlockHead()->_iSize - sizeof(tagBlockHead);
if(!HASNEXTCHUNK())
{
// 没有下一个chunk, 一个chunk就可以装下数据了
memcpy(getBlockHead()->_cData, (char*)pData, iDataLen);
getBlockHead()->_iDataLen = iDataLen;
}
else
{
// copy到第一个chunk中
memcpy(getBlockHead()->_cData, (char*)pData, iUseSize);
// 剩余程度
uint32_t iLeftLen = iDataLen - iUseSize;
uint32_t iCopyLen = iUseSize;
tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
while(true)
{
// 计算chunk的可用大小
iUseSize = pChunk->_iSize - sizeof(tagChunkHead);
if(!pChunk->_bNextChunk)
{
assert(iUseSize >= iLeftLen);
// copy到当前的chunk中
memcpy(pChunk->_cData, (char*)pData + iCopyLen, iLeftLen);
// 最后一个chunk, 才有数据长度, 先copy数据再赋值长度
pChunk->_iDataLen = iLeftLen;
iCopyLen += iLeftLen;
iLeftLen -= iLeftLen;
break;
}
else
{
// copy到当前的chunk中
memcpy(pChunk->_cData, (char*)pData + iCopyLen, iUseSize);
iCopyLen += iUseSize;
iLeftLen -= iUseSize;
pChunk = getChunkHead(pChunk->_iNextChunk);
}
}
assert(iLeftLen == 0);
}
return TC_Multi_HashMap::RT_OK;
}
void TC_Multi_HashMap::Block::setDirty(bool b)
{
if (b)
{
if(!isDirty())
{
SETDIRTY(b);
_pMap->incDirtyCount();
}
}
else
{
if(isDirty())
{
SETDIRTY(b);
_pMap->delDirtyCount();
}
}
}
bool TC_Multi_HashMap::Block::nextBlock()
{
_iHead = getBlockHead()->_iUKBlockNext;
_pHead = _pMap->getAbsolute(_iHead);
return _iHead != 0;
}
bool TC_Multi_HashMap::Block::prevBlock()
{
_iHead = getBlockHead()->_iUKBlockPrev;
_pHead = _pMap->getAbsolute(_iHead);
return _iHead != 0;
}
void TC_Multi_HashMap::Block::deallocate()
{
// 先释放所有的后续chunk
if(HASNEXTCHUNK())
{
deallocate(getBlockHead()->_iNextChunk);
}
// 再释放第一个chunk
vector<uint32_t> v;
v.push_back(_iHead);
_pMap->_pDataAllocator->deallocateMemChunk(v);
}
void TC_Multi_HashMap::Block::makeNew(uint32_t iMainKeyAddr, uint32_t uIndex, uint32_t iAllocSize, bool bHead)
{
getBlockHead()->_iSize = iAllocSize;
getBlockHead()->_iIndex = uIndex;
getBlockHead()->_iUKBlockNext = 0;
getBlockHead()->_iUKBlockPrev = 0;
getBlockHead()->_iMKBlockNext = 0;
getBlockHead()->_iMKBlockPrev = 0;
getBlockHead()->_iSetNext = 0;
getBlockHead()->_iSetPrev = 0;
getBlockHead()->_iMainKey = iMainKeyAddr;
getBlockHead()->_iSyncTime = 0;
getBlockHead()->_iDataLen = 0;
getBlockHead()->_iVersion = 1; // 有效版本范围1-255
SETONLYKEY(false);
SETDIRTY(true);
SETNEXTCHUNK(false);
_pMap->incDirtyCount();
_pMap->incElementCount();
_pMap->incListCount(uIndex);
// 增加主key下面的block数量
MainKey mainKey(_pMap, iMainKeyAddr);
_pMap->saveValue(&mainKey.getHeadPtr()->_iBlockCount, mainKey.getHeadPtr()->_iBlockCount + 1);
_pMap->updateMaxMainKeyBlockCount(mainKey.getHeadPtr()->_iBlockCount);
// 挂在block链表上
if(_pMap->item(uIndex)->_iBlockAddr == 0)
{
// 当前hash桶没有元素
_pMap->saveValue(&_pMap->item(uIndex)->_iBlockAddr, _iHead);
_pMap->saveValue(&getBlockHead()->_iUKBlockNext, (uint32_t)0);
_pMap->saveValue(&getBlockHead()->_iUKBlockPrev, (uint32_t)0);
}
else
{
// 当前hash桶有元素, 挂在桶开头
_pMap->saveValue(&getBlockHead(_pMap->item(uIndex)->_iBlockAddr)->_iUKBlockPrev, _iHead);
_pMap->saveValue(&getBlockHead()->_iUKBlockNext, _pMap->item(uIndex)->_iBlockAddr);
_pMap->saveValue(&_pMap->item(uIndex)->_iBlockAddr, _iHead);
_pMap->saveValue(&getBlockHead()->_iUKBlockPrev, (uint32_t)0);
}
// 挂在主key链上
if(mainKey.getHeadPtr()->_iAddr == 0)
{
// 当前主key链上还没有元素
_pMap->saveValue(&mainKey.getHeadPtr()->_iAddr, _iHead);
_pMap->saveValue(&getBlockHead()->_iMKBlockNext, (uint32_t)0);
_pMap->saveValue(&getBlockHead()->_iMKBlockPrev, (uint32_t)0);
}
else
{
// 当前主key链上已经有元素
if(bHead)
{
// 挂在最前面
_pMap->saveValue(&getBlockHead(mainKey.getHeadPtr()->_iAddr)->_iMKBlockPrev, _iHead);
_pMap->saveValue(&getBlockHead()->_iMKBlockNext, mainKey.getHeadPtr()->_iAddr);
_pMap->saveValue(&mainKey.getHeadPtr()->_iAddr, _iHead);
_pMap->saveValue(&getBlockHead()->_iMKBlockPrev, (uint32_t)0);
}
else
{
// 挂到最后面
Block blkHead(_pMap, mainKey.getHeadPtr()->_iAddr);
uint32_t iLast = blkHead.getLastBlockHead(false);
_pMap->saveValue(&getBlockHead(iLast)->_iMKBlockNext, _iHead);
_pMap->saveValue(&getBlockHead()->_iMKBlockNext, (uint32_t)0);
_pMap->saveValue(&getBlockHead()->_iMKBlockPrev, iLast);
}
}
// 挂在Set链表的头部
if(_pMap->_pHead->_iSetHead == 0)
{
assert(_pMap->_pHead->_iSetTail == 0);
_pMap->saveValue(&_pMap->_pHead->_iSetHead, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iSetTail, _iHead);
}
else
{
assert(_pMap->_pHead->_iSetTail != 0);
_pMap->saveValue(&getBlockHead()->_iSetNext, _pMap->_pHead->_iSetHead);
_pMap->saveValue(&getBlockHead(_pMap->_pHead->_iSetHead)->_iSetPrev, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iSetHead, _iHead);
}
}
void TC_Multi_HashMap::Block::erase()
{
//////////////////修改脏数据链表/////////////
if(_pMap->_pHead->_iDirtyTail == _iHead)
{
_pMap->saveValue(&_pMap->_pHead->_iDirtyTail, getBlockHead()->_iSetPrev);
}
//////////////////修改回写数据链表/////////////
if(_pMap->_pHead->_iSyncTail == _iHead)
{
_pMap->saveValue(&_pMap->_pHead->_iSyncTail, getBlockHead()->_iSetPrev);
}
////////////////////修改Set链表的数据//////////
{
bool bHead = (_pMap->_pHead->_iSetHead == _iHead);
bool bTail = (_pMap->_pHead->_iSetTail == _iHead);
if(!bHead)
{
if(bTail)
{
assert(getBlockHead()->_iSetNext == 0);
// 是尾部, 尾部指针指向上一个元素
_pMap->saveValue(&_pMap->_pHead->_iSetTail, getBlockHead()->_iSetPrev);
_pMap->saveValue(&getBlockHead(getBlockHead()->_iSetPrev)->_iSetNext, (uint32_t)0);
}
else
{
// 不是头部也不是尾部
assert(getBlockHead()->_iSetNext != 0);
_pMap->saveValue(&getBlockHead(getBlockHead()->_iSetPrev)->_iSetNext, getBlockHead()->_iSetNext);
_pMap->saveValue(&getBlockHead(getBlockHead()->_iSetNext)->_iSetPrev, getBlockHead()->_iSetPrev);
}
}
else
{
if(bTail)
{
assert(getBlockHead()->_iSetNext == 0);
assert(getBlockHead()->_iSetPrev == 0);
// 头部也是尾部, 指针都设置为0
_pMap->saveValue(&_pMap->_pHead->_iSetHead, (uint32_t)0);
_pMap->saveValue(&_pMap->_pHead->_iSetTail, (uint32_t)0);
}
else
{
// 头部不是尾部, 头部指针指向下一个元素
assert(getBlockHead()->_iSetNext != 0);
_pMap->saveValue(&_pMap->_pHead->_iSetHead, getBlockHead()->_iSetNext);
// 下一个元素上指针为0
_pMap->saveValue(&getBlockHead(getBlockHead()->_iSetNext)->_iSetPrev, (uint32_t)0);
}
}
}
////////////////////修改主key链表的数据//////////
//
{
MainKey mainKey(_pMap, getBlockHead()->_iMainKey);
if(getBlockHead()->_iMKBlockPrev != 0)
{
// 将上一下block指向下一个
_pMap->saveValue(&getBlockHead(getBlockHead()->_iMKBlockPrev)->_iMKBlockNext, getBlockHead()->_iMKBlockNext);
}
else
{
// 主key链上的第一个
_pMap->saveValue(&mainKey.getHeadPtr()->_iAddr, getBlockHead()->_iMKBlockNext);
}
if(getBlockHead()->_iMKBlockNext != 0)
{
// 将下一个block指向上一个
_pMap->saveValue(&getBlockHead(getBlockHead()->_iMKBlockNext)->_iMKBlockPrev, getBlockHead()->_iMKBlockPrev);
}
}
///////////////////从block链表中去掉///////////
//
//上一个block指向下一个block
if(getBlockHead()->_iUKBlockPrev != 0)
{
_pMap->saveValue(&getBlockHead(getBlockHead()->_iUKBlockPrev)->_iUKBlockNext, getBlockHead()->_iUKBlockNext);
}
//下一个block指向上一个
if(getBlockHead()->_iUKBlockNext != 0)
{
_pMap->saveValue(&getBlockHead(getBlockHead()->_iUKBlockNext)->_iUKBlockPrev, getBlockHead()->_iUKBlockPrev);
}
//////////////////如果是hash头部, 需要修改hash索引数据指针//////
//
_pMap->delListCount(getBlockHead()->_iIndex);
if(getBlockHead()->_iUKBlockPrev == 0)
{
//如果是hash桶的头部, 则还需要处理
TC_Multi_HashMap::tagHashItem *pItem = _pMap->item(getBlockHead()->_iIndex);
assert(pItem->_iBlockAddr == _iHead);
if(pItem->_iBlockAddr == _iHead)
{
_pMap->saveValue(&pItem->_iBlockAddr, getBlockHead()->_iUKBlockNext);
}
}
//////////////////脏数据///////////////////
//
if (isDirty())
{
_pMap->delDirtyCount();
}
if(isOnlyKey())
{
_pMap->delOnlyKeyCount();
}
//元素个数减少
_pMap->delElementCount();
// 减少主key下数据个数
MainKey mainKey(_pMap, getBlockHead()->_iMainKey);
_pMap->saveValue(&mainKey.getHeadPtr()->_iBlockCount, mainKey.getHeadPtr()->_iBlockCount - 1);
_pMap->updateMaxMainKeyBlockCount(mainKey.getHeadPtr()->_iBlockCount);
// 手工置空一些参数使在数据恢复区建立记录以便crash后恢复
_pMap->saveValue(&getBlockHead()->_iSize, (uint32_t)0);
_pMap->saveValue(&getBlockHead()->_iIndex, (uint32_t)0);
_pMap->saveValue(&getBlockHead()->_iSyncTime, (time_t)0);
_pMap->saveValue(&getBlockHead()->_iBitset, (uint8_t)0);
_pMap->saveValue(&getBlockHead()->_iDataLen, (uint32_t)0);
// 特别地这里一定要手工置block指向的mainkey为空否则crash后的恢复将无法建立起block与mainkey的联系
_pMap->saveValue(&getBlockHead()->_iMainKey, (uint32_t)0);
// 归还内存前先确认上述修改,因为内存被释放后是不能恢复的
// 即使后面的内存释放失败也不会造成数据的破坏,只会造成一个数据的丢失
_pMap->doUpdate();
//归还到内存中
deallocate();
}
void TC_Multi_HashMap::Block::refreshSetList()
{
assert(_pMap->_pHead->_iSetHead != 0);
assert(_pMap->_pHead->_iSetTail != 0);
//修改同步链表
if(_pMap->_pHead->_iSyncTail == _iHead && _pMap->_pHead->_iSetHead != _iHead)
{
_pMap->saveValue(&_pMap->_pHead->_iSyncTail, getBlockHead()->_iSetPrev);
}
//修改脏数据尾部链表指针, 不仅一个元素
if(_pMap->_pHead->_iDirtyTail == _iHead && _pMap->_pHead->_iSetHead != _iHead)
{
//脏数据尾部位置前移
_pMap->saveValue(&_pMap->_pHead->_iDirtyTail, getBlockHead()->_iSetPrev);
}
else if (_pMap->_pHead->_iDirtyTail == 0)
{
//原来没有脏数据
_pMap->saveValue(&_pMap->_pHead->_iDirtyTail, _iHead);
}
//是头部数据或者set新数据时走到这个分支
if(_pMap->_pHead->_iSetHead == _iHead)
{
//刷新Get链
MainKey mainKey(_pMap, getBlockHead()->_iMainKey);
mainKey.refreshGetList();
return;
}
uint32_t iPrev = getBlockHead()->_iSetPrev;
uint32_t iNext = getBlockHead()->_iSetNext;
assert(iPrev != 0);
//挂在链表头部
_pMap->saveValue(&getBlockHead()->_iSetNext, _pMap->_pHead->_iSetHead);
_pMap->saveValue(&getBlockHead(_pMap->_pHead->_iSetHead)->_iSetPrev, _iHead);
_pMap->saveValue(&_pMap->_pHead->_iSetHead, _iHead);
_pMap->saveValue(&getBlockHead()->_iSetPrev, (uint32_t)0);
//上一个元素的Next指针指向下一个元素
_pMap->saveValue(&getBlockHead(iPrev)->_iSetNext, iNext);
//下一个元素的Prev指向上一个元素
if (iNext != 0)
{
_pMap->saveValue(&getBlockHead(iNext)->_iSetPrev, iPrev);
}
else
{
//改变尾部指针
assert(_pMap->_pHead->_iSetTail == _iHead);
_pMap->saveValue(&_pMap->_pHead->_iSetTail, iPrev);
}
//刷新Get链
MainKey mainKey(_pMap, getBlockHead()->_iMainKey);
mainKey.refreshGetList();
}
void TC_Multi_HashMap::Block::deallocate(uint32_t iChunk)
{
tagChunkHead *pChunk = getChunkHead(iChunk);
vector<uint32_t> v;
v.push_back(iChunk);
//获取所有后续的chunk地址
while(true)
{
if(pChunk->_bNextChunk)
{
v.push_back(pChunk->_iNextChunk);
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
break;
}
}
//空间全部释放掉
_pMap->_pDataAllocator->deallocateMemChunk(v);
}
int TC_Multi_HashMap::Block::allocate(uint32_t iDataLen, vector<TC_Multi_HashMap::Value> &vtData)
{
uint32_t fn = 0;
// 第一个chunk的有效数据容量
fn = getBlockHead()->_iSize - sizeof(tagBlockHead);
if(fn >= iDataLen)
{
// 一个chunk就可以了, 后续的chunk都要释放掉
if(HASNEXTCHUNK())
{
uint32_t iNextChunk = getBlockHead()->_iNextChunk;
// 先修改自己的区块
_pMap->saveValue(&getBlockHead()->_iBitset, NEXTCHUNK_BIT, false);
_pMap->saveValue(&getBlockHead()->_iDataLen, (uint32_t)0);
// 修改成功后再释放区块, 从而保证, 不会core的时候导致整个内存块不可用
deallocate(iNextChunk);
}
return TC_Multi_HashMap::RT_OK;
}
// 计算还需要多少长度
fn = iDataLen - fn;
if(HASNEXTCHUNK())
{
tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
while(true)
{
if(fn <= (pChunk->_iSize - sizeof(tagChunkHead)))
{
//已经不需要chunk了, 释放多余的chunk
if(pChunk->_bNextChunk)
{
uint32_t iNextChunk = pChunk->_iNextChunk;
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
//一旦异常core, 最坏的情况就是少了可用的区块, 但是整个内存结构还是可用的
deallocate(iNextChunk);
}
return TC_Multi_HashMap::RT_OK ;
}
//计算, 还需要多少长度
fn -= pChunk->_iSize - sizeof(tagChunkHead);
if(pChunk->_bNextChunk)
{
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
//没有后续chunk了, 需要新分配fn的空间
vector<uint32_t> chunks;
int ret = allocateChunk(fn, chunks, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
//没有内存可以分配
return ret;
}
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)true);
_pMap->saveValue(&pChunk->_iNextChunk, chunks[0]);
//chunk指向分配的第一个chunk
pChunk = getChunkHead(chunks[0]);
//修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
//连接每个chunk
return joinChunk(pChunk, chunks);
}
}
}
else
{
//没有后续chunk了, 需要新分配fn空间
vector<uint32_t> chunks;
int ret = allocateChunk(fn, chunks, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
//没有内存可以分配
return ret;
}
_pMap->saveValue(&getBlockHead()->_iBitset, NEXTCHUNK_BIT, true);
_pMap->saveValue(&getBlockHead()->_iNextChunk, chunks[0]);
//chunk指向分配的第一个chunk
tagChunkHead *pChunk = getChunkHead(chunks[0]);
//修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
//连接每个chunk
return joinChunk(pChunk, chunks);
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::Block::joinChunk(tagChunkHead *pChunk, const vector<uint32_t>& chunks)
{
for (size_t i = 0; i < chunks.size(); ++i)
{
if (i == chunks.size() - 1)
{
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
return TC_Multi_HashMap::RT_OK;
}
else
{
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)true);
_pMap->saveValue(&pChunk->_iNextChunk, chunks[i+1]);
pChunk = getChunkHead(chunks[i+1]);
_pMap->saveValue(&pChunk->_bNextChunk, (uint8_t)false);
_pMap->saveValue(&pChunk->_iDataLen, (uint32_t)0);
}
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::Block::allocateChunk(uint32_t fn, vector<uint32_t> &chunks, vector<TC_Multi_HashMap::Value> &vtData)
{
assert(fn > 0);
while(true)
{
uint32_t iAllocSize = fn;
// 分配空间
// 正在分配的block所属的主key是不能被淘汰的
uint32_t t = _pMap->_pDataAllocator->allocateChunk(getBlockHead()->_iMainKey, iAllocSize, vtData);
if (t == 0)
{
//没有内存可以分配了, 先把分配的归还
_pMap->_pDataAllocator->deallocateMemChunk(chunks);
chunks.clear();
return TC_Multi_HashMap::RT_NO_MEMORY;
}
//设置分配的数据块的大小
getChunkHead(t)->_iSize = iAllocSize;
chunks.push_back(t);
//分配够了
if(fn <= (iAllocSize - sizeof(tagChunkHead)))
{
break;
}
//还需要多少空间
fn -= iAllocSize - sizeof(tagChunkHead);
}
return TC_Multi_HashMap::RT_OK;
}
uint32_t TC_Multi_HashMap::Block::getDataLen()
{
uint32_t n = 0;
if(!HASNEXTCHUNK())
{
n += getBlockHead()->_iDataLen;
return n;
}
//当前块的大小
n += getBlockHead()->_iSize - sizeof(tagBlockHead);
tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
while (true)
{
if(pChunk->_bNextChunk)
{
//当前块的大小
n += pChunk->_iSize - sizeof(tagChunkHead);
pChunk = getChunkHead(pChunk->_iNextChunk);
}
else
{
n += pChunk->_iDataLen;
break;
}
}
return n;
}
////////////////////////////////////////////////////////
uint32_t TC_Multi_HashMap::BlockAllocator::allocateMemBlock(uint32_t iMainKeyAddr, uint32_t index, bool bHead,
uint32_t &iAllocSize, vector<TC_Multi_HashMap::Value> &vtData)
{
begin:
size_t iAddr = 0;
size_t bigSize = iAllocSize;
_pChunkAllocator->allocate2(bigSize, bigSize, iAddr);
iAllocSize = (uint32_t)bigSize;
if(iAddr == 0)
{
size_t ret = _pMap->eraseExcept(iMainKeyAddr, vtData);
if(ret == 0)
{
return 0; //没有空间可以释放了
}
goto begin;
}
// 初始化block头部信息
Block block(_pMap, (uint32_t)iAddr);
block.makeNew(iMainKeyAddr, index, iAllocSize, bHead);
_pMap->incChunkCount();
return (uint32_t)iAddr;
}
uint32_t TC_Multi_HashMap::BlockAllocator::allocateMainKeyHead(uint32_t index, vector<TC_Multi_HashMap::Value> &vtData)
{
size_t iAllocSize = sizeof(MainKey::tagMainKeyHead);
begin:
size_t iAddr = 0;
_pChunkAllocator->allocate2(iAllocSize, iAllocSize, iAddr);
if(iAddr == 0)
{
size_t ret = _pMap->eraseExcept(0, vtData);
if(ret == 0)
{
return 0; //没有空间可以释放了
}
goto begin;
}
// 分配的新的MemBlock, 初始化一下
MainKey mainKey(_pMap, (uint32_t)iAddr);
mainKey.makeNew(index, (uint32_t)iAllocSize);
_pMap->incChunkCount();
return (uint32_t)iAddr;
}
uint32_t TC_Multi_HashMap::BlockAllocator::allocateChunk(uint32_t iAddr, uint32_t &iAllocSize, vector<TC_Multi_HashMap::Value> &vtData)
{
begin:
size_t iChunkAddr = 0;
size_t bigSize = iAllocSize;
_pChunkAllocator->allocate2(bigSize, bigSize, iChunkAddr);
iAllocSize = (uint32_t)bigSize;
if(iChunkAddr == 0)
{
size_t ret = _pMap->eraseExcept(iAddr, vtData);
if(ret == 0)
{
return 0; //没有空间可以释放了
}
goto begin;
}
_pMap->incChunkCount();
return iChunkAddr;
}
void TC_Multi_HashMap::BlockAllocator::deallocateMemChunk(const vector<uint32_t> &v)
{
for(size_t i = 0; i < v.size(); i++)
{
_pChunkAllocator->deallocate2(v[i]);
_pMap->delChunkCount();
}
}
void TC_Multi_HashMap::BlockAllocator::deallocateMemChunk(uint32_t iChunk)
{
_pChunkAllocator->deallocate2(iChunk);
_pMap->delChunkCount();
}
///////////////////////////////////////////////////////////////////
TC_Multi_HashMap::HashMapLockItem::HashMapLockItem(TC_Multi_HashMap *pMap, uint32_t iAddr)
: _pMap(pMap)
, _iAddr(iAddr)
{
}
TC_Multi_HashMap::HashMapLockItem::HashMapLockItem(const HashMapLockItem &mcmdi)
: _pMap(mcmdi._pMap)
, _iAddr(mcmdi._iAddr)
{
}
TC_Multi_HashMap::HashMapLockItem &TC_Multi_HashMap::HashMapLockItem::operator=(const TC_Multi_HashMap::HashMapLockItem &mcmdi)
{
if(this != &mcmdi)
{
_pMap = mcmdi._pMap;
_iAddr = mcmdi._iAddr;
}
return (*this);
}
bool TC_Multi_HashMap::HashMapLockItem::operator==(const TC_Multi_HashMap::HashMapLockItem &mcmdi)
{
return _pMap == mcmdi._pMap && _iAddr == mcmdi._iAddr;
}
bool TC_Multi_HashMap::HashMapLockItem::operator!=(const TC_Multi_HashMap::HashMapLockItem &mcmdi)
{
return _pMap != mcmdi._pMap || _iAddr != mcmdi._iAddr;
}
bool TC_Multi_HashMap::HashMapLockItem::isDirty()
{
Block block(_pMap, _iAddr);
return block.isDirty();
}
bool TC_Multi_HashMap::HashMapLockItem::isOnlyKey()
{
Block block(_pMap, _iAddr);
return block.isOnlyKey();
}
time_t TC_Multi_HashMap::HashMapLockItem::getSyncTime()
{
Block block(_pMap, _iAddr);
return block.getSyncTime();
}
int TC_Multi_HashMap::HashMapLockItem::get(TC_Multi_HashMap::Value &v)
{
Block block(_pMap, _iAddr);
MainKey mainKey(_pMap, block.getBlockHead()->_iMainKey);
// 先获取主key
int ret = mainKey.get(v._mkey);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
// 获取数据
ret = block.getBlockData(v._data);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::HashMapLockItem::get(string &mk, string &uk)
{
Block block(_pMap, _iAddr);
MainKey mainKey(_pMap, block.getBlockHead()->_iMainKey);
// 获取主key
int ret = mainKey.get(mk);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
// 获取数据区
string s;
ret = block.get(s);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
try
{
// 提取除主key外的联合主键
TC_PackOut po(s.c_str(), s.length());
po >> uk;
}
catch ( exception &ex )
{
return TC_Multi_HashMap::RT_EXCEPTION_ERR;
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::HashMapLockItem::set(const string &mk, const string &uk,
const string &v, uint8_t iVersion, vector<TC_Multi_HashMap::Value> &vtData)
{
Block block(_pMap, _iAddr);
TC_PackIn pi;
pi << uk; // 数据区只存放uk不存mk节省空间
pi << v;
return block.set(pi.topacket().c_str(), pi.topacket().length(), false, iVersion, vtData);
}
int TC_Multi_HashMap::HashMapLockItem::set(const string &mk, const string &uk, vector<TC_Multi_HashMap::Value> &vtData)
{
Block block(_pMap, _iAddr);
TC_PackIn pi;
pi << uk; // 数据区只存放uk
return block.set(pi.topacket().c_str(), pi.topacket().length(), true, 0, vtData);
}
bool TC_Multi_HashMap::HashMapLockItem::equal(const string &mk, const string &uk, TC_Multi_HashMap::Value &v, int &ret)
{
ret = get(v);
if ((ret == TC_Multi_HashMap::RT_OK || ret == TC_Multi_HashMap::RT_ONLY_KEY)
&& mk == v._mkey && uk == v._data._key)
{
return true;
}
return false;
}
bool TC_Multi_HashMap::HashMapLockItem::equal(const string &mk, const string &uk, int &ret)
{
string mk1, uk1;
ret = get(mk1, uk1);
if (ret == TC_Multi_HashMap::RT_OK && mk == mk1 && uk == uk1)
{
return true;
}
return false;
}
void TC_Multi_HashMap::HashMapLockItem::nextItem(int iType)
{
if(_iAddr == 0)
{
// 到头了
return;
}
Block block(_pMap, _iAddr);
if(iType == HashMapLockIterator::IT_BLOCK)
{
// 按联合主键索引下的block链遍历
uint32_t index = block.getBlockHead()->_iIndex;
//当前block链表有元素
if(block.nextBlock())
{
_iAddr = block.getHead();
return;
}
index += 1;
while(index < _pMap->_hash.size())
{
//当前的hash桶也没有数据
if (_pMap->item(index)->_iBlockAddr == 0)
{
++index;
continue;
}
_iAddr = _pMap->item(index)->_iBlockAddr;
return;
}
_iAddr = 0; //到尾部了
}
else if(iType == HashMapLockIterator::IT_SET)
{
// 按set链遍历
_iAddr = block.getBlockHead()->_iSetNext;
}
else if(iType == HashMapLockIterator::IT_GET)
{
// 按get(同一主key下的block)链遍历即获取下一个get链上的数据
_iAddr = block.getBlockHead()->_iMKBlockNext;
if(_iAddr == 0)
{
// 当前主key下的block链已经没有数据了移动GET链上的下一个主key链
MainKey mainKey(_pMap, block.getBlockHead()->_iMainKey);
while(mainKey.getHeadPtr()->_iGetNext)
{
mainKey = MainKey(_pMap, mainKey.getHeadPtr()->_iGetNext);
_iAddr = mainKey.getHeadPtr()->_iAddr;
if(_iAddr != 0)
{
break;
}
}
}
}
else if(iType == HashMapLockIterator::IT_MKEY)
{
// 按同一主key下block链遍历
_iAddr = block.getBlockHead()->_iMKBlockNext;
}
else if(iType == HashMapLockIterator::IT_UKEY)
{
// 按同一联合主键索引的block链遍历
_iAddr = block.getBlockHead()->_iUKBlockNext;
}
}
void TC_Multi_HashMap::HashMapLockItem::prevItem(int iType)
{
if(_iAddr == 0)
{
// 到头了
return;
}
Block block(_pMap, _iAddr);
if(iType == HashMapLockIterator::IT_BLOCK)
{
// 按联合主键索引下的block链遍历
uint32_t index = block.getBlockHead()->_iIndex;
if(block.prevBlock())
{
_iAddr = block.getHead();
return;
}
while(index > 0)
{
//当前的hash桶也没有数据
if (_pMap->item(index-1)->_iBlockAddr == 0)
{
--index;
continue;
}
//需要到这个桶的末尾
Block tmp(_pMap, _pMap->item(index-1)->_iBlockAddr);
_iAddr = tmp.getLastBlockHead(true);
return;
}
_iAddr = 0; //到尾部了
}
else if(iType == HashMapLockIterator::IT_SET)
{
// 按set链遍历
_iAddr = block.getBlockHead()->_iSetPrev;
}
else if(iType == HashMapLockIterator::IT_GET)
{
// 按get(同一主key下的block)链遍历即获取下一个get链上的数据
_iAddr = block.getBlockHead()->_iMKBlockPrev;
if(_iAddr == 0)
{
// 当前主key下的block链已经没有数据了移动get链上的上一个主key链
MainKey mainKey(_pMap, block.getBlockHead()->_iMainKey);
while(mainKey.getHeadPtr()->_iGetPrev)
{
mainKey = MainKey(_pMap, mainKey.getHeadPtr()->_iGetPrev);
_iAddr = mainKey.getHeadPtr()->_iAddr;
if(_iAddr != 0)
{
// 移动到主key链上的最后一个block
Block tmp(_pMap, _iAddr);
while(tmp.getBlockHead()->_iMKBlockNext)
{
_iAddr = tmp.getBlockHead()->_iMKBlockNext;
tmp = Block(_pMap, _iAddr);
}
break;
}
}
}
}
else if(iType == HashMapLockIterator::IT_MKEY)
{
// 按同一主key下block链遍历
_iAddr = block.getBlockHead()->_iMKBlockPrev;
}
else if(iType == HashMapLockIterator::IT_UKEY)
{
// 按同一联合主键索引的block链遍历
_iAddr = block.getBlockHead()->_iUKBlockPrev;
}
}
///////////////////////////////////////////////////////////////////
TC_Multi_HashMap::HashMapLockIterator::HashMapLockIterator()
: _pMap(NULL), _iItem(NULL, 0), _iType(IT_BLOCK), _iOrder(IT_NEXT)
{
}
TC_Multi_HashMap::HashMapLockIterator::HashMapLockIterator(TC_Multi_HashMap *pMap, uint32_t iAddr, int iType, int iOrder)
: _pMap(pMap), _iItem(_pMap, iAddr), _iType(iType), _iOrder(iOrder)
{
}
TC_Multi_HashMap::HashMapLockIterator::HashMapLockIterator(const HashMapLockIterator &it)
: _pMap(it._pMap),_iItem(it._iItem), _iType(it._iType), _iOrder(it._iOrder)
{
}
TC_Multi_HashMap::HashMapLockIterator& TC_Multi_HashMap::HashMapLockIterator::operator=(const HashMapLockIterator &it)
{
if(this != &it)
{
_pMap = it._pMap;
_iItem = it._iItem;
_iType = it._iType;
_iOrder = it._iOrder;
}
return (*this);
}
bool TC_Multi_HashMap::HashMapLockIterator::operator==(const HashMapLockIterator& mcmi)
{
if (_iItem.getAddr() != 0 || mcmi._iItem.getAddr() != 0)
{
return _pMap == mcmi._pMap
&& _iItem == mcmi._iItem
&& _iType == mcmi._iType
&& _iOrder == mcmi._iOrder;
}
return _pMap == mcmi._pMap;
}
bool TC_Multi_HashMap::HashMapLockIterator::operator!=(const HashMapLockIterator& mcmi)
{
if (_iItem.getAddr() != 0 || mcmi._iItem.getAddr() != 0 )
{
return _pMap != mcmi._pMap
|| _iItem != mcmi._iItem
|| _iType != mcmi._iType
|| _iOrder != mcmi._iOrder;
}
return _pMap != mcmi._pMap;
}
TC_Multi_HashMap::HashMapLockIterator& TC_Multi_HashMap::HashMapLockIterator::operator++()
{
if(_iOrder == IT_NEXT)
{
// 顺序遍历
_iItem.nextItem(_iType);
}
else
{
// 逆序遍历
_iItem.prevItem(_iType);
}
return (*this);
}
TC_Multi_HashMap::HashMapLockIterator TC_Multi_HashMap::HashMapLockIterator::operator++(int)
{
HashMapLockIterator it(*this);
if(_iOrder == IT_NEXT)
{
// 顺序遍历
_iItem.nextItem(_iType);
}
else
{
// 逆序遍历
_iItem.prevItem(_iType);
}
return it;
}
///////////////////////////////////////////////////////////////////
TC_Multi_HashMap::HashMapItem::HashMapItem(TC_Multi_HashMap *pMap, uint32_t iIndex)
: _pMap(pMap)
, _iIndex(iIndex)
{
}
TC_Multi_HashMap::HashMapItem::HashMapItem(const HashMapItem &mcmdi)
: _pMap(mcmdi._pMap)
, _iIndex(mcmdi._iIndex)
{
}
TC_Multi_HashMap::HashMapItem &TC_Multi_HashMap::HashMapItem::operator=(const TC_Multi_HashMap::HashMapItem &mcmdi)
{
if(this != &mcmdi)
{
_pMap = mcmdi._pMap;
_iIndex = mcmdi._iIndex;
}
return (*this);
}
bool TC_Multi_HashMap::HashMapItem::operator==(const TC_Multi_HashMap::HashMapItem &mcmdi)
{
return _pMap == mcmdi._pMap && _iIndex == mcmdi._iIndex;
}
bool TC_Multi_HashMap::HashMapItem::operator!=(const TC_Multi_HashMap::HashMapItem &mcmdi)
{
return _pMap != mcmdi._pMap || _iIndex != mcmdi._iIndex;
}
void TC_Multi_HashMap::HashMapItem::get(vector<TC_Multi_HashMap::Value> &vtData)
{
uint32_t iAddr = _pMap->item(_iIndex)->_iBlockAddr;
while(iAddr != 0)
{
Block block(_pMap, iAddr);
MainKey mainKey(_pMap, block.getBlockHead()->_iMainKey);
TC_Multi_HashMap::Value data;
// 获取主key
int ret = mainKey.get(data._mkey);
if(ret == TC_Multi_HashMap::RT_OK)
{
// 获取联合主键及数据
ret = block.getBlockData(data._data);
if(ret == TC_Multi_HashMap::RT_OK)
{
vtData.push_back(data);
}
}
iAddr = block.getBlockHead()->_iUKBlockNext;
}
}
void TC_Multi_HashMap::HashMapItem::nextItem()
{
if(_iIndex == (uint32_t)(-1))
{
return;
}
if(_iIndex >= _pMap->getHashCount() - 1)
{
_iIndex = (uint32_t)(-1);
return;
}
_iIndex++;
}
///////////////////////////////////////////////////////////////////
TC_Multi_HashMap::HashMapIterator::HashMapIterator()
: _pMap(NULL), _iItem(NULL, (uint32_t)-1)
{
}
TC_Multi_HashMap::HashMapIterator::HashMapIterator(TC_Multi_HashMap *pMap, uint32_t iIndex)
: _pMap(pMap), _iItem(_pMap, iIndex)
{
}
TC_Multi_HashMap::HashMapIterator::HashMapIterator(const HashMapIterator &it)
: _pMap(it._pMap),_iItem(it._iItem)
{
}
TC_Multi_HashMap::HashMapIterator& TC_Multi_HashMap::HashMapIterator::operator=(const HashMapIterator &it)
{
if(this != &it)
{
_pMap = it._pMap;
_iItem = it._iItem;
}
return (*this);
}
bool TC_Multi_HashMap::HashMapIterator::operator==(const HashMapIterator& mcmi)
{
if (_iItem.getIndex() != (uint32_t)-1 || mcmi._iItem.getIndex() != (uint32_t)-1)
{
return _pMap == mcmi._pMap && _iItem == mcmi._iItem;
}
return _pMap == mcmi._pMap;
}
bool TC_Multi_HashMap::HashMapIterator::operator!=(const HashMapIterator& mcmi)
{
if (_iItem.getIndex() != (uint32_t)-1 || mcmi._iItem.getIndex() != (uint32_t)-1 )
{
return _pMap != mcmi._pMap || _iItem != mcmi._iItem;
}
return _pMap != mcmi._pMap;
}
TC_Multi_HashMap::HashMapIterator& TC_Multi_HashMap::HashMapIterator::operator++()
{
_iItem.nextItem();
return (*this);
}
TC_Multi_HashMap::HashMapIterator TC_Multi_HashMap::HashMapIterator::operator++(int)
{
HashMapIterator it(*this);
_iItem.nextItem();
return it;
}
//////////////////////////////////////////////////////////////////////////////////
void TC_Multi_HashMap::init(void *pAddr)
{
_pHead = static_cast<tagMapHead*>(pAddr);
_pstModifyHead = static_cast<tagModifyHead*>((void*)((char*)pAddr + sizeof(tagMapHead)));
}
void TC_Multi_HashMap::initDataBlockSize(size_t iMinDataSize, size_t iMaxDataSize, float fFactor)
{
_iMinDataSize = iMinDataSize;
_iMaxDataSize = iMaxDataSize;
_fFactor = fFactor;
}
void TC_Multi_HashMap::create(void *pAddr, size_t iSize)
{
if(sizeof(tagHashItem)
+ sizeof(tagMainKeyHashItem)
+ sizeof(tagMapHead)
+ sizeof(tagModifyHead)
+ sizeof(TC_MemMultiChunkAllocator::tagChunkAllocatorHead)
+ 10 > iSize)
{
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::create] mem size not enougth.");
}
if(_iMinDataSize == 0 || _iMaxDataSize == 0 || _fFactor < 1.0)
{
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::create] init data size error:" + TC_Common::tostr(_iMinDataSize) + "|" + TC_Common::tostr(_iMaxDataSize) + "|" + TC_Common::tostr(_fFactor));
}
init(pAddr);
_pHead->_cMaxVersion = MAX_VERSION;
_pHead->_cMinVersion = MIN_VERSION;
_pHead->_bReadOnly = false;
_pHead->_bAutoErase = true;
_pHead->_cEraseMode = ERASEBYGET;
_pHead->_iMemSize = iSize;
_pHead->_iMinDataSize = _iMinDataSize;
_pHead->_iMaxDataSize = _iMaxDataSize;
_pHead->_fFactor = _fFactor;
_pHead->_fHashRatio = _fHashRatio;
_pHead->_fMainKeyRatio = _fMainKeyRatio;
_pHead->_iElementCount = 0;
_pHead->_iEraseCount = 10;
_pHead->_iSetHead = 0;
_pHead->_iSetTail = 0;
_pHead->_iGetHead = 0;
_pHead->_iGetTail = 0;
_pHead->_iDirtyCount = 0;
_pHead->_iDirtyTail = 0;
_pHead->_iSyncTime = 60 * 10; //缺省十分钟回写一次
_pHead->_iUsedChunk = 0;
_pHead->_iGetCount = 0;
_pHead->_iHitCount = 0;
_pHead->_iBackupTail = 0;
_pHead->_iSyncTail = 0;
_pHead->_iMKOnlyKeyCount= 0;
_pHead->_iOnlyKeyCount = 0;
_pHead->_iMaxBlockCount = 0;
memset(_pHead->_iReserve, 0, sizeof(_pHead->_iReserve));
size_t iMaxHeadSize = sizeof(Block::tagBlockHead) > sizeof(MainKey::tagMainKeyHead) ?
sizeof(Block::tagBlockHead) : sizeof(MainKey::tagMainKeyHead);
// 计算平均block大小
size_t iBlockSize = (_pHead->_iMinDataSize + _pHead->_iMaxDataSize)/2 + iMaxHeadSize;
// 计算近似主key Hash个数
size_t iMHashCount = (iSize - sizeof(tagMapHead) - sizeof(tagModifyHead) - sizeof(TC_MemChunkAllocator::tagChunkAllocatorHead)) /
((size_t)(iBlockSize*_fHashRatio*_fMainKeyRatio) +
(size_t)(sizeof(tagHashItem)*_fMainKeyRatio) + sizeof(tagMainKeyHashItem));
// 采用最近的素数作为hash值
iMHashCount = getMinPrimeNumber(iMHashCount);
// 联合hash个数
size_t iUHashCount = getMinPrimeNumber(size_t(iMHashCount * _fMainKeyRatio));
void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
// 主key hash索引区
size_t iHashMemSize = TC_MemVector<tagMainKeyHashItem>::calcMemSize(iMHashCount);
if((char*)pHashAddr - (char*)_pHead + iHashMemSize > iSize)
{
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::create] mem size not enougth.");
}
_hashMainKey.create(pHashAddr, iHashMemSize);
pHashAddr = (char*)pHashAddr + _hashMainKey.getMemSize();
// 联合hash索引区
iHashMemSize = TC_MemVector<tagHashItem>::calcMemSize(iUHashCount);
if((char*)pHashAddr - (char*)_pHead + iHashMemSize > iSize)
{
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::create] mem size not enougth.");
}
_hash.create(pHashAddr, iHashMemSize);
// chunk数据区
void *pDataAddr = (char*)pHashAddr + _hash.getMemSize();
if((char*)pDataAddr - (char*)_pHead + iMaxHeadSize + _pHead->_iMinDataSize > iSize)
{
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::create] mem size not enougth.");
}
_pDataAllocator->create(pDataAddr, iSize - ((char*)pDataAddr - (char*)_pHead),
iMaxHeadSize + _pHead->_iMinDataSize, iMaxHeadSize + _pHead->_iMaxDataSize, _pHead->_fFactor);
}
void TC_Multi_HashMap::connect(void *pAddr, size_t iSize)
{
init(pAddr);
if(_pHead->_cMaxVersion != MAX_VERSION || _pHead->_cMinVersion != MIN_VERSION)
{
// 版本不匹配
ostringstream os;
os << (int)_pHead->_cMaxVersion << "." << (int)_pHead->_cMinVersion << " != " << ((int)MAX_VERSION) << "." << ((int)MIN_VERSION);
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::connect] hash map version not equal:" + os.str() + " (data != code)");
}
if(_pHead->_iMemSize != iSize)
{
// 内存大小不匹配
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::connect] hash map size not equal:" + TC_Common::tostr(_pHead->_iMemSize) + "!=" + TC_Common::tostr(iSize));
}
// 连接主key hash区
void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
_hashMainKey.connect(pHashAddr);
// 连接联合hash区
pHashAddr = (char*)pHashAddr + _hashMainKey.getMemSize();
_hash.connect(pHashAddr);
// 连接chunk区
void *pDataAddr = (char*)pHashAddr + _hash.getMemSize();
_pDataAllocator->connect(pDataAddr);
_iMinDataSize = _pHead->_iMinDataSize;
_iMaxDataSize = _pHead->_iMaxDataSize;
_fFactor = _pHead->_fFactor;
_fHashRatio = _pHead->_fHashRatio;
_fMainKeyRatio = _pHead->_fMainKeyRatio;
// 恢复可能的错误
doRecover();
}
int TC_Multi_HashMap::append(void *pAddr, size_t iSize)
{
if(iSize <= _pHead->_iMemSize)
{
return -1;
}
init(pAddr);
if(_pHead->_cMaxVersion != MAX_VERSION || _pHead->_cMinVersion != MIN_VERSION)
{
// 版本不匹配
ostringstream os;
os << (int)_pHead->_cMaxVersion << "." << (int)_pHead->_cMinVersion << " != " << ((int)MAX_VERSION) << "." << ((int)MIN_VERSION);
throw TC_Multi_HashMap_Exception("[TC_Multi_HashMap::append] hash map version not equal:" + os.str() + " (data != code)");
}
_pHead->_iMemSize = iSize;
// 连接主key hash区
void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
_hashMainKey.connect(pHashAddr);
// 连接联合hash区
pHashAddr = (char*)pHashAddr + _hashMainKey.getMemSize();
_hash.connect(pHashAddr);
// 扩展chunk区
void *pDataAddr = (char*)pHashAddr + _hash.getMemSize();
_pDataAllocator->append(pDataAddr, iSize - ((size_t)pDataAddr - (size_t)pAddr));
_iMinDataSize = _pHead->_iMinDataSize;
_iMaxDataSize = _pHead->_iMaxDataSize;
_fFactor = _pHead->_fFactor;
_fHashRatio = _pHead->_fHashRatio;
_fMainKeyRatio = _pHead->_fMainKeyRatio;
return 0;
}
void TC_Multi_HashMap::clear()
{
assert(_pHead);
_pHead->_iElementCount = 0;
_pHead->_iSetHead = 0;
_pHead->_iSetTail = 0;
_pHead->_iGetHead = 0;
_pHead->_iGetTail = 0;
_pHead->_iDirtyCount = 0;
_pHead->_iDirtyTail = 0;
_pHead->_iUsedChunk = 0;
_pHead->_iGetCount = 0;
_pHead->_iHitCount = 0;
_pHead->_iBackupTail = 0;
_pHead->_iSyncTail = 0;
_hashMainKey.clear();
_hash.clear();
// 清除错误
doUpdate();
_pDataAllocator->rebuild();
}
int TC_Multi_HashMap::dump2file(const string &sFile)
{
FILE *fp = fopen(sFile.c_str(), "wb");
if(fp == NULL)
{
return RT_DUMP_FILE_ERR;
}
size_t ret = fwrite((void*)_pHead, 1, _pHead->_iMemSize, fp);
fclose(fp);
if(ret == _pHead->_iMemSize)
{
return RT_OK;
}
return RT_DUMP_FILE_ERR;
}
int TC_Multi_HashMap::load5file(const string &sFile)
{
FILE *fp = fopen(sFile.c_str(), "rb");
if(fp == NULL)
{
return RT_LOAD_FILE_ERR;
}
fseek(fp, 0L, SEEK_END);
size_t fs = ftell(fp);
if(fs != _pHead->_iMemSize)
{
fclose(fp);
return RT_LOAD_FILE_ERR;
}
fseek(fp, 0L, SEEK_SET);
size_t iSize = 1024*1024*10;
size_t iLen = 0;
char *pBuffer = new char[iSize];
bool bEof = false;
while(true)
{
int ret = fread(pBuffer, 1, iSize, fp);
if(ret != (int)iSize)
{
if(feof(fp))
{
bEof = true;
}
else
{
fclose(fp);
delete[] pBuffer;
return RT_LOAD_FILE_ERR;
}
}
//检查版本
if(iLen == 0)
{
if(pBuffer[0] != MAX_VERSION || pBuffer[1] != MIN_VERSION)
{
fclose(fp);
delete[] pBuffer;
return RT_VERSION_MISMATCH_ERR;
}
}
memcpy((char*)_pHead + iLen, pBuffer, ret);
iLen += ret;
if(bEof)
break;
}
fclose(fp);
delete[] pBuffer;
if(iLen == _pHead->_iMemSize)
{
return RT_OK;
}
return RT_LOAD_FILE_ERR;
}
int TC_Multi_HashMap::checkMainKey(const string &mk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = RT_OK;
uint32_t index = mhashIndex(mk);
if(itemMainKey(index)->_iMainKeyAddr == 0)
{
return RT_NO_DATA;
}
MainKey mainKey(this, itemMainKey(index)->_iMainKeyAddr);
do
{
string s;
ret = mainKey.get(s);
if(ret != RT_OK)
{
return ret;
}
if(s == mk)
{
incHitCount();
// 找到了
if(mainKey.getHeadPtr()->_iAddr == 0)
{
return RT_ONLY_KEY;
}
if(!mainKey.ISFULLDATA())
{
return RT_PART_DATA;
}
return RT_OK;
}
} while (mainKey.next());
return RT_NO_DATA;
}
int TC_Multi_HashMap::setFullData(const string &mk, bool bFull)
{
if(_pHead->_bReadOnly) return RT_READONLY;
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = RT_OK;
uint32_t index = mhashIndex(mk);
if(itemMainKey(index)->_iMainKeyAddr == 0)
{
return RT_NO_DATA;
}
MainKey mainKey(this, itemMainKey(index)->_iMainKeyAddr);
do
{
string s;
ret = mainKey.get(s);
if(ret != RT_OK)
{
return ret;
}
if(s == mk)
{
incHitCount();
// 找到了
mainKey.SETFULLDATA(bFull);
return RT_OK;
}
} while (mainKey.next());
return RT_NO_DATA;
}
int TC_Multi_HashMap::checkDirty(const string &mk, const string &uk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, ret);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
//没有数据
if(it == end())
{
return TC_Multi_HashMap::RT_NO_DATA;
}
incHitCount();
//只有Key
if(it->isOnlyKey())
{
return TC_Multi_HashMap::RT_ONLY_KEY;
}
Block block(this, it->getAddr());
if (block.isDirty())
{
return TC_Multi_HashMap::RT_DIRTY_DATA;
}
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::checkDirty(const string &mk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = RT_OK;
uint32_t index = mhashIndex(mk);
if(itemMainKey(index)->_iMainKeyAddr == 0)
{
return RT_NO_DATA;
}
MainKey mainKey(this, itemMainKey(index)->_iMainKeyAddr);
do
{
string s;
ret = mainKey.get(s);
if(ret != RT_OK)
{
return ret;
}
if(s == mk)
{
incHitCount();
// 找到了
if(mainKey.getHeadPtr()->_iAddr == 0)
{
ret = RT_ONLY_KEY;
}
lock_iterator it(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_MKEY, lock_iterator::IT_NEXT);
while(it != end())
{
if(it->isDirty())
{
if(_pHead->_iDirtyTail == 0)
{
_pHead->_iDirtyTail = mainKey.getHeadPtr()->_iAddr;
}
return RT_DIRTY_DATA;
}
it ++;
}
return RT_OK;
}
} while (mainKey.next());
return RT_NO_DATA;
}
int TC_Multi_HashMap::setDirty(const string &mk, const string &uk)
{
TC_Multi_HashMap::FailureRecover recover(this);
if(_pHead->_bReadOnly) return RT_READONLY;
incGetCount();
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it= find(mk, uk, index, ret);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
//没有数据或只有Key
if(it == end())
{
return TC_Multi_HashMap::RT_NO_DATA;
}
incHitCount();
//只有Key
if(it->isOnlyKey())
{
return TC_Multi_HashMap::RT_ONLY_KEY;
}
Block block(this, it->getAddr());
block.setDirty(true);
block.refreshSetList();
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::setClean(const string &mk, const string &uk)
{
TC_Multi_HashMap::FailureRecover recover(this);
if(_pHead->_bReadOnly) return RT_READONLY;
incGetCount();
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, ret);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
//没有数据或只有Key
if(it == end())
{
return TC_Multi_HashMap::RT_NO_DATA;
}
incHitCount();
//只有Key
if(it->isOnlyKey())
{
return TC_Multi_HashMap::RT_ONLY_KEY;
}
Block block(this, it->getAddr());
block.setDirty(false);
block.refreshSetList();
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::setSyncTime(const string &mk, const string &uk, time_t iSyncTime)
{
TC_Multi_HashMap::FailureRecover recover(this);
if(_pHead->_bReadOnly) return RT_READONLY;
incGetCount();
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, ret);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
//没有数据或只有Key
if(it == end())
{
return TC_Multi_HashMap::RT_NO_DATA;
}
incHitCount();
//只有Key
if(it->isOnlyKey())
{
return TC_Multi_HashMap::RT_ONLY_KEY;
}
Block block(this, it->getAddr());
block.setSyncTime(iSyncTime);
return TC_Multi_HashMap::RT_OK;
}
void TC_Multi_HashMap::incMainKeyBlockCount(const string &mk, bool bInc)
{
uint32_t index = mhashIndex(mk);
// 找到真正的主key头
if(itemMainKey(index)->_iMainKeyAddr != 0)
{
MainKey mainKey(this, itemMainKey(index)->_iMainKeyAddr);
do
{
string sKey;
mainKey.get(sKey);
if(mk == sKey)
{
// 找到了,增加计数
if(bInc)
{
saveValue(&mainKey.getHeadPtr()->_iBlockCount, mainKey.getHeadPtr()->_iBlockCount + 1);
updateMaxMainKeyBlockCount(mainKey.getHeadPtr()->_iBlockCount + 1);
}
else
{
saveValue(&mainKey.getHeadPtr()->_iBlockCount, mainKey.getHeadPtr()->_iBlockCount - 1);
updateMaxMainKeyBlockCount(mainKey.getHeadPtr()->_iBlockCount - 1);
}
break;
}
}while(mainKey.next());
}
}
void TC_Multi_HashMap::updateMaxMainKeyBlockCount(size_t iCount)
{
if(iCount > _pHead->_iMaxBlockCount)
{
saveValue(&_pHead->_iMaxBlockCount, iCount);
}
}
int TC_Multi_HashMap::get(const string &mk, const string &uk, Value &v)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, v, ret);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
if(it == end())
{
// 没有数据
// 查询主key信息
uint32_t mIndex = mhashIndex(mk);
uint32_t iAddr = find(mk, mIndex, ret);
if(ret != RT_OK)
{
// 这里有可能返回RT_ONLY_KEY
return ret;
}
if(iAddr != 0)
{
MainKey mainKey(this, iAddr);
if(mainKey.ISFULLDATA())
{
// 主key存在由于cache中的数据必须与数据源(如数据库)保持一致
// 说明数据源必定没有此记录返回only key即可可以使得调用者不必
// 从数据源再取数据
return RT_ONLY_KEY;
}
// 如果主key存在但数据不全则有可能会在数据库中有应该返回RT_NO_DATA
}
return RT_NO_DATA;
}
incHitCount();
// 只有Key
if(it->isOnlyKey())
{
return RT_ONLY_KEY;
}
Block block(this, it->getAddr());
// 如果只读, 则不刷新get链表
if(!_pHead->_bReadOnly)
{
MainKey mainKey(this, block.getBlockHead()->_iMainKey);
mainKey.refreshGetList();
}
return RT_OK;
}
int TC_Multi_HashMap::get(const string &mk, vector<Value> &vs)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = mhashIndex(mk);
uint32_t iMainKeyAddr = find(mk, index, ret);
if(ret != RT_OK)
{
return ret;
}
if(iMainKeyAddr == 0)
{
// 主key不存在
return RT_NO_DATA;
}
incHitCount();
MainKey mainKey(this, iMainKeyAddr);
if(mainKey.getHeadPtr()->_iAddr == 0)
{
return RT_ONLY_KEY;
}
uint32_t iAddr = mainKey.getHeadPtr()->_iAddr;
while(iAddr != 0)
{
Block block(this, iAddr);
Value v;
v._mkey = mk;
ret = block.getBlockData(v._data);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
if(ret == RT_OK)
{
// 仅取非only key的数据
vs.push_back(v);
}
iAddr = block.getBlockHead()->_iMKBlockNext;
}
if(!mainKey.ISFULLDATA())
{
return RT_PART_DATA;
}
return RT_OK;
}
int TC_Multi_HashMap::get(uint32_t &mh, map<string, vector<Value> > &vs)
{
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = mh % _hashMainKey.size();
uint32_t iMainKeyAddr = itemMainKey(index)->_iMainKeyAddr;
if(iMainKeyAddr == 0)
{
return RT_OK;
}
MainKey mainKey(this, iMainKeyAddr);
do
{
if(mainKey.getHeadPtr()->_iAddr != 0)
{
lock_iterator it(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_MKEY, lock_iterator::IT_NEXT);
while(it != end())
{
Value v;
ret = it->get(v);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
if(ret == RT_OK)
{
// 仅取非only key的数据
vs[v._mkey].push_back(v);
}
it ++;
}
}
}while(mainKey.next());
return RT_OK;
}
int TC_Multi_HashMap::set(const string &mk, const string &uk, const string &v,
uint8_t iVersion, bool bDirty, DATATYPE eType, bool bHead, vector<Value> &vtData)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
if(_pHead->_bReadOnly) return RT_READONLY;
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, ret);
bool bNewBlock = false;
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
incHitCount();
if(it == end())
{
// 数据尚不存在
// 查找是否已经存在于主key链
uint32_t mIndex = mhashIndex(mk); // 主key索引
uint32_t iMainKeyAddr = find(mk, mIndex, ret);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
if(iMainKeyAddr == 0)
{
// 主key头尚不存在新建一个
iMainKeyAddr = _pDataAllocator->allocateMainKeyHead(mIndex, vtData);
if(iMainKeyAddr == 0)
{
return TC_Multi_HashMap::RT_NO_MEMORY;
}
// 将主key设置到主key头中
MainKey mainKey(this, iMainKeyAddr);
ret = mainKey.set(mk.c_str(), mk.length(), vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
}
TC_PackIn pi;
pi << uk;
pi << v;
uint32_t iAllocSize = (uint32_t)pi.length();
// 先分配Blcok空间, 并获得淘汰的数据
uint32_t iAddr = _pDataAllocator->allocateMemBlock(iMainKeyAddr, index, bHead, iAllocSize, vtData);
if(iAddr == 0)
{
return TC_Multi_HashMap::RT_NO_MEMORY;
}
it = HashMapLockIterator(this, iAddr, HashMapLockIterator::IT_BLOCK, HashMapLockIterator::IT_NEXT);
bNewBlock = true;
}
ret = it->set(mk, uk, v, iVersion, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
// set数据失败可能的情况是空间不够了
if(bNewBlock)
{
// 如果是新set的数据此时要注意删除前面分配并挂接的block头
// 否则这个block将永远无法访问也不能删除因为block里是一个空的block
Block block(this, it->getAddr());
block.erase();
}
return ret;
}
Block block(this, it->getAddr());
if(bNewBlock)
{
block.setSyncTime(time(NULL));
}
block.setDirty(bDirty);
if(eType != AUTO_DATA)
{
MainKey mainKey(this, block.getBlockHead()->_iMainKey);
mainKey.SETFULLDATA(eType == FULL_DATA);
}
block.refreshSetList();
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::set(const string &mk, const string &uk, DATATYPE eType, bool bHead, vector<Value> &vtData)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
if(_pHead->_bReadOnly) return RT_READONLY;
int ret = TC_Multi_HashMap::RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, ret);
bool bNewBlock = false;
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
incHitCount();
if(it == end())
{
// 查找是否已经存在于主key链
uint32_t mIndex = mhashIndex(mk); // 主key索引
uint32_t iMainKeyAddr = find(mk, mIndex, ret);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
if(iMainKeyAddr == 0)
{
// 主key头尚不存在新建一个
iMainKeyAddr = _pDataAllocator->allocateMainKeyHead(mIndex, vtData);
if(iMainKeyAddr == 0)
{
return TC_Multi_HashMap::RT_NO_MEMORY;
}
// 将主key设置到主key头中
MainKey mainKey(this, iMainKeyAddr);
ret = mainKey.set(mk.c_str(), mk.length(), vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
}
TC_PackIn pi;
pi << uk;
uint32_t iAllocSize = (uint32_t)pi.length();
//先分配空间, 并获得淘汰的数据
uint32_t iAddr = _pDataAllocator->allocateMemBlock(iMainKeyAddr, index, bHead, iAllocSize, vtData);
if(iAddr == 0)
{
return TC_Multi_HashMap::RT_NO_MEMORY;
}
it = HashMapLockIterator(this, iAddr, HashMapLockIterator::IT_BLOCK, HashMapLockIterator::IT_NEXT);
bNewBlock = true;
}
ret = it->set(mk, uk, vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
// set数据失败可能的情况是空间不够了
if(bNewBlock)
{
// 如果是新set的数据此时要注意删除前面分配并挂接的block头
// 否则这个block将永远无法访问也不能删除因为block里是一个空的block
Block block(this, it->getAddr());
block.erase();
}
return ret;
}
Block block(this, it->getAddr());
if(bNewBlock)
{
block.setSyncTime(time(NULL));
}
if(eType != AUTO_DATA)
{
MainKey mainKey(this, block.getBlockHead()->_iMainKey);
mainKey.SETFULLDATA(eType == FULL_DATA);
}
block.refreshSetList();
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::set(const string &mk, vector<Value> &vtData)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
if(_pHead->_bReadOnly) return RT_READONLY;
int ret = TC_Multi_HashMap::RT_OK;
// 查找是否已经存在该主key
uint32_t mIndex = mhashIndex(mk); // 主key索引
uint32_t iMainKeyAddr = find(mk, mIndex, ret);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
return ret;
}
incHitCount();
if(iMainKeyAddr == 0)
{
// 主key头尚不存在新建一个
iMainKeyAddr = _pDataAllocator->allocateMainKeyHead(mIndex, vtData);
if(iMainKeyAddr == 0)
{
return TC_Multi_HashMap::RT_NO_MEMORY;
}
}
MainKey mainKey(this, iMainKeyAddr);
while(mainKey.getHeadPtr()->_iAddr != 0)
{
// 下面还有数据,需要清理这些数据
Block block(this, mainKey.getHeadPtr()->_iAddr);
Value value;
value._mkey = mk;
int ret = block.getBlockData(value._data);
if(ret == TC_Multi_HashMap::RT_OK)
{
vtData.push_back(value);
}
block.erase();
}
// 将主key设置到主key头中
ret = mainKey.set(mk.c_str(), mk.length(), vtData);
if(ret != TC_Multi_HashMap::RT_OK)
{
return ret;
}
mainKey.refreshGetList();
return TC_Multi_HashMap::RT_OK;
}
int TC_Multi_HashMap::set(const vector<Value> &vtSet, DATATYPE eType, bool bHead, bool bForce, vector<Value> &vtErased)
{
// 这里不需要加恢复代码
//TC_Multi_HashMap::FailureRecover recover(this);
int ret = RT_OK;
for(size_t i = 0; i < vtSet.size(); i ++)
{
if(bForce || checkMainKey(vtSet[i]._mkey) == RT_NO_DATA)
{
// 强制更新或主key下没有数据
if(vtSet[i]._data._key.empty())
{
// 没有联合key当作主key的only key设置
ret = set(vtSet[i]._mkey, vtErased);
}
else if(vtSet[i]._data._value.empty())
{
// 没有value当作联合主键的only key设置
ret = set(vtSet[i]._mkey, vtSet[i]._data._key, eType, bHead, vtErased);
}
else
{
ret = set(vtSet[i]._mkey, vtSet[i]._data._key, vtSet[i]._data._value,
vtSet[i]._data._iVersion, vtSet[i]._data._dirty, eType, bHead, vtErased);
}
if(ret != RT_OK)
{
return ret;
}
}
}
return RT_OK;
}
int TC_Multi_HashMap::del(const string &mk, const string &uk, Value &data)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
if(_pHead->_bReadOnly) return RT_READONLY;
int ret = RT_OK;
uint32_t index = hashIndex(mk, uk);
lock_iterator it = find(mk, uk, index, data, ret);
if(ret != TC_Multi_HashMap::RT_OK && ret != TC_Multi_HashMap::RT_ONLY_KEY)
{
return ret;
}
if(it == end())
{
return TC_Multi_HashMap::RT_NO_DATA;
}
incHitCount();
Block block(this, it->getAddr());
block.erase();
return ret;
}
int TC_Multi_HashMap::del(const string &mk, vector<Value> &data)
{
if(_pHead->_bReadOnly) return RT_READONLY;
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
uint32_t iIndex = mhashIndex(mk);
if(itemMainKey(iIndex)->_iMainKeyAddr != 0)
{
incHitCount();
MainKey mainKey(this, itemMainKey(iIndex)->_iMainKeyAddr);
do
{
string sKey;
mainKey.get(sKey);
if(mk == sKey)
{
// 找到主key头了
return mainKey.erase(data);
}
}while(mainKey.next());
}
return TC_Multi_HashMap::RT_NO_DATA;
}
int TC_Multi_HashMap::erase(int ratio, vector<Value> &vtData, bool bCheckDirty)
{
if(_pHead->_bReadOnly) return RT_READONLY;
TC_Multi_HashMap::FailureRecover recover(this);
if(ratio <= 0) ratio = 1;
if(ratio >= 100) ratio = 100;
uint32_t iAddr = _pHead->_iGetTail;
//到链表头部
if(iAddr == 0)
{
return RT_OK;
}
//删除到指定比率了
if((_pHead->_iUsedChunk * 100. / allBlockChunkCount()) < ratio)
{
return RT_OK;
}
// 删除是针对主key的
MainKey mainKey(this, iAddr);
if(bCheckDirty)
{
// 检查脏数据,脏数据不淘汰
// 只要主key下有一条脏数据就不淘汰
lock_iterator it(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_MKEY, lock_iterator::IT_NEXT);
while(it != end())
{
if(it->isDirty())
{
if(_pHead->_iDirtyTail == 0)
{
_pHead->_iDirtyTail = mainKey.getHeadPtr()->_iAddr;
}
return RT_OK;
}
it ++;
}
}
// 淘汰主key下的所有数据
mainKey.erase(vtData);
return RT_ERASE_OK;
}
void TC_Multi_HashMap::sync()
{
TC_Multi_HashMap::FailureRecover recover(this);
_pHead->_iSyncTail = _pHead->_iDirtyTail;
}
int TC_Multi_HashMap::sync(time_t iNowTime, Value &data)
{
TC_Multi_HashMap::FailureRecover recover(this);
uint32_t iAddr = _pHead->_iSyncTail;
//到链表头部了, 返回RT_OK
if(iAddr == 0)
{
return RT_OK;
}
Block block(this, iAddr);
_pHead->_iSyncTail = block.getBlockHead()->_iSetPrev;
//当前数据是干净数据
if( !block.isDirty())
{
if(_pHead->_iDirtyTail == iAddr)
{
_pHead->_iDirtyTail = block.getBlockHead()->_iSetPrev;
}
return RT_NONEED_SYNC;
}
// 取出主key
MainKey mainKey(this, block.getBlockHead()->_iMainKey);
mainKey.get(data._mkey);
int ret = block.getBlockData(data._data);
if(ret != TC_Multi_HashMap::RT_OK)
{
//没有获取完整的记录
if(_pHead->_iDirtyTail == iAddr)
{
_pHead->_iDirtyTail = block.getBlockHead()->_iSetPrev;
}
return ret;
}
//脏数据且超过_pHead->_iSyncTime没有回写, 需要回写
if(_pHead->_iSyncTime + data._data._synct < iNowTime && block.isDirty())
{
block.setDirty(false);
block.setSyncTime(iNowTime);
if(_pHead->_iDirtyTail == iAddr)
{
_pHead->_iDirtyTail = block.getBlockHead()->_iSetPrev;
}
return RT_NEED_SYNC;
}
//脏数据, 但是不需要回写, 脏链表不往前推
return RT_NONEED_SYNC;
}
void TC_Multi_HashMap::backup(bool bForceFromBegin)
{
TC_Multi_HashMap::FailureRecover recover(this);
if(bForceFromBegin || _pHead->_iBackupTail == 0)
{
//移动备份指针到Get链尾部, 准备开始备份数据
_pHead->_iBackupTail = _pHead->_iGetTail;
}
}
int TC_Multi_HashMap::backup(vector<Value> &vtData)
{
TC_Multi_HashMap::FailureRecover recover(this);
uint32_t iAddr = _pHead->_iBackupTail;
//到链表头部了, 返回RT_OK
if(iAddr == 0)
{
return RT_OK;
}
// 取出主key
MainKey mainKey(this, iAddr);
string mk;
mainKey.get(mk);
// 一次备份整个主key
int ret = RT_OK;
lock_iterator it(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_MKEY, lock_iterator::IT_NEXT);
while(it != end())
{
Block block(this, it->_iAddr);
Value value;
value._mkey = mk;
ret = block.getBlockData(value._data);
if(ret != RT_OK)
{
break;
}
vtData.push_back(value);
it++;
}
//迁移一次
_pHead->_iBackupTail = mainKey.getHeadPtr()->_iGetPrev;
if(ret == RT_OK)
{
return RT_NEED_BACKUP;
}
return ret;
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::begin()
{
TC_Multi_HashMap::FailureRecover recover(this);
for(size_t i = 0; i < _hash.size(); i++)
{
tagHashItem &hashItem = _hash[i];
if(hashItem._iBlockAddr != 0)
{
return lock_iterator(this, hashItem._iBlockAddr, lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
}
}
return end();
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::rbegin()
{
TC_Multi_HashMap::FailureRecover recover(this);
for(size_t i = _hash.size(); i > 0; i--)
{
tagHashItem &hashItem = _hash[i-1];
if(hashItem._iBlockAddr != 0)
{
Block block(this, hashItem._iBlockAddr);
return lock_iterator(this, block.getLastBlockHead(true), lock_iterator::IT_BLOCK, lock_iterator::IT_PREV);
}
}
return end();
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::beginSetTime()
{
TC_Multi_HashMap::FailureRecover recover(this);
return lock_iterator(this, _pHead->_iSetHead, lock_iterator::IT_SET, lock_iterator::IT_NEXT);
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::rbeginSetTime()
{
TC_Multi_HashMap::FailureRecover recover(this);
return lock_iterator(this, _pHead->_iSetTail, lock_iterator::IT_SET, lock_iterator::IT_PREV);
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::beginGetTime()
{
TC_Multi_HashMap::FailureRecover recover(this);
if(_pHead->_iGetHead != 0)
{
MainKey mainKey(this, _pHead->_iGetHead);
return lock_iterator(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_GET, lock_iterator::IT_NEXT);
}
else
{
return lock_iterator(this, 0, lock_iterator::IT_GET, lock_iterator::IT_NEXT);
}
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::rbeginGetTime()
{
TC_Multi_HashMap::FailureRecover recover(this);
if(_pHead->_iGetTail != 0)
{
MainKey mainKey(this, _pHead->_iGetTail);
// 找到主key链上的最后一个数据
uint32_t iAddr = mainKey.getHeadPtr()->_iAddr;
if(iAddr)
{
Block block(this, iAddr);
while(block.getBlockHead()->_iMKBlockNext)
{
iAddr = block.getBlockHead()->_iMKBlockNext;
block = Block(this, iAddr);
}
}
return lock_iterator(this, iAddr, lock_iterator::IT_GET, lock_iterator::IT_PREV);
}
else
{
return lock_iterator(this, 0, lock_iterator::IT_GET, lock_iterator::IT_PREV);
}
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::beginDirty()
{
TC_Multi_HashMap::FailureRecover recover(this);
return lock_iterator(this, _pHead->_iDirtyTail, lock_iterator::IT_SET, lock_iterator::IT_PREV);
}
TC_Multi_HashMap::hash_iterator TC_Multi_HashMap::hashBegin()
{
TC_Multi_HashMap::FailureRecover recover(this);
return hash_iterator(this, 0);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
string TC_Multi_HashMap::desc()
{
ostringstream s;
{
s << "[Version = " << (int)_pHead->_cMaxVersion << "." << (int)_pHead->_cMinVersion << "]" << endl;
s << "[ReadOnly = " << _pHead->_bReadOnly << "]" << endl;
s << "[AutoErase = " << _pHead->_bAutoErase << "]" << endl;
s << "[MemSize = " << _pHead->_iMemSize << "]" << endl;
s << "[Capacity = " << _pDataAllocator->getCapacity() << "]" << endl;
s << "[SingleBlockCount = " << TC_Common::tostr(singleBlockChunkCount()) << "]" << endl;
s << "[AllBlockChunk = " << allBlockChunkCount() << "]" << endl;
s << "[UsedChunk = " << _pHead->_iUsedChunk << "]" << endl;
s << "[FreeChunk = " << allBlockChunkCount() - _pHead->_iUsedChunk << "]" << endl;
s << "[MinDataSize = " << _pHead->_iMinDataSize << "]" << endl;
s << "[MaxDataSize = " << _pHead->_iMaxDataSize << "]" << endl;
s << "[HashCount = " << _hash.size() << "]" << endl;
s << "[MainKeyHashCount = " << _hashMainKey.size() << "]" << endl;
s << "[HashRatio = " << _pHead->_fHashRatio << "]" << endl;
s << "[MainKeyRatio = " << _pHead->_fMainKeyRatio << "]" << endl;
s << "[ElementCount = " << _pHead->_iElementCount << "]" << endl;
s << "[SetHead = " << _pHead->_iSetHead << "]" << endl;
s << "[SetTail = " << _pHead->_iSetTail << "]" << endl;
s << "[GetHead = " << _pHead->_iGetHead << "]" << endl;
s << "[GetTail = " << _pHead->_iGetTail << "]" << endl;
s << "[DirtyTail = " << _pHead->_iDirtyTail << "]" << endl;
s << "[SyncTail = " << _pHead->_iSyncTail << "]" << endl;
s << "[SyncTime = " << _pHead->_iSyncTime << "]" << endl;
s << "[BackupTail = " << _pHead->_iBackupTail << "]" << endl;
s << "[DirtyCount = " << _pHead->_iDirtyCount << "]" << endl;
s << "[GetCount = " << _pHead->_iGetCount << "]" << endl;
s << "[HitCount = " << _pHead->_iHitCount << "]" << endl;
s << "[HitRatio = " << (_pHead->_iGetCount == 0 ? 0 :_pHead->_iHitCount * 100 / _pHead->_iGetCount) << "]" << endl;
s << "[OnlyKeyCount = " << _pHead->_iOnlyKeyCount << "]" << endl;
s << "[MKOnlyKeyCount = " << _pHead->_iMKOnlyKeyCount << "]" << endl;
s << "[MaxMKBlockCount = " << _pHead->_iMaxBlockCount << "]" << endl;
s << "[ModifyStatus = " << (int)_pstModifyHead->_cModifyStatus << "]" << endl;
s << "[ModifyIndex = " << _pstModifyHead->_iNowIndex << "]" << endl;
}
uint32_t iMaxHash;
uint32_t iMinHash;
float fAvgHash;
analyseHash(iMaxHash, iMinHash, fAvgHash);
{
s << "[MaxHash = " << iMaxHash << "]" << endl;
s << "[MinHash = " << iMinHash << "]" << endl;
s << "[AvgHash = " << fAvgHash << "]" << endl;
}
analyseHashM(iMaxHash, iMinHash, fAvgHash);
{
s << "[MaxMainkeyHash = " << iMaxHash << "]" << endl;
s << "[MinMainKeyHash = " << iMinHash << "]" << endl;
s << "[AvgMainKeyHash = " << fAvgHash << "]" << endl;
}
vector<TC_MemChunk::tagChunkHead> vChunkHead = _pDataAllocator->getBlockDetail();
s << "*************************************************************************" << endl;
s << "[DiffBlockCount = " << vChunkHead.size() << "]" << endl;
for(size_t i = 0; i < vChunkHead.size(); i++)
{
s << "[BlockSize = " << vChunkHead[i]._iBlockSize << "] ";
s << "[BlockCount = " << vChunkHead[i]._iBlockCount << "] ";
s << "[BlockAvailable = " << vChunkHead[i]._blockAvailable << "]" << endl;
}
return s.str();
}
size_t TC_Multi_HashMap::eraseExcept(uint32_t iNowAddr, vector<Value> &vtData)
{
//不能被淘汰
if(!_pHead->_bAutoErase) return 0;
size_t n = _pHead->_iEraseCount;
if(n == 0) n = 10;
size_t d = n;
while (d != 0)
{
uint32_t iAddr;
//判断按照哪种方式淘汰
if(_pHead->_cEraseMode == TC_Multi_HashMap::ERASEBYSET)
{
// 按set链淘汰
iAddr = _pHead->_iSetTail;
if (iAddr == 0)
{
break;
}
// set链是block链换算成主key头的地址
Block block(this, iAddr);
iAddr = block.getBlockHead()->_iMainKey;
}
else
{
// 按get链淘汰
iAddr = _pHead->_iGetTail;
if (iAddr == 0)
{
break;
}
}
// 不管是按get链淘汰还是按set链淘汰都是要淘汰主key下所有数据
MainKey mainKey(this, iAddr);
if(iNowAddr == iAddr)
{
// 当前主key链中有正在分配的block跳过
iAddr = mainKey.getHeadPtr()->_iGetPrev;
}
if(iAddr == 0)
{
break;
}
uint32_t iBlockCount = mainKey.getHeadPtr()->_iBlockCount;
if(d >= iBlockCount)
{
// 淘汰主key链下的所有数据
int ret = mainKey.erase(vtData);
if(ret == RT_OK)
{
d -= iBlockCount;
}
}
else
{
if(d == n)
{
// 设置的要删除的数量太小没有满足条件的主key直接删除
int ret = mainKey.erase(vtData);
if(ret == RT_OK)
{
n = d + iBlockCount; // 使返回正确的数据量
}
}
break;
}
}
return n-d;
}
uint32_t TC_Multi_HashMap::hashIndex(const string &mk, const string &uk)
{
// mk是主keyuk是除主key外的辅key二者加起来作为联合主键
return hashIndex(mk + uk);
}
uint32_t TC_Multi_HashMap::hashIndex(const string& k)
{
return _hashf(k) % _hash.size();
}
uint32_t TC_Multi_HashMap::mhashIndex(const string &mk)
{
if(_mhashf)
{
return _mhashf(mk) % _hashMainKey.size();
}
else
{
// 如果没有单独指定主key hash函数则使用联合主键的hash函数
return _hashf(mk) % _hashMainKey.size();
}
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::find(const string &mk, const string &uk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
uint32_t index = hashIndex(mk, uk);
int ret = TC_Multi_HashMap::RT_OK;
if(item(index)->_iBlockAddr == 0)
{
return end();
}
Block mb(this, item(index)->_iBlockAddr);
while(true)
{
HashMapLockItem mcmdi(this, mb.getHead());
if(mcmdi.equal(mk, uk, ret))
{
// 找到了不仅索引相同key也相同
incHitCount();
return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
}
if (!mb.nextBlock())
{
return end();
}
}
return end();
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::find(const string &mk, const string &uk, uint32_t index, Value &v, int &ret)
{
ret = TC_Multi_HashMap::RT_OK;
if(item(index)->_iBlockAddr == 0)
{
return end();
}
Block mb(this, item(index)->_iBlockAddr);
while(true)
{
HashMapLockItem mcmdi(this, mb.getHead());
if(mcmdi.equal(mk, uk, v, ret))
{
// 找到了不仅索引相同key也相同
return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
}
if (!mb.nextBlock())
{
return end();
}
}
return end();
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::find(const string &mk, const string &uk, uint32_t index, int &ret)
{
ret = TC_Multi_HashMap::RT_OK;
if(item(index)->_iBlockAddr == 0)
{
return end();
}
Block mb(this, item(index)->_iBlockAddr);
while(true)
{
HashMapLockItem mcmdi(this, mb.getHead());
if(mcmdi.equal(mk, uk, ret))
{
// 找到了不仅索引相同key也相同
return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
}
if (!mb.nextBlock())
{
return end();
}
}
return end();
}
uint32_t TC_Multi_HashMap::find(const string &mk, uint32_t index, int &ret)
{
ret = TC_Multi_HashMap::RT_OK;
if(itemMainKey(index)->_iMainKeyAddr == 0)
{
return 0;
}
MainKey mainKey(this, itemMainKey(index)->_iMainKeyAddr);
do
{
string s;
ret = mainKey.get(s);
if(ret != RT_OK)
{
return 0;
}
if(s == mk)
{
// 找到了
if(mainKey.getHeadPtr()->_iAddr == 0)
{
ret = RT_ONLY_KEY;
}
return mainKey.getHead();
}
} while (mainKey.next());
return 0;
}
size_t TC_Multi_HashMap::count(const string &mk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
uint32_t iIndex = mhashIndex(mk);
if(itemMainKey(iIndex)->_iMainKeyAddr != 0)
{
MainKey mainKey(this, itemMainKey(iIndex)->_iMainKeyAddr);
do
{
string sKey;
mainKey.get(sKey);
if(mk == sKey)
{
// 找到对应的主key了
incHitCount();
return mainKey.getHeadPtr()->_iBlockCount;
}
}while(mainKey.next());
}
return 0;
}
TC_Multi_HashMap::lock_iterator TC_Multi_HashMap::find(const string &mk)
{
TC_Multi_HashMap::FailureRecover recover(this);
incGetCount();
uint32_t iIndex = mhashIndex(mk);
if(itemMainKey(iIndex)->_iMainKeyAddr != 0)
{
MainKey mainKey(this, itemMainKey(iIndex)->_iMainKeyAddr);
do
{
string sKey;
mainKey.get(sKey);
if(mk == sKey)
{
// 找到对应的主key了
incHitCount();
if(mainKey.getHeadPtr()->_iAddr != 0)
{
// 主key下面有数据
return lock_iterator(this, mainKey.getHeadPtr()->_iAddr, lock_iterator::IT_MKEY, lock_iterator::IT_NEXT);
}
break;
}
}while(mainKey.next());
}
return end();
}
void TC_Multi_HashMap::analyseHash(uint32_t &iMaxHash, uint32_t &iMinHash, float &fAvgHash)
{
iMaxHash = 0;
iMinHash = (uint32_t)-1;
fAvgHash = 0;
uint32_t n = 0;
for(uint32_t i = 0; i < _hash.size(); i++)
{
iMaxHash = max(_hash[i]._iListCount, iMaxHash);
iMinHash = min(_hash[i]._iListCount, iMinHash);
//平均值只统计非0的
if(_hash[i]._iListCount != 0)
{
n++;
fAvgHash += _hash[i]._iListCount;
}
}
if(n != 0)
{
fAvgHash = fAvgHash / n;
}
}
void TC_Multi_HashMap::analyseHashM(uint32_t &iMaxHash, uint32_t &iMinHash, float &fAvgHash)
{
iMaxHash = 0;
iMinHash = (uint32_t)-1;
fAvgHash = 0;
uint32_t n = 0;
for(uint32_t i = 0; i < _hashMainKey.size(); i++)
{
iMaxHash = max(_hashMainKey[i]._iListCount, iMaxHash);
iMinHash = min(_hashMainKey[i]._iListCount, iMinHash);
//平均值只统计非0的
if(_hashMainKey[i]._iListCount != 0)
{
n++;
fAvgHash += _hashMainKey[i]._iListCount;
}
}
if(n != 0)
{
fAvgHash = fAvgHash / n;
}
}
void TC_Multi_HashMap::doRecover()
{
//==1 copy过程中, 程序失败, 恢复原数据
if(_pstModifyHead->_cModifyStatus == 1)
{
for(int i = _pstModifyHead->_iNowIndex-1; i >=0; i--)
{
if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(uint64_t))
{
*(uint64_t*)((char*)_pHead + _pstModifyHead->_stModifyData[i]._iModifyAddr) = _pstModifyHead->_stModifyData[i]._iModifyValue;
}
//#if __WORDSIZE == 64 || defined _WIN64
else if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(uint32_t))
{
*(uint32_t*)((char*)_pHead + _pstModifyHead->_stModifyData[i]._iModifyAddr) = (uint32_t)_pstModifyHead->_stModifyData[i]._iModifyValue;
}
//#endif
else if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(uint8_t))
{
*(uint8_t*)((char*)_pHead + _pstModifyHead->_stModifyData[i]._iModifyAddr) = (bool)_pstModifyHead->_stModifyData[i]._iModifyValue;
}
else
{
assert(true);
}
}
_pstModifyHead->_iNowIndex = 0;
_pstModifyHead->_cModifyStatus = 0;
}
}
void TC_Multi_HashMap::doUpdate()
{
//==2,已经修改成功, 清除
if(_pstModifyHead->_cModifyStatus == 1)
{
_pstModifyHead->_iNowIndex = 0;
_pstModifyHead->_cModifyStatus = 0;
}
}
size_t TC_Multi_HashMap::getMinPrimeNumber(size_t n)
{
while(true)
{
if(TC_Common::isPrimeNumber(n))
{
return n;
}
++n;
}
return 3;
}
size_t TC_Multi_HashMap::checkBadBlock(uint32_t iHash, bool bRepair)
{
size_t iCount = 0;
if(iHash >= _hash.size())
{
return 0;
}
TC_Multi_HashMap::FailureRecover recover(this);
check:
uint32_t iAddr = item(iHash)->_iBlockAddr;
Block block(this, iAddr);
while(block.getHead() != 0)
{
BlockData blkData;
int ret = block.getBlockData(blkData);
if(ret != RT_OK && ret != RT_ONLY_KEY)
{
iCount ++;
if(bRepair)
{
// 删除这个block
block.erase();
goto check;
}
}
if(!block.nextBlock())
{
break;
}
}
return iCount;
}
}