mirror of https://gitee.com/bigwinds/arangodb
350 lines
12 KiB
C
Executable File
350 lines
12 KiB
C
Executable File
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief static hash and comparison functions
|
|
///
|
|
/// @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 <BasicsC/hashes.h>
|
|
#include <ShapedJson/json-shaper.h>
|
|
#include <ShapedJson/shaped-json.h>
|
|
#include <VocBase/document-collection.h>
|
|
|
|
#define USE_STATIC_HASHARRAY_COMPARE 1
|
|
|
|
#define HASHARRAY_ELEMENT_TYPE(a,b) \
|
|
struct a { \
|
|
size_t numFields; \
|
|
TRI_shaped_json_t* fields; \
|
|
void* data; \
|
|
void* collection; \
|
|
} b
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Forward declarations
|
|
// -----------------------------------------------------------------------------
|
|
|
|
static void IndexStaticClearElement (TRI_hasharray_t*, void*);
|
|
static bool IndexStaticCopyElementElement (TRI_hasharray_t*, void*, void*);
|
|
static void IndexStaticDestroyElement (TRI_hasharray_t*, void*);
|
|
static uint64_t IndexStaticHashElement (TRI_hasharray_t*, void*);
|
|
static uint64_t IndexStaticHashKey (TRI_hasharray_t*, void*);
|
|
static uint64_t IndexStaticHashShapedJson (const uint64_t, const TRI_shaped_json_t*);
|
|
static bool IndexStaticIsEmptyElement (TRI_hasharray_t*, void*);
|
|
static bool IndexStaticIsEqualElementElement (TRI_hasharray_t*, void*, void*);
|
|
static bool IndexStaticIsEqualElementElementMulti (TRI_hasharray_t*, void*, void*);
|
|
static bool IndexStaticIsEqualKeyElement (TRI_hasharray_t*, void*, void*);
|
|
static bool IndexStaticIsEqualKeyElementMulti (TRI_hasharray_t*, void*, void*);
|
|
static bool IndexStaticIsEqualShapedJsonShapedJson (const TRI_shaped_json_t* left, const TRI_shaped_json_t* right);
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Implementation
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief marks an element in the hash array as being 'cleared' or 'empty'
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void IndexStaticClearElement(TRI_hasharray_t* array, void* element) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hElement = (LocalElement_t*)(element);
|
|
if (element != NULL) {
|
|
hElement->numFields = 0;
|
|
hElement->fields = 0;
|
|
hElement->data = 0;
|
|
hElement->collection = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief deep copies the content of the right item into the left item
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool IndexStaticCopyElementElement (TRI_hasharray_t* array, void* left, void* right) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* leftElement = (LocalElement_t*)(left);
|
|
LocalElement_t* rightElement = (LocalElement_t*)(right);
|
|
|
|
if (leftElement == NULL || rightElement == NULL) {
|
|
assert(0);
|
|
return false;
|
|
}
|
|
|
|
leftElement->numFields = rightElement->numFields;
|
|
leftElement->data = rightElement->data;
|
|
leftElement->collection = rightElement->collection;
|
|
leftElement->fields = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_shaped_json_t) * leftElement->numFields, false);
|
|
|
|
if (leftElement->fields == NULL) {
|
|
return false;
|
|
}
|
|
|
|
memcpy(leftElement->fields, rightElement->fields, sizeof(TRI_shaped_json_t) * leftElement->numFields);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys an element -- removing any allocated memory within the structure
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void IndexStaticDestroyElement(TRI_hasharray_t* array, void* element) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
// ...........................................................................
|
|
// Each 'field' in the hElement->fields is a TRI_shaped_json_t object, this
|
|
// structure has internal structure of its own -- which also has memory
|
|
// allocated -- HOWEVER we DO NOT deallocate this memory here since it
|
|
// is actually part of the document structure. This memory should be deallocated
|
|
// when the document has been destroyed.
|
|
// ...........................................................................
|
|
|
|
LocalElement_t* hElement = (LocalElement_t*)(element);
|
|
if (element != NULL) {
|
|
if (hElement->fields != NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hElement->fields);
|
|
}
|
|
}
|
|
IndexStaticClearElement(array, element);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Given an element generates a hash integer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static uint64_t IndexStaticHashElement (TRI_hasharray_t* array, void* element) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hElement = (LocalElement_t*)(element);
|
|
uint64_t hash = TRI_FnvHashBlockInitial();
|
|
size_t j;
|
|
|
|
for (j = 0; j < hElement->numFields; j++) {
|
|
hash = IndexStaticHashShapedJson(hash, (j + hElement->fields) );
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Given an element generates a hash integer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static uint64_t IndexStaticHashKey (TRI_hasharray_t* array, void* element) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hElement = (LocalElement_t*)(element);
|
|
uint64_t hash = TRI_FnvHashBlockInitial();
|
|
size_t j;
|
|
|
|
for (j = 0; j < hElement->numFields; j++) {
|
|
hash = IndexStaticHashShapedJson(hash, (j + hElement->fields) );
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
|
|
|
|
static uint64_t IndexStaticHashShapedJson (const uint64_t hash, const TRI_shaped_json_t* shapedJson) {
|
|
return TRI_FnvHashBlock(hash, shapedJson->_data.data, shapedJson->_data.length);
|
|
} // end of function hashShapedJson
|
|
|
|
|
|
|
|
// .............................................................................
|
|
// returns true if an element in the unique assoc array is 'empty'
|
|
// .............................................................................
|
|
|
|
static bool IndexStaticIsEmptyElement (TRI_hasharray_t* array, void* element) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hElement = (LocalElement_t*)(element);
|
|
if (element != NULL) {
|
|
if (hElement->data == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
// .............................................................................
|
|
// Determines if two elements of the unique assoc array are equal
|
|
// Two elements are 'equal' if the document pointer is the same.
|
|
// .............................................................................
|
|
static bool IndexStaticIsEqualElementElement (TRI_hasharray_t* array, void* leftElement, void* rightElement) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hLeftElement = (LocalElement_t*)(leftElement);
|
|
LocalElement_t* hRightElement = (LocalElement_t*)(rightElement);
|
|
|
|
if (leftElement == NULL || rightElement == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (hLeftElement->numFields != hRightElement->numFields) {
|
|
return false; // should never happen
|
|
}
|
|
|
|
return (hLeftElement->data == hRightElement->data);
|
|
}
|
|
|
|
|
|
|
|
// .............................................................................
|
|
// Returns true if document pointers are the same, otherwise returns false
|
|
// .............................................................................
|
|
static bool IndexStaticIsEqualElementElementMulti (TRI_hasharray_t* array, void* leftElement, void* rightElement) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hLeftElement = (LocalElement_t*)(leftElement);
|
|
LocalElement_t* hRightElement = (LocalElement_t*)(rightElement);
|
|
|
|
if (leftElement == NULL || rightElement == NULL) {
|
|
return false;
|
|
}
|
|
|
|
return (hLeftElement->data == hRightElement->data);
|
|
}
|
|
|
|
|
|
// .............................................................................
|
|
// Determines if two elements of the unique assoc array are equal
|
|
// Two elements are 'equal' if the shaped json content is equal.
|
|
// .............................................................................
|
|
static bool IndexStaticIsEqualKeyElement (TRI_hasharray_t* array, void* leftElement, void* rightElement) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hLeftElement = (LocalElement_t*)(leftElement);
|
|
LocalElement_t* hRightElement = (LocalElement_t*)(rightElement);
|
|
size_t j;
|
|
|
|
if (leftElement == NULL || rightElement == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (hLeftElement->numFields != hRightElement->numFields) {
|
|
return false; // should never happen
|
|
}
|
|
|
|
for (j = 0; j < hLeftElement->numFields; j++) {
|
|
|
|
/*
|
|
printf("%s:%u:%f:%f,%u:%u\n",__FILE__,__LINE__,
|
|
*((double*)((j + hLeftElement->fields)->_data.data)),
|
|
*((double*)((j + hRightElement->fields)->_data.data)),
|
|
(uint64_t)(hLeftElement->data),
|
|
(uint64_t)(hRightElement->data)
|
|
);
|
|
*/
|
|
if (!IndexStaticIsEqualShapedJsonShapedJson((j + hLeftElement->fields), (j + hRightElement->fields))) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// .............................................................................
|
|
// Returns true if the "key" matches that of the element
|
|
// .............................................................................
|
|
static bool IndexStaticIsEqualKeyElementMulti (TRI_hasharray_t* array, void* leftElement, void* rightElement) {
|
|
typedef HASHARRAY_ELEMENT_TYPE(LocalElement_s,LocalElement_t);
|
|
|
|
LocalElement_t* hLeftElement = (LocalElement_t*)(leftElement);
|
|
LocalElement_t* hRightElement = (LocalElement_t*)(rightElement);
|
|
size_t j;
|
|
|
|
if (leftElement == NULL || rightElement == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (hLeftElement->numFields != hRightElement->numFields) {
|
|
return false; // should never happen
|
|
}
|
|
|
|
for (j = 0; j < hLeftElement->numFields; j++) {
|
|
TRI_shaped_json_t* left = (j + hLeftElement->fields);
|
|
TRI_shaped_json_t* right = (j + hRightElement->fields);
|
|
if (!IndexStaticIsEqualShapedJsonShapedJson(left, right)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool IndexStaticIsEqualShapedJsonShapedJson (const TRI_shaped_json_t* left, const TRI_shaped_json_t* right) {
|
|
if (left == NULL && right == NULL) {
|
|
return true;
|
|
}
|
|
|
|
if (left == NULL && right != NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (left != NULL && right == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (left->_data.length != right->_data.length) {
|
|
return false;
|
|
}
|
|
|
|
return ( memcmp(left->_data.data,right->_data.data, left->_data.length) == 0);
|
|
} // end of function isEqualShapedJsonShapedJson
|
|
|
|
|
|
|
|
|