1 Star 3 Fork 2

wuyi / shm_hash

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
multi_hashmap.cpp 33.33 KB
一键复制 编辑 原始数据 按行查看 历史
wuyi 提交于 2022-02-25 15:27 . add
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
#include "multi_hashmap.h"
#include <vector>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <math.h>
#include <fcntl.h>
#include <iostream>
#include <unistd.h>
#include "define.h"
#include "hashvalue_block.h"
#include "wx_log.h"
extern "C" uint64_t DefaultHashFunc(const void* key, uint32_t len)
{
uint64_t i, h = 0;
#define magic 131
const unsigned char* p = (const unsigned char*)key;
if (!key)
return 0;
for (i = 0; i < len; i++, p++)
h = h * magic + *p;
return h;
}
/*
* 返回n以下(不包括n)的最大质数
*/
static uint64_t MaxPrime(uint32_t n)
{
while (n--)
{
int k;
int sqr = (int)ceil(sqrt(n));
for (k = 2; k <= sqr; ++k)
if (n % k == 0)
break;
if (k == sqr + 1)return n;
}
return 0;
}
static inline
s_offset_list_t* offset_to_ptr(void* context, uint64_t offset) {
auto c = (MultiHashMap*)context;
return (s_offset_list_t*)(c->GetBaseAddr() + offset);
}
static inline
uint64_t ptr_to_offset(void* context, s_offset_list_t* node) {
auto c = (MultiHashMap*)context;
return ((uint8_t*)node-c->GetBaseAddr());
}
void MultiHashMap::initMemberAddress(const char* addr, const std::vector<int>& nodesInfo, bool keyMemIsNewCreate){
char* pos = (char*)addr;
m_header = (MhtHeader*)addr;
pos += sizeof(MhtHeader);
//-------------------------------------------------
m_context = (MhtContext*)pos;
if (keyMemIsNewCreate) {
//memset(m_context->mutex_buf,0,sizeof(m_context->mutex_buf));
}
{
//m_mutex = (SharedMutex*)m_context->mutex_buf;
loginfo("m_mutexKey=0x%x", m_mutexKey);
int new_flag;
void* p = getmemory(m_mutexKey, 2048, new_flag);
if (p == NULL) {
printf("getmemory failed\n");
return;
}
SharedMutex* mutex = (SharedMutex*)p;
mutex->create(new_flag);
m_mutex = mutex;
}
pos += sizeof(MhtContext);
m_rowsPrimNumInfo = nodesInfo;
for (uint32_t i = 0; i < nodesInfo.size(); i++) {
char* rowAddr = pos;
MhtRowHeader* row = (MhtRowHeader*)rowAddr;
row->nodeNum = nodesInfo[i];
pos += sizeof(MhtRowHeader);
pos += sizeof(MhtHashNode)* row->nodeNum;
m_rowLines.push_back(row);
}
m_htTail = (MhtTail*)pos;
}
void MultiHashMap::initHead(uint64_t blockSize) {
logdebug("init head");
memset((void*)m_header,0,sizeof(MhtHeader));
//块magicid
strcpy(m_header->magicID, MhtHead_MAGIC);
//版本号
m_header->version = MhtHead_VERSION;
//大小,包括头大小
m_header->size = blockSize;
//头大小
m_header->headerSzie = sizeof(MhtHeader);
//总行数
m_header->nodesRowNum = m_rowLines.size();
m_header->totalNodesNum = 0;
for (uint32_t i = 0; i < m_rowsPrimNumInfo.size(); i++) {
m_header->totalNodesNum += m_rowsPrimNumInfo[i];
}
//key最大大小
m_header->keyDataSize = HASH_NODE_KEY_DATA_SIZE;
m_header->nodeSize = sizeof(MhtHashNode);
strcpy(m_header->blockInitTag, HashBlockInitTag);
}
bool MultiHashMap::checkHead() {
logdebug("checkHead");
if (strcmp(m_header->magicID, MhtHead_MAGIC)!=0) {
logerror("magicID not match");
return false;
}
//版本号
if (m_header->version!= MhtHead_VERSION) {
logerror("version not match");
return false;
}
//---------------------------------------------
uint64_t outKeyMemTotalSize;
uint64_t outValueMemTotalSize;
uint64_t outCellNum;
uint32_t cellSize;
std::vector<int> nodesInfo;
MultiHashMap::calCreateThisBlockNeedMemSize(m_rowsPrimNumInfo, outKeyMemTotalSize, outValueMemTotalSize, outCellNum,cellSize);
if (outKeyMemTotalSize != m_header->size) {
logerror("outKeyMemTotalSize not match,outKeyMemTotalSize=%d,size=%d", outKeyMemTotalSize,m_header->size);
return false;
}
if (m_rowLines.size() != m_rowsPrimNumInfo.size()) {
logerror("m_rowLines not match");
return false;
}
//----------------------------------------------
//头大小
if (m_header->headerSzie != sizeof(MhtHeader)) {
logerror("headerSzie not match");
return false;
}
//总行数
if (m_header->nodesRowNum != m_rowLines.size()) {
logerror("nodesRowNum not match");
return false;
}
if (m_header->keyDataSize != HASH_NODE_KEY_DATA_SIZE) {
logerror("keyDataSize not match");
return false;
}
if (m_header->nodeSize != sizeof(MhtHashNode)) {
logerror("nodeSize not match");
return false;
}
if (strcmp(m_header->blockInitTag, HashBlockInitTag) != 0) {
logerror("blockInitTag not match");
return false;
}
return true;
}
void MultiHashMap::printHead() {
printf("# Head\n");
printf("head.magicID=%s\n", m_header->magicID);
printf("head.version=%d\n", m_header->version);
printf("head.size=%d\n", m_header->size);
printf("head.headerSzie=%d\n", m_header->headerSzie);
printf("head.nodesRowNum=%d\n", m_header->nodesRowNum);
printf("head.totalNodesNum=%d\n", m_header->totalNodesNum);
printf("head.keyDataSize=%d\n", m_header->keyDataSize);
printf("head.nodeSize=%d\n", m_header->nodeSize);
printf("head.blockInitTag=%s\n", m_header->blockInitTag);
printf("\n");
}
void MultiHashMap::initContext() {
memset((void*)m_context, 0, sizeof(MhtContext));
logdebug("initContext");
m_context->keySeq = 0;
//s_offset_list_init(&(m_context->inOpList));
}
bool MultiHashMap::checkContext() {
logdebug("checkContext");
return true;
}
void MultiHashMap::printContext() {
printf("# Context\n");
printf("context.keySeq=%lu\n", m_context->keySeq);
printf("\n");
}
void MultiHashMap::initRowLines() {
logdebug("initRowLines");
//uint32_t totalNodesNum;
for (uint32_t i = 0; i < m_rowLines.size(); i++) {
MhtRowHeader* row=m_rowLines[i];
strcpy(row->rowTag, HashNodeRowTag);
uint32_t row_size = row->nodeNum * sizeof(MhtHashNode);
row->rowBodySize = row_size;
char* pos = (char*)row + sizeof(MhtRowHeader);
memset(pos,0, row_size);
}
}
bool MultiHashMap::checkRowLines() {
logdebug("checkRowLines");
for (uint32_t i = 0; i < m_rowLines.size(); i++) {
MhtRowHeader* row = m_rowLines[i];
if (strcmp(row->rowTag, HashNodeRowTag)!=0) {
logerror("row:%d rowTag not match", i);
return false;
}
uint32_t row_size = row->nodeNum * sizeof(MhtHashNode);
if (row->rowBodySize != row_size) {
logerror("row:%d rowBodySize not match", i);
return false;
}
char* rowEnd = nullptr;
if (i < m_rowLines.size() - 1) {
rowEnd=(char*) m_rowLines[i + 1];
}
else{
rowEnd = (char*)m_htTail;
}
char* pos = (char*)row + sizeof(MhtRowHeader) + row_size;
if (pos != (char*)rowEnd) {
logerror("row:%d rowEnd not match", i);
return false;
}
}
return true;
}
void MultiHashMap::printRowLines() {
printf("# RowLines\n");
uint32_t totalNodesNum=0;
for (uint32_t i = 0; i < m_rowLines.size(); i++) {
MhtRowHeader* row = m_rowLines[i];
//printf("row.%d.tag=%s\n", i, row->rowTag);
printf("row.%d.nodeNum=%d\n", i, row->nodeNum);
printf("row.%d.rowBodySize=%d\n", i, row->rowBodySize);
totalNodesNum += row->nodeNum;
}
printf("row.totalNodesNum=%d\n", totalNodesNum);
printf("\n");
}
void MultiHashMap::initTail() {
logdebug("initTail");
memset((void*)m_htTail, 0, sizeof(MhtTail));
strcpy(m_htTail->magicID, MhtTail_MAGIC);
}
bool MultiHashMap::checkTail() {
logdebug("checkTail");
return (strcmp(m_htTail->magicID, MhtTail_MAGIC) == 0);
}
void MultiHashMap::printTail() {
printf("# Tail\n");
printf("tail.magicID=%s\n", m_htTail->magicID);
printf("\n");
}
void MultiHashMap::initAll(uint64_t blockSize) {
logdebug("begin initall");
initHead(blockSize);
initContext();
initRowLines();
initTail();
}
bool MultiHashMap::checkAll() {
logdebug("checkAll");
if (!checkHead()) {
return false;
}
if (!checkContext()) {
return false;
}
if (!checkRowLines()) {
return false;
}
if (!checkTail()) {
return false;
}
return true;
}
void MultiHashMap::printAll() {
printHead();
printContext();
printRowLines();
printTail();
}
std::vector<int>
MultiHashMap::getCreateThisBlockHashRowNodesInfo(const uint32_t inHashFirstRowsNodeNum, const uint32_t inHashRowsNum) {
uint32_t rowMaxNodeNum = inHashFirstRowsNodeNum;
uint64_t primeNodeNum = 0;
uint64_t totalHashNodesNum = 0;
//计算每行需要的质数节点数,和总节点数
std::vector<int> rowNodesNum;
for (uint32_t i = 0; i < inHashRowsNum; i++) {
primeNodeNum = MaxPrime(rowMaxNodeNum);
if (primeNodeNum <= 0) {
break;
}
rowNodesNum.push_back(primeNodeNum);
totalHashNodesNum += primeNodeNum;
//以这个个质数计算
rowMaxNodeNum = primeNodeNum;
}
return rowNodesNum;
}
void MultiHashMap::calCreateThisBlockNeedMemSize(const std::vector<int>& nodesInfo, uint64_t& outKeyMemTotalSize, uint64_t& outValueMemTotalSize, uint64_t& outCellNum,uint32_t& cellSize) {
logdebug("begin calCreateThisBlockNeedMemSize,outCellNum=%d,cellSize=%d,nodesInfo size=%d", outCellNum, cellSize, nodesInfo.size());
//uint64_t primeNodeNum = 0;
uint64_t totalHashNodesNum = 0;
for (uint32_t i = 0; i < nodesInfo.size(); i++) {
//logdebug("row:%d nodesInfo count:%d totalHashNodesNum=%d", i, nodesInfo[i], totalHashNodesNum);
totalHashNodesNum += nodesInfo[i];
}
//1:计算存储key的总内存数
uint64_t totalMemSize = 0;
totalMemSize+= sizeof(MhtHeader);
totalMemSize += sizeof(MhtContext);
totalMemSize += sizeof(MhtTail);
uint64_t totalHashNodesMemSize = (uint64_t)totalHashNodesNum * (uint64_t)sizeof(MhtHashNode);
totalHashNodesMemSize += (uint64_t)sizeof(MhtRowHeader) * (uint64_t)nodesInfo.size();
totalMemSize += totalHashNodesMemSize;
totalMemSize += sizeof(MhtTail);
outKeyMemTotalSize = totalMemSize;
loginfo("totalHashNodesMemSize=%u,MhtHashNode_size=%u,outKeyMemTotalSize=%u(M),outKeyMemTotalSize=%u(G)",
totalHashNodesNum, sizeof(MhtHashNode), outKeyMemTotalSize/1000000, outKeyMemTotalSize/1000000000);
//2:计算存储值的cell总数
uint64_t totalValueMemSize = 0;
uint64_t totalCellsNum = HASH_VALUE_CELL_KEY_NUMBER_RATION * totalHashNodesNum;
totalValueMemSize = HashValueBlock::GetCreateThisBlockNeedMemSize(totalCellsNum, cellSize);
outValueMemTotalSize = totalValueMemSize;
outCellNum = totalCellsNum;
loginfo("end calCreateThisBlockNeedMemSize,outCellNum=%d,totalHashNodesNum=%u,cellSize=%d,outKeyMemTotalSize=%lu,%lu(M),outValueMemTotalSize=%lu,%lu(M)",
outCellNum, totalHashNodesNum,cellSize,outKeyMemTotalSize, outKeyMemTotalSize/1000000,outValueMemTotalSize, outValueMemTotalSize/1000000);
}
std::vector<int> MultiHashMap::GetCreateThisBlockNeedMemSize(const uint32_t inHashFirstRowsNodeNum, const uint32_t inHashRowsNum, uint64_t& outKeyMemTotalSize, uint64_t& outValueMemTotalSize,
uint64_t& outCellNum, uint32_t cellSize){
std::vector<int> rowsInfo = MultiHashMap::getCreateThisBlockHashRowNodesInfo(inHashFirstRowsNodeNum, inHashRowsNum);
MultiHashMap::calCreateThisBlockNeedMemSize(rowsInfo, outKeyMemTotalSize, outValueMemTotalSize, outCellNum,cellSize);
return rowsInfo;
}
bool MultiHashMap::Create(int key, const uint32_t inHashFirstRowsNodeNum, const uint32_t valueDataSize, uint32_t inHashRowsNum ) {
if (key <= 0) {
LogError("invalid key parameter");
return false;
}
if (inHashFirstRowsNodeNum <= 100) {
LogError("invalid inHashFirstRowsNodeNum parameter");
return false;
}
if (!HashValueBlock::CheckCellDataSize(valueDataSize)) {
LogError("invalid valueDataSize parameter");
return false;
}
if (inHashRowsNum < HashNodeRowsMinNum) {
inHashRowsNum = HashNodeRowsMinNum;
}
uint64_t outKeyMemTotalSize=0;
uint64_t outValueMemTotalSize=0;
uint64_t outCellNum=0;
std::vector<int> hashPrimeNodesInfo = MultiHashMap::GetCreateThisBlockNeedMemSize(inHashFirstRowsNodeNum, inHashRowsNum, outKeyMemTotalSize, outValueMemTotalSize, outCellNum, valueDataSize);
for (uint32_t i = 0; i < hashPrimeNodesInfo.size(); i++) {
//LogDebug("hashPrimeNodesInfo,row[%03d] num:%d", i, hashPrimeNodesInfo[i]);
}
LogDebug("outKeyMemTotalSize=%d ,outValueMemTotalSize=%d", outKeyMemTotalSize, outValueMemTotalSize);
m_keyMemKey = key;
m_valMemKey= key + 0x10000;
m_mutexKey= key + 0x12345;
int new_flag;
void* p = getmemory(m_keyMemKey, outKeyMemTotalSize, new_flag);
char* keyMem = (char*)p;
if (p == nullptr) {
LogError("failed getmemory for keymem");
return false;
}
logdebug("create keyMem success,new_flag=%d", new_flag);
int new_flag2;
void* p1 = getmemory(m_valMemKey, outValueMemTotalSize, new_flag2);
char* valMem = (char*)p1;
if (p1 == nullptr) {
LogError("failed getmemory for valmem");
return false;
}
logdebug("create valMem success,new_flag=%d", new_flag2);
bool keyMemIsNewCreate = (new_flag != 0);
initMemberAddress(keyMem, hashPrimeNodesInfo, keyMemIsNewCreate);
//logerror("begin MyShareAutoLock");
MyShareAutoLock lockgard(m_mutex);
LogWarn("blockInitTag:%s", m_header->blockInitTag);
if (strcmp(m_header->blockInitTag, HashBlockInitTag) == 0) {
//已经初始化
logwarn("have initialized");
if (!checkAll()) {
printAll();
logerror("failed checkAll");
return false;
}
}
else {
//还没初始化,进行初始化
logwarn("not initialized");
initAll(outKeyMemTotalSize);
}
if (!m_hashValueBlock.Create((char*)valMem, outValueMemTotalSize, outCellNum, valueDataSize)) {
logerror("failed m_hashValueBlock.Create");
return false;
}
LogWarn("finish hashValueBlock.Create ");
return true;
}
void test(char* p1,size_t outValueMemTotalSize) {
char to_write = 0b01010101;
#define TEST_NUM 10000000
for (uint64_t i = 0; i < TEST_NUM * 100; i++) {
uint64_t pos = rand() % outValueMemTotalSize;
// memcpy(p + pos, &to_write, sizeof(char));
*(char*)((char*)p1 + pos) = to_write;
}
memset(p1, 0, outValueMemTotalSize);
}
MultiHashMap::MultiHashMap() {
}
MultiHashMap::~MultiHashMap() {
}
uint8_t* MultiHashMap::GetBaseAddr() {
return (uint8_t*)m_header;
}
void MultiHashMap::lock() {
if (m_mutex->lock()) {
//加锁成功
return;
}
//一些进程加锁后死掉了,进行异常恢复
repareException();
}
void MultiHashMap::unlock() {
m_mutex->unlock();
}
void MultiHashMap::CreateFromShm() {
}
bool MultiHashMap::GetKey(uint8_t* key, uint8_t keyLen, uint8_t** outValueP, uint32_t& outValueLen) {
if (key == nullptr || keyLen <= 0) {
return false;
}
*outValueP = nullptr;
uint64_t keyID = DefaultHashFunc(key, keyLen);
MhtHashNode outNode;
outValueLen = outNode.valueLen;
auto ret=findKey(key, keyLen, keyID, &outNode, outValueP);
outValueLen = outNode.valueLen;
return ret;
}
int MultiHashMap::GetKeyWithBuf(uint8_t* key, uint8_t keyLen, uint8_t* inBuf, uint32_t bufSize, uint32_t& outValueLen) {
outValueLen = 0;
if (inBuf == nullptr || key == nullptr) {
return 0;
}
if (keyLen <= 0 || bufSize <= 0) {
return 0;
}
uint64_t keyID = DefaultHashFunc(key, keyLen);
MhtHashNode outNode;
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
if (getKeyFromRowWithBuf(key, keyLen, keyID, row, &outNode, inBuf, bufSize)) {
outValueLen = outNode.valueLen;
if (bufSize > outNode.valueLen) {
return outNode.valueLen;
}
return bufSize;
}
}
return 0;
}
std::string MultiHashMap::GetKeyStringValue(const char* key) {
uint8_t* outValueP = nullptr;
uint32_t outValueLen = 0;
if (!GetKey((uint8_t*)key, strlen(key), &outValueP, outValueLen)) {
if (outValueP != nullptr) {
FreeGetKeyMem(outValueP);
}
return "";
}
std::string ret((const char*)outValueP);
if (outValueP != nullptr) {
FreeGetKeyMem(outValueP);
}
return ret;
}
const char* MultiHashMap::GetKeyCharValue(const char* key) {
uint8_t* outValueP = nullptr;
uint32_t outValueLen = 0;
if (!GetKey((uint8_t*)key, strlen(key), &outValueP, outValueLen)) {
if (outValueP != nullptr) {
FreeGetKeyMem(outValueP);
}
return nullptr;
}
return (const char*)outValueP;
}
int MultiHashMap::FreeGetKeyMem(uint8_t* p) {
if (p == nullptr) {
return 0;
}
delete[] p;
return 0;
}
bool MultiHashMap::HasKey(uint8_t* key, uint8_t keyLen) {
uint64_t keyID = DefaultHashFunc(key, keyLen);
MhtHashNode outNode;
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
if (hasKeyFromRow(key, keyLen, keyID, row, &outNode)) {
return true;
}
}
return false;
}
bool MultiHashMap::findKey(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtHashNode* outNode, uint8_t** outValue)
{
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
if (getKeyFromRow(key, keyLen, keyID, row, outNode, outValue)) {
return true;
}
}
return false;
}
int MultiHashMap::SetKey(const char* key, const char* val) {
int ret=SetKey((uint8_t*)key, strlen(key), (uint8_t*)val, strlen(val));
if (ret != 0) {
logerror("set faild for key[%s] ret=%d", key, ret);
}
return ret;
}
int MultiHashMap::SetKey(uint8_t* key, uint8_t keyLen, uint8_t* value, uint32_t valueLen) {
loginfo("SetKey keyLen=%d valueLen=%d", keyLen, valueLen);
uint64_t keyID = DefaultHashFunc(key, keyLen);
int ret = 0;
lock();
uint64_t newKeySeq = 0;
MhtHashNode* node = getSameKeyForSet(key, keyLen, keyID);
if (node == nullptr) {
logdebug("getSameKeyForSet not found");
node = getBlankKeyNodeForWrite(key, keyLen, keyID);
if (node == nullptr) {
unlock();
return SET_NO_SPACE;
}
}
logdebug("getSameKeyForSet node status=%d", node->keyStatus);
if (node->keyStatus == MNS_INVALID)
{
//这种状态算新增
s_offset_list_insert_head(&(m_context->inOpList), (s_offset_list_t*)node, (void*)this, offset_to_ptr, ptr_to_offset);
newKeySeq = ++m_context->keySeq;
node->valueSeq = newKeySeq;
node->keyDataLen = keyLen;
node->valueLen = valueLen;
node->valueID = 0;
memcpy(node->keyData, key, keyLen);
node->keyStatus = MNS_PRE_ALLOCED;
uint64_t newValueID = m_hashValueBlock.ReqCreateValue(value, valueLen, node->valueSeq);
if (newValueID == 0) {
//分配内存失败,
node->keyStatus = MNS_INVALID;
s_offset_list_remove_head(&(m_context->inOpList), (void*)this, offset_to_ptr, ptr_to_offset);
unlock();
return SET_NO_VALUE_SPACE;
}
node->valueID = newValueID;
ret=m_hashValueBlock.ReqAckUsedValue(node->valueID, valueLen, node->valueSeq);
if (ret != 0) {
unlock();
logerror("failed ReqAckUsedValue ret=[%d]",ret);
return ret;
}
node->keyStatus = MNS_SETED_OK;
s_offset_list_remove_head(&(m_context->inOpList), this, offset_to_ptr, ptr_to_offset);
unlock();
//新增成功
return SET_OK;
}
//当前是替换
if (node->keyStatus != MNS_SETED_OK) {
unlock();
logerror("SET_ERROR_NODE_STATUS,keyStatus=%d", node->keyStatus);
return SET_ERROR_NODE_STATUS;
}
s_offset_list_insert_head(&(m_context->inOpList), (s_offset_list_t*)node, this, offset_to_ptr, ptr_to_offset);
node->keyStatus = MNS_REPLACE_VAL;
newKeySeq = ++m_context->keySeq;
node->preAllocValueIDSeq = newKeySeq;
uint64_t newValueID = m_hashValueBlock.ReqCreateValue( value, valueLen, node->preAllocValueIDSeq);
if (newValueID == 0) {
//分配内存失败
unlock();
return SET_NO_VALUE_SPACE;
}
node->preAllocNewValueID = newValueID;
node->preAllocNewValueLen = valueLen;
ret=m_hashValueBlock.ReqAckUsedValue(node->preAllocNewValueID, valueLen, node->preAllocValueIDSeq);
if (ret != 0) {
unlock();
logerror("failed ReqAckUsedValue ret=[%d]", ret);
return ret;
}
auto newValueSeq = newKeySeq;
auto newValueLen = valueLen;
auto oldValueSeq = node->valueSeq;
auto oldValueLen = node->valueLen;
//节点覆盖,当前是替换(算修改)
uint64_t oldValID = node->valueID;
while (1) {
uint64_t oldSeq = node->nodeSeq;
uint64_t newSeq = oldSeq + 1;
//替换值
node->valueID = newValueID;
node->valueSeq = newValueSeq;
node->valueLen = newValueLen;
m_hashValueBlock.ReqDeleteValue(oldValID, oldValueSeq, oldValueLen);
if (__sync_bool_compare_and_swap(&(node->nodeSeq), oldSeq, newSeq)) {
break;
}
}
// 重复ACK 次
m_hashValueBlock.ReqAckUsedValue(node->valueID, node->valueLen, node->valueSeq);
node->keyStatus = MNS_SETED_OK;
//操作完成,从列表移除
s_offset_list_remove_head( &(m_context->inOpList), this, offset_to_ptr, ptr_to_offset);
unlock();
return SET_OK;
}
int MultiHashMap::DeleteKey(uint8_t* key, uint8_t keyLen) {
uint64_t keyID = DefaultHashFunc(key, keyLen);
lock();
repareException();
//bool isInsert = false;
MhtHashNode* node = getSameKeyForSet(key, keyLen, keyID);
if (node == nullptr) {
//不存在
unlock();
return REQ_KEY_NOT_EXISTED;
}
if (node->keyStatus == MNS_INVALID) {
//状态错误
unlock();
return REQ_KEY_NOT_EXISTED;
}
if (nodeIsEndStatus(node)) {
//异常状态,不是终结状态
unlock();
logerror("SET_ERROR_NODE_STATUS");
return SET_ERROR_NODE_STATUS;
}
s_offset_list_insert_head(&(m_context->inOpList), (s_offset_list_t*)node, this, offset_to_ptr, ptr_to_offset);
node->keyStatus = (uint8_t)MNS_PRE_DELETED;
if (node->valueID > 0) {
m_hashValueBlock.ReqDeleteValue(node->valueID, node->valueSeq, node->valueLen);
}
node->valueID = 0;
uint64_t oldValID = node->valueID;
auto oldValueSeq = node->valueSeq;
auto oldValueLen = node->valueSeq;
if (oldValID > 0) {
//进入互斥
while (1) {
uint64_t oldSeq = node->nodeSeq;
uint64_t newSeq = oldSeq + 1;
m_hashValueBlock.ReqDeleteValue(oldValID, oldValueSeq, oldValueLen);
node->valueID = 0;
node->valueSeq = 0;
if (__sync_bool_compare_and_swap(&(node->nodeSeq), oldSeq, newSeq) ){
break;
}
}
}
//操作完成,从列表移除
node->keyStatus = (uint8_t)MNS_INVALID;
s_offset_list_remove_head( &(m_context->inOpList), this, offset_to_ptr, ptr_to_offset);
unlock();
return REQ_OK;
}
bool MultiHashMap::getKeyFromRow(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row, MhtHashNode* outNode, uint8_t** outValue) {
char* node = (char*)row + sizeof(MhtRowHeader);
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
//logdebug("getKeyFromRow pos=%d len=%d", pos, row->nodeNum);
//1:先不读取值尝试读
ReadDataFromNode(n, false, outNode,outValue);
if (outNode->keyStatus != uint8_t(MNS_SETED_OK)) {
//这个节点没成功赋予数据
return false;
}
if (outNode->keyDataLen != keyLen) {
return false;
}
if (memcmp(outNode->keyData, key, keyLen)!=0) {
return false;
}
//2:可能是要找的节点,把值copy出来
ReadDataFromNode(n, true, outNode, outValue);
if (outNode->keyStatus != uint8_t(MNS_SETED_OK)) {
//这个节点没成功赋予数据
return false;
}
if (outNode->keyDataLen != keyLen) {
return false;
}
if (memcmp(outNode->keyData, key, keyLen) != 0) {
return false;
}
//找到了此节点
logdebug("find node key:%s", (char*)outNode->keyData);
return true;
}
bool MultiHashMap::getKeyFromRowWithBuf(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row, MhtHashNode* outNode, uint8_t* inBuf, uint32_t inBufSize) {
char* node = (char*)row + sizeof(MhtRowHeader);
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
//logdebug("getKeyFromRow pos=%d len=%d", pos, row->nodeNum);
//1:先不读取值尝试读
ReadDataFromNodeWithBuf(n, false, outNode, inBuf, inBufSize);
if (outNode->keyStatus != uint8_t(MNS_SETED_OK)) {
//这个节点没成功赋予数据
return false;
}
if (outNode->keyDataLen != keyLen) {
return false;
}
if (memcmp(outNode->keyData, key, keyLen) != 0) {
return false;
}
//2:可能是要找的节点,把值copy出来
ReadDataFromNodeWithBuf(n, true, outNode, inBuf, inBufSize);
if (outNode->keyStatus != uint8_t(MNS_SETED_OK)) {
//这个节点没成功赋予数据
return false;
}
if (outNode->keyDataLen != keyLen) {
return false;
}
if (memcmp(outNode->keyData, key, keyLen) != 0) {
return false;
}
//找到了此节点
logdebug("find node key:%s", (char*)outNode->keyData);
return true;
}
//只判断有没KEY ,不读value
bool MultiHashMap::hasKeyFromRow(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row, MhtHashNode* outNode)
{
char* node = (char*)row + sizeof(MhtRowHeader);
//MhtHashNode* nodeArray = (MhtHashNode*)node;
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
uint8_t* outValue;
//不读取值
ReadDataFromNode(n, false, outNode, &outValue);
if (outNode->keyStatus != uint8_t(MNS_SETED_OK)) {
//这个节点没成功赋予数据
return false;
}
if (outNode->keyDataLen != keyLen) {
return false;
}
if (memcmp(outNode->keyData, key, keyLen) != 0) {
return false;
}
//找到了此节点
return true;
}
void MultiHashMap::ReadDataFromNode(MhtHashNode* from, bool needReadValue, MhtHashNode* outNode, uint8_t** outValueP) {
*outValueP = nullptr;
uint8_t* outValue=nullptr;
uint32_t memValueLen = 0;
while (1)
{
uint64_t oldSeq = from->nodeSeq;
uint64_t newSeq = oldSeq + 1;
outNode->keyStatus = from->keyStatus;
outNode->keyDataLen = from->keyDataLen;
if (from->keyDataLen > 0) {
memcpy(outNode->keyData, from->keyData, from->keyDataLen);
}
outNode->valueLen = from->valueLen;
outNode->valueSeq = from->valueSeq;
outNode->valueID = from->valueID;
if (needReadValue) {
if(outNode->keyStatus >=(uint8_t)MNS_SETED_OK){
//需要读取值
if (outNode->valueID > 0) {
if (outValue == nullptr) {
outValue = new uint8_t[outNode->valueLen+1];
outValue[outNode->valueLen] = 0;
memValueLen = outNode->valueLen;
}
else {
if (memValueLen < outNode->valueLen) {
//需重新分配内存
delete[]outValue;
outValue = nullptr;
outValue = new uint8_t[outNode->valueLen + 1];
outValue[outNode->valueLen] = 0;
memValueLen = outNode->valueLen;
}
}
if (REQ_OK!= m_hashValueBlock.ReqReadValue(outNode->valueID, outNode->valueSeq, outNode->valueLen, outValue, outNode->valueLen)) {
continue;
}
}
}
}
if (__sync_bool_compare_and_swap(&(from->nodeSeq), oldSeq, newSeq) ){
break;
}
};
if (outValue != nullptr) {
outValue[outNode->valueLen] = 0;
}
*outValueP = outValue;
}
int MultiHashMap::ReadDataFromNodeWithBuf(MhtHashNode* from, bool needReadValue, MhtHashNode* outNode,uint8_t* inBuf, uint32_t inBufSize) {
uint8_t* dest = inBuf;
while (1)
{
uint64_t oldSeq = from->nodeSeq;
uint64_t newSeq = oldSeq + 1;
outNode->keyStatus = from->keyStatus;
outNode->keyDataLen = from->keyDataLen;
if (from->keyDataLen > 0) {
memcpy(outNode->keyData, from->keyData, from->keyDataLen);
}
outNode->valueLen = from->valueLen;
outNode->valueSeq = from->valueSeq;
outNode->valueID = from->valueID;
if (needReadValue) {
if (outNode->keyStatus >= (uint8_t)MNS_SETED_OK) {
if (outNode->valueID > 0) {
if (REQ_OK != m_hashValueBlock.ReqReadValue(outNode->valueID, outNode->valueSeq, outNode->valueLen, dest, inBufSize)) {
continue;
}
}
}
}
if (__sync_bool_compare_and_swap(&(from->nodeSeq), oldSeq, newSeq)) {
break;
}
};
return 0;
}
MhtHashNode* MultiHashMap::getSameKeyFromRowForSet(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row) {
char* node = (char*)row + sizeof(MhtRowHeader);
//MhtHashNode* nodeArray = (MhtHashNode*)node;
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
if (n->keyStatus ==uint8_t(MNS_INVALID)) {
//这个节点是不需要关注的了
logdebug("keyStatus==MNS_INVALID");
return nullptr;
}
if (n->keyDataLen != keyLen) {
logdebug("keyDataLen,%d!=%d", n->keyDataLen, keyLen);
return nullptr;
}
if (memcmp(n->keyData, key, keyLen) != 0) {
return nullptr;
}
//找到了此节点
return n;
}
//用于新增一个不存在的KEY 的查找
MhtHashNode* MultiHashMap::getSameKeyFromRowForInsert(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row) {
char* node = (char*)row + sizeof(MhtRowHeader);
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
if (n->keyStatus < uint8_t(MNS_SETED_OK)) {
//这个节点是不需要关注的了
return nullptr;
}
if (n->keyDataLen != keyLen) {
return nullptr;
}
if (memcmp(n->keyData, key, keyLen) != 0) {
return nullptr;
}
//找到了此节点
return n;
}
MhtHashNode* MultiHashMap::getSameKeyForSet(uint8_t* key, uint8_t keyLen, uint64_t keyID)
{
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
MhtHashNode* node = getSameKeyFromRowForSet(key, keyLen, keyID, row);
if (node != nullptr) {
return node;
}
}
return nullptr;
}
MhtHashNode* MultiHashMap::getSameKeyForInsert(uint8_t* key, uint8_t keyLen, uint64_t keyID)
{
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
MhtHashNode* node = getSameKeyFromRowForInsert(key, keyLen, keyID, row);
if (node != nullptr) {
return node;
}
}
return nullptr;
}
MhtHashNode* MultiHashMap::getBlankKeyNodeForWrite(uint8_t* key, uint8_t keyLen, uint64_t keyID) {
for (uint32_t i = 0; i < m_rowLines.size(); i++)
{
MhtRowHeader* row = m_rowLines[i];
MhtHashNode* node = getBlankKeyNodeFromRowForWrite(key, keyLen, keyID, row);
if (node != nullptr) {
logdebug("getBlankKeyNodeFromRowForWrite node:%p",node);
return node;
}
}
return nullptr;
}
MhtHashNode* MultiHashMap::getBlankKeyNodeFromRowForWrite(uint8_t* key, uint8_t keyLen, uint64_t keyID, MhtRowHeader* row) {
char* node = (char*)row + sizeof(MhtRowHeader);
//MhtHashNode* nodeArray = (MhtHashNode*)node;
uint32_t pos = keyID % row->nodeNum;
MhtHashNode* n = (MhtHashNode*)(node + (m_header->nodeSize * pos));
if (n->keyStatus != uint8_t(MNS_INVALID)) {
//这个节点已经被使用
return nullptr;
}
logdebug("getBlankKeyNodeFromRowForWrite node:%d status:%d", pos, n->keyStatus);
//找到了此节点
return n;
}
void MultiHashMap::repareException() {
if (m_context->inOpList.next == 0) {
//链表空,没有异常恢复的
return;
}
std::vector<s_offset_list_t*> toOpVector;
s_offset_list_t* head = s_offset_list_get_head(&(m_context->inOpList), this, offset_to_ptr, ptr_to_offset);
while (head!=nullptr) {
toOpVector.push_back(head);
s_offset_list_t* next = s_offset_list_get_head(head, this, offset_to_ptr, ptr_to_offset);
head = next;
}
//倒序操作,因为是节点在头部插入的,按先后时间顺序
for (int i = toOpVector.size() - 1; i >= 0; i--) {
s_offset_list_t* node=toOpVector[i];
s_offset_list_t* pre_node = nullptr;
if (i >= 1) {
pre_node = toOpVector[i - 1];
}
handleExceptionNode((MhtHashNode*)node,pre_node);
}
}
//节点是终结状态
bool MultiHashMap::nodeIsEndStatus(MhtHashNode* node) {
switch (node->keyStatus) {
case MNS_INVALID:
//无效节点
return true;
case MNS_SETED_OK:
//已经设置了值
return true;
}
return false;
}
void MultiHashMap::handleExceptionNode(MhtHashNode* node, s_offset_list_t* pre_node) {
if (nodeIsEndStatus(node)) {
//非异常节点
pre_node->next = 0;
return;
}
if (node->keyStatus == MNS_PRE_DELETED) {
//上次准备删除,但是可能程序崩了,没完成删除
if (node->valueID > 0) {
m_hashValueBlock.ReqDeleteValue(node->valueID, node->valueSeq,node->valueLen);
node->valueID = 0;
node->valueLen = 0;
}
if (node->preAllocNewValueID > 0) {
m_hashValueBlock.ReqDeleteValue(node->preAllocNewValueID, node->preAllocValueIDSeq,node->preAllocNewValueLen);
node->preAllocNewValueID = 0;
}
node->keyDataLen = 0;
//这个节点处理完, 吧他的前个节点,从链表移除这个节点
node->keyStatus = MNS_INVALID;
pre_node->next = 0;
//完成删除
}
else if (node->keyStatus == MNS_PRE_ALLOCED)
{
//上次的异常状态
if (node->valueID > 0) {
m_hashValueBlock.ReqDeleteValue(node->valueID, node->valueSeq,node->valueLen);
node->valueID = 0;
}
node->keyStatus = MNS_INVALID;
pre_node->next = 0;
}
else if (node->keyStatus == MNS_REPLACE_VAL) {
//上次值替换没完成
if (node->preAllocNewValueID == 0) {
//没有待替换的值,放弃替换
m_hashValueBlock.ReqAckUsedValue(node->valueID, node->valueLen, node->valueSeq);
node->keyStatus = MNS_SETED_OK;
pre_node->next = 0;
return;
}
if (node->preAllocValueIDSeq == node->valueSeq) {
//待替换的值一样,不需要替换
m_hashValueBlock.ReqAckUsedValue(node->valueID, node->valueLen, node->valueSeq);
node->keyStatus = MNS_SETED_OK;
pre_node->next = 0;
return;
}
uint64_t oldValID = node->valueID;
uint64_t oldvalueSeq = node->valueSeq;
auto oldValLen = node->valueLen;
uint64_t newValueID = node->preAllocNewValueID;
uint64_t newValSeq = node->preAllocValueIDSeq;
uint32_t newValLen= node->preAllocNewValueLen;
//先进行确认
m_hashValueBlock.ReqAckUsedValue(node->preAllocNewValueID, node->preAllocNewValueLen, node->preAllocValueIDSeq);
while (1) {
uint64_t oldSeq = node->nodeSeq;
uint64_t newSeq = oldSeq + 1;
//替换值
node->valueID = newValueID;
node->valueLen = newValLen;
m_hashValueBlock.ReqDeleteValue(oldValID, oldvalueSeq, oldValLen);
node->valueSeq = newValSeq;
if (__sync_bool_compare_and_swap(&(node->nodeSeq), oldSeq, newSeq)) {
break;
}
}
m_hashValueBlock.ReqAckUsedValue(node->preAllocNewValueID, node->preAllocNewValueLen, node->preAllocValueIDSeq);
node->keyStatus = MNS_SETED_OK;
pre_node->next = 0;
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/243416724/shm_hash.git
git@gitee.com:243416724/shm_hash.git
243416724
shm_hash
shm_hash
master

搜索帮助