123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595 |
- /**
- * 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_hashmap.h"
- #include "util/tc_pack.h"
- #include "util/tc_common.h"
- namespace tars
- {
- int TC_HashMap::Block::getBlockData(TC_HashMap::BlockData &data)
- {
- data._dirty = isDirty();
- data._synct = getSyncTime();
- string s;
- int ret = get(s);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- try
- {
- TC_PackOut po(s.c_str(), s.length());
- po >> data._key;
- //如果不是只有Key
- if(!isOnlyKey())
- {
- po >> data._value;
- }
- else
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- }
- catch(exception &ex)
- {
- ret = TC_HashMap::RT_DECODE_ERR;
- }
- return ret;
- }
- size_t TC_HashMap::Block::getLastBlockHead()
- {
- size_t iHead = _iHead;
- while(getBlockHead(iHead)->_iBlockNext != 0)
- {
- iHead = getBlockHead(iHead)->_iBlockNext;
- }
- return iHead;
- }
- int TC_HashMap::Block::get(void *pData, size_t &iDataLen)
- {
- //没有下一个chunk, 一个chunk就可以装下数据了
- if(!getBlockHead()->_bNextChunk)
- {
- memcpy(pData, getBlockHead()->_cData, min(getBlockHead()->_iDataLen, iDataLen));
- iDataLen = getBlockHead()->_iDataLen;
- return TC_HashMap::RT_OK;
- }
- else
- {
- size_t iUseSize = getBlockHead()->_iSize - sizeof(tagBlockHead);
- size_t iCopyLen = min(iUseSize, iDataLen);
- //copy到当前的block中
- memcpy(pData, getBlockHead()->_cData, iCopyLen);
- if (iDataLen < iUseSize)
- {
- return TC_HashMap::RT_NOTALL_ERR; //copy数据不完全
- }
- //已经copy长度
- size_t iHasLen = iCopyLen;
- //最大剩余长度
- size_t iLeftLen = iDataLen - iCopyLen;
- tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
- while(iHasLen < iDataLen)
- {
- iUseSize = pChunk->_iSize - sizeof(tagChunkHead);
- if(!pChunk->_bNextChunk)
- {
- //copy到当前的chunk中
- size_t iCopyLen = min(pChunk->_iDataLen, iLeftLen);
- memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
- iDataLen = iHasLen + iCopyLen;
- if(iLeftLen < pChunk->_iDataLen)
- {
- return TC_HashMap::RT_NOTALL_ERR; //copy不完全
- }
- return TC_HashMap::RT_OK;
- }
- else
- {
- size_t iCopyLen = min(iUseSize, iLeftLen);
- //copy当前的chunk
- memcpy((char*)pData + iHasLen, pChunk->_cData, iCopyLen);
- // 这里有bug, = 的时候正好可以,不能返回出错!
- //if (iLeftLen <= iUseSize)
- if (iLeftLen < iUseSize)
- {
- iDataLen = iHasLen + iCopyLen;
- return TC_HashMap::RT_NOTALL_ERR; //copy不完全
- }
- //copy当前chunk完全
- iHasLen += iCopyLen;
- iLeftLen -= iCopyLen;
- pChunk = getChunkHead(pChunk->_iNextChunk);
- }
- }
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::Block::get(string &s)
- {
- size_t iLen = getDataLen();
- char *cData = new char[iLen];
- size_t iGetLen = iLen;
- int ret = get(cData, iGetLen);
- if(ret == TC_HashMap::RT_OK)
- {
- s.assign(cData, iGetLen);
- }
- delete[] cData;
- return ret;
- }
- int TC_HashMap::Block::set(const void *pData, size_t iDataLen, bool bOnlyKey, vector<TC_HashMap::BlockData> &vtData)
- {
- //首先分配刚刚够的长度, 不能多一个chunk, 也不能少一个chunk
- int ret = allocate(iDataLen, vtData);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- if(bOnlyKey)
- {
- //原始数据是脏数据
- if(getBlockHead()->_bDirty)
- {
- _pMap->delDirtyCount();
- }
- //数据被修改, 设置为脏数据
- getBlockHead()->_bDirty = false;
- //原始数据不是OnlyKey数据
- if(!getBlockHead()->_bOnlyKey)
- {
- _pMap->incOnlyKeyCount();
- }
- }
- else
- {
- //原始数据不是脏数据
- if(!getBlockHead()->_bDirty)
- {
- _pMap->incDirtyCount();
- }
- //数据被修改, 设置为脏数据
- getBlockHead()->_bDirty = true;
- //原始数据是OnlyKey数据
- if(getBlockHead()->_bOnlyKey)
- {
- _pMap->delOnlyKeyCount();
- }
- }
- //设置是否只有Key
- getBlockHead()->_bOnlyKey = bOnlyKey;
- size_t iUseSize = getBlockHead()->_iSize - sizeof(tagBlockHead);
- //没有下一个chunk, 一个chunk就可以装下数据了
- if(!getBlockHead()->_bNextChunk)
- {
- memcpy(getBlockHead()->_cData, (char*)pData, iDataLen);
- //先copy数据, 再复制数据长度
- getBlockHead()->_iDataLen = iDataLen;
- }
- else
- {
- //copy到当前的block中
- memcpy(getBlockHead()->_cData, (char*)pData, iUseSize);
- //剩余程度
- size_t iLeftLen = iDataLen - iUseSize;
- size_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);
- }
- _pMap->doUpdate(true);
- return TC_HashMap::RT_OK;
- }
- void TC_HashMap::Block::setDirty(bool b)
- {
- if(getBlockHead()->_bDirty != b)
- {
- if (b)
- {
- _pMap->incDirtyCount();
- }
- else
- {
- _pMap->delDirtyCount();
- }
- _pMap->update(&getBlockHead()->_bDirty, b);
- _pMap->doUpdate(true);
- }
- }
- bool TC_HashMap::Block::nextBlock()
- {
- _iHead = getBlockHead()->_iBlockNext;
- return _iHead != 0;
- }
- bool TC_HashMap::Block::prevBlock()
- {
- _iHead = getBlockHead()->_iBlockPrev;
- return _iHead != 0;
- }
- void TC_HashMap::Block::deallocate()
- {
- vector<size_t> v;
- v.push_back(_iHead);
- if(getBlockHead()->_bNextChunk)
- {
- deallocate(getBlockHead()->_iNextChunk);
- }
- _pMap->_pDataAllocator->deallocateMemBlock(v);
- }
- void TC_HashMap::Block::makeNew(size_t index, size_t iAllocSize)
- {
- getBlockHead()->_iSize = (uint32_t)iAllocSize;
- getBlockHead()->_iIndex = (uint32_t)index;
- getBlockHead()->_iSetNext = 0;
- getBlockHead()->_iSetPrev = 0;
- getBlockHead()->_iGetNext = 0;
- getBlockHead()->_iGetPrev = 0;
- getBlockHead()->_iSyncTime = 0;
- getBlockHead()->_iBlockNext = 0;
- getBlockHead()->_iBlockPrev = 0;
- getBlockHead()->_bNextChunk = false;
- getBlockHead()->_iDataLen = 0;
- getBlockHead()->_bDirty = true;
- getBlockHead()->_bOnlyKey = false;
- _pMap->incDirtyCount();
- _pMap->incElementCount();
- _pMap->incListCount((uint32_t)index);
- //挂在block链表上
- if(_pMap->item(index)->_iBlockAddr == 0)
- {
- //当前hash桶没有元素
- _pMap->update(&_pMap->item(index)->_iBlockAddr, _iHead);
- _pMap->update(&getBlockHead()->_iBlockNext, (size_t)0);
- _pMap->update(&getBlockHead()->_iBlockPrev, (size_t)0);
- }
- else
- {
- //当然hash桶有元素, 挂在桶开头
- _pMap->update(&getBlockHead(_pMap->item(index)->_iBlockAddr)->_iBlockPrev, _iHead);
- _pMap->update(&getBlockHead()->_iBlockNext, _pMap->item(index)->_iBlockAddr);
- _pMap->update(&_pMap->item(index)->_iBlockAddr, _iHead);
- _pMap->update(&getBlockHead()->_iBlockPrev, (size_t)0);
- }
- //挂在Set链表的头部
- if(_pMap->_pHead->_iSetHead == 0)
- {
- assert(_pMap->_pHead->_iSetTail == 0);
- _pMap->update(&_pMap->_pHead->_iSetHead, _iHead);
- _pMap->update(&_pMap->_pHead->_iSetTail, _iHead);
- }
- else
- {
- assert(_pMap->_pHead->_iSetTail != 0);
- _pMap->update(&getBlockHead()->_iSetNext, _pMap->_pHead->_iSetHead);
- _pMap->update(&getBlockHead(_pMap->_pHead->_iSetHead)->_iSetPrev, _iHead);
- _pMap->update(&_pMap->_pHead->_iSetHead, _iHead);
- }
- //挂在Get链表头部
- if(_pMap->_pHead->_iGetHead == 0)
- {
- assert(_pMap->_pHead->_iGetTail == 0);
- _pMap->update(&_pMap->_pHead->_iGetHead, _iHead);
- _pMap->update(&_pMap->_pHead->_iGetTail, _iHead);
- }
- else
- {
- assert(_pMap->_pHead->_iGetTail != 0);
- _pMap->update(&getBlockHead()->_iGetNext, _pMap->_pHead->_iGetHead);
- _pMap->update(&getBlockHead(_pMap->_pHead->_iGetHead)->_iGetPrev, _iHead);
- _pMap->update(&_pMap->_pHead->_iGetHead, _iHead);
- }
- //一次写更新操作
- _pMap->doUpdate(true);
- }
- void TC_HashMap::Block::erase()
- {
- //////////////////修改脏数据链表/////////////
- if(_pMap->_pHead->_iDirtyTail == _iHead)
- {
- _pMap->update(&_pMap->_pHead->_iDirtyTail, getBlockHead()->_iSetPrev);
- }
- //////////////////修改回写数据链表/////////////
- if(_pMap->_pHead->_iSyncTail == _iHead)
- {
- _pMap->update(&_pMap->_pHead->_iSyncTail, getBlockHead()->_iSetPrev);
- }
- //////////////////修改备份数据链表/////////////
- if(_pMap->_pHead->_iBackupTail == _iHead)
- {
- _pMap->update(&_pMap->_pHead->_iBackupTail, getBlockHead()->_iGetPrev);
- }
- ////////////////////修改Set链表的数据//////////
- {
- bool bHead = (_pMap->_pHead->_iSetHead == _iHead);
- bool bTail = (_pMap->_pHead->_iSetTail == _iHead);
- if(!bHead)
- {
- if(bTail)
- {
- assert(getBlockHead()->_iSetNext == 0);
- //是尾部, 尾部指针指向上一个元素
- _pMap->update(&_pMap->_pHead->_iSetTail, getBlockHead()->_iSetPrev);
- _pMap->update(&getBlockHead(getBlockHead()->_iSetPrev)->_iSetNext, (size_t)0);
- }
- else
- {
- //不是头部也不是尾部
- assert(getBlockHead()->_iSetNext != 0);
- _pMap->update(&getBlockHead(getBlockHead()->_iSetPrev)->_iSetNext, getBlockHead()->_iSetNext);
- _pMap->update(&getBlockHead(getBlockHead()->_iSetNext)->_iSetPrev, getBlockHead()->_iSetPrev);
- }
- }
- else
- {
- if(bTail)
- {
- assert(getBlockHead()->_iSetNext == 0);
- assert(getBlockHead()->_iSetPrev == 0);
- //头部也是尾部, 指针都设置为0
- _pMap->update(&_pMap->_pHead->_iSetHead, (size_t)0);
- _pMap->update(&_pMap->_pHead->_iSetTail, (size_t)0);
- }
- else
- {
- //头部不是尾部, 头部指针指向下一个元素
- assert(getBlockHead()->_iSetNext != 0);
- _pMap->update(&_pMap->_pHead->_iSetHead, getBlockHead()->_iSetNext);
- //下一个元素上指针为0
- _pMap->update(&getBlockHead(getBlockHead()->_iSetNext)->_iSetPrev, (size_t)0);
- }
- }
- }
- ////////////////////修改Get链表的数据//////////
- //
- {
- bool bHead = (_pMap->_pHead->_iGetHead == _iHead);
- bool bTail = (_pMap->_pHead->_iGetTail == _iHead);
- if(!bHead)
- {
- if(bTail)
- {
- assert(getBlockHead()->_iGetNext == 0);
- //是尾部, 尾部指针指向上一个元素
- _pMap->update(&_pMap->_pHead->_iGetTail, getBlockHead()->_iGetPrev);
- _pMap->update(&getBlockHead(getBlockHead()->_iGetPrev)->_iGetNext, (size_t)0);
- }
- else
- {
- //不是头部也不是尾部
- assert(getBlockHead()->_iGetNext != 0);
- _pMap->update(&getBlockHead(getBlockHead()->_iGetPrev)->_iGetNext, getBlockHead()->_iGetNext);
- _pMap->update(&getBlockHead(getBlockHead()->_iGetNext)->_iGetPrev, getBlockHead()->_iGetPrev);
- }
- }
- else
- {
- if(bTail)
- {
- assert(getBlockHead()->_iGetNext == 0);
- assert(getBlockHead()->_iGetPrev == 0);
- //头部也是尾部, 指针都设置为0
- _pMap->update(&_pMap->_pHead->_iGetHead, (size_t)0);
- _pMap->update(&_pMap->_pHead->_iGetTail, (size_t)0);
- }
- else
- {
- //头部不是尾部, 头部指针指向下一个元素
- assert(getBlockHead()->_iGetNext != 0);
- _pMap->update(&_pMap->_pHead->_iGetHead, getBlockHead()->_iGetNext);
- //下一个元素上指针为0
- _pMap->update(&getBlockHead(getBlockHead()->_iGetNext)->_iGetPrev, (size_t)0);
- }
- }
- }
- ///////////////////从block链表中去掉///////////
- //
- //上一个block指向下一个block
- if(getBlockHead()->_iBlockPrev != 0)
- {
- _pMap->update(&getBlockHead(getBlockHead()->_iBlockPrev)->_iBlockNext, getBlockHead()->_iBlockNext);
- }
- //下一个block指向上一个
- if(getBlockHead()->_iBlockNext != 0)
- {
- _pMap->update(&getBlockHead(getBlockHead()->_iBlockNext)->_iBlockPrev, getBlockHead()->_iBlockPrev);
- }
- //////////////////如果是hash头部, 需要修改hash索引数据指针//////
- //
- _pMap->delListCount(getBlockHead()->_iIndex);
- if(getBlockHead()->_iBlockPrev == 0)
- {
- //如果是hash桶的头部, 则还需要处理
- TC_HashMap::tagHashItem *pItem = _pMap->item(getBlockHead()->_iIndex);
- assert(pItem->_iBlockAddr == _iHead);
- if(pItem->_iBlockAddr == _iHead)
- {
- _pMap->update(&pItem->_iBlockAddr, getBlockHead()->_iBlockNext);
- }
- }
- //////////////////脏数据///////////////////
- //
- if (isDirty())
- {
- _pMap->delDirtyCount();
- }
- if(isOnlyKey())
- {
- _pMap->delOnlyKeyCount();
- }
- //元素个数减少
- _pMap->delElementCount();
- //一次写更新操作
- _pMap->doUpdate(true);
- //归还到内存中
- deallocate();
- }
- void TC_HashMap::Block::refreshSetList()
- {
- assert(_pMap->_pHead->_iSetHead != 0);
- assert(_pMap->_pHead->_iSetTail != 0);
- //修改同步链表
- if(_pMap->_pHead->_iSyncTail == _iHead && _pMap->_pHead->_iSetHead != _iHead)
- {
- _pMap->update(&_pMap->_pHead->_iSyncTail, getBlockHead()->_iSetPrev);
- }
- //修改脏数据尾部链表指针, 不仅一个元素
- if(_pMap->_pHead->_iDirtyTail == _iHead && _pMap->_pHead->_iSetHead != _iHead)
- {
- //脏数据尾部位置前移
- _pMap->update(&_pMap->_pHead->_iDirtyTail, getBlockHead()->_iSetPrev);
- }
- else if (_pMap->_pHead->_iDirtyTail == 0)
- {
- //原来没有脏数据
- _pMap->update(&_pMap->_pHead->_iDirtyTail, _iHead);
- }
- //是头部数据或者set新数据时走到这个分支
- if(_pMap->_pHead->_iSetHead == _iHead)
- {
- _pMap->doUpdate(true);
- //刷新Get链
- refreshGetList();
- return;
- }
- size_t iPrev = getBlockHead()->_iSetPrev;
- size_t iNext = getBlockHead()->_iSetNext;
- assert(iPrev != 0);
- //挂在链表头部
- _pMap->update(&getBlockHead()->_iSetNext, _pMap->_pHead->_iSetHead);
- _pMap->update(&getBlockHead(_pMap->_pHead->_iSetHead)->_iSetPrev, _iHead);
- _pMap->update(&_pMap->_pHead->_iSetHead, _iHead);
- _pMap->update(&getBlockHead()->_iSetPrev, (size_t)0);
- //上一个元素的Next指针指向下一个元素
- _pMap->update(&getBlockHead(iPrev)->_iSetNext, iNext);
- //下一个元素的Prev指向上一个元素
- if (iNext != 0)
- {
- _pMap->update(&getBlockHead(iNext)->_iSetPrev, iPrev);
- }
- else
- {
- //改变尾部指针
- assert(_pMap->_pHead->_iSetTail == _iHead);
- _pMap->update(&_pMap->_pHead->_iSetTail, iPrev);
- }
- _pMap->doUpdate(true);
- //刷新Get链
- refreshGetList();
- }
- void TC_HashMap::Block::refreshGetList()
- {
- assert(_pMap->_pHead->_iGetHead != 0);
- assert(_pMap->_pHead->_iGetTail != 0);
- //是头部数据
- if(_pMap->_pHead->_iGetHead == _iHead)
- {
- return;
- }
- size_t iPrev = getBlockHead()->_iGetPrev;
- size_t iNext = getBlockHead()->_iGetNext;
- assert(iPrev != 0);
- //是正在备份的数据
- if(_pMap->_pHead->_iBackupTail == _iHead)
- {
- _pMap->update(&_pMap->_pHead->_iBackupTail, iPrev);
- }
- //挂在链表头部
- _pMap->update(&getBlockHead()->_iGetNext, _pMap->_pHead->_iGetHead);
- _pMap->update(&getBlockHead(_pMap->_pHead->_iGetHead)->_iGetPrev, _iHead);
- _pMap->update(&_pMap->_pHead->_iGetHead, _iHead);
- _pMap->update(&getBlockHead()->_iGetPrev, (size_t)0);
- //上一个元素的Next指针指向下一个元素
- _pMap->update(&getBlockHead(iPrev)->_iGetNext, iNext);
- //下一个元素的Prev指向上一个元素
- if (iNext != 0)
- {
- _pMap->update(&getBlockHead(iNext)->_iGetPrev, iPrev);
- }
- else
- {
- //改变尾部指针
- assert(_pMap->_pHead->_iGetTail == _iHead);
- _pMap->update(&_pMap->_pHead->_iGetTail, iPrev);
- }
- _pMap->doUpdate(true);
- }
- void TC_HashMap::Block::deallocate(size_t iChunk)
- {
- tagChunkHead *pChunk = getChunkHead(iChunk);
- vector<size_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->deallocateMemBlock(v);
- }
- int TC_HashMap::Block::allocate(size_t iDataLen, vector<TC_HashMap::BlockData> &vtData)
- {
- size_t fn = 0;
- //一个块的真正的数据容量
- fn = getBlockHead()->_iSize - sizeof(tagBlockHead);
- if(fn >= iDataLen)
- {
- //一个block就可以了, 后续的chunk都要释放掉
- if(getBlockHead()->_bNextChunk)
- {
- size_t iNextChunk = getBlockHead()->_iNextChunk;
- //先修改自己的区块
- _pMap->update(&getBlockHead()->_bNextChunk, false);
- _pMap->update(&getBlockHead()->_iDataLen, (size_t)0);
- _pMap->doUpdate(true);
- //修改成功后再释放区块, 从而保证, 不会core的时候导致整个内存块不可用
- deallocate(iNextChunk);
- }
- return TC_HashMap::RT_OK;
- }
- //计算还需要多少长度
- fn = iDataLen - fn;
- if(getBlockHead()->_bNextChunk)
- {
- tagChunkHead *pChunk = getChunkHead(getBlockHead()->_iNextChunk);
- while(true)
- {
- if(fn <= (pChunk->_iSize - sizeof(tagChunkHead)))
- {
- //已经不需要chunk了, 释放多余的chunk
- if(pChunk->_bNextChunk)
- {
- size_t iNextChunk = pChunk->_iNextChunk;
- _pMap->update(&pChunk->_bNextChunk, false);
- _pMap->doUpdate(true);
- //一旦异常core, 最坏的情况就是少了可用的区块, 但是整个内存结构还是可用的
- deallocate(iNextChunk);
- }
- return TC_HashMap::RT_OK ;
- }
- //计算, 还需要多少长度
- fn -= pChunk->_iSize - sizeof(tagChunkHead);
- if(pChunk->_bNextChunk)
- {
- pChunk = getChunkHead(pChunk->_iNextChunk);
- }
- else
- {
- //没有后续chunk了, 需要新分配fn的空间
- vector<size_t> chunks;
- int ret = allocateChunk(fn, chunks, vtData);
- if(ret != TC_HashMap::RT_OK)
- {
- //没有内存可以分配
- return ret;
- }
- _pMap->update(&pChunk->_bNextChunk, true);
- _pMap->update(&pChunk->_iNextChunk, chunks[0]);
- //chunk指向分配的第一个chunk
- pChunk = getChunkHead(chunks[0]);
- //修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
- _pMap->update(&pChunk->_bNextChunk, false);
- _pMap->update(&pChunk->_iDataLen, (size_t)0);
- _pMap->doUpdate(true);
- //连接每个chunk
- return joinChunk(pChunk, chunks);
- }
- }
- }
- else
- {
- //没有后续chunk了, 需要新分配fn空间
- vector<size_t> chunks;
- int ret = allocateChunk(fn, chunks, vtData);
- if(ret != TC_HashMap::RT_OK)
- {
- //没有内存可以分配
- return ret;
- }
- _pMap->update(&getBlockHead()->_bNextChunk, true);
- _pMap->update(&getBlockHead()->_iNextChunk, chunks[0]);
- //chunk指向分配的第一个chunk
- tagChunkHead *pChunk = getChunkHead(chunks[0]);
- //修改第一个chunk的属性, 保证异常core的时候, chunk链表不会有问题
- _pMap->update(&pChunk->_bNextChunk, false);
- _pMap->update(&pChunk->_iDataLen, (size_t)0);
- _pMap->doUpdate(true);
- //连接每个chunk
- return joinChunk(pChunk, chunks);
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::Block::joinChunk(tagChunkHead *pChunk, const vector<size_t> chunks)
- {
- for (size_t i = 0; i < chunks.size(); ++i)
- {
- if (i == chunks.size() - 1)
- {
- _pMap->update(&pChunk->_bNextChunk, false);
- _pMap->doUpdate(true);
- return TC_HashMap::RT_OK;
- }
- else
- {
- _pMap->update(&pChunk->_bNextChunk, true);
- _pMap->update(&pChunk->_iNextChunk, chunks[i+1]);
- pChunk = getChunkHead(chunks[i+1]);
- _pMap->update(&pChunk->_bNextChunk, false);
- _pMap->update(&pChunk->_iDataLen, (size_t)0);
- _pMap->doUpdate(true);
- }
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::Block::allocateChunk(size_t fn, vector<size_t> &chunks, vector<TC_HashMap::BlockData> &vtData)
- {
- assert(fn > 0);
- while(true)
- {
- size_t iAllocSize = fn;
- //分配空间
- size_t t = _pMap->_pDataAllocator->allocateChunk(_iHead, iAllocSize, vtData);
- if (t == 0)
- {
- //没有内存可以分配了, 先把分配的归还
- _pMap->_pDataAllocator->deallocateMemBlock(chunks);
- chunks.clear();
- return TC_HashMap::RT_NO_MEMORY;
- }
- //设置分配的数据块的大小
- getChunkHead(t)->_iSize = (uint32_t)iAllocSize;
- chunks.push_back(t);
- //分配够了
- if(fn <= (iAllocSize - sizeof(tagChunkHead)))
- {
- break;
- }
- //还需要多少空间
- fn -= iAllocSize - sizeof(tagChunkHead);
- }
- return TC_HashMap::RT_OK;
- }
- size_t TC_HashMap::Block::getDataLen()
- {
- size_t n = 0;
- if(!getBlockHead()->_bNextChunk)
- {
- 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;
- }
- ////////////////////////////////////////////////////////
- size_t TC_HashMap::BlockAllocator::allocateMemBlock(size_t index, size_t &iAllocSize, vector<TC_HashMap::BlockData> &vtData)
- {
- begin:
- void *pAddr = _pChunkAllocator->allocate(iAllocSize, iAllocSize);
- if(pAddr == NULL)
- {
- size_t ret = _pMap->eraseExcept(0, vtData);
- if(ret == 0)
- return 0; //没有空间可以释放了
- goto begin;
- }
- //分配的新的MemBlock, 初始化一下
- size_t iAddr = _pMap->getRelative(pAddr);
- Block block(_pMap, iAddr);
- block.makeNew(index, iAllocSize);
- _pMap->incChunkCount();
- return iAddr;
- }
- size_t TC_HashMap::BlockAllocator::allocateChunk(size_t iAddr, size_t &iAllocSize, vector<TC_HashMap::BlockData> &vtData)
- {
- begin:
- void *pAddr = _pChunkAllocator->allocate(iAllocSize, iAllocSize);
- if(pAddr == NULL)
- {
- size_t ret = _pMap->eraseExcept(iAddr, vtData);
- if(ret == 0)
- return 0; //没有空间可以释放了
- goto begin;
- }
- _pMap->incChunkCount();
- return _pMap->getRelative(pAddr);
- }
- void TC_HashMap::BlockAllocator::deallocateMemBlock(const vector<size_t> &v)
- {
- for(size_t i = 0; i < v.size(); i++)
- {
- _pChunkAllocator->deallocate(_pMap->getAbsolute(v[i]));
- _pMap->delChunkCount();
- }
- }
- void TC_HashMap::BlockAllocator::deallocateMemBlock(size_t v)
- {
- _pChunkAllocator->deallocate(_pMap->getAbsolute(v));
- _pMap->delChunkCount();
- }
- ///////////////////////////////////////////////////////////////////
- TC_HashMap::HashMapLockItem::HashMapLockItem(TC_HashMap *pMap, size_t iAddr)
- : _pMap(pMap)
- , _iAddr(iAddr)
- {
- }
- TC_HashMap::HashMapLockItem::HashMapLockItem(const HashMapLockItem &mcmdi)
- : _pMap(mcmdi._pMap)
- , _iAddr(mcmdi._iAddr)
- {
- }
- TC_HashMap::HashMapLockItem &TC_HashMap::HashMapLockItem::operator=(const TC_HashMap::HashMapLockItem &mcmdi)
- {
- if(this != &mcmdi)
- {
- _pMap = mcmdi._pMap;
- _iAddr = mcmdi._iAddr;
- }
- return (*this);
- }
- bool TC_HashMap::HashMapLockItem::operator==(const TC_HashMap::HashMapLockItem &mcmdi)
- {
- return _pMap == mcmdi._pMap && _iAddr == mcmdi._iAddr;
- }
- bool TC_HashMap::HashMapLockItem::operator!=(const TC_HashMap::HashMapLockItem &mcmdi)
- {
- return _pMap != mcmdi._pMap || _iAddr != mcmdi._iAddr;
- }
- bool TC_HashMap::HashMapLockItem::isDirty()
- {
- Block block(_pMap, _iAddr);
- return block.isDirty();
- }
- bool TC_HashMap::HashMapLockItem::isOnlyKey()
- {
- Block block(_pMap, _iAddr);
- return block.isOnlyKey();
- }
- time_t TC_HashMap::HashMapLockItem::getSyncTime()
- {
- Block block(_pMap, _iAddr);
- return block.getSyncTime();
- }
- int TC_HashMap::HashMapLockItem::get(string& k, string& v)
- {
- string s;
- Block block(_pMap, _iAddr);
- int ret = block.get(s);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- try
- {
- TC_PackOut po(s.c_str(), s.length());
- po >> k;
- if(!block.isOnlyKey())
- {
- po >> v;
- }
- else
- {
- v = "";
- return TC_HashMap::RT_ONLY_KEY;
- }
- }
- catch ( exception &ex )
- {
- return TC_HashMap::RT_EXCEPTION_ERR;
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::HashMapLockItem::get(string& k)
- {
- string s;
- Block block(_pMap, _iAddr);
- int ret = block.get(s);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- try
- {
- TC_PackOut po(s.c_str(), s.length());
- po >> k;
- }
- catch ( exception &ex )
- {
- return TC_HashMap::RT_EXCEPTION_ERR;
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::HashMapLockItem::set(const string& k, const string& v, vector<TC_HashMap::BlockData> &vtData)
- {
- Block block(_pMap, _iAddr);
- TC_PackIn pi;
- pi << k;
- pi << v;
- return block.set(pi.topacket().c_str(), pi.topacket().length(), false, vtData);
- }
- int TC_HashMap::HashMapLockItem::set(const string& k, vector<TC_HashMap::BlockData> &vtData)
- {
- Block block(_pMap, _iAddr);
- TC_PackIn pi;
- pi << k;
- return block.set(pi.topacket().c_str(), pi.topacket().length(), true, vtData);
- }
- bool TC_HashMap::HashMapLockItem::equal(const string &k, string &v, int &ret)
- {
- string k1;
- ret = get(k1, v);
- if ((ret == TC_HashMap::RT_OK || ret == TC_HashMap::RT_ONLY_KEY) && k == k1)
- {
- return true;
- }
- return false;
- }
- bool TC_HashMap::HashMapLockItem::equal(const string& k, int &ret)
- {
- string k1;
- ret = get(k1);
- if (ret == TC_HashMap::RT_OK && k == k1)
- {
- return true;
- }
- return false;
- }
- void TC_HashMap::HashMapLockItem::nextItem(int iType)
- {
- Block block(_pMap, _iAddr);
- if(iType == HashMapLockIterator::IT_BLOCK)
- {
- size_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)
- {
- _iAddr = block.getBlockHead()->_iSetNext;
- }
- else if(iType == HashMapLockIterator::IT_GET)
- {
- _iAddr = block.getBlockHead()->_iGetNext;
- }
- }
- void TC_HashMap::HashMapLockItem::prevItem(int iType)
- {
- Block block(_pMap, _iAddr);
- if(iType == HashMapLockIterator::IT_BLOCK)
- {
- size_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();
- return;
- }
- _iAddr = 0; //到尾部了
- }
- else if(iType == HashMapLockIterator::IT_SET)
- {
- _iAddr = block.getBlockHead()->_iSetPrev;
- }
- else if(iType == HashMapLockIterator::IT_GET)
- {
- _iAddr = block.getBlockHead()->_iGetPrev;
- }
- }
- ///////////////////////////////////////////////////////////////////
- TC_HashMap::HashMapLockIterator::HashMapLockIterator()
- : _pMap(NULL), _iItem(NULL, 0), _iType(IT_BLOCK), _iOrder(IT_NEXT)
- {
- }
- TC_HashMap::HashMapLockIterator::HashMapLockIterator(TC_HashMap *pMap, size_t iAddr, int iType, int iOrder)
- : _pMap(pMap), _iItem(_pMap, iAddr), _iType(iType), _iOrder(iOrder)
- {
- }
- TC_HashMap::HashMapLockIterator::HashMapLockIterator(const HashMapLockIterator &it)
- : _pMap(it._pMap),_iItem(it._iItem), _iType(it._iType), _iOrder(it._iOrder)
- {
- }
- TC_HashMap::HashMapLockIterator& TC_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_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_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_HashMap::HashMapLockIterator& TC_HashMap::HashMapLockIterator::operator++()
- {
- if(_iOrder == IT_NEXT)
- {
- _iItem.nextItem(_iType);
- }
- else
- {
- _iItem.prevItem(_iType);
- }
- return (*this);
- }
- TC_HashMap::HashMapLockIterator TC_HashMap::HashMapLockIterator::operator++(int)
- {
- HashMapLockIterator it(*this);
- if(_iOrder == IT_NEXT)
- {
- _iItem.nextItem(_iType);
- }
- else
- {
- _iItem.prevItem(_iType);
- }
- return it;
- }
- ///////////////////////////////////////////////////////////////////
- TC_HashMap::HashMapItem::HashMapItem(TC_HashMap *pMap, size_t iIndex)
- : _pMap(pMap)
- , _iIndex(iIndex)
- {
- }
- TC_HashMap::HashMapItem::HashMapItem(const HashMapItem &mcmdi)
- : _pMap(mcmdi._pMap)
- , _iIndex(mcmdi._iIndex)
- {
- }
- TC_HashMap::HashMapItem &TC_HashMap::HashMapItem::operator=(const TC_HashMap::HashMapItem &mcmdi)
- {
- if(this != &mcmdi)
- {
- _pMap = mcmdi._pMap;
- _iIndex = mcmdi._iIndex;
- }
- return (*this);
- }
- bool TC_HashMap::HashMapItem::operator==(const TC_HashMap::HashMapItem &mcmdi)
- {
- return _pMap == mcmdi._pMap && _iIndex == mcmdi._iIndex;
- }
- bool TC_HashMap::HashMapItem::operator!=(const TC_HashMap::HashMapItem &mcmdi)
- {
- return _pMap != mcmdi._pMap || _iIndex != mcmdi._iIndex;
- }
- void TC_HashMap::HashMapItem::get(vector<TC_HashMap::BlockData> &vtData)
- {
- size_t iAddr = _pMap->item(_iIndex)->_iBlockAddr;
- while(iAddr != 0)
- {
- Block block(_pMap, iAddr);
- TC_HashMap::BlockData data;
- int ret = block.getBlockData(data);
- if(ret == TC_HashMap::RT_OK)
- {
- vtData.push_back(data);
- }
- iAddr = block.getBlockHead()->_iBlockNext;
- }
- }
- void TC_HashMap::HashMapItem::nextItem()
- {
- if(_iIndex == (size_t)(-1))
- {
- return;
- }
- if(_iIndex >= _pMap->getHashCount() - 1)
- {
- _iIndex = (size_t)(-1);
- return;
- }
- _iIndex++;
- }
- int TC_HashMap::HashMapItem::setDirty()
- {
- if(_pMap->getMapHead()._bReadOnly) return RT_READONLY;
- size_t iAddr = _pMap->item(_iIndex)->_iBlockAddr;
- while(iAddr != 0)
- {
- Block block(_pMap, iAddr);
- if(!block.isOnlyKey())
- {
- _pMap->doUpdate();
- block.setDirty(true);
- block.refreshSetList();
- }
- iAddr = block.getBlockHead()->_iBlockNext;
- }
- return RT_OK;
- }
- ///////////////////////////////////////////////////////////////////
- TC_HashMap::HashMapIterator::HashMapIterator()
- : _pMap(NULL), _iItem(NULL, 0)
- {
- }
- TC_HashMap::HashMapIterator::HashMapIterator(TC_HashMap *pMap, size_t iIndex)
- : _pMap(pMap), _iItem(_pMap, iIndex)
- {
- }
- TC_HashMap::HashMapIterator::HashMapIterator(const HashMapIterator &it)
- : _pMap(it._pMap),_iItem(it._iItem)
- {
- }
- TC_HashMap::HashMapIterator& TC_HashMap::HashMapIterator::operator=(const HashMapIterator &it)
- {
- if(this != &it)
- {
- _pMap = it._pMap;
- _iItem = it._iItem;
- }
- return (*this);
- }
- bool TC_HashMap::HashMapIterator::operator==(const HashMapIterator& mcmi)
- {
- if (_iItem.getIndex() != -1 || mcmi._iItem.getIndex() != -1)
- {
- return _pMap == mcmi._pMap && _iItem == mcmi._iItem;
- }
- return _pMap == mcmi._pMap;
- }
- bool TC_HashMap::HashMapIterator::operator!=(const HashMapIterator& mcmi)
- {
- if (_iItem.getIndex() != -1 || mcmi._iItem.getIndex() != -1 )
- {
- return _pMap != mcmi._pMap || _iItem != mcmi._iItem;
- }
- return _pMap != mcmi._pMap;
- }
- TC_HashMap::HashMapIterator& TC_HashMap::HashMapIterator::operator++()
- {
- _iItem.nextItem();
- return (*this);
- }
- TC_HashMap::HashMapIterator TC_HashMap::HashMapIterator::operator++(int)
- {
- HashMapIterator it(*this);
- _iItem.nextItem();
- return it;
- }
- //////////////////////////////////////////////////////////////////////////////////
- void TC_HashMap::init(void *pAddr)
- {
- _pHead = static_cast<tagMapHead*>(pAddr);
- _pstModifyHead = static_cast<tagModifyHead*>((void*)((char*)pAddr + sizeof(tagMapHead)));
- }
- void TC_HashMap::initDataBlockSize(size_t iMinDataSize, size_t iMaxDataSize, float fFactor)
- {
- _iMinDataSize = iMinDataSize;
- _iMaxDataSize = iMaxDataSize;
- _fFactor = fFactor;
- }
- void TC_HashMap::create(void *pAddr, size_t iSize)
- {
- if(sizeof(tagHashItem) * 1
- + sizeof(tagMapHead)
- + sizeof(tagModifyHead)
- + sizeof(TC_MemMultiChunkAllocator::tagChunkAllocatorHead)
- + 10 > iSize)
- {
- throw TC_HashMap_Exception("[TC_HashMap::create] mem size not enougth.");
- }
- if(_iMinDataSize == 0 || _iMaxDataSize == 0 || _fFactor < 1.0)
- {
- throw TC_HashMap_Exception("[TC_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->_fRadio = _fRadio;
- _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;
- //计算平均block大小
- size_t iBlockSize = (_pHead->_iMinDataSize + _pHead->_iMaxDataSize)/2 + sizeof(Block::tagBlockHead);
- //Hash个数
- size_t iHashCount = (iSize - sizeof(TC_MemChunkAllocator::tagChunkAllocatorHead)) / ((size_t)(iBlockSize*_fRadio) + sizeof(tagHashItem));
- //采用最近的素数作为hash值
- iHashCount = getMinPrimeNumber(iHashCount);
- void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
- size_t iHashMemSize = TC_MemVector<tagHashItem>::calcMemSize(iHashCount);
- _hash.create(pHashAddr, iHashMemSize);
- void *pDataAddr = (char*)pHashAddr + _hash.getMemSize();
- _pDataAllocator->create(pDataAddr, iSize - ((char*)pDataAddr - (char*)_pHead), sizeof(Block::tagBlockHead) + _pHead->_iMinDataSize, sizeof(Block::tagBlockHead) + _pHead->_iMaxDataSize, _pHead->_fFactor);
- }
- void TC_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_HashMap_Exception("[TC_HashMap::connect] hash map version not equal:" + os.str() + " (data != code)");
- }
- if(_pHead->_iMemSize != iSize)
- {
- throw TC_HashMap_Exception("[TC_HashMap::connect] hash map size not equal:" + TC_Common::tostr(_pHead->_iMemSize) + "!=" + TC_Common::tostr(iSize));
- }
- void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
- _hash.connect(pHashAddr);
- void *pDataAddr = (char*)pHashAddr + _hash.getMemSize();
- _pDataAllocator->connect(pDataAddr);
- _iMinDataSize = _pHead->_iMinDataSize;
- _iMaxDataSize = _pHead->_iMaxDataSize;
- _fFactor = _pHead->_fFactor;
- _fRadio = _pHead->_fRadio;
- }
- int TC_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_HashMap_Exception("[TC_HashMap::append] hash map version not equal:" + os.str() + " (data != code)");
- }
- _pHead->_iMemSize = iSize;
- void *pHashAddr = (char*)_pHead + sizeof(tagMapHead) + sizeof(tagModifyHead);
- _hash.connect(pHashAddr);
- 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;
- _fRadio = _pHead->_fRadio;
- return 0;
- }
- void TC_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;
- _hash.clear();
- _pDataAllocator->rebuild();
- }
- int TC_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_HashMap::load5file(const string &sFile)
- {
- FILE *fp = fopen(sFile.c_str(), "rb");
- if(fp == NULL)
- {
- return RT_LOAL_FILE_ERR;
- }
- fseek(fp, 0L, SEEK_END);
- size_t fs = ftell(fp);
- if(fs != _pHead->_iMemSize)
- {
- fclose(fp);
- return RT_LOAL_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_LOAL_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_LOAL_FILE_ERR;
- }
- int TC_HashMap::recover(size_t i, bool bRepair)
- {
- doUpdate();
- if( i >= _hash.size())
- {
- return 0;
- }
- size_t e = 0;
- check:
- size_t iAddr = item(i)->_iBlockAddr;
- Block block(this, iAddr);
- while(block.getHead() != 0)
- {
- BlockData data;
- int ret = block.getBlockData(data);
- if(ret != TC_HashMap::RT_OK && ret != TC_HashMap::RT_ONLY_KEY)
- {
- //增加删除block数
- ++e;
- if(bRepair)
- {
- block.erase();
- goto check;
- }
- }
- if(!block.nextBlock())
- {
- break;
- }
- }
- return e;
- }
- int TC_HashMap::checkDirty(const string &k)
- {
- doUpdate();
- incGetCount();
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it= find(k, index, ret);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- //没有数据
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- //只有Key
- if(it->isOnlyKey())
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- Block block(this, it->getAddr());
- if (block.isDirty())
- {
- return TC_HashMap::RT_DIRTY_DATA;
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::setDirty(const string& k)
- {
- doUpdate();
- if(_pHead->_bReadOnly) return RT_READONLY;
- incGetCount();
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it= find(k, index, ret);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- //没有数据或只有Key
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- //只有Key
- if(it->isOnlyKey())
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- Block block(this, it->getAddr());
- block.setDirty(true);
- block.refreshSetList();
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::setDirtyAfterSync(const string& k)
- {
- doUpdate();
- if(_pHead->_bReadOnly) return RT_READONLY;
- incGetCount();
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it= find(k, index, ret);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- //没有数据或只有Key
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- //只有Key
- if(it->isOnlyKey())
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- Block block(this, it->getAddr());
- block.setDirty(true);
- if(_pHead->_iDirtyTail == block.getBlockHead()->_iSetPrev)
- {
- _pHead->_iDirtyTail = block.getHead();
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::setClean(const string& k)
- {
- doUpdate();
- if(_pHead->_bReadOnly) return RT_READONLY;
- incGetCount();
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it= find(k, index, ret);
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- //没有数据或只有Key
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- //只有Key
- if(it->isOnlyKey())
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- Block block(this, it->getAddr());
- block.setDirty(false);
- block.refreshSetList();
- doUpdate(true);
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::get(const string& k, string &v, time_t &iSyncTime)
- {
- doUpdate();
- incGetCount();
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it = find(k, index, v, ret);
- if(ret != TC_HashMap::RT_OK && ret != TC_HashMap::RT_ONLY_KEY)
- {
- return ret;
- }
- //没有数据
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- //只有Key
- if(it->isOnlyKey())
- {
- return TC_HashMap::RT_ONLY_KEY;
- }
- Block block(this, it->getAddr());
- iSyncTime = block.getSyncTime();
- //如果只读, 则不刷新get链表
- if(!_pHead->_bReadOnly)
- {
- block.refreshGetList();
- }
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::get(const string& k, string &v)
- {
- time_t iSyncTime;
- return get(k, v, iSyncTime);
- }
- int TC_HashMap::set(const string& k, const string& v, bool bDirty, vector<BlockData> &vtData)
- {
- doUpdate();
- incGetCount();
- if(_pHead->_bReadOnly) return RT_READONLY;
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it = find(k, index, ret);
- bool bNewBlock = false;
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- if(it == end())
- {
- TC_PackIn pi;
- pi << k;
- pi << v;
- size_t iAllocSize = sizeof(Block::tagBlockHead) + pi.length();
- //先分配空间, 并获得淘汰的数据
- size_t iAddr = _pDataAllocator->allocateMemBlock(index, iAllocSize, vtData);
- if(iAddr == 0)
- {
- return TC_HashMap::RT_NO_MEMORY;
- }
- it = HashMapLockIterator(this, iAddr, HashMapLockIterator::IT_BLOCK, HashMapLockIterator::IT_NEXT);
- bNewBlock = true;
- }
- ret = it->set(k, v, vtData);
- if(ret != TC_HashMap::RT_OK)
- {
- //新记录, 写失败了, 要删除该块
- if(bNewBlock)
- {
- Block block(this, it->getAddr());
- block.erase();
- }
- return ret;
- }
- Block block(this, it->getAddr());
- if(bNewBlock)
- {
- block.setSyncTime(time(NULL));
- }
- block.setDirty(bDirty);
- block.refreshSetList();
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::set(const string& k, vector<BlockData> &vtData)
- {
- doUpdate();
- incGetCount();
- if(_pHead->_bReadOnly) return RT_READONLY;
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- lock_iterator it = find(k, index, ret);
- bool bNewBlock = false;
- if(ret != TC_HashMap::RT_OK)
- {
- return ret;
- }
- if(it == end())
- {
- TC_PackIn pi;
- pi << k;
- size_t iAllocSize = sizeof(Block::tagBlockHead) + pi.length();
- //先分配空间, 并获得淘汰的数据
- size_t iAddr = _pDataAllocator->allocateMemBlock(index, iAllocSize, vtData);
- if(iAddr == 0)
- {
- return TC_HashMap::RT_NO_MEMORY;
- }
- it = HashMapLockIterator(this, iAddr, HashMapLockIterator::IT_BLOCK, HashMapLockIterator::IT_NEXT);
- bNewBlock = true;
- }
- ret = it->set(k, vtData);
- if(ret != TC_HashMap::RT_OK)
- {
- //新记录, 写失败了, 要删除该块
- if(bNewBlock)
- {
- Block block(this, it->getAddr());
- block.erase();
- }
- return ret;
- }
- Block block(this, it->getAddr());
- if(bNewBlock)
- {
- block.setSyncTime(time(NULL));
- }
- block.refreshSetList();
- return TC_HashMap::RT_OK;
- }
- int TC_HashMap::del(const string& k, BlockData &data)
- {
- doUpdate();
- incGetCount();
- if(_pHead->_bReadOnly) return RT_READONLY;
- int ret = TC_HashMap::RT_OK;
- size_t index = hashIndex(k);
- data._key = k;
- lock_iterator it = find(k, index, data._value, ret);
- if(ret != TC_HashMap::RT_OK && ret != TC_HashMap::RT_ONLY_KEY)
- {
- return ret;
- }
- if(it == end())
- {
- return TC_HashMap::RT_NO_DATA;
- }
- Block block(this, it->getAddr());
- ret = block.getBlockData(data);
- block.erase();
- return ret;
- }
- int TC_HashMap::erase(int radio, BlockData &data, bool bCheckDirty)
- {
- doUpdate();
- if(_pHead->_bReadOnly) return RT_READONLY;
- if(radio <= 0) radio = 1;
- if(radio >= 100) radio = 100;
- size_t iAddr = _pHead->_iGetTail;
- //到链表头部
- if(iAddr == 0)
- {
- return RT_OK;
- }
- //删除到指定比率了
- if((_pHead->_iUsedChunk * 100. / allBlockChunkCount()) < radio)
- {
- return RT_OK;
- }
- Block block(this, iAddr);
- if(bCheckDirty)
- {
- if(block.isDirty())
- {
- if(_pHead->_iDirtyTail == 0)
- {
- _pHead->_iDirtyTail = iAddr;
- }
- // 将脏数据移动到get链的头部,使可以继续淘汰
- if(_pHead->_iGetHead == iAddr)
- {
- // 既是头也是尾,只有一个元素了
- return RT_OK;
- }
- if(block._pMap->_pHead->_iBackupTail == block._iHead)
- {
- update(&block._pMap->_pHead->_iBackupTail, block.getBlockHead()->_iGetPrev);
- }
- // 将GetTail上移
- update(&_pHead->_iGetTail, block.getBlockHead()->_iGetPrev);
- // 从Get尾部移除
- update(&block.getBlockHead(block.getBlockHead()->_iGetPrev)->_iGetNext, (size_t)0);
- update(&block.getBlockHead()->_iGetPrev, (size_t)0);
- // 移到Get头部
- update(&block.getBlockHead()->_iGetNext, _pHead->_iGetHead);
- update(&block.getBlockHead(_pHead->_iGetHead)->_iGetPrev, iAddr);
- update(&_pHead->_iGetHead, iAddr);
- doUpdate(true);
- return RT_DIRTY_DATA;
- }
- }
- int ret = block.getBlockData(data);
- block.erase();
- if(ret == TC_HashMap::RT_OK)
- {
- return TC_HashMap::RT_ERASE_OK;
- }
- return ret;
- }
- void TC_HashMap::sync()
- {
- doUpdate();
-
- _pHead->_iSyncTail = _pHead->_iDirtyTail;
- }
- int TC_HashMap::sync(time_t iNowTime, BlockData &data)
- {
- doUpdate();
- size_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;
- }
- int ret = block.getBlockData(data);
- if(ret != TC_HashMap::RT_OK)
- {
- //没有获取完整的记录
- if(_pHead->_iDirtyTail == iAddr)
- {
- _pHead->_iDirtyTail = block.getBlockHead()->_iSetPrev;
- }
- return ret;
- }
- //脏数据且超过_pHead->_iSyncTime没有回写, 需要回写
- if(_pHead->_iSyncTime + 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_HashMap::backup(bool bForceFromBegin)
- {
- doUpdate();
- if(bForceFromBegin || _pHead->_iBackupTail == 0)
- {
- //移动备份指针到Get链尾部, 准备开始备份数据
- _pHead->_iBackupTail = _pHead->_iGetTail;
- }
- }
- int TC_HashMap::backup(BlockData &data)
- {
- doUpdate();
- size_t iAddr = _pHead->_iBackupTail;
- //到链表头部了, 返回RT_OK
- if(iAddr == 0)
- {
- return RT_OK;
- }
- Block block(this, iAddr);
- int ret = block.getBlockData(data);
- //迁移一次
- _pHead->_iBackupTail = block.getBlockHead()->_iGetPrev;
- doUpdate(true);
- if(ret == TC_HashMap::RT_OK)
- {
- return TC_HashMap::RT_NEED_BACKUP;
- }
- return ret;
- }
- TC_HashMap::lock_iterator TC_HashMap::find(const string& k)
- {
- size_t index = hashIndex(k);
- int ret = TC_HashMap::RT_OK;
- doUpdate();
- if(item(index)->_iBlockAddr == 0)
- {
- return end();
- }
- Block mb(this, item(index)->_iBlockAddr);
- while(true)
- {
- HashMapLockItem mcmdi(this, mb.getHead());
- if(mcmdi.equal(k, ret))
- {
- incHitCount();
- return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
- }
- if (!mb.nextBlock())
- {
- return end();
- }
- }
- return end();
- }
- TC_HashMap::lock_iterator TC_HashMap::begin()
- {
- doUpdate();
- 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_HashMap::lock_iterator TC_HashMap::rbegin()
- {
- doUpdate();
- 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(), lock_iterator::IT_BLOCK, lock_iterator::IT_PREV);
- }
- }
- return end();
- }
- TC_HashMap::lock_iterator TC_HashMap::beginSetTime()
- {
- doUpdate();
- return lock_iterator(this, _pHead->_iSetHead, lock_iterator::IT_SET, lock_iterator::IT_NEXT);
- }
- TC_HashMap::lock_iterator TC_HashMap::rbeginSetTime()
- {
- doUpdate();
- return lock_iterator(this, _pHead->_iSetTail, lock_iterator::IT_SET, lock_iterator::IT_PREV);
- }
- TC_HashMap::lock_iterator TC_HashMap::beginGetTime()
- {
- doUpdate();
- return lock_iterator(this, _pHead->_iGetHead, lock_iterator::IT_GET, lock_iterator::IT_NEXT);
- }
- TC_HashMap::lock_iterator TC_HashMap::rbeginGetTime()
- {
- doUpdate();
- return lock_iterator(this, _pHead->_iGetTail, lock_iterator::IT_GET, lock_iterator::IT_PREV);
- }
- TC_HashMap::lock_iterator TC_HashMap::beginDirty()
- {
- doUpdate();
- return lock_iterator(this, _pHead->_iDirtyTail, lock_iterator::IT_SET, lock_iterator::IT_PREV);
- }
- TC_HashMap::hash_iterator TC_HashMap::hashBegin()
- {
- doUpdate();
- return hash_iterator(this, 0);
- }
- TC_HashMap::hash_iterator TC_HashMap::hashIndex(size_t iIndex)
- {
- doUpdate();
- return hash_iterator(this, iIndex);
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////
- string TC_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 << "[HashRadio = " << _pHead->_fRadio << "]" << 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 << "[ModifyStatus = " << (int)_pstModifyHead->_cModifyStatus << "]" << endl;
- s << "[ModifyIndex = " << _pstModifyHead->_iNowIndex << "]" << endl;
- s << "[OnlyKeyCount = " << _pHead->_iOnlyKeyCount << "]" << 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;
- }
- 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_HashMap::eraseExcept(size_t iNowAddr, vector<BlockData> &vtData)
- {
- //不能被淘汰
- if(!_pHead->_bAutoErase) return 0;
- size_t n = _pHead->_iEraseCount;
- if(n == 0) n = 10;
- size_t d = n;
- while (d != 0)
- {
- size_t iAddr;
- //判断按照哪种方式淘汰
- if(_pHead->_cEraseMode == TC_HashMap::ERASEBYSET)
- {
- iAddr = _pHead->_iSetTail;
- }
- else
- {
- iAddr = _pHead->_iGetTail;
- }
- if (iAddr == 0)
- {
- break;
- }
- Block block(this, iAddr);
- //当前block正在分配空间, 不能删除, 移到上一个数据
- if (iNowAddr == iAddr)
- {
- if(_pHead->_cEraseMode == TC_HashMap::ERASEBYSET)
- {
- iAddr = block.getBlockHead()->_iSetPrev;
- }
- else
- {
- iAddr = block.getBlockHead()->_iGetPrev;
- }
- }
- if(iAddr == 0)
- {
- break;
- }
- Block block1(this, iAddr);
- BlockData data;
- int ret = block1.getBlockData(data);
- if(ret == TC_HashMap::RT_OK)
- {
- vtData.push_back(data);
- d--;
- }
- else if(ret == TC_HashMap::RT_NO_DATA)
- {
- d--;
- }
- //删除数据
- block1.erase();
- }
- return n-d;
- }
- size_t TC_HashMap::hashIndex(const string& k)
- {
- return _hashf(k) % _hash.size();
- }
- TC_HashMap::lock_iterator TC_HashMap::find(const string& k, size_t index, string &v, int &ret)
- {
- ret = TC_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(k, v, ret))
- {
- incHitCount();
- return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
- }
- if (!mb.nextBlock())
- {
- return end();
- }
- }
- return end();
- }
- TC_HashMap::lock_iterator TC_HashMap::find(const string& k, size_t index, int &ret)
- {
- ret = TC_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(k, ret))
- {
- incHitCount();
- return lock_iterator(this, mb.getHead(), lock_iterator::IT_BLOCK, lock_iterator::IT_NEXT);
- }
- if (!mb.nextBlock())
- {
- return end();
- }
- }
- return end();
- }
- void TC_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_HashMap::doUpdate(bool bUpdate)
- {
- if(bUpdate)
- {
- _pstModifyHead->_cModifyStatus = 2;
- }
- //==1, copy过程中, 程序失败, 需要清除状态
- if(_pstModifyHead->_cModifyStatus == 1)
- {
- _pstModifyHead->_iNowIndex = 0;
- for(size_t i = 0; i < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData); i++)
- {
- _pstModifyHead->_stModifyData[i]._iModifyAddr = 0;
- _pstModifyHead->_stModifyData[i]._cBytes = 0;
- _pstModifyHead->_stModifyData[i]._iModifyValue = 0;
- }
- _pstModifyHead->_cModifyStatus = 0;
- }
- //==2, 已经修改成功, 但是没有copy到内存中, 需要更新到内存中
- else if(_pstModifyHead->_cModifyStatus == 2)
- {
- for(size_t i = 0; i < _pstModifyHead->_iNowIndex; i++)
- {
- if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(size_t))
- {
- *(size_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(bool))
- {
- *(bool*)((char*)_pHead + _pstModifyHead->_stModifyData[i]._iModifyAddr) = (bool)_pstModifyHead->_stModifyData[i]._iModifyValue;
- }
- else
- {
- assert(true);
- }
- }
- _pstModifyHead->_iNowIndex = 0;
- _pstModifyHead->_cModifyStatus = 0;
- }
- //==0, 正常状态
- else if(_pstModifyHead->_cModifyStatus == 0)
- {
- return;
- }
- }
- void TC_HashMap::update(void* iModifyAddr, size_t iModifyValue)
- {
- _pstModifyHead->_cModifyStatus = 1;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyAddr = getRelative(iModifyAddr);
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyValue = iModifyValue;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._cBytes = sizeof(iModifyValue);
- _pstModifyHead->_iNowIndex++;
- assert(_pstModifyHead->_iNowIndex < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData));
- }
- #if __WORDSIZE == 64 || defined _WIN64
- void TC_HashMap::update(void* iModifyAddr, uint32_t iModifyValue)
- {
- _pstModifyHead->_cModifyStatus = 1;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyAddr = getRelative(iModifyAddr);
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyValue = iModifyValue;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._cBytes = sizeof(iModifyValue);
- _pstModifyHead->_iNowIndex++;
- assert(_pstModifyHead->_iNowIndex < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData));
- }
- #endif
- void TC_HashMap::update(void* iModifyAddr, bool bModifyValue)
- {
- _pstModifyHead->_cModifyStatus = 1;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyAddr = getRelative(iModifyAddr);
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyValue = bModifyValue;
- _pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._cBytes = sizeof(bModifyValue);
- _pstModifyHead->_iNowIndex++;
- assert(_pstModifyHead->_iNowIndex < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData));
- }
- size_t TC_HashMap::getMinPrimeNumber(size_t n)
- {
- while(true)
- {
- if(TC_Common::isPrimeNumber(n))
- {
- return n;
- }
- ++n;
- }
- return 3;
- }
- }
|