/* * FUNCTION: pkix_pl_HashTableLookup * DESCRIPTION: * * Looks up object using the key pointed to by "key" and hashCode value * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the * function pointed to by "keyComp" to compare keys, and stores the object's * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object. * This function sets "pResult" to NULL if the key is not in the hashtable. * * PARAMETERS: * "ht" * Address of PrimHashtable to lookup object from. Must be non-NULL. * "key" * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object. * Must be non-NULL. * "keyComp" * Address of function used to determine if two keys are equal. * If NULL, pkix_pl_KeyComparator_Default is used. * "hashCode" * Hashcode value of the key. * "pResult" * Address where value will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditionally Thread Safe * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_PrimHashTable_Lookup( pkix_pl_PrimHashTable *ht, void *key, PKIX_UInt32 hashCode, PKIX_PL_EqualsCallback keyComp, void **pResult, void *plContext) { pkix_pl_HT_Elem *element = NULL; PKIX_Boolean compResult = PKIX_FALSE; PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Lookup"); PKIX_NULLCHECK_THREE(ht, key, pResult); *pResult = NULL; for (element = (ht->buckets)[hashCode%ht->size]; (element != NULL) && (*pResult == NULL); element = element->next) { if (element->hashCode != hashCode){ /* no possibility of a match */ continue; } if (keyComp == NULL){ PKIX_CHECK(pkix_pl_KeyComparator_Default ((PKIX_UInt32 *)key, (PKIX_UInt32 *)(element->key), &compResult, plContext), PKIX_COULDNOTTESTWHETHERKEYSEQUAL); } else { pkixErrorResult = keyComp((PKIX_PL_Object *)key, (PKIX_PL_Object *)(element->key), &compResult, plContext); if (pkixErrorResult) { pkixErrorClass = PKIX_FATAL_ERROR; pkixErrorCode = PKIX_COULDNOTTESTWHETHERKEYSEQUAL; goto cleanup; } } if ((element->hashCode == hashCode) && (compResult == PKIX_TRUE)){ *pResult = element->value; goto cleanup; } } /* if we've reached here, specified key doesn't exist in hashtable */ *pResult = NULL; cleanup: PKIX_RETURN(HASHTABLE); }
// // leftmostSearchPos - 从左到右最后一个比key小的数的下标,如果都大于key的话,返回-1 // int BPlusNode::leftmostSearchPos(KeyPtr key) { int pos = 0; int begin = 0, end = size_ - 1; while (begin <= end) { int mid = (begin + end) / 2; KeyPtr k = keyAt(mid); int res = keyComp(k, key); if (res < 0) begin = mid + 1; else if (res > 0) end = mid - 1; else end = mid - 1; } if (begin >= size_) return size_ - 1; if (begin == 0) return keyComp(keyAt(0), key) > 0 ? -1 : 0; return begin - 1; }
int BPlusNode::search(KeyPtr key, const RID &rid) { int low = lowerBound(key); if (low < 0) return -1; for (int i = low; i < size_; i++) { if (keyComp(keyAt(i), key) != 0) break; if (rids_[i] == rid) return i; } return -1; }
// // lowerBound - 在本node节点的寻找和key一致的最左边的键的下标 // int BPlusNode::lowerBound(KeyPtr key) { KeyPtr k; int begin = 0, end = size_ - 1; while (begin <= end) { int mid = (begin + end) / 2; k = keyAt(mid); int res = keyComp(k, key); if (res < 0) { begin = mid + 1; } else if (res > 0) { end = mid - 1; } else { // k == key end = mid - 1; } } if (begin >= size_) return -1; return keyComp(keyAt(begin), key) == 0 ? begin : -1; }
// // insert - 将一个索引的item装入Node里面 // bool BPlusNode::insert(const KeyPtr key, const RID& rid) { int i = -1; KeyPtr prev = nullptr, curr = nullptr; // 从后往前扫描 for (i = size_ - 1; i >= 0; i--) { prev = curr; curr = keyAt(i); if (keyComp(key, curr) > 0) break; rids_[i + 1] = rids_[i]; updateKey(i + 1, curr); } rids_[i + 1] = rid; updateKey(i + 1, key); size_++; setSize(size_); page_.setDirty(); return true; }
// // leftmostInsertPos - 查找key在最左侧的插入位置 // int BPlusNode::leftmostInsertPos(KeyPtr key) { int pos = 0; KeyPtr k; int begin = 0, end = size_ - 1; while (begin <= end) { int mid = (begin + end) / 2; k = keyAt(mid); int res = keyComp(k, key); if (res < 0) { begin = mid + 1; } else if (res > 0) { end = mid - 1; } else { // k == key end = mid - 1; } } return end + 1; }
/* * FUNCTION: pkix_pl_PrimHashTable_Remove * DESCRIPTION: * * Removes any objects with the key pointed to by "key" and hashCode value * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the * function pointed to by "keyComp" to compare keys, and stores the object's * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object. * This function sets "pResult" to NULL if the key is not in the hashtable. * * PARAMETERS: * "ht" * Address of PrimHashtable to remove object. Must be non-NULL. * "key" * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object. * Must be non-NULL. * "value" * Address of Object to be added to PrimHashtable. Must be non-NULL. * "hashCode" * Hashcode value of the key. * "keyComp" * Address of function used to determine if two keys are equal. * If NULL, pkix_pl_KeyComparator_Default is used. * "pResult" * Address where value will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "ht" * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a HashTable Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_PrimHashTable_Remove( pkix_pl_PrimHashTable *ht, void *key, PKIX_UInt32 hashCode, PKIX_PL_EqualsCallback keyComp, void **pKey, void **pValue, void *plContext) { pkix_pl_HT_Elem *element = NULL; pkix_pl_HT_Elem *prior = NULL; PKIX_Boolean compResult; PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove"); PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue); *pKey = NULL; *pValue = NULL; for (element = ht->buckets[hashCode%ht->size], prior = element; (element != NULL); prior = element, element = element->next) { if (element->hashCode != hashCode){ /* no possibility of a match */ continue; } if (keyComp == NULL){ PKIX_CHECK(pkix_pl_KeyComparator_Default ((PKIX_UInt32 *)key, (PKIX_UInt32 *)(element->key), &compResult, plContext), PKIX_COULDNOTTESTWHETHERKEYSEQUAL); } else { PKIX_CHECK(keyComp ((PKIX_PL_Object *)key, (PKIX_PL_Object *)(element->key), &compResult, plContext), PKIX_COULDNOTTESTWHETHERKEYSEQUAL); } if ((element->hashCode == hashCode) && (compResult == PKIX_TRUE)){ if (element != prior) { prior->next = element->next; } else { ht->buckets[hashCode%ht->size] = element->next; } *pKey = element->key; *pValue = element->value; element->key = NULL; element->value = NULL; element->next = NULL; PKIX_FREE(element); goto cleanup; } } cleanup: PKIX_RETURN(HASHTABLE); }
/* * FUNCTION: pkix_pl_PrimHashTable_Add * DESCRIPTION: * * Adds the value pointed to by "value" to the PrimHashTable pointed to by * "ht" using the key pointed to by "key" and the hashCode value equal to * "hashCode", using the function pointed to by "keyComp" to compare keys. * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value * already exists in the hashtable, this function returns a non-fatal error. * * PARAMETERS: * "ht" * Address of PrimHashtable to insert into. Must be non-NULL. * "key" * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object. * Must be non-NULL. * "value" * Address of Object to be added to PrimHashtable. Must be non-NULL. * "hashCode" * Hashcode value of the key. * "keyComp" * Address of function used to determine if two keys are equal. * If NULL, pkix_pl_KeyComparator_Default is used. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "ht" * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a HashTable Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_PrimHashTable_Add( pkix_pl_PrimHashTable *ht, void *key, void *value, PKIX_UInt32 hashCode, PKIX_PL_EqualsCallback keyComp, void *plContext) { pkix_pl_HT_Elem **elemPtr = NULL; pkix_pl_HT_Elem *element = NULL; PKIX_Boolean compResult = PKIX_FALSE; PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Add"); PKIX_NULLCHECK_THREE(ht, key, value); for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr; element != NULL; elemPtr = &(element->next), element = *elemPtr) { if (element->hashCode != hashCode){ /* no possibility of a match */ continue; } if (keyComp == NULL){ PKIX_CHECK(pkix_pl_KeyComparator_Default ((PKIX_UInt32 *)key, (PKIX_UInt32 *)(element->key), &compResult, plContext), PKIX_COULDNOTTESTWHETHERKEYSEQUAL); } else { PKIX_CHECK(keyComp ((PKIX_PL_Object *)key, (PKIX_PL_Object *)(element->key), &compResult, plContext), PKIX_COULDNOTTESTWHETHERKEYSEQUAL); } if ((element->hashCode == hashCode) && (compResult == PKIX_TRUE)){ /* Same key already exists in the table */ PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY); } } /* Next Element should be NULL at this point */ if (element != NULL) { PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET); } /* Create a new HT_Elem */ PKIX_CHECK(PKIX_PL_Malloc (sizeof (pkix_pl_HT_Elem), (void **)elemPtr, plContext), PKIX_MALLOCFAILED); element = *elemPtr; element->key = key; element->value = value; element->hashCode = hashCode; element->next = NULL; cleanup: PKIX_RETURN(HASHTABLE); }