Example #1
0
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;
}
Example #2
0
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;
}
Example #4
0
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];
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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++;
}
Example #11
0
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;
}
Example #13
0
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;
}