Example #1
0
static void AddNewElement (TRI_hash_array_t* array,
                           TRI_hash_index_element_t* element) {
  uint64_t hash;
  uint64_t i;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);

  // ...........................................................................
  // search the table
  // ...........................................................................

  i = hash % array->_nrAlloc;

  while (! IsEmptyElement(array, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesR++;
#endif
  }

  // ...........................................................................
  // add a new element to the associative array
  // memcpy ok here since are simply moving array items internally
  // ...........................................................................

  memcpy(&array->_table[i], element, sizeof(TRI_hash_index_element_t));
  array->_nrUsed++;
}
void JingleFileTransferFileInfoParser::handleEndElement(const std::string& element, const std::string&) {
    --level;
    if (level == 1) {
        if (element == "date") {
            getPayloadInternal()->setDate(stringToDateTime(charData));
        }
        else if (element == "desc") {
            getPayloadInternal()->setDescription(charData);
        }
        else if (element == "media-type") {
            getPayloadInternal()->setMediaType(charData);
        }
        else if (element == "name") {
            getPayloadInternal()->setName(charData);
        }
        else if (element == "size") {
            boost::optional<boost::uintmax_t> size = safeLexicalCast<boost::uintmax_t>(charData);
            if (size) {
                getPayloadInternal()->setSize(size.get());
            }
        }
        else if (element == "range") {
            getPayloadInternal()->setSupportsRangeRequests(true);
            if (rangeOffset) {
                getPayloadInternal()->setRangeOffset(rangeOffset.get_value_or(0));
            }
        }
        else if (element == "hash") {
            getPayloadInternal()->addHash(HashElement(hashAlg, Base64::decode(charData)));
        }
    }
}
Example #3
0
TRI_vector_pointer_t TRI_LookupByElementHashArrayMulti (TRI_hash_array_t* array,
                                                        TRI_hash_index_element_t* element) {
  TRI_vector_pointer_t result;
  uint64_t hash;
  uint64_t i;

  // ...........................................................................
  // initialise the vector which will hold the result if any
  // ...........................................................................

  TRI_InitVectorPointer(&result, TRI_UNKNOWN_MEM_ZONE);

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrFinds++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])) {
    if (IsEqualElementElement(array, element, &array->_table[i])) {
      TRI_PushBackVectorPointer(&result, &array->_table[i]);
    }

#ifdef TRI_INTERNAL_STATS
    else {
      array->_nrProbesF++;
    }
#endif

    i = (i + 1) % array->_nrAlloc;
  }

  // ...........................................................................
  // return whatever we found -- which could be an empty vector list if nothing
  // matches. Note that we allow multiple elements (compare with pointer impl).
  // ...........................................................................

  return result;
}
static int ResizeHashArray (TRI_hash_array_multi_t* array,
                            uint64_t targetSize,
                            bool allowShrink) {
  if (array->_nrAlloc >= targetSize && ! allowShrink) {
    return TRI_ERROR_NO_ERROR;
  }

  TRI_hash_index_element_multi_t* oldTable    = array->_table;
  TRI_hash_index_element_multi_t* oldTablePtr = array->_tablePtr;
  uint64_t oldAlloc = array->_nrAlloc;

  TRI_ASSERT(targetSize > 0);

  int res = AllocateTable(array, targetSize);

  if (res != TRI_ERROR_NO_ERROR) {
    return res;
  }

  if (array->_nrUsed > 0) {
    uint64_t const n = array->_nrAlloc;

    for (uint64_t j = 0; j < oldAlloc; j++) {
      TRI_hash_index_element_multi_t* element = &oldTable[j];

      if (element->_document != nullptr) {
        uint64_t i, k;
        i = k = HashElement(array, element) % n;

        for (; i < n && array->_table[i]._document != nullptr; ++i);
        if (i == n) {
          for (i = 0; i < k && array->_table[i]._document != nullptr; ++i);
        }

        TRI_ASSERT_EXPENSIVE(i < n);

        // ...........................................................................
        // add a new element to the associative array
        // memcpy ok here since are simply moving array items internally
        // ...........................................................................

        memcpy(&array->_table[i], element, TableEntrySize());
      }
    }
  }

  TRI_Free(TRI_UNKNOWN_MEM_ZONE, oldTablePtr);

  return TRI_ERROR_NO_ERROR;
}
Example #5
0
TRI_hash_index_element_t* TRI_LookupByElementHashArray (TRI_hash_array_t* array,
                                                        TRI_hash_index_element_t* element) {
  uint64_t hash;
  uint64_t i;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrFinds++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])
      && ! IsEqualElementElement(array, element, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesF++;
#endif
  }

  // ...........................................................................
  // return whatever we found
  // ...........................................................................

  return &array->_table[i];
}
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 #7
0
int TRI_RemoveKeyHashArray (TRI_hash_array_t* array,
                            TRI_index_search_value_t* key) {
  uint64_t hash;
  uint64_t i;
  uint64_t k;
  bool found;
  void* arrayElement;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashKey(array, key);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrRems++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])
      && ! IsEqualKeyElement(array, key, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesD++;
#endif
  }

  arrayElement = &array->_table[i];

  // ...........................................................................
  // if we did not find such an item return false
  // ...........................................................................

  found = ! IsEmptyElement(array, arrayElement);

  if (! found) {
    return TRI_RESULT_KEY_NOT_FOUND;
  }

  // ...........................................................................
  // remove item
  // ...........................................................................

  DestroyElement(array, arrayElement);
  array->_nrUsed--;

  // ...........................................................................
  // and now check the following places for items to move here
  // ...........................................................................

  k = (i + 1) % array->_nrAlloc;

  while (! IsEmptyElement(array, &array->_table[k])) {
    uint64_t j = 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];
      ClearElement(array, &array->_table[k]);
      i = k;
    }

    k = (k + 1) % array->_nrAlloc;
  }

  // ...........................................................................
  // return success
  // ...........................................................................

  return TRI_ERROR_NO_ERROR;
}
Example #8
0
int TRI_RemoveElementHashArray (TRI_hash_array_t* array,
                                TRI_hash_index_element_t* element) {
  uint64_t hash;
  uint64_t i;
  uint64_t k;
  bool found;
  void* arrayElement;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrRems++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])
      && ! IsEqualElementElement(array, element, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesD++;
#endif
  }

  arrayElement = &array->_table[i];

  // ...........................................................................
  // if we did not find such an item return false
  // ...........................................................................

  found = ! IsEmptyElement(array, arrayElement);

  if (! found) {
    return TRI_RESULT_ELEMENT_NOT_FOUND;
  }

  // ...........................................................................
  // remove item - destroy any internal memory associated with the element structure
  // ...........................................................................

  DestroyElement(array, arrayElement);
  array->_nrUsed--;

  // ...........................................................................
  // and now check the following places for items to move closer together
  // so that there are no gaps in the array
  // ...........................................................................

  k = (i + 1) % array->_nrAlloc;

  while (! IsEmptyElement(array, &array->_table[k])) {
    uint64_t j = 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];
      ClearElement(array, &array->_table[k]);
      i = k;
    }

    k = (k + 1) % array->_nrAlloc;
  }

  return TRI_ERROR_NO_ERROR;
}
Example #9
0
int TRI_InsertElementHashArray (TRI_hash_array_t* array,
                                TRI_hash_index_element_t* element,
                                bool overwrite) {
  uint64_t hash;
  uint64_t i;
  bool found;
  int res;
  TRI_hash_index_element_t* arrayElement;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrAdds++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])
      && ! IsEqualElementElement(array, element, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesA++;
#endif
  }

  arrayElement = &array->_table[i];

  // ...........................................................................
  // if we found an element, return
  // ...........................................................................

  found = ! IsEmptyElement(array, arrayElement);

  if (found) {
    if (overwrite) {
      // destroy the underlying element since we are going to stomp on top if it
      DestroyElement(array, arrayElement);
      *arrayElement = *element;
    }
    else {
      DestroyElement(array, element);
    }

    return TRI_RESULT_ELEMENT_EXISTS;
  }

  // ...........................................................................
  // add a new element to the hash array (existing item is empty so no need to
  // destroy it)
  // ...........................................................................

  *arrayElement = *element;
  array->_nrUsed++;

  // ...........................................................................
  // we are adding and the table is more than half full, extend it
  // ...........................................................................

  if (array->_nrAlloc < 2 * array->_nrUsed) {
    res = ResizeHashArray(array);

    if (res != TRI_ERROR_NO_ERROR) {
      return res;
    }
  }

  return TRI_ERROR_NO_ERROR;
}
Example #10
0
int TRI_InsertElementHashArrayMulti (TRI_hash_array_t* array,
                                     TRI_hash_index_element_t* element,
                                     bool overwrite) {

  uint64_t hash;
  uint64_t i;
  bool found;
  int res;
  TRI_hash_index_element_t* arrayElement;

  // ...........................................................................
  // compute the hash
  // ...........................................................................

  hash = HashElement(array, element);
  i = hash % array->_nrAlloc;

  // ...........................................................................
  // update statistics
  // ...........................................................................

#ifdef TRI_INTERNAL_STATS
  array->_nrAdds++;
#endif

  // ...........................................................................
  // search the table
  // ...........................................................................

  while (! IsEmptyElement(array, &array->_table[i])
      && ! IsEqualElementElement(array, element, &array->_table[i])) {
    i = (i + 1) % array->_nrAlloc;

#ifdef TRI_INTERNAL_STATS
    array->_nrProbesA++;
#endif
  }

  arrayElement = &array->_table[i];

  // ...........................................................................
  // If we found an element, return. While we allow duplicate entries in the
  // hash table, we do not allow duplicate elements. Elements would refer to the
  // (for example) an actual row in memory. This is different from the
  // TRI_InsertElementMultiArray function below where we only have keys to
  // differentiate between elements.
  // ...........................................................................

  found = ! IsEmptyElement(array, arrayElement);

  if (found) {
    if (overwrite) {
      // destroy the underlying element since we are going to stomp on top if it
      DestroyElement(array, arrayElement);
      *arrayElement = *element;
    }
    else {
      DestroyElement(array, element);
    }

    return TRI_RESULT_ELEMENT_EXISTS;
  }

  // ...........................................................................
  // add a new element to the associative array
  // ...........................................................................

  *arrayElement = *element;
  array->_nrUsed++;

  // ...........................................................................
  // if we were adding and the table is more than half full, extend it
  // ...........................................................................

  if (array->_nrAlloc < 2 * array->_nrUsed) {
    res = ResizeHashArray(array);

    if (res != TRI_ERROR_NO_ERROR) {
      return res;
    }
  }

  return TRI_ERROR_NO_ERROR;
}