void SampleVehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData) { CHECK_MSG(0==qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries"); qryFilterData->word3 = (PxU32)SAMPLEVEHICLE_UNDRIVABLE_SURFACE; }
static int DEHT_queryEx(DEHT *ht, const unsigned char *key, int keyLength, const unsigned char *data, int dataMaxAllowedLength, byte_t * keyBlockOut, ulong_t keyBlockSize, DEHT_DISK_PTR * keyBlockDiskOffset, ulong_t * keyIndex) { int ret = DEHT_STATUS_FAIL; int hashTableIndex = 0; byte_t * validationKey = NULL; KeyFilePair_t * currPair = NULL; DEHT_DISK_PTR dataBlockOffset = 0; ulong_t bytesRead = 0; TRACE_FUNC_ENTRY(); CHECK(NULL != ht); CHECK(NULL != key); CHECK(NULL != data); CHECK(NULL != keyBlockOut); CHECK(KEY_FILE_BLOCK_SIZE(ht) <= keyBlockSize); CHECK(NULL != keyBlockDiskOffset); CHECK(NULL != keyIndex); TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): key=%s\n", __FILE__, __LINE__, __FUNCTION__, key)); /* calc hash for key */ CHECK(NULL != ht->hashFunc); hashTableIndex = ht->hashFunc(key, keyLength, ht->header.numEntriesInHashTable); TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): bucket index=%#x\n", __FILE__, __LINE__, __FUNCTION__, (uint_t) hashTableIndex)); CHECK(DEHT_findFirstBlockForBucketAndAlloc(ht, hashTableIndex, keyBlockDiskOffset)); CHECK(0 != *keyBlockDiskOffset); TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): first block for bucket %d at offset=%#x\n", __FILE__, __LINE__, __FUNCTION__, hashTableIndex, (uint_t) *keyBlockDiskOffset)); /* If there is no block for this bucket, return with nothing */ if (0 == *keyBlockDiskOffset) { ret = DEHT_STATUS_NOT_NEEDED; goto LBL_CLEANUP; } /* alloc space and calc validation key */ validationKey = malloc(ht->header.nBytesPerValidationKey); CHECK_MSG("malloc", (NULL != validationKey)); /*! Note: return value isn't checked since the spec does not include details regarding the key validation function interface */ CHECK(NULL != ht->comparisonHashFunc); (void) ht->comparisonHashFunc(key, keyLength, validationKey); while (0 != *keyBlockDiskOffset) { /* read block to mem */ CHECK_MSG(ht->sKeyfileName, (pfread(ht->keyFP, *keyBlockDiskOffset, keyBlockOut, KEY_FILE_BLOCK_SIZE(ht)))); /* scan this block */ for(*keyIndex = 0; *keyIndex < ht->header.nPairsPerBlock; ++*keyIndex) { currPair = GET_N_REC_PTR_IN_BLOCK(ht, keyBlockOut, *keyIndex); if (0 == memcmp(currPair->key, validationKey, ht->header.nBytesPerValidationKey)) { break; } } if (*keyIndex < ht->header.nPairsPerBlock) { break; } /* disk offset of the next pointer is the last element in the block */ *keyBlockDiskOffset = *( (DEHT_DISK_PTR *) (keyBlockOut + KEY_FILE_BLOCK_SIZE(ht) - sizeof(DEHT_DISK_PTR)) ); TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): next ptr from disk: %#x\n", __FILE__, __LINE__, __FUNCTION__, (uint_t) *keyBlockDiskOffset)); } dataBlockOffset = 0; if (*keyIndex < ht->header.nPairsPerBlock) { dataBlockOffset = currPair->dataOffset; } else { /* we scanned everything, but found no matching key */ ret = DEHT_STATUS_NOT_NEEDED; TRACE("key not found"); goto LBL_CLEANUP; } bytesRead = 0; CHECK(DEHT_readDataAtOffset(ht, dataBlockOffset, (byte_t *) data, dataMaxAllowedLength, &bytesRead)); TRACE("key found"); ret = bytesRead; goto LBL_CLEANUP; LBL_ERROR: ret = DEHT_STATUS_FAIL; TRACE_FUNC_ERROR(); LBL_CLEANUP: FREE(validationKey); TRACE_FUNC_EXIT(); return ret; }
static DEHT * DEHT_initInstance (const char * prefix, char * fileMode, hashKeyIntoTableFunctionPtr hashfun, hashKeyforEfficientComparisonFunctionPtr validfun) { bool_t filesAlreadyExist = FALSE; bool_t errorState = TRUE; bool_t deleteFilesOnError = FALSE; DEHT * ht = NULL; char tempFileMode[MAX_FILE_MODE_LEN] = {0}; TRACE_FUNC_ENTRY(); /* sanity */ CHECK(NULL != prefix); CHECK(NULL != fileMode); CHECK(NULL != hashfun); CHECK(NULL != validfun); ht = malloc(sizeof(DEHT)); CHECK_MSG("malloc", (NULL != ht)); memset(ht, 0, sizeof(DEHT)); SAFE_STRNCPY(ht->sKeyfileName, prefix, sizeof(ht->sKeyfileName)); SAFE_STRNCAT(ht->sKeyfileName, KEY_FILE_EXT, sizeof(ht->sKeyfileName)); SAFE_STRNCPY(ht->sDatafileName, prefix, sizeof(ht->sKeyfileName)); SAFE_STRNCAT(ht->sDatafileName, DATA_FILE_EXT, sizeof(ht->sKeyfileName)); /* Open key file. If file mode begins with 'c', first check that the file does not exist */ SAFE_STRNCPY(tempFileMode, fileMode, sizeof(tempFileMode)); if ('c' == tempFileMode[0]) { /* we were asked to make sure the files weren't already present first */ ht->keyFP = fopen(ht->sKeyfileName, "rb"); if (NULL != ht->keyFP) { deleteFilesOnError = FALSE; filesAlreadyExist = TRUE; fprintf(stderr, "Error: File \"%s\" already exist\n", ht->sKeyfileName); } ht->dataFP = fopen(ht->sDatafileName, "rb"); if (NULL != ht->dataFP) { deleteFilesOnError = FALSE; filesAlreadyExist = TRUE; fprintf(stderr, "Error: File \"%s\" already exist\n", ht->sDatafileName); } /* fail if files already exist */ CHECK(!filesAlreadyExist); /* that check passed. Now modify the file mode back to a standard one */ tempFileMode[0] = 'w'; /* From now on, if we fail, we'd like to clean up the files */ deleteFilesOnError = TRUE; } /* Open key file */ ht->keyFP = fopen(ht->sKeyfileName, tempFileMode); CHECK_MSG(ht->sKeyfileName, (NULL != ht->keyFP)); /* Open data file */ ht->dataFP = fopen(ht->sDatafileName, tempFileMode); CHECK_MSG(ht->sDatafileName, (NULL != ht->dataFP)); ht->hashTableOfPointersImageInMemory = NULL; ht->hashPointersForLastBlockImageInMemory = NULL; ht->hashFunc = hashfun; ht->comparisonHashFunc = validfun; errorState = FALSE; goto LBL_CLEANUP; LBL_ERROR: errorState = TRUE; TRACE_FUNC_ERROR(); LBL_CLEANUP: if (errorState) { if (NULL != ht) { DEHT_freeResources(ht, deleteFilesOnError); } ht = NULL; } TRACE_FUNC_EXIT(); return ht; }
int insert_uniquely_DEHT ( DEHT *ht, const unsigned char *key, int keyLength, const unsigned char *data, int dataLength) { int ret = DEHT_STATUS_FAIL; byte_t * tempKeyBlock = NULL; DEHT_DISK_PTR keyBlockDiskOffset = 0; ulong_t keyIndex = 0; KeyFilePair_t * targetRecord = NULL; DEHT_DISK_PTR newDataOffset = 0; byte_t tempData[DEHT_MAX_DATA_LEN] = {0}; TRACE_FUNC_ENTRY(); CHECK(NULL != ht); CHECK(NULL != key); CHECK(NULL != data); /* allocate a buffer for DEHT_queryEx */ tempKeyBlock = malloc(KEY_FILE_BLOCK_SIZE(ht)); CHECK_MSG("malloc", (NULL != tempKeyBlock)); ret = DEHT_queryEx(ht, key, keyLength, tempData, sizeof(tempData), tempKeyBlock, KEY_FILE_BLOCK_SIZE(ht), &keyBlockDiskOffset, &keyIndex); switch(ret) { case DEHT_STATUS_NOT_NEEDED: TRACE("simple insert"); /* not found - just insert */ CHECK(DEHT_STATUS_SUCCESS == add_DEHT (ht, key, keyLength, data, dataLength)); ret = DEHT_STATUS_SUCCESS; break; case DEHT_STATUS_FAIL: default: if (0 >= ret) { /* internal error */ goto LBL_ERROR; } /* if we got here, the key was found */ TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): key already in DEHT. Updating record at %#x\n", __FILE__, __LINE__, __FUNCTION__, (uint_t) keyBlockDiskOffset)); /* update data in the data file */ CHECK(DEHT_addData(ht, data, dataLength, &newDataOffset)); /* get the key record */ targetRecord = GET_N_REC_PTR_IN_BLOCK(ht, tempKeyBlock, keyIndex); /* update key record */ targetRecord->dataOffset = newDataOffset; /* update block on disk */ CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, keyBlockDiskOffset, tempKeyBlock, KEY_FILE_BLOCK_SIZE(ht)))); ret = DEHT_STATUS_NOT_NEEDED; break; } goto LBL_CLEANUP; LBL_ERROR: ret = DEHT_STATUS_FAIL; TRACE_FUNC_ERROR(); LBL_CLEANUP: FREE(tempKeyBlock); TRACE_FUNC_EXIT(); return ret; }
static bool_t DEHT_allocEmptyLocationInBucket(DEHT * ht, ulong_t bucketIndex, byte_t * blockDataOut, ulong_t blockDataLen, DEHT_DISK_PTR * blockDiskPtr, ulong_t * firstFreeIndex) { bool_t ret = FALSE; DEHT_DISK_PTR newBlock = 0; TRACE_FUNC_ENTRY(); CHECK(NULL != ht); CHECK(bucketIndex < ht->header.numEntriesInHashTable); CHECK(NULL != blockDataOut); CHECK(KEY_FILE_BLOCK_SIZE(ht) <= blockDataLen); CHECK(NULL != blockDiskPtr); CHECK(NULL != firstFreeIndex); CHECK(DEHT_findLastBlockForBucket(ht, bucketIndex, blockDiskPtr)); if (0 == *blockDiskPtr) { /* if this is the first ever block, call DEHT_findFirstBlockForBucketAndAlloc() which will also alloc the first block */ CHECK(DEHT_findFirstBlockForBucketAndAlloc(ht, bucketIndex, blockDiskPtr)); CHECK(0 != *blockDiskPtr); } /* read it */ CHECK_MSG(ht->sKeyfileName, (pfread(ht->keyFP, *blockDiskPtr, blockDataOut, KEY_FILE_BLOCK_SIZE(ht)))); /* get the current used block count */ *firstFreeIndex = GET_USED_RECORD_COUNT(blockDataOut); /* see if this block is full */ if (*firstFreeIndex >= ht->header.nPairsPerBlock) { newBlock = DEHT_allocKeyBlock(ht); CHECK(0 != newBlock); /* update old block */ SET_NEXT_BLOCK_PTR(ht, blockDataOut, newBlock); /* update last block reference if cache is present */ if (NULL != ht->hashPointersForLastBlockImageInMemory) { ht->hashPointersForLastBlockImageInMemory[bucketIndex] = newBlock; } CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, *blockDiskPtr, blockDataOut, KEY_FILE_BLOCK_SIZE(ht)))); /* now, just return the reference to the start of the new block */ memset(blockDataOut, 0, KEY_FILE_BLOCK_SIZE(ht)); *blockDiskPtr = newBlock; *firstFreeIndex = 0; } /* increase used pairs count by one. If & when the user will update the block on disk, this will be updated as well */ SET_USED_RECORD_COUNT(blockDataOut, GET_USED_RECORD_COUNT(blockDataOut) + 1); ret = TRUE; goto LBL_CLEANUP; LBL_ERROR: *blockDiskPtr = 0; *firstFreeIndex = 0; ret = FALSE; TRACE_FUNC_ERROR(); LBL_CLEANUP: TRACE_FUNC_EXIT(); return ret; }