// get or create the record for a specified key void *Untyped::Open(Key aKey) { // convert key to a slot // (HACK: assume key is already a hash) size_t slot = FindSlot(aKey); // if the slot is not empty... if (slot != EMPTY) { // return the record return GetRecord(slot); } // grow if the database is full if (mCount >= mLimit) Grow(); // add a new record void *record = AllocRecord(aKey); // check parent const void *source = mNil; if (this != &parent && parent.GetCount()) if (Key aParentKey = parent.Get(aKey)) source = Find(aParentKey); CreateRecord(record, source); // return the record return record; }
tBOOL AddHash(DWHASH_TYPE *lpHash, tVOID *lpItem, tINT nInfo) { tINT nPos; DWHASH_BLOCK_TYPE HashItem; DWHASH_NEXT_TYPE NextItem; nPos = lpHash->pHashCalFunc(lpItem); if (nPos < 0) nPos *= -1; if (nPos >= lpHash->nBucketCount) { // exception nPos %= lpHash->nBucketCount; } memcpy(&HashItem, lpHash->lpBuf + nPos*sizeof(DWHASH_BLOCK_TYPE), sizeof(DWHASH_BLOCK_TYPE)); if (HashItem.nInfo == -1) { // 아무 것도 없다. good HashItem.nInfo = nInfo; HashItem.lpNextRec = NULL; // 여기에 해슁이 같으면 달리겠지.. memcpy(lpHash->lpBuf + nPos*sizeof(DWHASH_BLOCK_TYPE), &HashItem, sizeof(DWHASH_BLOCK_TYPE)); } else { // collision 발생 if (HashItem.lpNextRec == NULL) { // 벌써 collision이 일어났군.. HashItem.lpNextRec = (RECORD *)malloc(sizeof(RECORD)); if (HashItem.lpNextRec == NULL) { return FALSE; } if (AllocRecord(HashItem.lpNextRec, sizeof(DWHASH_NEXT_TYPE), 5, 5) == FALSE) { return FALSE; } memcpy(lpHash->lpBuf + nPos*sizeof(DWHASH_BLOCK_TYPE), &HashItem, sizeof(DWHASH_BLOCK_TYPE)); // mem alloc 했으니.. update 해야지 } NextItem.nInfo = nInfo; AppendRecord(HashItem.lpNextRec, &NextItem); lpHash->nCollision ++; } return TRUE; }
uint32 CRdbPrefixIndex::QueryHelp(char* sKey, uint32 nStrLen, CSqlParameterSet* pCondition, CSqlFilter& oFilter, CRecordSet *pResult, uint32* pSkipCount, uint32* pCount, uint32* pMaxCount, bool bUpdate, FOnTravelIndex OnTravel, void * pPara) { uint64 nList; TNTreeNode* pNode = m_oTree.GetNode((const uint8*)sKey, nStrLen, nList); if(pNode == NULL) return RDB_SUCCESS; CRecord* pRecord = NULL; uint32 nRet = AllocRecord(pResult, pRecord); if(nRet) { m_oTree.ReleaseNode(nList, pNode); return nRet; } uint32 nFull; while(pNode) { uint64 nRowId = pNode->oObject, nNext; TNTreeNode* pNext = m_oTree.GetNextNode(pNode, nNext); m_oTree.ReleaseNode(nList, pNode); pNode = pNext; nList = nNext; nRet = IsCoincident(pRecord, nRowId, pCondition, oFilter, pResult, pSkipCount, pCount, pMaxCount, nFull, bUpdate, OnTravel, pPara); if(nRet) { if(pNode) m_oTree.ReleaseNode(nList, pNode); return nRet; } if(nFull) break; } if(pRecord) { if(pResult) pResult->PopRecord(); else delete pRecord; } if(pNode) m_oTree.ReleaseNode(nList, pNode); return RDB_SUCCESS; }
tBOOL InitThPool(tINT nCountThread, lpProcP Proc_ThreadFunc, tINT nSocketId, tINT nDelayTimeOut) { BeginMutexMan(&gMutexThPool, C_MUTEX_THPOOL); bFlagCloseServer = FALSE; gfProc_ThreadFunc_THPOOL = Proc_ThreadFunc; gnSocketId_THPOOL = nSocketId; gnTotalThread_THPOOL = nCountThread; gnDelayTimeOut = nDelayTimeOut; AllocRecord(&gTHPOOL, sizeof(THPOOL_ITEMTYPE), nCountThread, 1); return TRUE; }
tBOOL StartSafeTh(tBOOL bTimerTh) { // pthread_t *worker; #if defined(_USE_SAFETH) if (AllocRecord(&RecordThTime, sizeof(SAFETH_FORMAT), 32, 32) == FALSE) { printf("create thread error..\n"); return FALSE; } if (pthread_mutex_init(&gCheckTh, NULL) != 0) { printf("mutex error\n"); FreeRecord(&RecordThTime); } if (pthread_mutex_init(&gSigMutex, NULL) != 0) { printf("mutex error\n"); pthread_mutex_destroy(&gCheckTh); FreeRecord(&RecordThTime); } if (pthread_cond_init(&gSigCond, NULL) != 0) { printf("cond error\n"); pthread_mutex_destroy(&gCheckTh); pthread_mutex_destroy(&gSigMutex); FreeRecord(&RecordThTime); } if (bTimerTh) { //worker = (pthread_t *)malloc(sizeof(pthread_t)); if (CreateTThread( NULL/*worker*/, &lpMutexTThreadIdle, &lpCondVarIdle, DELAY_SEC, (lpProcP) CheckIdleTimeTh, NULL) == FALSE) { // free(worker); printf("Error Timer Thread\n"); //EndMutexMan(&ThIdleMutexMan); FreeRecord(&RecordThTime); pthread_mutex_destroy(&gCheckTh); pthread_mutex_destroy(&gSigMutex); pthread_cond_destroy(&gSigCond); return FALSE; } //pthread_detach(*worker); //printf("Safe Thread ID : %d\n", *worker); //free(worker); } bStSafeTh = TRUE; #endif return TRUE; }
// create or update a record for a specified key void Untyped::Put(Key aKey, const void *aValue) { // convert key to a slot // (HACK: assume key is already a hash) size_t slot = FindSlot(aKey); // if the slot is not empty... if (slot != EMPTY) { // update the record UpdateRecord(GetRecord(slot), aValue); return; } // grow if the database is full if (mCount >= mLimit) Grow(); // add a new record void *record = AllocRecord(aKey); CreateRecord(record, aValue); }
// allocate the record for a specified key void *Untyped::Alloc(Key aKey) { // convert key to a slot // (HACK: assume key is already a hash) size_t slot = FindSlot(aKey); // if the slot is not empty... if (slot != EMPTY) { // return the record assert(false); return NULL; } // grow if the database is full if (mCount >= mLimit) Grow(); // add a new record void *record = AllocRecord(aKey); // return the record return record; }
tBOOL File2Hash(tCHAR *szSrcFileName, DWHASH_TYPE *lpHash, HASH_CalFunc pHashCalFunc, HASH_PutFunc pHashPutFunc) { tINT i, j; DWHASH_BLOCK_TYPE BlockItem; DWHASH_BLOCK_FILE_TYPE BlockFileItem; FILE *Fp; FILE *recFp; tCHAR szFile[MAX_PATH]; tINT nCount; tBOOL bRetVal = TRUE; tCHAR szFileName[MAX_PATH], *p; strcpy(szFileName, szSrcFileName); p = strrchr(szFileName, '.'); if (p) { *p = '\0'; } sprintf(szFile, "%s.dic", szFileName); if ((Fp = fopen(szFile, "rb")) == NULL) { return FALSE; } sprintf(szFile, "%s.hdic", szFileName); if ((recFp = fopen(szFile, "rb")) == NULL) { fclose(Fp); return FALSE; } memset(lpHash, 0, sizeof(DWHASH_TYPE)); if (fread(lpHash, sizeof(DWHASH_TYPE), 1, Fp) != 1) { fclose(Fp); fclose(recFp); return FALSE; } lpHash->nBucketCount = DwordCvt(lpHash->nBucketCount); lpHash->nCollision = DwordCvt(lpHash->nCollision); if (lpHash->nBucketCount > 0) { // mem alloc lpHash->lpBuf = (tBYTE *)malloc(lpHash->nBucketCount * sizeof(DWHASH_BLOCK_TYPE)); if (lpHash->lpBuf == NULL) { memset(lpHash, 0, sizeof(DWHASH_TYPE)); fclose(Fp); fclose(recFp); return FALSE; } } for ( i = 0 ; i < lpHash->nBucketCount ; i ++ ) { if (fread(&BlockFileItem, sizeof(DWHASH_BLOCK_FILE_TYPE), 1, Fp) != 1) { bRetVal = FALSE; return FALSE; } BlockItem.nInfo = BlockFileItem.nInfo; BlockItem.lpNextRec = NULL; #if defined(_DEBUG) if (BlockItem.nInfo == 15300) { printf("www.dreamwiz.com/ next = %d\n", BlockFileItem.nPosNextRec); } #endif if (BlockFileItem.nPosNextRec != -1) { // 다른 info가 있다. 해슁이 같아서 ... // sequence하게 넣어잖아.. 괜찮지.. //fseek(recFp, BlockFileItem.nPosNextRec, SEEK_SET); if (fread(&nCount, sizeof(tINT), 1, recFp)!=1) { bRetVal = FALSE; break; } nCount = DwordCvt(nCount); #if defined(_DEBUG) if (BlockItem.nInfo == 15300) { printf("www.dreamwiz.com/ count = %d\n", nCount); } #endif BlockItem.lpNextRec = (RECORD *)malloc(sizeof(RECORD)); if (BlockItem.lpNextRec == NULL) { bRetVal = FALSE; break; } if (AllocRecord(BlockItem.lpNextRec, sizeof(DWHASH_NEXT_TYPE), nCount+1, 5) == FALSE) { bRetVal = FALSE; break; } if (fread(BlockItem.lpNextRec->lpBuf, nCount * BlockItem.lpNextRec->nWidth, 1, recFp)!=1) { bRetVal = FALSE; break; } BlockItem.lpNextRec->nUsed = nCount; } memcpy(lpHash->lpBuf + i*sizeof(DWHASH_BLOCK_TYPE), &BlockItem, sizeof(DWHASH_BLOCK_TYPE)); } if (bRetVal == FALSE) { // 메모리 정리 for ( j = 0 ; j <= i && j < lpHash->nBucketCount ; j ++ ) { memcpy(&BlockItem, lpHash->lpBuf + j*sizeof(DWHASH_BLOCK_TYPE), sizeof(DWHASH_BLOCK_TYPE)); if (BlockItem.lpNextRec) { FreeRecord(BlockItem.lpNextRec); free(BlockItem.lpNextRec); } } if (lpHash->lpBuf) free(lpHash->lpBuf); memset(&lpHash, 0, sizeof(DWHASH_TYPE)); fclose(Fp); fclose(recFp); return FALSE; } fclose(Fp); fclose(recFp); lpHash->pHashCalFunc = pHashCalFunc; lpHash->pHashPutFunc = pHashPutFunc; return TRUE; }
uint32 CBaseRbTreeIndex::QueryHelp(CSqlParameterSet* pCondition, CSqlFilter& oFilter, CRecordSet *pResult, uint32* pSkipCount, uint32* pCount, uint32* pMaxCount, bool bUpdate, FOnTravelIndex OnTravel, void * pPara) { CCondField oMinField, oMaxField; uint32 nFieldNo = m_pIdxDef->GetFieldNo(m_nCurLevel); oMinField.pField = NULL; oMaxField.pField = NULL; if(!pCondition->GetCondField(nFieldNo, oMinField, oMaxField)) return RDB_SUCCESS; CVmmRbTree<CRdbRbTreeItem, CIndexKeyValue>::CIterator idx = m_oTree.Begin(); CVmmRbTree<CRdbRbTreeItem, CIndexKeyValue>::CIterator end = m_oTree.End(); CIndexKeyValue oKey; oKey.Create(m_nType, m_nSize, m_pTabDef); if(oMinField.pField) { oKey.SetFromField(oMinField.pField); if(oMinField.nOperator == RDB_SQLPARA_OPERATOR_MOREEQUAL) idx = m_oTree.LowerBound(oKey); else idx = m_oTree.UpperBound(oKey); if(idx == m_oTree.End()) return RDB_SUCCESS; } if(oMaxField.pField) { oKey.SetFromField(oMaxField.pField); if(oMaxField.nOperator == RDB_SQLPARA_OPERATOR_LESSEQUAL) end = m_oTree.UpperBound(oKey); else end = m_oTree.LowerBound(oKey); --end; if(end == m_oTree.End()) return RDB_SUCCESS; } if(end != m_oTree.End()) ++end; uint64 nHandle; if(m_nCurLevel != m_nTotalLevel-1) { for(; idx!=end;) { nHandle = idx.GetValue().nHandle; CBaseRbTreeIndex* pSubIndex = m_pIndexPool->QueryObject(nHandle, this); ++idx; uint32 nRet = pSubIndex->QueryHelp(pCondition, oFilter, pResult, pSkipCount, pCount, pMaxCount, bUpdate, OnTravel, pPara); m_pIndexPool->ReleaseObject(nHandle); if(nRet || (pResult && (pResult->GetRecordCount() == pResult->GetRecordSetSize())) || (pMaxCount && pMaxCount[0] == pCount[0])) return nRet; } } else { CRecord* pRecord = NULL; uint32 nFull, nRet = AllocRecord(pResult, pRecord); if(nRet) return nRet; for(; idx!=end;) { nHandle = idx.GetValue().nHandle; ++idx; nRet = IsCoincident(pRecord, nHandle, pCondition, oFilter, pResult, pSkipCount, pCount, pMaxCount, nFull, bUpdate, OnTravel, pPara); if(nRet) return nRet; if(nFull) break; } if(pRecord) { if(pResult) pResult->PopRecord(); else delete pRecord; } } return RDB_SUCCESS; }
uint32 CRdbHashIndex::QueryHelp(CSqlParameterSet* pCondition, CSqlFilter& oFilter, CRecordSet *pResult, uint32* pSkipCount, uint32* pCount, uint32* pMaxCount, bool bUpdate, FOnTravelIndex OnTravel, void* pPara) { uint32 nHashValue; uint32 nIdxFieldCount = m_pIdxDef->m_nFieldCount; if(nIdxFieldCount == 1) { uint32 nHashCount = 0; uint32 nFieldNo = m_pIdxDef->m_pFields[0]; pCondition->GetHashValue(nFieldNo, nHashValue, nHashCount); if(nHashCount != 1) return RDB_INVALID_COND; nHashValue = nHashValue; } else { uint32 * pHashValue = new uint32[nIdxFieldCount]; if(!pHashValue) { FocpLogEx(GetLogName(), FOCP_LOG_ERROR, ("CRdbHashIndex::QueryHelp(%s): RDB_LACK_MEMORY", m_pTabDef->m_pBaseAttr->sTableName)); return RDB_LACK_MEMORY; } for(uint32 i=0; i<nIdxFieldCount; ++i) { uint32 nHashCount = 0; uint32 nFieldNo = m_pIdxDef->m_pFields[i]; pCondition->GetHashValue(nFieldNo, nHashValue, nHashCount); if(nHashCount != 1) return RDB_INVALID_COND; pHashValue[i] = nHashValue; } nHashValue = GetCrc32((const uint8*)pHashValue, nIdxFieldCount<<2, 1); delete[] pHashValue; } uint64 nList; THashBlock * idx = m_oHash.GetNode(nHashValue, nList); if(idx == NULL) return RDB_SUCCESS; uint64 nNext; THashBlock oBlock = *idx; THashBlock* pNext = m_oHash.GetNextNode(idx, nNext); m_oHash.ReleaseBlock(nList, idx); CRecord* pRecord = NULL; uint32 nRet = AllocRecord(pResult, pRecord); if(nRet) { if(pNext) m_oHash.ReleaseBlock(nNext, pNext); return nRet; } uint32 nFull; while(true) { bool Done = false; uint32 nCount = 0; for(uint32 i=0; nCount<oBlock.nSize; ++i) { uint64 nRowId = oBlock.oNode[i].oObject; if(nRowId) { ++nCount; if(oBlock.oNode[i].nHashValue == nHashValue) { nRet = IsCoincident(pRecord, nRowId, pCondition, oFilter, pResult, pSkipCount, pCount, pMaxCount, nFull, bUpdate, OnTravel, pPara); if(nRet) { if(pNext) m_oHash.ReleaseBlock(nNext, pNext); return nRet; } Done = true; if(nFull || m_oHash.IsUnique()) break; } } } if(Done && (nFull || m_oHash.IsUnique())) break; if(!pNext) break; nList = nNext; idx = pNext; oBlock = *idx; pNext = m_oHash.GetNextNode(idx, nNext); m_oHash.ReleaseBlock(nList, idx); } if(pRecord) { if(pResult) pResult->PopRecord(); else delete pRecord; } return RDB_SUCCESS; }