mirror of https://gitee.com/bigwinds/arangodb
399 lines
15 KiB
C
399 lines
15 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief geo index
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright by triAGENS GmbH - All rights reserved.
|
|
///
|
|
/// The Programs (which include both the software and documentation)
|
|
/// contain proprietary information of triAGENS GmbH; they are
|
|
/// provided under a license agreement containing restrictions on use and
|
|
/// disclosure and are also protected by copyright, patent and other
|
|
/// intellectual and industrial property laws. Reverse engineering,
|
|
/// disassembly or decompilation of the Programs, except to the extent
|
|
/// required to obtain interoperability with other independently created
|
|
/// software or as specified by law, is prohibited.
|
|
///
|
|
/// The Programs are not intended for use in any nuclear, aviation, mass
|
|
/// transit, medical, or other inherently dangerous applications. It shall
|
|
/// be the licensee's responsibility to take all appropriate fail-safe,
|
|
/// backup, redundancy, and other measures to ensure the safe use of such
|
|
/// applications if the Programs are used for such purposes, and triAGENS
|
|
/// GmbH disclaims liability for any damages caused by such use of
|
|
/// the Programs.
|
|
///
|
|
/// This software is the confidential and proprietary information of
|
|
/// triAGENS GmbH. You shall not disclose such confidential and
|
|
/// proprietary information and shall use it only in accordance with the
|
|
/// terms of the license agreement you entered into with triAGENS GmbH.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Dr. O
|
|
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "hashindex.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// private functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a hash index results list
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeResults (TRI_hash_index_elements_t* list) {
|
|
if (list->_elements) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, list->_elements);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, list);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// destructors public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys the hash index by calling the hash array's own Free function
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void HashIndex_destroy(HashIndex* hashIndex) {
|
|
if (hashIndex != NULL) {
|
|
TRI_FreeHashArray(hashIndex->hashArray);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys the hash index and frees the memory associated with the index structure
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void HashIndex_free(HashIndex* hashIndex) {
|
|
if (hashIndex != NULL) {
|
|
HashIndex_destroy(hashIndex);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashIndex);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a result set allocated by HashIndex_find
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void HashIndex_freeResult(TRI_hash_index_elements_t* const list) {
|
|
FreeResults(list);
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// constructors public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Creates a new hash array used for storage of elements in the hash index
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
HashIndex* HashIndex_new() {
|
|
HashIndex* hashIndex;
|
|
|
|
hashIndex = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(HashIndex), false);
|
|
if (hashIndex == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
hashIndex->unique = true;
|
|
hashIndex->hashArray = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_hasharray_t), false);
|
|
if (hashIndex->hashArray == NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashIndex);
|
|
return NULL;
|
|
}
|
|
|
|
if (! TRI_InitHashArray(hashIndex->hashArray, sizeof(HashIndexElement), NULL, NULL, NULL, NULL, NULL, NULL) ) {
|
|
HashIndex_free(hashIndex);
|
|
return NULL;
|
|
}
|
|
|
|
return hashIndex;
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// public functions : INSERT, REMOVE & LOOKUP
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Adds (inserts) a data element into the hash array part of the hash index
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int HashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
|
|
bool result;
|
|
|
|
// .............................................................................
|
|
// Since we do not allow duplicates - we must compare using keys, rather than
|
|
// documents.
|
|
// .............................................................................
|
|
|
|
result = TRI_InsertKeyHashArray(hashIndex->hashArray, element, element, false);
|
|
return result ? TRI_ERROR_NO_ERROR : TRI_set_errno(TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Locates an entry within the hash array part of the hash index
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_hash_index_elements_t* HashIndex_find(HashIndex* hashIndex, HashIndexElement* element) {
|
|
HashIndexElement* result;
|
|
TRI_hash_index_elements_t* results;
|
|
|
|
|
|
// .............................................................................
|
|
// Create storage for the returned results if any. A return of NULL indicates
|
|
// some sort of error.
|
|
// .............................................................................
|
|
|
|
results = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_hash_index_elements_t), false);
|
|
|
|
if (results == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// .............................................................................
|
|
// A find request means that a set of values for the "key" was sent. We need
|
|
// to locate the hash array entry by key.
|
|
// .............................................................................
|
|
|
|
result = (HashIndexElement*) (TRI_FindByKeyHashArray(hashIndex->hashArray, element));
|
|
|
|
if (result != NULL) {
|
|
results->_elements = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(HashIndexElement) * 1, false); // unique hash index maximum number is 1
|
|
if (results->_elements == NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, results);
|
|
return NULL;
|
|
}
|
|
results->_elements[0] = *result;
|
|
results->_numElements = 1;
|
|
}
|
|
else {
|
|
results->_elements = NULL;
|
|
results->_numElements = 0;
|
|
}
|
|
return results;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief An alias for HashIndex_add
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int HashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
|
return HashIndex_add(hashIndex,element);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Removes an entry from the hash array part of the hash index
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
|
bool result;
|
|
|
|
result = TRI_RemoveElementHashArray(hashIndex->hashArray, element);
|
|
return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief updates and entry from the associative array, first removes beforeElement,
|
|
/// @brief then adds the afterElement
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
|
|
const HashIndexElement* afterElement) {
|
|
// ...........................................................................
|
|
// This function is not currently implemented and must not be called.
|
|
// It's purpose would be to remove the existing beforeElement and replace it
|
|
// with the afterElement.
|
|
// ...........................................................................
|
|
|
|
assert(false);
|
|
return TRI_ERROR_INTERNAL;
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
// Multi-hash non-unique hash indexes
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// destructors public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys the hash index by calling the hash array's own Free function
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MultiHashIndex_destroy(HashIndex* hashIndex) {
|
|
HashIndex_destroy(hashIndex);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys the hash index and frees the memory associated with the index structure
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MultiHashIndex_free(HashIndex* hashIndex) {
|
|
HashIndex_free(hashIndex);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a result set allocated by MultiHashIndex_find
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MultiHashIndex_freeResult(TRI_hash_index_elements_t* const list) {
|
|
FreeResults(list);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// constructors public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Creates a new multi (non-unique) hash index
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HashIndex* MultiHashIndex_new() {
|
|
HashIndex* hashIndex;
|
|
|
|
hashIndex = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(HashIndex), false);
|
|
if (hashIndex == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
hashIndex->unique = false;
|
|
hashIndex->hashArray = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_hasharray_t), false);
|
|
if (hashIndex->hashArray == NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashIndex);
|
|
return NULL;
|
|
}
|
|
|
|
if (! TRI_InitHashArray(hashIndex->hashArray, sizeof(HashIndexElement), NULL, NULL, NULL, NULL, NULL, NULL) ) {
|
|
HashIndex_free(hashIndex);
|
|
return NULL;
|
|
}
|
|
|
|
return hashIndex;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// public functions : INSERT, REMOVE & LOOKUP
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Adds (inserts) a data element into the hash array (hash index)
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int MultiHashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
|
|
bool result;
|
|
result = TRI_InsertElementHashArrayMulti(hashIndex->hashArray, element, false);
|
|
if (result) {
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// ...............................................................................
|
|
// Locates an entry within the associative array
|
|
// ...............................................................................
|
|
|
|
TRI_hash_index_elements_t* MultiHashIndex_find(HashIndex* hashIndex, HashIndexElement* element) {
|
|
TRI_vector_pointer_t result;
|
|
TRI_hash_index_elements_t* results;
|
|
size_t j;
|
|
|
|
results = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_hash_index_elements_t), false);
|
|
if (results == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// .............................................................................
|
|
// We can only use the LookupByKey method for non-unique hash indexes, since
|
|
// we want more than one result returned!
|
|
// .............................................................................
|
|
|
|
result = TRI_LookupByKeyHashArrayMulti (hashIndex->hashArray, element);
|
|
|
|
|
|
if (result._length == 0) {
|
|
results->_elements = NULL;
|
|
results->_numElements = 0;
|
|
}
|
|
else {
|
|
results->_numElements = result._length;
|
|
results->_elements = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(HashIndexElement) * result._length, false);
|
|
if (results->_elements == NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, results);
|
|
return NULL;
|
|
}
|
|
for (j = 0; j < result._length; ++j) {
|
|
results->_elements[j] = *((HashIndexElement*)(result._buffer[j]));
|
|
}
|
|
}
|
|
TRI_DestroyVectorPointer(&result);
|
|
|
|
return results;
|
|
}
|
|
|
|
|
|
// ...............................................................................
|
|
// An alias for addIndex
|
|
// ...............................................................................
|
|
|
|
int MultiHashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
|
return MultiHashIndex_add(hashIndex,element);
|
|
}
|
|
|
|
|
|
// ...............................................................................
|
|
// Removes an entry from the associative array
|
|
// ...............................................................................
|
|
|
|
int MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
|
bool result;
|
|
result = TRI_RemoveElementHashArrayMulti(hashIndex->hashArray, element);
|
|
return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
|
|
}
|
|
|
|
|
|
// ...............................................................................
|
|
// updates and entry from the associative array, first removes beforeElement,
|
|
// then adds the afterElement
|
|
// ...............................................................................
|
|
|
|
int MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
|
|
HashIndexElement* afterElement) {
|
|
assert(false);
|
|
return TRI_ERROR_INTERNAL;
|
|
}
|
|
|