bool TRI_RemoveKeyAssociativeArray (TRI_associative_array_t* array, void* key, void* old) { uint64_t hash; uint64_t i; uint64_t k; hash = array->hashKey(array, key); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrRems++; #endif // search the table while (! array->isEmptyElement(array, array->_table + i * array->_elementSize) && ! array->isEqualKeyElement(array, key, array->_table + i * array->_elementSize)) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesD++; #endif } // if we did not find such an item return false if (array->isEmptyElement(array, array->_table + i * array->_elementSize)) { if (old != NULL) { memset(old, 0, array->_elementSize); } return false; } // remove item if (old != NULL) { memcpy(old, array->_table + i * array->_elementSize, array->_elementSize); } array->clearElement(array, array->_table + i * array->_elementSize); array->_nrUsed--; // and now check the following places for items to move here k = TRI_IncModU64(i, array->_nrAlloc); while (! array->isEmptyElement(array, array->_table + k * array->_elementSize)) { uint64_t j = array->hashElement(array, array->_table + k * array->_elementSize) % array->_nrAlloc; if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) { memcpy(array->_table + i * array->_elementSize, array->_table + k * array->_elementSize, array->_elementSize); array->clearElement(array, array->_table + k * array->_elementSize); i = k; } k = TRI_IncModU64(k, array->_nrAlloc); } // return success return true; }
void* TRI_RemoveElementAssociativePointer (TRI_associative_pointer_t* array, void const* element) { uint64_t hash; uint64_t i; uint64_t k; void* old; hash = array->hashElement(array, element); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrRems++; #endif // search the table while (array->_table[i] != NULL && ! array->isEqualElementElement(array, element, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesD++; #endif } // if we did not find such an item return 0 if (array->_table[i] == NULL) { return NULL; } // remove item old = array->_table[i]; array->_table[i] = NULL; array->_nrUsed--; // and now check the following places for items to move here k = TRI_IncModU64(i, array->_nrAlloc); while (array->_table[k] != NULL) { uint64_t j = array->hashElement(array, array->_table[k]) % array->_nrAlloc; if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) { array->_table[i] = array->_table[k]; array->_table[k] = NULL; i = k; } k = TRI_IncModU64(k, array->_nrAlloc); } // return success return old; }
void* TRI_RemoveKeyPrimaryIndex (TRI_primary_index_t* idx, char const* key) { uint64_t const hash = TRI_HashKeyPrimaryIndex(key); uint64_t const n = idx->_nrAlloc; uint64_t i, k; i = k = hash % n; // search the table for (; i < n && idx->_table[i] != nullptr && IsDifferentHashElement(key, hash, idx->_table[i]); ++i); if (i == n) { for (i = 0; i < k && idx->_table[i] != nullptr && IsDifferentHashElement(key, hash, idx->_table[i]); ++i); } TRI_ASSERT_EXPENSIVE(i < n); // if we did not find such an item return false if (idx->_table[i] == nullptr) { return nullptr; } // remove item void* old = idx->_table[i]; idx->_table[i] = nullptr; idx->_nrUsed--; // and now check the following places for items to move here k = TRI_IncModU64(i, n); while (idx->_table[k] != nullptr) { uint64_t j = (static_cast<TRI_doc_mptr_t const*>(idx->_table[k])->_hash) % n; if ((i < k && ! (i < j && j <= k)) || (k < i && ! (i < j || j <= k))) { idx->_table[i] = idx->_table[k]; idx->_table[k] = nullptr; i = k; } k = TRI_IncModU64(k, n); } if (idx->_nrUsed == 0) { ResizePrimaryIndex(idx, InitialSize(), true); } // return success return old; }
void* TRI_LookupByKeyAssociativePointer (TRI_associative_pointer_t* array, void const* key) { uint64_t hash; uint64_t i; if (array->_nrUsed == 0) { return NULL; } // compute the hash hash = array->hashKey(array, key); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrFinds++; #endif // search the table while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesF++; #endif } // return whatever we found return array->_table[i]; }
void* TRI_LookupByElementAssociativeArray (TRI_associative_array_t* array, void* element) { uint64_t hash; uint64_t i; // compute the hash hash = array->hashElement(array, element); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrFinds++; #endif // search the table while (! array->isEmptyElement(array, array->_table + i * array->_elementSize) && ! array->isEqualElementElement(array, element, array->_table + i * array->_elementSize)) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesF++; #endif } // return whatever we found return array->_table + i * array->_elementSize; }
void* TRI_RemoveKeyAssociativeSynced (TRI_associative_synced_t* array, void const* key) { uint64_t hash; uint64_t i; uint64_t k; void* old; hash = array->hashKey(array, key); TRI_WriteLockReadWriteLock(&array->_lock); i = hash % array->_nrAlloc; // search the table while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); } // if we did not find such an item return false if (array->_table[i] == NULL) { TRI_WriteUnlockReadWriteLock(&array->_lock); return NULL; } // remove item old = array->_table[i]; array->_table[i] = NULL; array->_nrUsed--; // and now check the following places for items to move here k = TRI_IncModU64(i, array->_nrAlloc); while (array->_table[k] != NULL) { uint64_t j = array->hashElement(array, array->_table[k]) % array->_nrAlloc; if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) { array->_table[i] = array->_table[k]; array->_table[k] = NULL; i = k; } k = TRI_IncModU64(k, array->_nrAlloc); } // return success TRI_WriteUnlockReadWriteLock(&array->_lock); return old; }
void* TRI_InsertKeyAssociativePointer (TRI_associative_pointer_t* array, void const* key, void* element, bool overwrite) { uint64_t hash; uint64_t i; void* old; // check for out-of-memory if (array->_nrAlloc == array->_nrUsed) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return NULL; } // compute the hash hash = array->hashKey(array, key); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrAdds++; #endif // search the table while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } old = array->_table[i]; // if we found an element, return if (old != NULL) { if (overwrite) { array->_table[i] = element; } return old; } // add a new element to the associative array array->_table[i] = element; array->_nrUsed++; // if we were adding and the table is more than half full, extend it if (array->_nrAlloc < 2 * array->_nrUsed) { ResizeAssociativePointer(array, (uint32_t) (2 * array->_nrAlloc) + 1); } return NULL; }
void* TRI_InsertKeyAssociativeSynced (TRI_associative_synced_t* array, void const* key, void* element, bool overwrite) { uint64_t hash; uint64_t i; void* old; // compute the hash hash = array->hashKey(array, key); // search the table TRI_WriteLockReadWriteLock(&array->_lock); // check for out-of-memory if (array->_nrAlloc == array->_nrUsed && ! overwrite) { TRI_WriteUnlockReadWriteLock(&array->_lock); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return NULL; } i = hash % array->_nrAlloc; while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); } old = array->_table[i]; // if we found an element, return if (old != NULL) { if (overwrite) { array->_table[i] = element; } TRI_WriteUnlockReadWriteLock(&array->_lock); return old; } // add a new element to the associative array array->_table[i] = element; array->_nrUsed++; // if we were adding and the table is more than half full, extend it if (array->_nrAlloc < 2 * array->_nrUsed) { ResizeAssociativeSynced(array, (uint32_t) (2 * array->_nrAlloc + 1)); } TRI_WriteUnlockReadWriteLock(&array->_lock); return NULL; }
bool TRI_InsertKeyAssociativeArray (TRI_associative_array_t* array, void* key, void* element, bool overwrite) { uint64_t hash; uint64_t i; // check for out-of-memory if (array->_nrAlloc == array->_nrUsed) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return false; } // compute the hash hash = array->hashKey(array, key); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrAdds++; #endif // search the table while (! array->isEmptyElement(array, array->_table + i * array->_elementSize) && ! array->isEqualKeyElement(array, key, array->_table + i * array->_elementSize)) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } // if we found an element, return if (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) { if (overwrite) { memcpy(array->_table + i * array->_elementSize, element, array->_elementSize); } return false; } // add a new element to the associative array memcpy(array->_table + i * array->_elementSize, element, array->_elementSize); array->_nrUsed++; // if we were adding and the table is more than half full, extend it if (array->_nrAlloc < 2 * array->_nrUsed) { ResizeAssociativeArray(array, (uint32_t) (2 * array->_nrAlloc + 1)); } return true; }
static void AddNewElement (TRI_associative_array_t* array, void* element) { uint64_t hash; uint64_t i; // compute the hash hash = array->hashElement(array, element); // search the table i = hash % array->_nrAlloc; while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesR++; #endif } // add a new element to the associative array memcpy(array->_table + i * array->_elementSize, element, array->_elementSize); array->_nrUsed++; }
static void AddNewElementPointer (TRI_associative_pointer_t* array, void* element) { uint64_t hash; uint64_t i; // compute the hash hash = array->hashElement(array, element); // search the table i = hash % array->_nrAlloc; while (array->_table[i] != NULL) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesR++; #endif } // add a new element to the associative array array->_table[i] = element; array->_nrUsed++; }
int TRI_RemoveElementHashArrayMulti (TRI_hash_array_multi_t* array, TRI_index_search_value_t const* key, TRI_hash_index_element_multi_t* element) { uint64_t const n = array->_nrAlloc; uint64_t i, k; i = k = HashKey(array, key) % n; for (; i < n && array->_table[i]._document != nullptr && ! IsEqualKeyElement(array, key, &array->_table[i]); ++i); if (i == n) { for (i = 0; i < k && array->_table[i]._document != nullptr && ! IsEqualKeyElement(array, key, &array->_table[i]); ++i); } TRI_ASSERT_EXPENSIVE(i < n); TRI_hash_index_element_multi_t* arrayElement = &array->_table[i]; bool found = (arrayElement->_document != nullptr); if (! found) { return TRI_RESULT_ELEMENT_NOT_FOUND; } if (arrayElement->_document != element->_document) { // look in the overflow list for the sought document auto next = &(arrayElement->_next); while (*next != nullptr) { if ((*next)->_document == element->_document) { auto ptr = (*next)->_next; DestroyElement(array, *next); ReturnToFreelist(array, *next); *next = ptr; return TRI_ERROR_NO_ERROR; } next = &((*next)->_next); } return TRI_RESULT_ELEMENT_NOT_FOUND; } // the element itself is the document to remove TRI_ASSERT(arrayElement->_document == element->_document); if (arrayElement->_next != nullptr) { auto next = arrayElement->_next; // destroy our own data first, otherwise we'll leak TRI_ASSERT(arrayElement->_subObjects != nullptr); TRI_Free(TRI_UNKNOWN_MEM_ZONE, arrayElement->_subObjects); // copy data from first overflow element into ourselves arrayElement->_document = next->_document; arrayElement->_subObjects = next->_subObjects; arrayElement->_next = next->_next; // and remove the first overflow element next->_subObjects = nullptr; DestroyElement(array, next); ReturnToFreelist(array, next); return TRI_ERROR_NO_ERROR; } TRI_ASSERT(arrayElement->_next == nullptr); DestroyElement(array, arrayElement); array->_nrUsed--; // ........................................................................... // and now check the following places for items to move here // ........................................................................... k = TRI_IncModU64(i, n); while (array->_table[k]._document != nullptr) { uint64_t j = HashElement(array, &array->_table[k]) % n; if ((i < k && ! (i < j && j <= k)) || (k < i && ! (i < j || j <= k))) { array->_table[i] = array->_table[k]; array->_table[k]._document = nullptr; array->_table[k]._next = nullptr; array->_table[k]._subObjects = nullptr; i = k; } k = TRI_IncModU64(k, n); } if (array->_nrUsed == 0) { TRI_ASSERT(array->_nrOverflowUsed == 0); ResizeHashArray(array, InitialSize(), true); } return TRI_ERROR_NO_ERROR; }
int TRI_InsertKeyAssociativePointer2 (TRI_associative_pointer_t* array, void const* key, void* element, void const** found) { uint64_t hash; uint64_t i; void* old; if (found != NULL) { *found = NULL; } // check for out-of-memory if (array->_nrAlloc == array->_nrUsed) { return TRI_ERROR_OUT_OF_MEMORY; } // compute the hash hash = array->hashKey(array, key); i = hash % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS // update statistics array->_nrAdds++; #endif // search the table while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } old = array->_table[i]; // if we found an element, return if (old != NULL) { if (found != NULL) { *found = old; } return TRI_ERROR_NO_ERROR; } // if we were adding and the table is more than half full, extend it if (array->_nrAlloc < 2 * array->_nrUsed) { if (! ResizeAssociativePointer(array, (uint32_t) (2 * array->_nrAlloc) + 1)) { return TRI_ERROR_OUT_OF_MEMORY; } // now we need to recalc the position i = hash % array->_nrAlloc; // search the table while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { i = TRI_IncModU64(i, array->_nrAlloc); #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } } // add a new element to the associative array array->_table[i] = element; array->_nrUsed++; return TRI_ERROR_NO_ERROR; }