mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
a62abac85d
|
@ -3741,7 +3741,9 @@ static int FillIndex (TRI_document_collection_t* document,
|
|||
void** end;
|
||||
void** ptr;
|
||||
int res;
|
||||
// double starttime;
|
||||
//double starttime;
|
||||
//extern uint64_t ALL_HASH_ADDS;
|
||||
//extern uint64_t ALL_HASH_COLLS;
|
||||
|
||||
primary = &document->base;
|
||||
|
||||
|
@ -3755,9 +3757,7 @@ static int FillIndex (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
|
||||
// starttime = TRI_microtime();
|
||||
//printf("FillIndex _iid=%llu start time: %f\n",(unsigned long long) idx->_iid,
|
||||
// starttime);
|
||||
//starttime = TRI_microtime();
|
||||
inserted = 0;
|
||||
|
||||
for (; ptr < end; ++ptr) {
|
||||
|
@ -3787,6 +3787,8 @@ static int FillIndex (TRI_document_collection_t* document,
|
|||
//printf("FillIndex _iid=%llu time spent: %f\n",(unsigned long long) idx->_iid,
|
||||
// TRI_microtime()-starttime);
|
||||
|
||||
//printf("FillIndex adds=%llu colls=%llu\n",(unsigned long long) ALL_HASH_ADDS, (unsigned long long) ALL_HASH_COLLS);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,16 +42,12 @@
|
|||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief find the edges index of a document collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_multi_pointer_t* FindEdgesIndex (TRI_document_collection_t* const document) {
|
||||
static TRI_edge_index_t* FindEdgesIndex (
|
||||
TRI_document_collection_t* const document) {
|
||||
size_t i, n;
|
||||
|
||||
if (document->base.base._info._type != TRI_COL_TYPE_EDGE) {
|
||||
|
@ -61,11 +57,11 @@ static TRI_multi_pointer_t* FindEdgesIndex (TRI_document_collection_t* const doc
|
|||
|
||||
n = document->_allIndexes._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx = (TRI_index_t*) TRI_AtVectorPointer(&document->_allIndexes, i);
|
||||
TRI_index_t* idx
|
||||
= (TRI_index_t*) TRI_AtVectorPointer(&document->_allIndexes, i);
|
||||
if (idx->_type == TRI_IDX_TYPE_EDGE_INDEX) {
|
||||
TRI_edge_index_t* edgesIndex = (TRI_edge_index_t*) idx;
|
||||
|
||||
return &edgesIndex->_edges;
|
||||
return edgesIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,11 +70,21 @@ static TRI_multi_pointer_t* FindEdgesIndex (TRI_document_collection_t* const doc
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether an edge is self-reflexive
|
||||
/// @brief check whether the _from and _to end of an edge are identical
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsReflexive (const TRI_edge_header_t* const edge) {
|
||||
return ((edge->_flags & TRI_EDGE_BIT_REFLEXIVE) > 0);
|
||||
static bool IsReflexive (TRI_doc_mptr_t const* mptr) {
|
||||
TRI_doc_edge_key_marker_t const* edge;
|
||||
char* fromKey;
|
||||
char* toKey;
|
||||
|
||||
edge = mptr->_data;
|
||||
if (edge->_toCid == edge->_fromCid) {
|
||||
fromKey = (char*) edge + edge->_offsetFromKey;
|
||||
toKey = (char*) edge + edge->_offsetToKey;
|
||||
return strcmp(fromKey, toKey) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -90,17 +96,28 @@ static bool IsReflexive (const TRI_edge_header_t* const edge) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool FindEdges (const TRI_edge_direction_e direction,
|
||||
TRI_multi_pointer_t* idx,
|
||||
TRI_edge_index_t* idx,
|
||||
TRI_vector_pointer_t* result,
|
||||
TRI_edge_header_t* entry,
|
||||
const int matchType) {
|
||||
TRI_vector_pointer_t found;
|
||||
TRI_doc_mptr_t* edge;
|
||||
|
||||
entry->_flags = TRI_LookupFlagsEdge(direction);
|
||||
found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE, idx, entry);
|
||||
if (direction == TRI_EDGE_OUT) {
|
||||
found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE,
|
||||
&idx->_edges_from,
|
||||
entry);
|
||||
}
|
||||
else if (direction == TRI_EDGE_IN) {
|
||||
found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE,
|
||||
&idx->_edges_to,
|
||||
entry);
|
||||
}
|
||||
else {
|
||||
assert(false); // TRI_EDGE_ANY not supported here
|
||||
}
|
||||
|
||||
if (found._length > 0) {
|
||||
TRI_edge_header_t* edge;
|
||||
size_t i;
|
||||
|
||||
if (result->_capacity == 0) {
|
||||
|
@ -119,99 +136,57 @@ static bool FindEdges (const TRI_edge_direction_e direction,
|
|||
|
||||
// add all results found
|
||||
for (i = 0; i < found._length; ++i) {
|
||||
edge = (TRI_edge_header_t*) found._buffer[i];
|
||||
edge = (TRI_doc_mptr_t*) found._buffer[i];
|
||||
|
||||
// the following queries will use the following sequences of matchTypes:
|
||||
// inEdges(): 1, 2, outEdges(): 1, 2, edges(): 1, 3
|
||||
// inEdges(): 1, outEdges(): 1, edges(): 1, 3
|
||||
|
||||
// if matchType is 1, we'll return all found edges without further filtering
|
||||
//
|
||||
// if matchType is 2 (inEdges or outEdges query), the direction is reversed.
|
||||
// We'll exclude all self-reflexive edges now (we already got them in iteration 1),
|
||||
// if matchType is 1, we'll return all found edges without filtering
|
||||
// We'll exclude all loop edges now (we already got them in iteration 1),
|
||||
// and alsoexclude all unidirectional edges
|
||||
//
|
||||
// if matchType is 3, the direction is also reversed. We'll exclude all
|
||||
// self-reflexive edges now (we already got them in iteration 1)
|
||||
// loop edges now (we already got them in iteration 1)
|
||||
|
||||
if (matchType > 1) {
|
||||
// if the edge is self-reflexive, we have already found it in iteration 1
|
||||
|
||||
// if the edge is a loop, we have already found it in iteration 1
|
||||
// we must skip it here, otherwise we would produce duplicates
|
||||
if (IsReflexive(edge)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_PushBackVectorPointer(result, CONST_CAST(edge));
|
||||
|
||||
TRI_PushBackVectorPointer(result, CONST_CAST(edge->_mptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TRI_DestroyVectorPointer(&found);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compose edge flags aggregate out of only the direction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_edge_flags_t TRI_LookupFlagsEdge (const TRI_edge_direction_e direction) {
|
||||
if (direction == TRI_EDGE_IN) {
|
||||
return TRI_EDGE_BIT_DIRECTION_IN;
|
||||
}
|
||||
if (direction == TRI_EDGE_OUT) {
|
||||
return TRI_EDGE_BIT_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
// invalid direction type
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compose edge flags aggregate out of multiple individual parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_edge_flags_t TRI_FlagsEdge (const TRI_edge_direction_e direction,
|
||||
const bool isReflexive) {
|
||||
TRI_edge_flags_t result = TRI_LookupFlagsEdge(direction);
|
||||
|
||||
if (isReflexive) {
|
||||
result |= TRI_EDGE_BIT_REFLEXIVE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up edges
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (TRI_document_collection_t* document,
|
||||
TRI_edge_direction_e direction,
|
||||
TRI_voc_cid_t cid,
|
||||
TRI_voc_key_t key) {
|
||||
TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (
|
||||
TRI_document_collection_t* document,
|
||||
TRI_edge_direction_e direction,
|
||||
TRI_voc_cid_t cid,
|
||||
TRI_voc_key_t key) {
|
||||
TRI_vector_pointer_t result;
|
||||
TRI_edge_header_t entry;
|
||||
TRI_multi_pointer_t* edgesIndex;
|
||||
TRI_edge_index_t* edgesIndex;
|
||||
|
||||
// search criteria
|
||||
entry._mptr = NULL;
|
||||
entry._cid = cid;
|
||||
entry._searchKey._key = key;
|
||||
entry._key = key;
|
||||
|
||||
// initialise the result vector
|
||||
TRI_InitVectorPointer(&result, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
@ -240,10 +215,6 @@ TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (TRI_document_collection_
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
|
|
|
@ -126,10 +126,8 @@ TRI_edge_direction_e;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_edge_header_s {
|
||||
TRI_doc_mptr_t const* _mptr;
|
||||
TRI_voc_cid_t _cid; // from or to, depending on the direction
|
||||
union { TRI_voc_key_t _key; TRI_voc_size_t _offsetKey; } _searchKey;
|
||||
TRI_edge_flags_t _flags;
|
||||
TRI_voc_key_t _key;
|
||||
}
|
||||
TRI_edge_header_t;
|
||||
|
||||
|
@ -145,36 +143,15 @@ TRI_edge_header_t;
|
|||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compose edge flags aggregate out of only the direction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_edge_flags_t TRI_LookupFlagsEdge (const TRI_edge_direction_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compose edge flags aggregate out of multiple individual parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_edge_flags_t TRI_FlagsEdge (const TRI_edge_direction_e,
|
||||
const bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up edges
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (TRI_document_collection_t*,
|
||||
TRI_edge_direction_e,
|
||||
TRI_voc_cid_t,
|
||||
TRI_voc_key_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TRI_vector_pointer_t TRI_LookupEdgesDocumentCollection (
|
||||
TRI_document_collection_t*,
|
||||
TRI_edge_direction_e,
|
||||
TRI_voc_cid_t,
|
||||
TRI_voc_key_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "BasicsC/string-buffer.h"
|
||||
#include "BasicsC/tri-strings.h"
|
||||
#include "BasicsC/utf8-helper.h"
|
||||
#include "BasicsC/fasthash.h"
|
||||
#include "BasicsC/xxhash.h"
|
||||
#include "CapConstraint/cap-constraint.h"
|
||||
#include "GeoIndex/geo-index.h"
|
||||
#include "FulltextIndex/fulltext-index.h"
|
||||
|
@ -688,100 +690,188 @@ void TRI_FreePrimaryIndex (TRI_index_t* idx) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an edge header
|
||||
/// @brief hashes an edge key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashElementEdge (TRI_multi_pointer_t* array, void const* data) {
|
||||
static uint64_t HashElementKey (TRI_multi_pointer_t* array, void const* data) {
|
||||
TRI_edge_header_t const* h;
|
||||
uint64_t hash[3];
|
||||
uint64_t hash;
|
||||
char* key;
|
||||
|
||||
h = data;
|
||||
|
||||
if (h->_mptr != NULL) {
|
||||
key = ((char*) h->_mptr->_data) + h->_searchKey._offsetKey;
|
||||
}
|
||||
else {
|
||||
key = h->_searchKey._key;
|
||||
}
|
||||
key = h->_key;
|
||||
|
||||
// only include directional bits for hashing, exclude special bits
|
||||
hash[0] = (uint64_t) (h->_flags & TRI_EDGE_BITS_DIRECTION);
|
||||
hash[1] = h->_cid;
|
||||
hash[2] = TRI_FnvHashString(key);
|
||||
hash = h->_cid;
|
||||
hash ^= (uint64_t) fasthash64(key, strlen(key), 0x87654321);
|
||||
|
||||
return TRI_FnvHashPointer(hash, sizeof(hash));
|
||||
return fasthash64(&hash, sizeof(hash), 0x56781234);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if key and element match
|
||||
/// @brief hashes an edge (_from case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualKeyEdge (TRI_multi_pointer_t* array,
|
||||
void const* left,
|
||||
void const* right) {
|
||||
TRI_edge_header_t const* l;
|
||||
TRI_edge_header_t const* r;
|
||||
const char* lKey;
|
||||
const char* rKey;
|
||||
static uint64_t HashElementEdgeFrom (TRI_multi_pointer_t* array,
|
||||
void const* data,
|
||||
bool byKey) {
|
||||
TRI_doc_mptr_t const* mptr;
|
||||
TRI_doc_edge_key_marker_t const* edge;
|
||||
char const* key;
|
||||
|
||||
l = left;
|
||||
r = right;
|
||||
uint64_t hash;
|
||||
|
||||
if (l->_mptr != NULL) {
|
||||
lKey = ((char*) ((TRI_doc_edge_key_marker_t const*) l->_mptr->_data)) + l->_searchKey._offsetKey;
|
||||
if (!byKey) {
|
||||
hash = (uint64_t) data;
|
||||
}
|
||||
else {
|
||||
lKey = l->_searchKey._key;
|
||||
mptr = data;
|
||||
edge = mptr->_data;
|
||||
key = (char*) edge + edge->_offsetFromKey;
|
||||
|
||||
hash = edge->_fromCid;
|
||||
hash ^= (uint64_t) fasthash64(key, strlen(key), 0x87654321);
|
||||
}
|
||||
|
||||
if (r->_mptr != NULL) {
|
||||
rKey = ((char*) ((TRI_doc_edge_key_marker_t const*) r->_mptr->_data)) + r->_searchKey._offsetKey;
|
||||
}
|
||||
else {
|
||||
rKey = r->_searchKey._key;
|
||||
}
|
||||
|
||||
// only include directional flags, exclude special bits
|
||||
return ((l->_flags & TRI_EDGE_BITS_DIRECTION) == (r->_flags & TRI_EDGE_BITS_DIRECTION)) &&
|
||||
(l->_cid == r->_cid) &&
|
||||
(strcmp(lKey, rKey) == 0);
|
||||
return fasthash64(&hash, sizeof(hash), 0x56781234);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks for elements are equal
|
||||
/// @brief hashes an edge (_to case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualElementEdge (TRI_multi_pointer_t* array,
|
||||
static uint64_t HashElementEdgeTo (TRI_multi_pointer_t* array,
|
||||
void const* data,
|
||||
bool byKey) {
|
||||
TRI_doc_mptr_t const* mptr;
|
||||
TRI_doc_edge_key_marker_t const* edge;
|
||||
char const* key;
|
||||
|
||||
uint64_t hash;
|
||||
|
||||
if (!byKey) {
|
||||
hash = (uint64_t) data;
|
||||
}
|
||||
else {
|
||||
mptr = data;
|
||||
edge = mptr->_data;
|
||||
key = (char*) edge + edge->_offsetToKey;
|
||||
|
||||
hash = edge->_toCid;
|
||||
hash ^= (uint64_t) fasthash64(key, strlen(key), 0x87654321);
|
||||
}
|
||||
|
||||
return fasthash64(&hash, sizeof(hash), 0x56781234);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if key and element match (_from case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualKeyEdgeFrom (TRI_multi_pointer_t* array,
|
||||
void const* left,
|
||||
void const* right) {
|
||||
// left is a key
|
||||
// right is an element, that is a master pointer
|
||||
TRI_edge_header_t const* l;
|
||||
TRI_edge_header_t const* r;
|
||||
TRI_doc_mptr_t const* rMptr;
|
||||
TRI_doc_edge_key_marker_t const* rEdge;
|
||||
const char* lKey;
|
||||
const char* rKey;
|
||||
|
||||
l = left;
|
||||
r = right;
|
||||
lKey = l->_key;
|
||||
|
||||
if (l->_mptr != NULL) {
|
||||
lKey = ((char*) ((TRI_doc_edge_key_marker_t const*) l->_mptr->_data)) + l->_searchKey._offsetKey;
|
||||
rMptr = right;
|
||||
rEdge = rMptr->_data;
|
||||
rKey = (char*) rEdge + rEdge->_offsetFromKey;
|
||||
|
||||
return (strcmp(lKey, rKey) == 0) && l->_cid == rEdge->_fromCid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if key and element match (_to case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualKeyEdgeTo (TRI_multi_pointer_t* array,
|
||||
void const* left,
|
||||
void const* right) {
|
||||
// left is a key
|
||||
// right is an element, that is a master pointer
|
||||
TRI_edge_header_t const* l;
|
||||
TRI_doc_mptr_t const* rMptr;
|
||||
TRI_doc_edge_key_marker_t const* rEdge;
|
||||
const char* lKey;
|
||||
const char* rKey;
|
||||
|
||||
l = left;
|
||||
lKey = l->_key;
|
||||
|
||||
rMptr = right;
|
||||
rEdge = rMptr->_data;
|
||||
rKey = (char*) rEdge + rEdge->_offsetToKey;
|
||||
|
||||
return (strcmp(lKey, rKey) == 0) && l->_cid == rEdge->_toCid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks for elements are equal (_from case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualElementEdgeFrom (TRI_multi_pointer_t* array,
|
||||
void const* left,
|
||||
void const* right,
|
||||
bool byKey) {
|
||||
TRI_doc_mptr_t const* lMptr;
|
||||
TRI_doc_mptr_t const* rMptr;
|
||||
TRI_doc_edge_key_marker_t const* lEdge;
|
||||
TRI_doc_edge_key_marker_t const* rEdge;
|
||||
char const* lKey;
|
||||
char const* rKey;
|
||||
|
||||
if (!byKey) {
|
||||
return left == right;
|
||||
}
|
||||
else {
|
||||
lKey = l->_searchKey._key;
|
||||
}
|
||||
lMptr = left;
|
||||
rMptr = right;
|
||||
lEdge = lMptr->_data;
|
||||
rEdge = rMptr->_data;
|
||||
lKey = (char*) lEdge + lEdge->_offsetFromKey;
|
||||
rKey = (char*) rEdge + rEdge->_offsetFromKey;
|
||||
|
||||
if (r->_mptr != NULL) {
|
||||
rKey = ((char*) ((TRI_doc_edge_key_marker_t const*) r->_mptr->_data)) + r->_searchKey._offsetKey;
|
||||
return strcmp(lKey, rKey) == 0 && lEdge->_fromCid == rEdge->_fromCid;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks for elements are equal (_to case)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualElementEdgeTo (TRI_multi_pointer_t* array,
|
||||
void const* left,
|
||||
void const* right,
|
||||
bool byKey) {
|
||||
TRI_doc_mptr_t const* lMptr;
|
||||
TRI_doc_mptr_t const* rMptr;
|
||||
TRI_doc_edge_key_marker_t const* lEdge;
|
||||
TRI_doc_edge_key_marker_t const* rEdge;
|
||||
char const* lKey;
|
||||
char const* rKey;
|
||||
|
||||
if (!byKey) {
|
||||
return left == right;
|
||||
}
|
||||
else {
|
||||
rKey = r->_searchKey._key;
|
||||
}
|
||||
lMptr = left;
|
||||
rMptr = right;
|
||||
lEdge = lMptr->_data;
|
||||
rEdge = rMptr->_data;
|
||||
lKey = (char*) lEdge + lEdge->_offsetToKey;
|
||||
rKey = (char*) rEdge + rEdge->_offsetToKey;
|
||||
|
||||
// only include directional flags, exclude special bits
|
||||
return (l->_mptr == r->_mptr) &&
|
||||
((l->_flags & TRI_EDGE_BITS_DIRECTION) == (r->_flags & TRI_EDGE_BITS_DIRECTION)) &&
|
||||
(l->_cid == r->_cid) &&
|
||||
(strcmp(lKey, rKey) == 0);
|
||||
return strcmp(lKey, rKey) == 0 && lEdge->_toCid == rEdge->_toCid;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -791,42 +881,15 @@ static bool IsEqualElementEdge (TRI_multi_pointer_t* array,
|
|||
static int InsertEdge (TRI_index_t* idx,
|
||||
TRI_doc_mptr_t const* mptr,
|
||||
const bool isRollback) {
|
||||
TRI_edge_header_t* entryIn;
|
||||
TRI_edge_header_t* entryOut;
|
||||
char* memory;
|
||||
TRI_doc_edge_key_marker_t const* edge;
|
||||
bool isReflexive;
|
||||
|
||||
TRI_multi_pointer_t* edgesIndex = &(((TRI_edge_index_t*) idx)->_edges);
|
||||
TRI_multi_pointer_t* edgesIndex;
|
||||
|
||||
edge = mptr->_data;
|
||||
|
||||
// is the edge self-reflexive (_from & _to are identical)?
|
||||
isReflexive = (edge->_toCid == edge->_fromCid && strcmp(((char*) edge) + edge->_offsetToKey, ((char*) edge) + edge->_offsetFromKey) == 0);
|
||||
|
||||
// allocate memory for both edge headers and return early if memory allocation fails
|
||||
memory = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, 2 * sizeof(TRI_edge_header_t), false);
|
||||
|
||||
if (memory == NULL) {
|
||||
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
entryIn = (TRI_edge_header_t*) memory;
|
||||
entryOut = (TRI_edge_header_t*) (memory + sizeof(TRI_edge_header_t));
|
||||
|
||||
// first slot: IN
|
||||
entryIn->_mptr = mptr;
|
||||
entryIn->_flags = TRI_FlagsEdge(TRI_EDGE_IN, isReflexive);
|
||||
entryIn->_cid = edge->_toCid;
|
||||
entryIn->_searchKey._offsetKey = edge->_offsetToKey;
|
||||
TRI_InsertElementMultiPointer(edgesIndex, entryIn, true, isRollback);
|
||||
|
||||
// second slot: OUT
|
||||
entryOut->_mptr = mptr;
|
||||
entryOut->_flags = TRI_FlagsEdge(TRI_EDGE_OUT, isReflexive);
|
||||
entryOut->_cid = edge->_fromCid;
|
||||
entryOut->_searchKey._offsetKey = edge->_offsetFromKey;
|
||||
TRI_InsertElementMultiPointer(edgesIndex, entryOut, true, isRollback);
|
||||
// OUT
|
||||
edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_from);
|
||||
TRI_InsertElementMultiPointer(edgesIndex, CONST_CAST(mptr), true, isRollback);
|
||||
// IN
|
||||
edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_to);
|
||||
TRI_InsertElementMultiPointer(edgesIndex, CONST_CAST(mptr), true, isRollback);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -836,34 +899,17 @@ static int InsertEdge (TRI_index_t* idx,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int RemoveEdge (TRI_index_t* idx,
|
||||
TRI_doc_mptr_t const* doc,
|
||||
TRI_doc_mptr_t const* mptr,
|
||||
const bool isRollback) {
|
||||
TRI_edge_header_t entry;
|
||||
TRI_edge_header_t* old;
|
||||
TRI_doc_edge_key_marker_t const* edge;
|
||||
TRI_multi_pointer_t* edgesIndex = &(((TRI_edge_index_t*) idx)->_edges);
|
||||
|
||||
edge = doc->_data;
|
||||
|
||||
entry._mptr = doc;
|
||||
TRI_multi_pointer_t* edgesIndex;
|
||||
|
||||
// OUT
|
||||
entry._flags = TRI_LookupFlagsEdge(TRI_EDGE_OUT);
|
||||
entry._cid = edge->_fromCid;
|
||||
entry._searchKey._offsetKey = edge->_offsetFromKey;
|
||||
TRI_RemoveElementMultiPointer(edgesIndex, &entry);
|
||||
// we do not need to free the OUT element
|
||||
|
||||
edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_from);
|
||||
TRI_RemoveElementMultiPointer(edgesIndex, mptr);
|
||||
// IN
|
||||
entry._flags = TRI_LookupFlagsEdge(TRI_EDGE_IN);
|
||||
entry._cid = edge->_toCid;
|
||||
entry._searchKey._offsetKey = edge->_offsetToKey;
|
||||
old = TRI_RemoveElementMultiPointer(edgesIndex, &entry);
|
||||
|
||||
// the pointer to the IN element is also the memory pointer we need to free
|
||||
if (old != NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, old);
|
||||
}
|
||||
edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_from);
|
||||
TRI_RemoveElementMultiPointer(edgesIndex, mptr);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -897,14 +943,31 @@ static TRI_json_t* JsonEdge (TRI_index_t* idx) {
|
|||
static int SizeHintEdge (TRI_index_t* idx,
|
||||
size_t size) {
|
||||
|
||||
TRI_multi_pointer_t* edgesIndex = &(((TRI_edge_index_t*) idx)->_edges);
|
||||
int err;
|
||||
|
||||
// we assume this is called when setting up the index and the index is still empty
|
||||
TRI_multi_pointer_t* edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_from);
|
||||
|
||||
// we assume this is called when setting up the index and the index
|
||||
// is still empty
|
||||
assert(edgesIndex->_nrUsed == 0);
|
||||
|
||||
// set an initial size for the index and allow for some new nodes to be created
|
||||
// set an initial size for the index for some new nodes to be created
|
||||
// without resizing
|
||||
return TRI_ResizeMultiPointer(edgesIndex, 2 * size + 2049);
|
||||
err = TRI_ResizeMultiPointer(edgesIndex, size + 2049);
|
||||
|
||||
if (err != TRI_ERROR_NO_ERROR) {
|
||||
return err;
|
||||
}
|
||||
|
||||
edgesIndex = &(((TRI_edge_index_t*) idx)->_edges_to);
|
||||
|
||||
// we assume this is called when setting up the index and the index
|
||||
// is still empty
|
||||
assert(edgesIndex->_nrUsed == 0);
|
||||
|
||||
// set an initial size for the index for some new nodes to be created
|
||||
// without resizing
|
||||
return TRI_ResizeMultiPointer(edgesIndex, size + 2049);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -938,19 +1001,31 @@ TRI_index_t* TRI_CreateEdgeIndex (struct TRI_primary_collection_s* primary,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
res = TRI_InitMultiPointer(&edgeIndex->_edges,
|
||||
res = TRI_InitMultiPointer(&edgeIndex->_edges_from,
|
||||
TRI_UNKNOWN_MEM_ZONE,
|
||||
HashElementEdge,
|
||||
HashElementEdge,
|
||||
IsEqualKeyEdge,
|
||||
IsEqualElementEdge);
|
||||
HashElementKey,
|
||||
HashElementEdgeFrom,
|
||||
IsEqualKeyEdgeFrom,
|
||||
IsEqualElementEdgeFrom);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, edgeIndex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
res = TRI_InitMultiPointer(&edgeIndex->_edges_to,
|
||||
TRI_UNKNOWN_MEM_ZONE,
|
||||
HashElementKey,
|
||||
HashElementEdgeTo,
|
||||
IsEqualKeyEdgeTo,
|
||||
IsEqualElementEdgeTo);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyMultiPointer(&edgeIndex->_edges_from);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, edgeIndex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idx = &edgeIndex->base;
|
||||
|
||||
|
@ -975,38 +1050,13 @@ TRI_index_t* TRI_CreateEdgeIndex (struct TRI_primary_collection_s* primary,
|
|||
|
||||
void TRI_DestroyEdgeIndex (TRI_index_t* idx) {
|
||||
TRI_edge_index_t* edgesIndex;
|
||||
size_t i, n;
|
||||
|
||||
edgesIndex = (TRI_edge_index_t*) idx;
|
||||
|
||||
LOG_TRACE("destroying edge index");
|
||||
|
||||
// free all elements in the edges index
|
||||
n = (size_t) edgesIndex->_edges._nrAlloc;
|
||||
|
||||
// deletion from the index is done in two steps as memory was only allocated for IN edges
|
||||
// the OUT edges are at memory position IN + sizeof(edge_header) and
|
||||
// must not be freed themselves
|
||||
|
||||
// step 1: zero out all the out edges (we must not free them directly)
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_edge_header_t* element = edgesIndex->_edges._table[i];
|
||||
|
||||
if (element != NULL && (element->_flags & TRI_EDGE_BIT_DIRECTION_OUT)) {
|
||||
edgesIndex->_edges._table[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// step 2: free the allocated memory
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_edge_header_t* element = edgesIndex->_edges._table[i];
|
||||
|
||||
if (element != NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, element);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_DestroyMultiPointer(&edgesIndex->_edges);
|
||||
TRI_DestroyMultiPointer(&edgesIndex->_edges_to);
|
||||
TRI_DestroyMultiPointer(&edgesIndex->_edges_from);
|
||||
|
||||
TRI_DestroyVectorString(&idx->_fields);
|
||||
}
|
||||
|
|
|
@ -185,7 +185,8 @@ TRI_geo_index_t;
|
|||
typedef struct TRI_edge_index_s {
|
||||
TRI_index_t base;
|
||||
|
||||
TRI_multi_pointer_t _edges;
|
||||
TRI_multi_pointer_t _edges_from;
|
||||
TRI_multi_pointer_t _edges_to;
|
||||
}
|
||||
TRI_edge_index_t;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# remove-on-drop = true
|
||||
|
||||
[server]
|
||||
disable-authentication = false
|
||||
disable-authentication = true
|
||||
endpoint = tcp://localhost:8529
|
||||
threads = 5
|
||||
keyfile = UnitTests/server.pem
|
||||
|
|
|
@ -35,5 +35,5 @@ data-path = ./cluster/data
|
|||
log-path = ./cluster/log
|
||||
agent-path = ./bin/etcd-arango
|
||||
arangod-path = ./bin/arangod
|
||||
dbserver-config = ./etc/relative/arangod.conf
|
||||
coordinator-config = ./etc/relative/arangod.conf
|
||||
dbserver-config = ./etc/relative/arangod-dbserver.conf
|
||||
coordinator-config = ./etc/relative/arangod-coordinator.conf
|
||||
|
|
|
@ -2,494 +2,492 @@
|
|||
/*global window, $, Backbone, document, arangoCollectionModel*/
|
||||
/*global arangoHelper,dashboardView,arangoDatabase*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
window.Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
"" : "dashboard",
|
||||
"dashboard" : "dashboard",
|
||||
"collection/:colid" : "collection",
|
||||
"collections" : "collections",
|
||||
"collectionInfo/:colid" : "collectionInfo",
|
||||
"new" : "newCollection",
|
||||
"login" : "login",
|
||||
"collection/:colid/documents/:pageid" : "documents",
|
||||
"collection/:colid/:docid" : "document",
|
||||
"shell" : "shell",
|
||||
"query" : "query",
|
||||
"logs" : "logs",
|
||||
"api" : "api",
|
||||
"databases" : "databases",
|
||||
"application/installed/:key" : "applicationEdit",
|
||||
"application/available/:key" : "applicationInstall",
|
||||
"applications" : "applications",
|
||||
"application/documentation/:key" : "appDocumentation",
|
||||
"graph" : "graph",
|
||||
"graphManagement" : "graphManagement",
|
||||
"graphManagement/add" : "graphAddNew",
|
||||
"graphManagement/delete/:name" : "graphDelete",
|
||||
"userManagement" : "userManagement",
|
||||
"userProfile" : "userProfile",
|
||||
"testing" : "testview"
|
||||
},
|
||||
window.Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
"": "dashboard",
|
||||
"dashboard": "dashboard",
|
||||
"collection/:colid": "collection",
|
||||
"collections": "collections",
|
||||
"collectionInfo/:colid": "collectionInfo",
|
||||
"new": "newCollection",
|
||||
"login": "login",
|
||||
"collection/:colid/documents/:pageid": "documents",
|
||||
"collection/:colid/:docid": "document",
|
||||
"shell": "shell",
|
||||
"query": "query",
|
||||
"logs": "logs",
|
||||
"api": "api",
|
||||
"databases": "databases",
|
||||
"application/installed/:key": "applicationEdit",
|
||||
"application/available/:key": "applicationInstall",
|
||||
"applications": "applications",
|
||||
"application/documentation/:key": "appDocumentation",
|
||||
"graph": "graph",
|
||||
"graphManagement": "graphManagement",
|
||||
"graphManagement/add": "graphAddNew",
|
||||
"graphManagement/delete/:name": "graphDelete",
|
||||
"userManagement": "userManagement",
|
||||
"userProfile": "userProfile",
|
||||
"testing": "testview"
|
||||
},
|
||||
|
||||
testview: function() {
|
||||
this.testView = new window.testView();
|
||||
this.testView.render();
|
||||
},
|
||||
testview: function () {
|
||||
this.testView = new window.testView();
|
||||
this.testView.render();
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.bind('all', function(trigger, args) {
|
||||
var routeData = trigger.split(":");
|
||||
if (trigger === "route") {
|
||||
if (this.currentRoute === "dashboard" && this.dashboardView) {
|
||||
this.dashboardView.stopUpdating();
|
||||
} else if (args === "dashboard") {
|
||||
delete this.dashboardView;
|
||||
}
|
||||
this.currentRoute = args;
|
||||
}
|
||||
});
|
||||
this.graphs = new window.GraphCollection();
|
||||
this.notificationList = new window.NotificationCollection();
|
||||
|
||||
window.currentDB = new window.CurrentDatabase();
|
||||
window.currentDB.fetch({
|
||||
async: false
|
||||
});
|
||||
|
||||
window.userCollection = new window.ArangoUsers();
|
||||
|
||||
window.arangoDatabase = new window.ArangoDatabase();
|
||||
|
||||
window.arangoCollectionsStore = new window.arangoCollections();
|
||||
window.arangoDocumentsStore = new window.arangoDocuments();
|
||||
window.arangoDocumentStore = new window.arangoDocument();
|
||||
|
||||
window.collectionsView = new window.CollectionsView({
|
||||
collection: window.arangoCollectionsStore
|
||||
});
|
||||
window.arangoCollectionsStore.fetch();
|
||||
window.documentsView = new window.DocumentsView();
|
||||
window.documentView = new window.DocumentView({
|
||||
collection: window.arangoDocumentStore
|
||||
});
|
||||
window.arangoLogsStore = new window.ArangoLogs();
|
||||
window.arangoLogsStore.fetch({
|
||||
success: function () {
|
||||
window.logsView = new window.LogsView({
|
||||
collection: window.arangoLogsStore
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.foxxList = new window.FoxxCollection();
|
||||
|
||||
this.footerView = new window.FooterView();
|
||||
this.naviView = new window.NavigationView({
|
||||
notificationCollection: this.notificationList,
|
||||
userCollection: window.userCollection
|
||||
});
|
||||
this.footerView.render();
|
||||
this.naviView.render();
|
||||
this.graphView = new window.GraphView({
|
||||
graphs: this.graphs,
|
||||
collection: window.arangoCollectionsStore
|
||||
});
|
||||
|
||||
this.initVersionCheck();
|
||||
|
||||
var self = this;
|
||||
$(window).resize(function() {
|
||||
self.handleResize();
|
||||
});
|
||||
//this.handleResize();
|
||||
},
|
||||
|
||||
initVersionCheck: function () {
|
||||
// this checks for version updates
|
||||
|
||||
var self = this;
|
||||
var versionCheck = function () {
|
||||
$.ajax({
|
||||
async: true,
|
||||
crossDomain: true,
|
||||
dataType: "jsonp",
|
||||
url: "https://www.arangodb.org/repositories/versions.php?callback=parseVersions",
|
||||
success: function (json) {
|
||||
if (typeof json !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
// turn our own version string into a version object
|
||||
var currentVersion = window.versionHelper.fromString(self.footerView.system.version);
|
||||
|
||||
// get our mainline version
|
||||
var mainLine = window.versionHelper.toStringMainLine(currentVersion);
|
||||
|
||||
var mainLines = Object.keys(json).sort(window.versionHelper.compareVersionStrings);
|
||||
var latestMainLine;
|
||||
mainLines.forEach(function (l) {
|
||||
if (json[l].stable) {
|
||||
if (window.versionHelper.compareVersionStrings(l, mainLine) > 0) {
|
||||
latestMainLine = json[l];
|
||||
}
|
||||
}
|
||||
initialize: function () {
|
||||
var self = this;
|
||||
this.bind('all', function (trigger, args) {
|
||||
var routeData = trigger.split(":");
|
||||
if (trigger === "route") {
|
||||
if (self.currentRoute === "dashboard" && self.dashboardView) {
|
||||
self.dashboardView.stopUpdating();
|
||||
} else if (args === "dashboard") {
|
||||
delete self.dashboardView;
|
||||
}
|
||||
self.currentRoute = args;
|
||||
}
|
||||
});
|
||||
|
||||
var update;
|
||||
var mainLineVersions;
|
||||
var latest;
|
||||
if (latestMainLine !== undefined &&
|
||||
Object.keys(latestMainLine.versions.length > 0)) {
|
||||
mainLineVersions = Object.keys(latestMainLine.versions);
|
||||
mainLineVersions = mainLineVersions.sort(window.versionHelper.compareVersionStrings);
|
||||
latest = mainLineVersions[mainLineVersions.length - 1];
|
||||
this.graphs = new window.GraphCollection();
|
||||
this.notificationList = new window.NotificationCollection();
|
||||
|
||||
update = {
|
||||
type: "major",
|
||||
version: latest,
|
||||
changes: latestMainLine.versions[latest].changes
|
||||
};
|
||||
window.currentDB = new window.CurrentDatabase();
|
||||
window.currentDB.fetch({
|
||||
async: false
|
||||
});
|
||||
|
||||
window.userCollection = new window.ArangoUsers();
|
||||
|
||||
window.arangoDatabase = new window.ArangoDatabase();
|
||||
|
||||
window.arangoCollectionsStore = new window.arangoCollections();
|
||||
window.arangoDocumentsStore = new window.arangoDocuments();
|
||||
window.arangoDocumentStore = new window.arangoDocument();
|
||||
|
||||
window.collectionsView = new window.CollectionsView({
|
||||
collection: window.arangoCollectionsStore
|
||||
});
|
||||
window.arangoCollectionsStore.fetch();
|
||||
window.documentsView = new window.DocumentsView();
|
||||
window.documentView = new window.DocumentView({
|
||||
collection: window.arangoDocumentStore
|
||||
});
|
||||
window.arangoLogsStore = new window.ArangoLogs();
|
||||
window.arangoLogsStore.fetch({
|
||||
success: function () {
|
||||
window.logsView = new window.LogsView({
|
||||
collection: window.arangoLogsStore
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.foxxList = new window.FoxxCollection();
|
||||
|
||||
this.footerView = new window.FooterView();
|
||||
this.naviView = new window.NavigationView({
|
||||
notificationCollection: this.notificationList,
|
||||
userCollection: window.userCollection
|
||||
});
|
||||
this.footerView.render();
|
||||
this.naviView.render();
|
||||
this.graphView = new window.GraphView({
|
||||
graphs: this.graphs,
|
||||
collection: window.arangoCollectionsStore
|
||||
});
|
||||
|
||||
this.initVersionCheck();
|
||||
|
||||
$(window).resize(function () {
|
||||
self.handleResize();
|
||||
});
|
||||
//this.handleResize();
|
||||
},
|
||||
|
||||
initVersionCheck: function () {
|
||||
// this checks for version updates
|
||||
|
||||
var self = this;
|
||||
var versionCheck = function () {
|
||||
$.ajax({
|
||||
async: true,
|
||||
crossDomain: true,
|
||||
dataType: "jsonp",
|
||||
url: "https://www.arangodb.org/repositories/versions.php" +
|
||||
"?callback=parseVersions",
|
||||
success: function (json) {
|
||||
if (typeof json !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
// turn our own version string into a version object
|
||||
var currentVersion =
|
||||
window.versionHelper.fromString(self.footerView.system.version);
|
||||
|
||||
// get our mainline version
|
||||
var mainLine = window.versionHelper.toStringMainLine(currentVersion);
|
||||
|
||||
var mainLines = Object.keys(json).
|
||||
sort(window.versionHelper.compareVersionStrings);
|
||||
var latestMainLine;
|
||||
mainLines.forEach(function (l) {
|
||||
if (json[l].stable) {
|
||||
if (window.versionHelper.compareVersionStrings(l, mainLine) > 0) {
|
||||
latestMainLine = json[l];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var update;
|
||||
var mainLineVersions;
|
||||
var latest;
|
||||
if (latestMainLine !== undefined &&
|
||||
Object.keys(latestMainLine.versions).length > 0) {
|
||||
mainLineVersions = Object.keys(latestMainLine.versions);
|
||||
mainLineVersions = mainLineVersions.
|
||||
sort(window.versionHelper.compareVersionStrings);
|
||||
latest = mainLineVersions[mainLineVersions.length - 1];
|
||||
|
||||
update = {
|
||||
type: "major",
|
||||
version: latest,
|
||||
changes: latestMainLine.versions[latest].changes
|
||||
};
|
||||
}
|
||||
|
||||
// check which stable mainline versions are available remotely
|
||||
if (update === undefined &&
|
||||
json.hasOwnProperty(mainLine) &&
|
||||
json[mainLine].stable &&
|
||||
json[mainLine].hasOwnProperty("versions") &&
|
||||
Object.keys(json[mainLine].versions).length > 0) {
|
||||
// sort by version numbers
|
||||
mainLineVersions = Object.keys(json[mainLine].versions);
|
||||
mainLineVersions = mainLineVersions.
|
||||
sort(window.versionHelper.compareVersionStrings);
|
||||
latest = mainLineVersions[mainLineVersions.length - 1];
|
||||
|
||||
var result = window.versionHelper.compareVersions(
|
||||
currentVersion,
|
||||
window.versionHelper.fromString(latest)
|
||||
);
|
||||
if (result < 0) {
|
||||
update = {
|
||||
type: "minor",
|
||||
version: latest,
|
||||
changes: json[mainLine].versions[latest].changes
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (update !== undefined) {
|
||||
var msg = "A newer version of ArangoDB (" + update.version +
|
||||
") has become available. You may want to check the " +
|
||||
"changelog at <a href=\"" + update.changes + "\">" +
|
||||
update.changes + "</a>";
|
||||
arangoHelper.arangoNotification(msg, 15000);
|
||||
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
// re-schedule the version check
|
||||
window.setTimeout(versionCheck, 60000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.setTimeout(versionCheck, 5000);
|
||||
},
|
||||
|
||||
logsAllowed: function () {
|
||||
return (window.currentDB.get('name') === '_system');
|
||||
},
|
||||
|
||||
checkUser: function () {
|
||||
if (window.userCollection.models.length === 0) {
|
||||
this.navigate("login", {trigger: true});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
login: function () {
|
||||
if (!this.loginView) {
|
||||
this.loginView = new window.loginView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.loginView.render();
|
||||
this.naviView.selectMenuItem('');
|
||||
},
|
||||
|
||||
collections: function () {
|
||||
var naviView = this.naviView;
|
||||
window.arangoCollectionsStore.fetch({
|
||||
success: function () {
|
||||
window.collectionsView.render();
|
||||
naviView.selectMenuItem('collections-menu');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
collection: function (colid) {
|
||||
if (!this.collectionView) {
|
||||
this.collectionView = new window.CollectionView();
|
||||
}
|
||||
this.collectionView.setColId(colid);
|
||||
this.collectionView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
collectionInfo: function (colid) {
|
||||
if (!this.collectionInfoView) {
|
||||
this.collectionInfoView = new window.CollectionInfoView();
|
||||
}
|
||||
this.collectionInfoView.setColId(colid);
|
||||
this.collectionInfoView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
newCollection: function () {
|
||||
if (!this.newCollectionView) {
|
||||
this.newCollectionView = new window.newCollectionView({});
|
||||
}
|
||||
this.newCollectionView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
|
||||
documents: function (colid, pageid) {
|
||||
if (!window.documentsView) {
|
||||
window.documentsView.initTable(colid, pageid);
|
||||
}
|
||||
window.documentsView.collectionID = colid;
|
||||
var type = arangoHelper.collectionApiType(colid);
|
||||
window.documentsView.colid = colid;
|
||||
window.documentsView.pageid = pageid;
|
||||
window.documentsView.type = type;
|
||||
window.documentsView.render();
|
||||
window.arangoDocumentsStore.getDocuments(colid, pageid);
|
||||
},
|
||||
|
||||
document: function (colid, docid) {
|
||||
window.documentView.colid = colid;
|
||||
window.documentView.docid = docid;
|
||||
window.documentView.render();
|
||||
var type = arangoHelper.collectionApiType(colid);
|
||||
window.documentView.type = type;
|
||||
window.documentView.typeCheck(type);
|
||||
},
|
||||
|
||||
shell: function () {
|
||||
if (!this.shellView) {
|
||||
this.shellView = new window.shellView();
|
||||
}
|
||||
this.shellView.render();
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
query: function () {
|
||||
if (!this.queryView) {
|
||||
this.queryView = new window.queryView();
|
||||
}
|
||||
this.queryView.render();
|
||||
this.naviView.selectMenuItem('query-menu');
|
||||
},
|
||||
|
||||
api: function () {
|
||||
if (!this.apiView) {
|
||||
this.apiView = new window.apiView();
|
||||
}
|
||||
this.apiView.render();
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
databases: function () {
|
||||
if (arangoHelper.databaseAllowed() === true) {
|
||||
if (!this.databaseView) {
|
||||
this.databaseView = new window.databaseView({
|
||||
collection: arangoDatabase
|
||||
});
|
||||
}
|
||||
this.databaseView.render();
|
||||
this.naviView.selectMenuItem('databases-menu');
|
||||
}
|
||||
else {
|
||||
this.navigate("#", {trigger: true});
|
||||
this.naviView.selectMenuItem('dashboard-menu');
|
||||
$('#databaseNavi').css('display', 'none');
|
||||
$('#databaseNaviSelect').css('display', 'none');
|
||||
}
|
||||
},
|
||||
|
||||
logs: function () {
|
||||
if (!this.logsAllowed()) {
|
||||
this.navigate('', { trigger: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// check which stable mainline versions are available remotely
|
||||
if (update === undefined &&
|
||||
json.hasOwnProperty(mainLine) &&
|
||||
json[mainLine].stable &&
|
||||
json[mainLine].hasOwnProperty("versions") &&
|
||||
Object.keys(json[mainLine].versions).length > 0) {
|
||||
// sort by version numbers
|
||||
mainLineVersions = Object.keys(json[mainLine].versions);
|
||||
mainLineVersions = mainLineVersions.sort(window.versionHelper.compareVersionStrings);
|
||||
latest = mainLineVersions[mainLineVersions.length - 1];
|
||||
window.arangoLogsStore.fetch({
|
||||
success: function () {
|
||||
window.logsView.render();
|
||||
$('#logNav a[href="#all"]').tab('show');
|
||||
window.logsView.initLogTables();
|
||||
window.logsView.drawTable();
|
||||
$('#all-switch').click();
|
||||
}
|
||||
});
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
var result = window.versionHelper.compareVersions(
|
||||
currentVersion,
|
||||
window.versionHelper.fromString(latest)
|
||||
);
|
||||
if (result < 0) {
|
||||
update = {
|
||||
type: "minor",
|
||||
version: latest,
|
||||
changes: json[mainLine].versions[latest].changes
|
||||
};
|
||||
}
|
||||
dashboard: function () {
|
||||
this.naviView.selectMenuItem('dashboard-menu');
|
||||
if (this.statisticsDescriptionCollection === undefined) {
|
||||
this.statisticsDescriptionCollection = new window.StatisticsDescriptionCollection();
|
||||
this.statisticsDescriptionCollection.fetch({
|
||||
async: false
|
||||
});
|
||||
}
|
||||
|
||||
if (update !== undefined) {
|
||||
var msg = "A newer version of ArangoDB (" + update.version +
|
||||
") has become available. You may want to check the " +
|
||||
"changelog at <a href=\"" + update.changes + "\">" +
|
||||
update.changes + "</a>";
|
||||
// arangoHelper.arangoNotification(msg, 15000);
|
||||
if (this.statistics === undefined) {
|
||||
this.statisticsCollection = new window.StatisticsCollection();
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
// re-schedule the version check
|
||||
window.setTimeout(versionCheck, 60000);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (this.dashboardView === undefined) {
|
||||
this.dashboardView = new dashboardView({
|
||||
collection: this.statisticsCollection,
|
||||
description: this.statisticsDescriptionCollection,
|
||||
documentStore: window.arangoDocumentsStore,
|
||||
dygraphConfig: window.dygraphConfig
|
||||
});
|
||||
}
|
||||
this.dashboardView.render();
|
||||
},
|
||||
|
||||
window.setTimeout(versionCheck, 5000);
|
||||
},
|
||||
graph: function () {
|
||||
var self = this;
|
||||
window.arangoCollectionsStore.fetch({
|
||||
success: function () {
|
||||
self.graphView.render();
|
||||
self.naviView.selectMenuItem('graphviewer-menu');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
logsAllowed: function () {
|
||||
return (window.currentDB.get('name') === '_system');
|
||||
},
|
||||
graphManagement: function () {
|
||||
if (!this.graphManagementView) {
|
||||
this.graphManagementView =
|
||||
new window.GraphManagementView({collection: this.graphs});
|
||||
}
|
||||
this.graphManagementView.render();
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
checkUser: function () {
|
||||
if (window.userCollection.models.length === 0) {
|
||||
this.navigate("login", {trigger: true});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
graphAddNew: function () {
|
||||
if (!this.addNewGraphView) {
|
||||
this.addNewGraphView = new window.AddNewGraphView({
|
||||
collection: window.arangoCollectionsStore,
|
||||
graphs: this.graphs
|
||||
});
|
||||
}
|
||||
this.addNewGraphView.render();
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
login: function () {
|
||||
if (!this.loginView) {
|
||||
this.loginView = new window.loginView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.loginView.render();
|
||||
this.naviView.selectMenuItem('');
|
||||
},
|
||||
graphDelete: function (name) {
|
||||
if (!this.deleteGraphView) {
|
||||
this.deleteGraphView = new window.DeleteGraphView({
|
||||
collection: this.graphs
|
||||
});
|
||||
}
|
||||
this.deleteGraphView.render(name);
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
collections: function() {
|
||||
var naviView = this.naviView;
|
||||
window.arangoCollectionsStore.fetch({
|
||||
success: function () {
|
||||
window.collectionsView.render();
|
||||
naviView.selectMenuItem('collections-menu');
|
||||
applications: function () {
|
||||
if (this.applicationsView === undefined) {
|
||||
this.applicationsView = new window.ApplicationsView({
|
||||
collection: this.foxxList
|
||||
});
|
||||
}
|
||||
this.applicationsView.reload();
|
||||
this.naviView.selectMenuItem('applications-menu');
|
||||
},
|
||||
|
||||
applicationEdit: function (appkey) {
|
||||
this.foxxList.fetch({
|
||||
async: false
|
||||
});
|
||||
var editAppView = new window.foxxEditView(
|
||||
{model: this.foxxList.findWhere({_key: appkey})}
|
||||
);
|
||||
editAppView.render();
|
||||
},
|
||||
|
||||
applicationInstall: function (appkey) {
|
||||
this.foxxList.fetch({
|
||||
async: false
|
||||
});
|
||||
if (!this.installAppView) {
|
||||
this.installAppView = new window.foxxMountView({
|
||||
collection: this.foxxList
|
||||
});
|
||||
}
|
||||
this.installAppView.render(appkey);
|
||||
},
|
||||
|
||||
appDocumentation: function (key) {
|
||||
var docuView = new window.AppDocumentationView({key: key});
|
||||
docuView.render();
|
||||
this.naviView.selectMenuItem('applications-menu');
|
||||
},
|
||||
|
||||
handleSelectDatabase: function () {
|
||||
this.naviView.handleSelectDatabase();
|
||||
},
|
||||
|
||||
handleResize: function () {
|
||||
if (this.dashboardView) {
|
||||
this.dashboardView.resize();
|
||||
}
|
||||
var oldWidth = $('#content').width();
|
||||
var containerWidth = $(window).width() - 70;
|
||||
/*var spanWidth = 242;*/
|
||||
var spanWidth = 243;
|
||||
var divider = containerWidth / spanWidth;
|
||||
var roundDiv = parseInt(divider, 10);
|
||||
var newWidth = roundDiv * spanWidth - 2;
|
||||
var marginWidth = ((containerWidth + 30) - newWidth) / 2;
|
||||
/*
|
||||
$('#content').width(newWidth)
|
||||
.css('margin-left', marginWidth)
|
||||
.css('margin-right', marginWidth);
|
||||
*/
|
||||
// $('.footer-right p').css('margin-right', marginWidth + 20);
|
||||
// $('.footer-left p').css('margin-left', marginWidth + 20);
|
||||
if (newWidth !== oldWidth) {
|
||||
this.graphView.handleResize(newWidth);
|
||||
}
|
||||
},
|
||||
|
||||
userManagement: function () {
|
||||
if (!this.userManagementView) {
|
||||
this.userManagementView = new window.userManagementView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.userManagementView.render();
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
userProfile: function () {
|
||||
if (!this.userProfileView) {
|
||||
this.userProfileView = new window.userProfileView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.userProfileView.render();
|
||||
this.naviView.selectMenuItem('user-menu');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
collection: function(colid) {
|
||||
if (!this.collectionView) {
|
||||
this.collectionView = new window.CollectionView();
|
||||
}
|
||||
this.collectionView.setColId(colid);
|
||||
this.collectionView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
collectionInfo: function(colid) {
|
||||
if (!this.collectionInfoView) {
|
||||
this.collectionInfoView = new window.CollectionInfoView();
|
||||
}
|
||||
this.collectionInfoView.setColId(colid);
|
||||
this.collectionInfoView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
newCollection: function() {
|
||||
if (!this.newCollectionView) {
|
||||
this.newCollectionView = new window.newCollectionView({});
|
||||
}
|
||||
this.newCollectionView.render();
|
||||
this.naviView.selectMenuItem('collections-menu');
|
||||
},
|
||||
|
||||
documents: function(colid, pageid) {
|
||||
if (!window.documentsView) {
|
||||
window.documentsView.initTable(colid, pageid);
|
||||
}
|
||||
window.documentsView.collectionID = colid;
|
||||
var type = arangoHelper.collectionApiType(colid);
|
||||
window.documentsView.colid = colid;
|
||||
window.documentsView.pageid = pageid;
|
||||
window.documentsView.type = type;
|
||||
window.documentsView.render();
|
||||
window.arangoDocumentsStore.getDocuments(colid, pageid);
|
||||
},
|
||||
|
||||
document: function(colid, docid) {
|
||||
window.documentView.colid = colid;
|
||||
window.documentView.docid = docid;
|
||||
window.documentView.render();
|
||||
var type = arangoHelper.collectionApiType(colid);
|
||||
window.documentView.type = type;
|
||||
window.documentView.typeCheck(type);
|
||||
},
|
||||
|
||||
shell: function() {
|
||||
if (!this.shellView) {
|
||||
this.shellView = new window.shellView();
|
||||
}
|
||||
this.shellView.render();
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
query: function() {
|
||||
if (!this.queryView) {
|
||||
this.queryView = new window.queryView();
|
||||
}
|
||||
this.queryView.render();
|
||||
this.naviView.selectMenuItem('query-menu');
|
||||
},
|
||||
|
||||
api: function() {
|
||||
if (!this.apiView) {
|
||||
this.apiView = new window.apiView();
|
||||
}
|
||||
this.apiView.render();
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
databases: function() {
|
||||
if (arangoHelper.databaseAllowed() === true) {
|
||||
if (!this.databaseView) {
|
||||
this.databaseView = new window.databaseView({
|
||||
collection: arangoDatabase
|
||||
});
|
||||
}
|
||||
this.databaseView.render();
|
||||
this.naviView.selectMenuItem('databases-menu');
|
||||
}
|
||||
else {
|
||||
this.navigate("#", {trigger: true});
|
||||
this.naviView.selectMenuItem('dashboard-menu');
|
||||
$('#databaseNavi').css('display','none');
|
||||
$('#databaseNaviSelect').css('display','none');
|
||||
}
|
||||
},
|
||||
|
||||
logs: function() {
|
||||
if (! this.logsAllowed()) {
|
||||
this.navigate('', { trigger: true });
|
||||
return;
|
||||
}
|
||||
|
||||
window.arangoLogsStore.fetch({
|
||||
success: function () {
|
||||
window.logsView.render();
|
||||
$('#logNav a[href="#all"]').tab('show');
|
||||
window.logsView.initLogTables();
|
||||
window.logsView.drawTable();
|
||||
$('#all-switch').click();
|
||||
}
|
||||
});
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
dashboard: function() {
|
||||
this.naviView.selectMenuItem('dashboard-menu');
|
||||
if (this.statisticsDescriptionCollection === undefined) {
|
||||
this.statisticsDescriptionCollection = new window.StatisticsDescriptionCollection();
|
||||
this.statisticsDescriptionCollection.fetch({
|
||||
async:false
|
||||
});
|
||||
}
|
||||
if (this.statistics === undefined) {
|
||||
this.statisticsCollection = new window.StatisticsCollection();
|
||||
}
|
||||
if (this.dashboardView === undefined) {
|
||||
this.dashboardView = new dashboardView({
|
||||
collection: this.statisticsCollection,
|
||||
description: this.statisticsDescriptionCollection,
|
||||
documentStore: window.arangoDocumentsStore,
|
||||
dygraphConfig : window.dygraphConfig
|
||||
});
|
||||
}
|
||||
this.dashboardView.render();
|
||||
},
|
||||
|
||||
graph: function() {
|
||||
var self = this;
|
||||
window.arangoCollectionsStore.fetch({
|
||||
success: function () {
|
||||
self.graphView.render();
|
||||
self.naviView.selectMenuItem('graphviewer-menu');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
graphManagement: function() {
|
||||
if (!this.graphManagementView) {
|
||||
this.graphManagementView = new window.GraphManagementView({collection: this.graphs});
|
||||
}
|
||||
this.graphManagementView.render();
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
graphAddNew: function() {
|
||||
if (!this.addNewGraphView) {
|
||||
this.addNewGraphView = new window.AddNewGraphView({
|
||||
collection: window.arangoCollectionsStore,
|
||||
graphs: this.graphs
|
||||
});
|
||||
}
|
||||
this.addNewGraphView.render();
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
graphDelete: function(name) {
|
||||
if (!this.deleteGraphView) {
|
||||
this.deleteGraphView = new window.DeleteGraphView({
|
||||
collection: this.graphs
|
||||
});
|
||||
}
|
||||
this.deleteGraphView.render(name);
|
||||
this.naviView.selectMenuItem('graphviewer-menu');
|
||||
},
|
||||
|
||||
applications: function() {
|
||||
if (this.applicationsView === undefined) {
|
||||
this.applicationsView = new window.ApplicationsView({
|
||||
collection: this.foxxList
|
||||
});
|
||||
}
|
||||
this.applicationsView.reload();
|
||||
this.naviView.selectMenuItem('applications-menu');
|
||||
},
|
||||
|
||||
applicationEdit: function(appkey) {
|
||||
this.foxxList.fetch({
|
||||
async: false
|
||||
});
|
||||
var editAppView = new window.foxxEditView({model: this.foxxList.findWhere({_key: appkey})});
|
||||
editAppView.render();
|
||||
},
|
||||
|
||||
applicationInstall: function(appkey) {
|
||||
this.foxxList.fetch({
|
||||
async: false
|
||||
});
|
||||
if (!this.installAppView) {
|
||||
this.installAppView = new window.foxxMountView({
|
||||
collection: this.foxxList
|
||||
});
|
||||
}
|
||||
this.installAppView.render(appkey);
|
||||
},
|
||||
|
||||
appDocumentation: function(key) {
|
||||
var docuView = new window.AppDocumentationView({key: key});
|
||||
docuView.render();
|
||||
this.naviView.selectMenuItem('applications-menu');
|
||||
},
|
||||
|
||||
handleSelectDatabase: function () {
|
||||
this.naviView.handleSelectDatabase();
|
||||
},
|
||||
|
||||
handleResize: function () {
|
||||
if (this.dashboardView) {
|
||||
this.dashboardView.resize();
|
||||
}
|
||||
var oldWidth = $('#content').width();
|
||||
var containerWidth = $(window).width() - 70;
|
||||
/*var spanWidth = 242;*/
|
||||
var spanWidth = 243;
|
||||
var divider = containerWidth / spanWidth;
|
||||
var roundDiv = parseInt(divider, 10);
|
||||
var newWidth = roundDiv*spanWidth -2;
|
||||
var marginWidth = ((containerWidth+30) - newWidth)/2;
|
||||
/*
|
||||
$('#content').width(newWidth)
|
||||
.css('margin-left', marginWidth)
|
||||
.css('margin-right', marginWidth);
|
||||
*/
|
||||
// $('.footer-right p').css('margin-right', marginWidth + 20);
|
||||
// $('.footer-left p').css('margin-left', marginWidth + 20);
|
||||
if (newWidth !== oldWidth) {
|
||||
this.graphView.handleResize(newWidth);
|
||||
}
|
||||
},
|
||||
|
||||
userManagement: function() {
|
||||
if (!this.userManagementView) {
|
||||
this.userManagementView = new window.userManagementView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.userManagementView.render(false);
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
},
|
||||
|
||||
userProfile: function() {
|
||||
if (!this.userManagementView) {
|
||||
this.userManagementView = new window.userManagementView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.userManagementView.render(true);
|
||||
this.naviView.selectMenuItem('tools-menu');
|
||||
}
|
||||
/*
|
||||
userProfile: function() {
|
||||
if (!this.userProfileView) {
|
||||
this.userProfileView = new window.userProfileView({
|
||||
collection: window.userCollection
|
||||
});
|
||||
}
|
||||
this.userProfileView.render();
|
||||
this.naviView.selectMenuItem('user-menu');
|
||||
}
|
||||
*/
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
}());
|
||||
|
|
|
@ -143,7 +143,9 @@
|
|||
"frontend/js/views/foxxActiveView.js",
|
||||
"frontend/js/views/foxxInstalledView.js",
|
||||
"frontend/js/views/foxxEditView.js",
|
||||
"frontend/js/views/databaseView.js",
|
||||
"frontend/js/views/foxxMountView.js",
|
||||
"frontend/js/views/testView.js",
|
||||
"frontend/js/views/appDocumentationView.js",
|
||||
"frontend/js/views/graphView.js",
|
||||
"frontend/js/views/graphManagementView.js",
|
||||
|
@ -159,6 +161,9 @@
|
|||
"frontend/js/views/clusterDatabaseView.js",
|
||||
"frontend/js/views/clusterCollectionView.js",
|
||||
"frontend/js/views/clusterShardsView.js",
|
||||
"frontend/js/views/userManagementView.js",
|
||||
"frontend/js/views/userProfileView.js",
|
||||
"frontend/js/views/userBarView.js",
|
||||
|
||||
"frontend/js/views/statisticBarView.js",
|
||||
"frontend/js/views/userBarView.js",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -24,6 +24,7 @@
|
|||
/// @author Dr. Frank Celler
|
||||
/// @author Martin Schoenert
|
||||
/// @author Dr. Oreste Costa-Panaia
|
||||
/// @author Max Neunhoeffer
|
||||
/// @author Copyright 2006-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -39,152 +40,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE ARRAY
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief associative multi array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_multi_array_s {
|
||||
uint64_t (*hashKey) (struct TRI_multi_array_s*, void*);
|
||||
uint64_t (*hashElement) (struct TRI_multi_array_s*, void*);
|
||||
|
||||
void (*clearElement) (struct TRI_multi_array_s*, void*);
|
||||
|
||||
bool (*isEmptyElement) (struct TRI_multi_array_s*, void*);
|
||||
bool (*isEqualKeyElement) (struct TRI_multi_array_s*, void*, void*);
|
||||
bool (*isEqualElementElement) (struct TRI_multi_array_s*, void*, void*);
|
||||
|
||||
uint32_t _elementSize; // the size of the elements which are to be stored in the table
|
||||
|
||||
uint64_t _nrAlloc; // the size of the table
|
||||
uint64_t _nrUsed; // the number of used entries
|
||||
|
||||
char* _table; // the table itself
|
||||
|
||||
#ifdef TRI_INTERNAL_STATS
|
||||
uint64_t _nrFinds; // statistics: number of lookup calls
|
||||
uint64_t _nrAdds; // statistics: number of insert calls
|
||||
uint64_t _nrRems; // statistics: number of remove calls
|
||||
uint64_t _nrResizes; // statistics: number of resizes
|
||||
|
||||
uint64_t _nrProbesF; // statistics: number of misses while looking up
|
||||
uint64_t _nrProbesA; // statistics: number of misses while inserting
|
||||
uint64_t _nrProbesD; // statistics: number of misses while removing
|
||||
uint64_t _nrProbesR; // statistics: number of misses while adding
|
||||
#endif
|
||||
|
||||
TRI_memory_zone_t* _memoryZone;
|
||||
}
|
||||
TRI_multi_array_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InitMultiArray (TRI_multi_array_t*,
|
||||
TRI_memory_zone_t*,
|
||||
size_t elementSize,
|
||||
uint64_t (*hashKey) (TRI_multi_array_t*, void*),
|
||||
uint64_t (*hashElement) (TRI_multi_array_t*, void*),
|
||||
void (*clearElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEmptyElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEqualKeyElement) (TRI_multi_array_t*, void*, void*),
|
||||
bool (*isEqualElementElement) (TRI_multi_array_t*, void*, void*));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyMultiArray (TRI_multi_array_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeMultiArray (TRI_memory_zone_t*, TRI_multi_array_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByKeyMultiArray (TRI_memory_zone_t*,
|
||||
TRI_multi_array_t*,
|
||||
void* key);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given an element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByElementMultiArray (TRI_memory_zone_t*,
|
||||
TRI_multi_array_t*,
|
||||
void* element);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertElementMultiArray (TRI_multi_array_t*, void* element, bool overwrite);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertKeyMultiArray (TRI_multi_array_t*, void* key, void* element, bool overwrite);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an element from the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveElementMultiArray (TRI_multi_array_t*, void* element, void* old);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveKeyMultiArray (TRI_multi_array_t*, void* key, void* old);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE POINTERS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -194,25 +49,73 @@ bool TRI_RemoveKeyMultiArray (TRI_multi_array_t*, void* key, void* old);
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
/// @brief associative multi array of pointers
|
||||
///
|
||||
/// This is a data structure that can store pointers to objects. Each object
|
||||
/// has a unique key (for example a certain attribute) and multiple
|
||||
/// objects in the associative array can have the same key. Every object
|
||||
/// can be at most once in the array.
|
||||
/// We want to offer constant time complexity for the following
|
||||
/// operations:
|
||||
/// - insert pointer to an object into the array
|
||||
/// - lookup pointer to an object in the array
|
||||
/// - delete pointer to an object from the array
|
||||
/// - find one pointer to an object with a given key
|
||||
/// Furthermore, we want to offer O(n) complexity for the following
|
||||
/// operation:
|
||||
/// - find all pointers whose objects have a given key k, where n is
|
||||
/// the number of objects in the array with this key
|
||||
/// To this end, we use a hash table and ask the user to provide the following:
|
||||
/// - a way to hash objects by keys, and to hash keys themselves,
|
||||
/// - a way to hash objects by their full identity
|
||||
/// - a way to compare a key to the key of a given object
|
||||
/// - a way to compare two elements, either by their keys or by their full
|
||||
/// identities.
|
||||
/// To avoid unnecessary comparisons the user can guarantee that s/he will
|
||||
/// only try to store non-identical elements into the array. This enables
|
||||
/// the code to skip comparisons which would otherwise be necessary to
|
||||
/// ensure uniqueness.
|
||||
/// The idea of the algorithm is as follows: Each slot in the hash table
|
||||
/// contains a pointer to the actual object, as well as two unsigned
|
||||
/// integers "prev" and "next" (being indices in the hash table) to
|
||||
/// organise a linked list of entries, *within the same hash table*. All
|
||||
/// objects with the same key are kept in a doubly linked list. The first
|
||||
/// element in such a linked list is kept at the position determined by
|
||||
/// its hash with respect to its key (or in the first free slot after this
|
||||
/// position). All further elements in such a linked list are kept at the
|
||||
/// position determined by its hash with respect to its full identity
|
||||
/// (or in the first free slot after this position). Provided the hash
|
||||
/// table is large enough and the hash functions distribute well enough,
|
||||
/// this gives the proposed complexity.
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief associative multi array of pointers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef uint64_t TRI_multi_pointer_index_t;
|
||||
#define TRI_MULTI_POINTER_INVALID_INDEX (((TRI_multi_pointer_index_t)0)-1)
|
||||
|
||||
typedef struct TRI_multi_pointer_entry_s {
|
||||
void* ptr; // a pointer to the data stored in this slot
|
||||
TRI_multi_pointer_index_t next; // index of the data following in the linked
|
||||
// list of all items with the same key
|
||||
TRI_multi_pointer_index_t prev; // index of the data preceding in the linked
|
||||
// list of all items with the same key
|
||||
} TRI_multi_pointer_entry_t;
|
||||
|
||||
typedef struct TRI_multi_pointer_s {
|
||||
uint64_t (*hashKey) (struct TRI_multi_pointer_s*, void const*);
|
||||
uint64_t (*hashElement) (struct TRI_multi_pointer_s*, void const*);
|
||||
uint64_t (*hashKey) (struct TRI_multi_pointer_s*, void const* key);
|
||||
uint64_t (*hashElement) (struct TRI_multi_pointer_s*, void const* element,
|
||||
bool byKey);
|
||||
|
||||
bool (*isEqualKeyElement) (struct TRI_multi_pointer_s*, void const*, void const*);
|
||||
bool (*isEqualElementElement) (struct TRI_multi_pointer_s*, void const*, void const*);
|
||||
bool (*isEqualKeyElement) (struct TRI_multi_pointer_s*, void const* key,
|
||||
void const* element);
|
||||
bool (*isEqualElementElement) (struct TRI_multi_pointer_s*,
|
||||
void const* el1, void const* el2, bool byKey);
|
||||
|
||||
uint64_t _nrAlloc; // the size of the table
|
||||
uint64_t _nrUsed; // the number of used entries
|
||||
|
||||
void** _table; // the table itself
|
||||
TRI_multi_pointer_entry_t* _table_alloc; // the table itself
|
||||
TRI_multi_pointer_entry_t* _table; // the table itself, 64 aligned
|
||||
|
||||
#ifdef TRI_INTERNAL_STATS
|
||||
uint64_t _nrFinds; // statistics: number of lookup calls
|
||||
|
@ -220,39 +123,36 @@ typedef struct TRI_multi_pointer_s {
|
|||
uint64_t _nrRems; // statistics: number of remove calls
|
||||
uint64_t _nrResizes; // statistics: number of resizes
|
||||
|
||||
uint64_t _nrProbes; // statistics: number of misses in FindElementPlace
|
||||
// and LookupByElement, used by insert, lookup and
|
||||
// remove
|
||||
uint64_t _nrProbesF; // statistics: number of misses while looking up
|
||||
uint64_t _nrProbesA; // statistics: number of misses while inserting
|
||||
uint64_t _nrProbesD; // statistics: number of misses while removing
|
||||
uint64_t _nrProbesR; // statistics: number of misses while adding
|
||||
#endif
|
||||
|
||||
TRI_memory_zone_t* _memoryZone;
|
||||
}
|
||||
TRI_multi_pointer_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InitMultiPointer (TRI_multi_pointer_t* array,
|
||||
TRI_memory_zone_t*,
|
||||
uint64_t (*hashKey) (TRI_multi_pointer_t*, void const*),
|
||||
uint64_t (*hashElement) (TRI_multi_pointer_t*, void const*),
|
||||
bool (*isEqualKeyElement) (TRI_multi_pointer_t*, void const*, void const*),
|
||||
bool (*isEqualElementElement) (TRI_multi_pointer_t*, void const*, void const*));
|
||||
uint64_t (*hashKey) (TRI_multi_pointer_t*,
|
||||
void const*),
|
||||
uint64_t (*hashElement) (TRI_multi_pointer_t*,
|
||||
void const*, bool),
|
||||
bool (*isEqualKeyElement) (TRI_multi_pointer_t*,
|
||||
void const*, void const*),
|
||||
bool (*isEqualElementElement) (TRI_multi_pointer_t*,
|
||||
void const*,
|
||||
void const*, bool));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array, but does not free the pointer
|
||||
|
@ -266,19 +166,10 @@ void TRI_DestroyMultiPointer (TRI_multi_pointer_t*);
|
|||
|
||||
void TRI_FreeMultiPointer (TRI_memory_zone_t*, TRI_multi_pointer_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -291,16 +182,17 @@ TRI_vector_pointer_t TRI_LookupByKeyMultiPointer (TRI_memory_zone_t*,
|
|||
/// @brief lookups an element given an element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_LookupByElementMultiPointer (TRI_multi_pointer_t*, void const* element);
|
||||
void* TRI_LookupByElementMultiPointer (TRI_multi_pointer_t*,
|
||||
void const* element);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an key/element to the array
|
||||
/// @brief adds a key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t*,
|
||||
void*,
|
||||
const bool,
|
||||
const bool);
|
||||
bool const overwrite,
|
||||
bool const checkEquality);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an element from the array
|
||||
|
@ -314,10 +206,189 @@ void* TRI_RemoveElementMultiPointer (TRI_multi_pointer_t*, void const* element);
|
|||
|
||||
int TRI_ResizeMultiPointer (TRI_multi_pointer_t*, size_t);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE POINTERS WITH MULTIPLE KEYS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
/// @brief associative multi array of pointers with multiple keys
|
||||
///
|
||||
/// This is a data structure that can store pairs (p,h) where p is a
|
||||
/// pointer to an object and h is a pointer to something identifying
|
||||
/// one of the keys of the object. Each object has one ore more keys
|
||||
/// (for example multiple values in a list in a certain attribute) and
|
||||
/// multiple objects in the associative array can have the same key.
|
||||
/// Every pair (p,h) can be at most once in the array.
|
||||
/// We want to offer constant time complexity for the following
|
||||
/// operations:
|
||||
/// - insert a pair into the array
|
||||
/// - delete a pair from the array
|
||||
/// - find one pair (p,h) with a given key k
|
||||
/// Furthermore, we want to offer O(n) complexity for the following
|
||||
/// operation:
|
||||
/// - find the list of pointers p for which there is at least one pair
|
||||
/// (p,h) in the array, where n is the number of objects in the array
|
||||
/// with the given key k
|
||||
/// To this end, we use a hash table and ask the user to provide the following:
|
||||
/// - a way to hash a pair (p,h) by its full identity
|
||||
/// - a way to hash a pair (p,h) but only with respect to its key k
|
||||
/// - a way to hash a given key k
|
||||
/// - a way to compare the key of a pair (p,h) with an external key k
|
||||
/// - a way to compare the keys of two pairs (p,h) and (p',h')
|
||||
/// - a way to compare two pairs (p,h) and (p',h')
|
||||
/// To avoid unnecessary comparisons the user can guarantee that s/he will
|
||||
/// only try to store non-identical pairs into the array. This enables
|
||||
/// the code to skip comparisons which would otherwise be necessary to
|
||||
/// ensure uniqueness.
|
||||
/// The idea of the algorithm is as follows: Each slot in the hash table
|
||||
/// contains a pointer to the actual object, a pointer to its key helper, as
|
||||
/// well as two unsigned integers "prev" and "next" (being indices in
|
||||
/// the hash table) to organise a linked list of entries, *within the
|
||||
/// same hash table*. All pairs with the same key are kept in a doubly
|
||||
/// linked list. The first element in such a linked list is kept at the
|
||||
/// position determined by the hash of its key (or in the first free
|
||||
/// slot after this position). All further pairs in such a linked list
|
||||
/// are kept at the position determined by the hash of the pair. (or in
|
||||
/// the first free slot after this position). Provided the hash table
|
||||
/// is large enough and the hash functions distribute well enough, this
|
||||
/// gives the proposed complexity.
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_multi_pair_entry_s {
|
||||
void* ptr; // a pointer to the data stored in this slot
|
||||
void* key; // a pointer to the helper to find the key stored in this slot
|
||||
TRI_multi_pointer_index_t next; // index of the data following in the linked
|
||||
// list of all items with the same key
|
||||
TRI_multi_pointer_index_t prev; // index of the data preceding in the linked
|
||||
// list of all items with the same key
|
||||
} TRI_multi_pair_entry_t;
|
||||
|
||||
typedef struct TRI_multi_pair_s {
|
||||
uint64_t (*hashKeyKey) (struct TRI_multi_pair_s*, void const* key);
|
||||
uint64_t (*hashKeyPair) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper);
|
||||
uint64_t (*hashPair) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper);
|
||||
|
||||
bool (*isEqualKeyPairKey) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper,
|
||||
void const* key);
|
||||
bool (*isEqualKeyPairPair) (struct TRI_multi_pair_s*,
|
||||
void const* element1, void const* keyhelper1,
|
||||
void const* element2, void const* keyhelper2);
|
||||
bool (*isEqualPairPair) (struct TRI_multi_pair_s*,
|
||||
void const* element1, void const* keyhelper1,
|
||||
void const* element2, void const* keyhelper2);
|
||||
|
||||
uint64_t _nrAlloc; // the size of the table
|
||||
uint64_t _nrUsed; // the number of used entries
|
||||
|
||||
TRI_multi_pair_entry_t* _table; // the table itself
|
||||
|
||||
#ifdef TRI_INTERNAL_STATS
|
||||
uint64_t _nrFinds; // statistics: number of lookup calls
|
||||
uint64_t _nrAdds; // statistics: number of insert calls
|
||||
uint64_t _nrRems; // statistics: number of remove calls
|
||||
uint64_t _nrResizes; // statistics: number of resizes
|
||||
|
||||
uint64_t _nrProbes; // statistics: number of misses in FindPairPlace
|
||||
// and LookupByPair, used by insert, lookup and
|
||||
// remove
|
||||
uint64_t _nrProbesF; // statistics: number of misses while looking up
|
||||
uint64_t _nrProbesD; // statistics: number of misses while removing
|
||||
#endif
|
||||
|
||||
TRI_memory_zone_t* _memoryZone;
|
||||
}
|
||||
TRI_multi_pair_t;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InitMultiPair (
|
||||
TRI_multi_pair_t* array,
|
||||
TRI_memory_zone_t*,
|
||||
uint64_t (*hashKeyKey) (struct TRI_multi_pair_s*, void const* key),
|
||||
uint64_t (*hashKeyPair) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper),
|
||||
uint64_t (*hashPair) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper),
|
||||
bool (*isEqualKeyPairKey) (struct TRI_multi_pair_s*,
|
||||
void const* element, void const* keyhelper,
|
||||
void const* key),
|
||||
bool (*isEqualKeyPairPair) (struct TRI_multi_pair_s*,
|
||||
void const* element1, void const* keyhelper1,
|
||||
void const* element2, void const* keyhelper2),
|
||||
bool (*isEqualPairPair) (struct TRI_multi_pair_s*,
|
||||
void const* element1, void const* keyhelper1,
|
||||
void const* element2, void const* keyhelper2));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyMultiPair (TRI_multi_pair_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeMultiPair (TRI_memory_zone_t*, TRI_multi_pair_t*);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByKeyMultiPair (TRI_memory_zone_t*,
|
||||
TRI_multi_pair_t*,
|
||||
void const* key);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a pair to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_InsertPairMultiPair (TRI_multi_pair_t*,
|
||||
void* element,
|
||||
void* keyhelper,
|
||||
bool const overwrite,
|
||||
bool const checkEquality);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a pair in the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_LookupPairMultiPair (TRI_multi_pair_t*,
|
||||
void* element,
|
||||
void* keyhelper);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes pair from the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_RemovePairMultiPair (TRI_multi_pair_t*,
|
||||
void const* element,
|
||||
void const* keyhelper);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resize the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ResizeMultiPair (TRI_multi_pair_t*, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/* The MIT License
|
||||
|
||||
Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "fasthash.h"
|
||||
|
||||
// Compression function for Merkle-Damgard construction.
|
||||
// This function is generated using the framework provided.
|
||||
#define mix(h) ({ \
|
||||
(h) ^= (h) >> 23; \
|
||||
(h) *= 0x2127599bf4325c37ULL; \
|
||||
(h) ^= (h) >> 47; })
|
||||
|
||||
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
|
||||
{
|
||||
const uint64_t m = 0x880355f21e6d1965ULL;
|
||||
const uint64_t *pos = (const uint64_t *)buf;
|
||||
const uint64_t *end = pos + (len / 8);
|
||||
const unsigned char *pos2;
|
||||
uint64_t h = seed ^ (len * m);
|
||||
uint64_t v;
|
||||
|
||||
while (pos != end) {
|
||||
v = *pos++;
|
||||
h ^= mix(v);
|
||||
h *= m;
|
||||
}
|
||||
|
||||
pos2 = (const unsigned char*)pos;
|
||||
v = 0;
|
||||
|
||||
switch (len & 7) {
|
||||
case 7: v ^= (uint64_t)pos2[6] << 48;
|
||||
case 6: v ^= (uint64_t)pos2[5] << 40;
|
||||
case 5: v ^= (uint64_t)pos2[4] << 32;
|
||||
case 4: v ^= (uint64_t)pos2[3] << 24;
|
||||
case 3: v ^= (uint64_t)pos2[2] << 16;
|
||||
case 2: v ^= (uint64_t)pos2[1] << 8;
|
||||
case 1: v ^= (uint64_t)pos2[0];
|
||||
h ^= mix(v);
|
||||
h *= m;
|
||||
}
|
||||
|
||||
return mix(h);
|
||||
}
|
||||
|
||||
uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
|
||||
{
|
||||
// the following trick converts the 64-bit hashcode to Fermat
|
||||
// residue, which shall retain information from both the higher
|
||||
// and lower parts of hashcode.
|
||||
uint64_t h = fasthash64(buf, len, seed);
|
||||
return h - (h >> 32);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* The MIT License
|
||||
|
||||
Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FASTHASH_H
|
||||
#define _FASTHASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fasthash32 - 32-bit implementation of fasthash
|
||||
* @buf: data buffer
|
||||
* @len: data size
|
||||
* @seed: the seed
|
||||
*/
|
||||
uint32_t fasthash32(const void *buf, size_t len, uint32_t seed);
|
||||
|
||||
/**
|
||||
* fasthash64 - 64-bit implementation of fasthash
|
||||
* @buf: data buffer
|
||||
* @len: data size
|
||||
* @seed: the seed
|
||||
*/
|
||||
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,475 @@
|
|||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
*/
|
||||
|
||||
|
||||
//**************************************
|
||||
// Tuning parameters
|
||||
//**************************************
|
||||
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
|
||||
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
|
||||
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
|
||||
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
|
||||
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_USE_UNALIGNED_ACCESS 1
|
||||
#endif
|
||||
|
||||
// XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
// This option has a very small performance cost (only measurable on small inputs).
|
||||
// By default, this option is disabled. To enable it, uncomment below define :
|
||||
//#define XXH_ACCEPT_NULL_INPUT_POINTER 1
|
||||
|
||||
// XXH_FORCE_NATIVE_FORMAT :
|
||||
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
||||
// Results are therefore identical for little-endian and big-endian CPU.
|
||||
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
|
||||
// It will improve speed for Big-endian CPU.
|
||||
// This option has no impact on Little_Endian CPU.
|
||||
#define XXH_FORCE_NATIVE_FORMAT 0
|
||||
|
||||
|
||||
//**************************************
|
||||
// Compiler Specific Options
|
||||
//**************************************
|
||||
// Disable some Visual warning messages
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Includes & Memory related functions
|
||||
//**************************************
|
||||
#include "xxhash.h"
|
||||
// Modify the local functions below should you wish to use some other memory related routines
|
||||
// for malloc(), free()
|
||||
#include <stdlib.h>
|
||||
FORCE_INLINE void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
FORCE_INLINE void XXH_free (void* p) { free(p); }
|
||||
// for memcpy()
|
||||
#include <string.h>
|
||||
FORCE_INLINE void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
|
||||
|
||||
//**************************************
|
||||
// Basic Types
|
||||
//**************************************
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
# define _PACKED __attribute__ ((packed))
|
||||
#else
|
||||
# define _PACKED
|
||||
#endif
|
||||
|
||||
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
|
||||
# ifdef __IBMC__
|
||||
# pragma pack(1)
|
||||
# else
|
||||
# pragma pack(push, 1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
||||
|
||||
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define A32(x) (((U32_S *)(x))->v)
|
||||
|
||||
|
||||
//***************************************
|
||||
// Compiler-specific Functions and Macros
|
||||
//***************************************
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) // Visual Studio
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
#else
|
||||
static inline U32 XXH_swap32 (U32 x) {
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );}
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Constants
|
||||
//**************************************
|
||||
#define PRIME32_1 2654435761U
|
||||
#define PRIME32_2 2246822519U
|
||||
#define PRIME32_3 3266489917U
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
|
||||
//**************************************
|
||||
// Architecture Macros
|
||||
//**************************************
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
|
||||
static const int one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one))
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Macros
|
||||
//**************************************
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations
|
||||
|
||||
|
||||
//****************************
|
||||
// Memory reads
|
||||
//****************************
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
|
||||
|
||||
|
||||
//****************************
|
||||
// Simple Hash Functions
|
||||
//****************************
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
U32 h32;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) { len=0; p=(const BYTE*)(size_t)16; }
|
||||
#endif
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
|
||||
v2 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
|
||||
v3 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
|
||||
v4 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p<=bEnd-4)
|
||||
{
|
||||
h32 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32(const void* input, int len, U32 seed)
|
||||
{
|
||||
#if 0
|
||||
// Simple version, good for code maintenance, but unfortunately slow for small inputs
|
||||
void* state = XXH32_init(seed);
|
||||
XXH32_update(state, input, len);
|
||||
return XXH32_digest(state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//****************************
|
||||
// Advanced Hash Functions
|
||||
//****************************
|
||||
|
||||
struct XXH_state32_t
|
||||
{
|
||||
U64 total_len;
|
||||
U32 seed;
|
||||
U32 v1;
|
||||
U32 v2;
|
||||
U32 v3;
|
||||
U32 v4;
|
||||
int memsize;
|
||||
char memory[16];
|
||||
};
|
||||
|
||||
|
||||
int XXH32_sizeofState()
|
||||
{
|
||||
XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough
|
||||
return sizeof(struct XXH_state32_t);
|
||||
}
|
||||
|
||||
|
||||
XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state->v2 = seed + PRIME32_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME32_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
void* XXH32_init (U32 seed)
|
||||
{
|
||||
void* state = XXH_malloc (sizeof(struct XXH_state32_t));
|
||||
XXH32_resetState(state, seed);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 16) // fill in tmp buffer
|
||||
{
|
||||
XXH_memcpy(state->memory + state->memsize, input, len);
|
||||
state->memsize += len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) // some data left from previous update
|
||||
{
|
||||
XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
|
||||
{
|
||||
const U32* p32 = (const U32*)state->memory;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
|
||||
v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
|
||||
v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
|
||||
v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->memory, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH32_update (void* state_in, const void* input, int len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
|
||||
{
|
||||
struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->memory;
|
||||
BYTE* bEnd = (BYTE*)state->memory + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->total_len >= 16)
|
||||
{
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = state->seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) state->total_len;
|
||||
|
||||
while (p<=bEnd-4)
|
||||
{
|
||||
h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_intermediateDigest (void* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_digest (void* state_in)
|
||||
{
|
||||
U32 h32 = XXH32_intermediateDigest(state_in);
|
||||
|
||||
XXH_free(state_in);
|
||||
|
||||
return h32;
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
*/
|
||||
|
||||
/* Notice extracted from xxHash homepage :
|
||||
|
||||
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
|
||||
It also successfully passes all tests from the SMHasher suite.
|
||||
|
||||
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
|
||||
|
||||
Name Speed Q.Score Author
|
||||
xxHash 5.4 GB/s 10
|
||||
CrapWow 3.2 GB/s 2 Andrew
|
||||
MumurHash 3a 2.7 GB/s 10 Austin Appleby
|
||||
SpookyHash 2.0 GB/s 10 Bob Jenkins
|
||||
SBox 1.4 GB/s 9 Bret Mulvey
|
||||
Lookup3 1.2 GB/s 9 Bob Jenkins
|
||||
SuperFastHash 1.2 GB/s 1 Paul Hsieh
|
||||
CityHash64 1.05 GB/s 10 Pike & Alakuijala
|
||||
FNV 0.55 GB/s 5 Fowler, Noll, Vo
|
||||
CRC32 0.43 GB/s 9
|
||||
MD5-32 0.33 GB/s 10 Ronald L. Rivest
|
||||
SHA1-32 0.28 GB/s 10
|
||||
|
||||
Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
//****************************
|
||||
// Type
|
||||
//****************************
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Simple Hash Functions
|
||||
//****************************
|
||||
|
||||
unsigned int XXH32 (const void* input, int len, unsigned int seed);
|
||||
|
||||
/*
|
||||
XXH32() :
|
||||
Calculate the 32-bits hash of sequence of length "len" stored at memory address "input".
|
||||
The memory between input & input+len must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function successfully passes all SMHasher tests.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, use the advanced functions below.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Advanced Hash Functions
|
||||
//****************************
|
||||
|
||||
void* XXH32_init (unsigned int seed);
|
||||
XXH_errorcode XXH32_update (void* state, const void* input, int len);
|
||||
unsigned int XXH32_digest (void* state);
|
||||
|
||||
/*
|
||||
These functions calculate the xxhash of an input provided in several small packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
It must be started with :
|
||||
void* XXH32_init()
|
||||
The function returns a pointer which holds the state of calculation.
|
||||
|
||||
This pointer must be provided as "void* state" parameter for XXH32_update().
|
||||
XXH32_update() can be called as many times as necessary.
|
||||
The user must provide a valid (allocated) input.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, it is recommended to chunk your data into blocks
|
||||
of size for example 2^30 (1GB) to avoid any "int" overflow issue.
|
||||
|
||||
Finally, you can end the calculation anytime, by using XXH32_digest().
|
||||
This function returns the final 32-bits hash.
|
||||
You must provide the same "void* state" parameter created by XXH32_init().
|
||||
Memory will be freed by XXH32_digest().
|
||||
*/
|
||||
|
||||
|
||||
int XXH32_sizeofState(void);
|
||||
XXH_errorcode XXH32_resetState(void* state, unsigned int seed);
|
||||
|
||||
#define XXH32_SIZEOFSTATE 48
|
||||
typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
|
||||
/*
|
||||
These functions allow user application to make its own allocation for state.
|
||||
|
||||
XXH32_sizeofState() is used to know how much space must be allocated for the xxHash 32-bits state.
|
||||
Note that the state must be aligned to access 'long long' fields. Memory must be allocated and referenced by a pointer.
|
||||
This pointer must then be provided as 'state' into XXH32_resetState(), which initializes the state.
|
||||
|
||||
For static allocation purposes (such as allocation on stack, or freestanding systems without malloc()),
|
||||
use the structure XXH32_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields.
|
||||
*/
|
||||
|
||||
|
||||
unsigned int XXH32_intermediateDigest (void* state);
|
||||
/*
|
||||
This function does the same as XXH32_digest(), generating a 32-bit hash,
|
||||
but preserve memory context.
|
||||
This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXH32_update().
|
||||
To free memory context, use XXH32_digest(), or free().
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Deprecated function names
|
||||
//****************************
|
||||
// The following translations are provided to ease code transition
|
||||
// You are encouraged to no longer this function names
|
||||
#define XXH32_feed XXH32_update
|
||||
#define XXH32_result XXH32_digest
|
||||
#define XXH32_getIntermediateResult XXH32_intermediateDigest
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -42,6 +42,7 @@ lib_libarango_a_SOURCES = \
|
|||
lib/BasicsC/csv.c \
|
||||
lib/BasicsC/debugging.c \
|
||||
lib/BasicsC/error.c \
|
||||
lib/BasicsC/fasthash.c \
|
||||
lib/BasicsC/files.c \
|
||||
lib/BasicsC/hashes.c \
|
||||
lib/BasicsC/init.c \
|
||||
|
@ -71,6 +72,7 @@ lib_libarango_a_SOURCES = \
|
|||
lib/BasicsC/vector.c \
|
||||
lib/BasicsC/voc-errors.c \
|
||||
lib/BasicsC/voc-mimetypes.c \
|
||||
lib/BasicsC/xxhash.c \
|
||||
lib/BasicsC/tri-zip.c \
|
||||
lib/JsonParser/json-parser.c \
|
||||
lib/ProgramOptions/program-options.c \
|
||||
|
|
Loading…
Reference in New Issue