Example #1
0
/*
 * 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);
}
Example #2
0
//
// 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;
}
Example #3
0
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;
}
Example #4
0
//
// 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;
}
Example #5
0
//
// 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;
}
Example #6
0
//
// 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;
}
Example #7
0
/*
 * 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);
}
Example #8
0
/*
 * 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);
}