1
0
Fork 0

improved interface to GEO SPATIAL index

This commit is contained in:
Frank Celler 2011-10-30 14:17:28 +01:00
parent d5d2534fbc
commit 36fa9bc0b4
21 changed files with 5581 additions and 3915 deletions

View File

@ -28,6 +28,7 @@
#include "conversions.h"
#include <Basics/strings.h>
#include <Basics/string-buffer.h>
// -----------------------------------------------------------------------------
// --SECTION-- public functions for string to number
@ -398,6 +399,19 @@ char* TRI_StringUInt64 (uint64_t attr) {
return TRI_DuplicateString(buffer);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert to string from double
////////////////////////////////////////////////////////////////////////////////
char* TRI_StringDouble (double value) {
TRI_string_buffer_t buffer;
TRI_InitStringBuffer(&buffer);
TRI_AppendDoubleStringBuffer(&buffer, value);
return buffer._buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -128,6 +128,12 @@ char* TRI_StringInt64 (int64_t);
char* TRI_StringUInt64 (uint64_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert to string from double
////////////////////////////////////////////////////////////////////////////////
char* TRI_StringDouble (double);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

837
Basics/fsrt.inc Normal file
View File

@ -0,0 +1,837 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief High-Performance Database Framework made by triagens
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Martin Schoenert
/// @author Copyright 2009-2010, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page FruitSort Fruit Sort
///
/// @section Pre-processor directive FSRT_TYPE
///
/// The directive @ec FSRT_TYPE refers to the type of each element which is to
/// be sorted. If this directive is undefined, then the type @c char* is used
/// instead, which may result in a reduction in the speed of the sort
/// algorithm. For example,
///
/// If you define @c FSRT_TYPE the corresponding macros functions will have the
/// following signatures:
///
/// <tt>void FSRT_NAME( FSRT_TYPE * fs_b, FSRT_TYPE * fs_e )</tt> @n
/// <tt>int FSRT_LT( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
/// <tt>int FSRT_EQ( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
/// <tt>int FSRT_COMP( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
/// <tt>void FSRT_COPY( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
///
/// If @c FSRT_TYPE is undefined the corresponding macros functions will macros
/// have the following signatures:
///
/// <tt>void FSRT_NAME( char * fs_b, char * fs_e, size_t fs_s, char * fs_t )</tt> @n
/// <tt>int FSRT_LT( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
/// <tt>int FSRT_EQ( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
/// <tt>int FSRT_COMP( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
/// <tt>void FSRT_COPY( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
///
/// @section Pre-processor directive FSRT_NAME
///
/// The pre-processor directive @c FSRT_NAME must be defined.
///
/// The function @c FSRT_NAME(fs_b,fs_e) sorts an array of statically sized
/// elements. The parameters @c fs_b and @c fs_e are pointers or iterators
/// which access the first and last - 1 element.
///
/// The function @c FSRT_NAME(fs_b,fs_e,fs_s,fs_t) can be used to sort elements
/// whose complete type and size is unkown at compile time. The additional
/// parameter @c fs_s refers to the size of the elements, while the parameter
/// @c fs_t refers to a location in memory used to store a temporary element.
///
/// @section Pre-processor directive FSRT_UNIQ
///
/// The directive @c FSRT_UNIQ provides a hint that the elements to be sorted
/// are unique (or little repetitions). In this case, the sorting algorithm will
/// use a 2-way partitioning of the elements into <= and >=. The default
/// alogorithm is a 3-way partitioning of the elements into <, = and >.
///
/// Define this directive when know that the number of repetitions is small.
///
/// @section Pre-processor directive FSRT_INSR
///
/// The directive @c FSRT_INSR represents the cutoff where the algorithm
/// switches from quick sort to insertion sort, i.e. subranges shorter than
/// @c FSRT_INSR will be sorted with Insertion sort algorithm rather than the
/// Quicksort algorithm.
///
/// Thus optimal value for @c FSRT_INSR is dependent on the costs associated
/// with the comparisons copies of elements. The default value of 8 (when
/// @c FSRT_INSR is undefined) is reasonable most of the time. If the cost of
/// comparisons and copies is small, you can use larger values (up to about 40)
/// to increase performance. Consider reducing the value of @c FSRT_INSR where
/// the cost of comparisons and copies is high (down to 4).
///
/// @section Pre-processor directive FSRT_THREE
///
/// The directive @c FSRT_THREE represents the cutoff for median of 3 pivot
/// selection. Defaults to 10 unless otherwise defined. The directive
/// @c FSRT_NINE represents the cutoff for median of 9 pivot selection.
/// Defaults to 10 unless otherwise defined.
///
/// @section Pre-processor directive FSRT_EXTRA_ARGS
///
/// The directive @c FSRT_EXTRA_ARGS provides a list of additional arguments
/// which may be required by the copy and comparison functions.
/// @c FSRT_EXTRA_ARGS is a comma separated list of names of the additional
/// function arguments required. By default no additional arguments are defined.
/// The directive @c FSRT_EXTRA_DECL provides additional declarations for any
/// extra arguments which may be required. @c FSRT_EXTRA_DECL is a comman
/// separated list of declarations.
///
/// By default no additional declarations are defined. For example:
///
/// <tt>#define FSRT_EXTRA_ARGS dsd, loc</tt> @n
/// <tt>#define FSRT_EXTRA_DECL DataSetDescription* dsd, Locale* loc</tt> @n
/// <tt>#define FSRT_LT(x,y,s,d,l) my_str_cmp(x,y,d,l)</tt> @n
///
/// @section Required Directives
///
/// @c FSRT_NAME and @c FSRT_NAM2.
///
/// @section Required Macros
///
/// @c FSRT_LT and @c FSRT_EQ or @c FSRT_COMP.
///
/// @section Optional Macros
///
/// @c FSRT_COPY, @c FSRT_TYPE, @c FSRT_UNIQ, @c FSRT_INSR, @c FSRT_THREE,
/// @c FSRT_NINE @c FSRT_EXTRA_ARGS, @c FSRT_EXTRA_DECL, @c FSRT_COUNT, @c
/// FSRT_DEBUG, @c FSRT_COUNT.
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup FruitSort Fruit Sort
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT_COUNT
/// @brief statistics buffer
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_COUNT
static uint32_t FSRT_Count [20];
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__TYPE
/// @brief the type of the elements which are begin sorted
///
/// Optional. Unless specified the type defaults to a @c char.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__UNIT
/// @brief the size of an element specified in terms of the @c FSRT_TYPE
///
/// When the default value of @c FSRT_TYPE is @c char, this defaults
/// to the size of the elements in bytes. That is, @c fs_s.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__SIZE
/// @brief the size of an element given in bytes
///
/// That is, @a fs_s.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__TEMP
/// @brief the address of some memory storage set aside for an element
///
/// The address of some memory storage set aside at least as large as the size
/// of an element. This temporary storage is used by the function @c FSRT_NAME.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__DIST
/// @brief The number of elements between a given two elements.
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_TYPE
#define FSRT__TYPE FSRT_TYPE
#define FSRT__UNIT 1
#define FSRT__SIZE sizeof(FSRT_TYPE)
#define FSRT__TEMP &fs_t
#define FSRT__DIST(fs_x,fs_y,fs_s) ((fs_x) - (fs_y))
#else
#define FSRT__TYPE char
#define FSRT__UNIT (fs_s)
#define FSRT__SIZE (fs_s)
#define FSRT__TEMP fs_t
#define FSRT__DIST(fs_x,fs_y,fs_s) (((fs_x) - (fs_y)) / (fs_s))
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__LT(x,y,s,d)
/// @brief less-than comparison
///
/// Returns true if @c x is less than @c y. Otherwise, returns false.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__EQ(x,y,s,d)
/// @brief equal-than comparison
///
/// Returns the integer 0 if the elements @c x and @c y both of size @c s are
/// equal. A non-zero value is returned otherwise.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__LEC(x,y,s,d)
/// @brief comparison
///
/// Sets the var @c fs_c to the result of a comparision of @c x and @c y. A
/// value of 0 indicates equality between @c x and @c y. This variable is used
/// as part of the sorting algorithm.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__EQC(x,y,s,d)
/// @brief equalitity test
///
/// Performs a test of equality between @c x and @c y. The value of the variable
/// @a fs_c contains an integer which is the result of a @em previous
/// comparision between @a x and @a y.
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_LT
#ifndef FSRT__COUNT
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) FSRT_LT((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (! FSRT_LT((fs_y),(fs_x),(fs_s) FSRT__EXTRA_ARGS))
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
#else
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_LT((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (! FSRT_LT((fs_y),(fs_x),(fs_s) FSRT__EXTRA_ARGS)))
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
#endif
#else
#ifndef FSRT__COUNT
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) < 0)
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) == 0)
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) ((fs_c = FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)) <= 0)
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (fs_c == 0)
#else
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) < 0))
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) == 0))
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, ((fs_c = FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)) <= 0))
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (fs_c == 0))
#endif
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__COPY
/// @brief copies one element onto another
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__SWAP
/// @brief swaps two elements
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_COPY
#ifndef FSRT__COUNT
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) FSRT_COPY((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
#else
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_COPY((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
#endif
#else
#ifndef FSRT__COUNT
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (memmove( (char*)(fs_x), (char*)(fs_y), (fs_s) ))
#else
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (memcpy( (char*)(fs_x), (char*)(fs_y), (fs_s) )))
#endif
#endif
#define FSRT__SWAP(fs_x,fs_y,fs_s,fs_d) (FSRT__COPY( FSRT__TEMP, (fs_x), (fs_s), (fs_d) ), \
FSRT__COPY( (fs_x), (fs_y), (fs_s), (0) ), \
FSRT__COPY( (fs_y), FSRT__TEMP, (fs_s), (0) ))
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__INSR
/// @brief Cutoff point when to use the insertion short algorithm.
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_INSR
#define FSRT__INSR FSRT_INSR
#else
#define FSRT__INSR 8
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__THREE
/// @brief Used for sorting short arrays.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__NINE
/// @brief Used for sorting short arrays.
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_THREE
#define FSRT__THREE FSRT_THREE
#else
#define FSRT__THREE 10
#endif
#ifdef FSRT_NINE
#define FSRT__NINE FSRT_NINE
#else
#define FSRT__NINE 40
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__EXTRA_ARGS
/// @brief additional arguments which may be required for the algorithm
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__EXTRA_DECL
/// @brief additional declarations which may be required for the algorithm
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_EXTRA_ARGS
#define FSRT__EXTRA_ARGS , FSRT_EXTRA_ARGS
#define FSRT__EXTRA_DECL , FSRT_EXTRA_DECL
#else
#define FSRT__EXTRA_ARGS // none
#define FSRT__EXTRA_DECL // none
#endif
////////////////////////////////////////////////////////////////////////////////
/// @fn FSRT__TYPE * FSRT_NAM2 (
/// FSRT__TYPE * fs_x,
/// FSRT__TYPE * fs_y,
/// FSRT__TYPE * fs_z
/// FSRT__EXTRA_DECL )
///
/// @brief returns the middle element given three elements
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__MED3
/// @brief an alias for the FSRT_NAM2 function
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_TYPE
#define FSRT__MED3(fs_x,fs_y,fs_z,fs_s) FSRT_NAM2((fs_x),(fs_y),(fs_z) FSRT__EXTRA_ARGS)
FSRT__TYPE * FSRT_NAM2 (
FSRT__TYPE * fs_x,
FSRT__TYPE * fs_y,
FSRT__TYPE * fs_z
FSRT__EXTRA_DECL ) {
#else
#define FSRT__MED3(fs_x,fs_y,fs_z,fs_s) FSRT_NAM2((fs_x),(fs_y),(fs_z),(fs_s) FSRT__EXTRA_ARGS)
FSRT__TYPE * FSRT_NAM2 (
FSRT__TYPE * fs_x,
FSRT__TYPE * fs_y,
FSRT__TYPE * fs_z,
size_t fs_s
FSRT__EXTRA_DECL ) {
#endif
if ( FSRT__LT( fs_x, fs_y, FSRT__SIZE, 1 ) ) {
if ( FSRT__LT( fs_y, fs_z, FSRT__SIZE, 1 ) ) { return fs_y; }
else if ( FSRT__LT( fs_x, fs_z, FSRT__SIZE, 1 ) ) { return fs_z; }
else { return fs_x; }
}
else {
if ( FSRT__LT( fs_x, fs_z, FSRT__SIZE, 1 ) ) { return fs_x; }
else if ( FSRT__LT( fs_y, fs_z, FSRT__SIZE, 1 ) ) { return fs_z; }
else { return fs_y; }
}
}
////////////////////////////////////////////////////////////////////////////////
/// @var FSRT_Rand
/// @brief stores the position of the current random element within the array
////////////////////////////////////////////////////////////////////////////////
#ifndef FSRT__RAND
uint32_t FSRT_Rand;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__RAND
/// @brief computes a quasi-random element
////////////////////////////////////////////////////////////////////////////////
#ifndef FSRT__RAND
#define FSRT__RAND \
((fs_b) + FSRT__UNIT * ((FSRT_Rand = FSRT_Rand * 31415 + 27818) % FSRT__DIST(fs_e,fs_b,FSRT__SIZE)))
#endif
////////////////////////////////////////////////////////////////////////////////
/// @fn void FSRT_NAME (
/// FSRT__TYPE * fs_b,
/// FSRT__TYPE * fs_e
/// FSRT__EXTRA_DECL )
///
/// @brief The actual sorting algorithm.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @def FSRT__SORT
///
/// @brief An alias for the sorting algorithm FSRT_NAME.
////////////////////////////////////////////////////////////////////////////////
#ifdef FSRT_TYPE
#define FSRT__SORT(fs_x,fs_y,fs_s,fs_t) FSRT_NAME((fs_x),(fs_y) FSRT__EXTRA_ARGS)
void FSRT_NAME (
FSRT__TYPE * fs_b,
FSRT__TYPE * fs_e
FSRT__EXTRA_DECL ) {
FSRT__TYPE * fs_l;
FSRT__TYPE * fs_r;
FSRT__TYPE * fs_p;
#ifndef FSRT_UNIQ
FSRT__TYPE * fs_m;
FSRT__TYPE * fs_q;
#endif
FSRT__TYPE fs_t;
#else
#define FSRT__SORT(fs_x,fs_y,fs_s,fs_t) FSRT_NAME((fs_x),(fs_y),(fs_s),(fs_t) FSRT__EXTRA_ARGS)
void FSRT_NAME (
FSRT__TYPE * fs_b,
FSRT__TYPE * fs_e,
size_t fs_s,
FSRT__TYPE * fs_t
FSRT__EXTRA_DECL ) {
FSRT__TYPE * fs_l;
FSRT__TYPE * fs_r;
FSRT__TYPE * fs_p;
#ifndef FSRT_UNIQ
FSRT__TYPE * fs_m;
FSRT__TYPE * fs_q;
#endif
#endif
#ifndef FSRT_LT
int fs_c;
#endif
// iterate while the number of elements in the range is large enough
while ( FSRT__INSR <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
// for larger ranges take the median-of-median of nine random elms
if ( FSRT__NINE <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
fs_l = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
fs_r = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
fs_p = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
fs_p = FSRT__MED3( fs_l, fs_r, fs_p, FSRT__SIZE );
}
// for smaller ranges take the median of three random elms
else if ( FSRT__THREE <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
fs_p = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
}
// and for very small ranges take one random element
else {
fs_p = FSRT__RAND;
}
// swap the pivot to the beg pos (out of the way for partitioning)
FSRT__SWAP( fs_b, fs_p, FSRT__SIZE, 4 );
#ifdef FSRT_UNIQ
// 2-way partitioning into elements le and ge.
// Swap elements smaller (or equal) to the pivot to the left,
// and elements larger (or equal) to the pivot to the right.
// Note that scanning pointers stop on and exchange equal elements
// This is important if we sort arrays with few different keys
// because after a few iterations the subranges contain only
// elements with equal keys, and if we would scan over elements
// equal to the pivot, the right pointer would scan all the way
// down and the quick sort would degenerate to a quadratic algo.
#define FSRT__UNIQ__ALG1
#ifdef FSRT__UNIQ__ALG1
// Note that this code is a lot trickier than it appears ;-)
// It is faster than other more obvious formulations, because
// it compares every element exactly once to the pivot and
// it keeps the number of statements (especially jumps) minimal
// so the optimizer can generate compact and fast code.
fs_p = fs_b;
fs_l = fs_b;
fs_r = fs_e;
// *(b==l) <= *p and *p <= *r .. *(e-1) since the set is empty
while ( fs_l < fs_r ) {
// *b .. *(l-1) *l <= *p *p <= *r *(r+1) .. *(e-1)
do { fs_r -= FSRT__UNIT; }
while ( fs_l < fs_r && FSRT__LT( fs_p, fs_r, FSRT__SIZE, 2 ) );
// *p >= *r *p <= *(r+1) .. *(e-1)
do { fs_l += FSRT__UNIT; }
while ( fs_l < fs_r && FSRT__LT( fs_l, fs_p, FSRT__SIZE, 2 ) );
// *b .. *(l-1) <= *p and ((l < r & *l >= *p) or (l >= r))
if ( fs_l < fs_r ) {
// .. *(l-1) <= *p *l >= *p *p >= *r *p <= *(r+1) ..
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
// *b .. *(l-1) *l <= *p *p >= *r *(r+1) .. *(e-1)
}
}
// l == r and *b .. *(l-1) *(l==r) <= *p <= *(r+1) .. *(e-1)
// l == r+1 and *b .. *(l-1==r) <= *p <= *(l==r+1) .. *(e-1)
// swap the pivot to the middle
FSRT__SWAP( fs_b, fs_r, FSRT__SIZE, 4 );
fs_l = fs_r;
fs_r = fs_l + FSRT__UNIT;
#endif
#ifdef FSRT__UNIQ__ALG2
// This is a 2-way partitioning algorithm.
// It performs exactely the same comparisons and swaps as alg1.
// However it is formulated slightly different.
// This is bad for the performance (the code is bit slower).
// But I leave it in here, because this algorithm serves as a good
// starting point for the 3-way partitioning algorithm below.
fs_p = fs_b;
fs_l = fs_b+FSRT__UNIT;
fs_r = fs_e-FSRT__UNIT;
while ( 1 ) {
while ( fs_l <= fs_r && FSRT__LT( fs_p, fs_r, FSRT__SIZE, 2 ) ) {
fs_r -= FSRT__UNIT;
}
while ( fs_l < fs_r && FSRT__LT( fs_l, fs_p, FSRT__SIZE, 2 ) ) {
fs_l += FSRT__UNIT;
}
if ( fs_r <= fs_l ) { break; }
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
fs_r -= FSRT__UNIT;
fs_l += FSRT__UNIT;
}
fs_l = fs_r + FSRT__UNIT;
if ( fs_b < fs_r ) { FSRT__SWAP( fs_b, fs_r, FSRT__SIZE, 4 ); }
fs_l -= FSRT__UNIT;
fs_r += FSRT__UNIT;
#endif
#ifdef FSRT_DEBUG
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
if ( fs_p < fs_l ) {
if ( FSRT__LT( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x not less equal after partitioning\n",fs_p);
break;
}
}
else if ( fs_p < fs_r ) {
if ( ! FSRT__EQ( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x not equal after partitioning\n",fs_p);
break;
}
}
else {
if ( FSRT__LT( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x not greater equal after partitioning\n",fs_p);
break;
}
}
}
#endif
#else
// 3-way partitioning into elements lt, eq, and gt
// This is a bit slower than 2-way partitioning but a lot faster
// if the range contains only elements with few different keys.
// In the first step this does a split-end partitioning,
// i.e. the elements equal to the pivot end up at the very left
// (left of m) or at the very right (right of q) end of the range.
// In the second step (down below) they are swapped to the middle.
// This has the advantage, that it executes fewer swaps
// (which is quite counter to the intuition).
// It executes about 1/4 N swaps for the not-equal elements and
// 2 E swaps for the equal elements (and even fewer if E > N).
// The alternative (that keeps the equal elements during the
// partitioning in the middle) executes about 3/4 N swaps for the
// not-equal elements and 1 E swaps for the equal elements.
fs_p = fs_b;
fs_l = fs_b+FSRT__UNIT;
fs_m = fs_b+FSRT__UNIT;
fs_r = fs_e-FSRT__UNIT;
fs_q = fs_e-FSRT__UNIT;
while ( 1 ) {
while ( fs_l <= fs_r && FSRT__LEC( fs_p, fs_r, FSRT__SIZE, 2 ) ) {
if ( FSRT__EQC( fs_p, fs_r, FSRT__SIZE, 0 ) ) {
if ( fs_r < fs_q ) { FSRT__SWAP( fs_r, fs_q, FSRT__SIZE, 4 ); }
fs_q -= FSRT__UNIT;
}
fs_r -= FSRT__UNIT;
}
while ( fs_l < fs_r && FSRT__LEC( fs_l, fs_p, FSRT__SIZE, 2 ) ) {
if ( FSRT__EQC( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
if ( fs_m < fs_l ) { FSRT__SWAP( fs_m, fs_l, FSRT__SIZE, 4 ); }
fs_m += FSRT__UNIT;
}
fs_l += FSRT__UNIT;
}
if ( fs_r <= fs_l ) { break; }
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
fs_r -= FSRT__UNIT;
fs_l += FSRT__UNIT;
}
fs_l = fs_r + FSRT__UNIT;
#ifdef FSRT_DEBUG
// printf("%08x %08x %08x %08x %08x %08x\n",fs_b,fs_m,fs_l,fs_r,fs_q,fs_e);
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
if ( fs_p < fs_m ) {
if ( ! FSRT__EQ( fs_p, fs_b, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x < fs_m not equal after partitioning\n",fs_p);
break;
}
}
else if ( fs_p < fs_l ) {
if ( ! FSRT__LT( fs_p, fs_b, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x < fs_l not less after partitioning\n",fs_p);
break;
}
}
if ( fs_q < fs_p ) {
if ( ! FSRT__EQ( fs_b, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_q < fs_p %08x not equal after partitioning\n",fs_p);
break;
}
}
else if ( fs_r < fs_p ) {
if ( ! FSRT__LT( fs_b, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_r < fs_p %08x not greater after partitioning\n",fs_p);
break;
}
}
}
#endif
// Swap the equal elements (including the pivot) to the middle.
// I found it not so easy to get this code correct, so beware ;-)
fs_p = fs_b;
while ( fs_p < fs_m && fs_m < fs_l ) {
fs_l -= FSRT__UNIT;
FSRT__SWAP( fs_p, fs_l, FSRT__SIZE, 4 );
fs_p += FSRT__UNIT;
}
if ( fs_l == fs_m ) {
fs_l = fs_p;
}
fs_p = fs_e-FSRT__UNIT;
while ( fs_q < fs_p && fs_r < fs_q ) {
fs_r += FSRT__UNIT;
FSRT__SWAP( fs_r, fs_p, FSRT__SIZE, 4 );
fs_p -= FSRT__UNIT;
}
if ( fs_r == fs_q ) {
fs_r = fs_p;
}
fs_r = fs_r + FSRT__UNIT;
#ifdef FSRT_DEBUG
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
if ( fs_p < fs_l ) {
if ( ! FSRT__LT( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x < fs_l not less after swapping\n",fs_p);
break;
}
}
else if ( fs_p < fs_r ) {
if ( ! FSRT__EQ( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_p %08x < fs_r not equal after swapping\n",fs_p);
break;
}
}
else {
if ( ! FSRT__LT( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
printf("fs_r <= fs_p %08x not greater after swapping\n",fs_p);
break;
}
}
}
#endif
#endif
// Now sort the range before and the range after the pivot.
// Sort the smaller range recursively and the larger iteratively.
// This limits the maximal redursion depth to log2(N).
// To avoid extra variables we modify the arguments of the func.
if ( fs_l-fs_b < fs_e-fs_r ) {
FSRT__SORT( fs_b, fs_l, FSRT__SIZE, FSRT__TEMP );
fs_b = fs_r;
}
else {
FSRT__SORT( fs_r, fs_e, FSRT__SIZE, FSRT__TEMP );
fs_e = fs_l;
}
}
// Finally the remaining short subrange is sorted with insertion sort.
// Sorting each individual short subrange instead of executing one
// insertion sort over the entire range at the end is more efficient,
// because we know that all the pivots (and all the elements equal to
// them) are at the right location, so we need not compare them with
// their predecessor and successor.
// It may also be a bit more cache friendly.
// I tried other algorithms (shell sort, special cases, etc.)
// but in the end this algorithm always was the fastest
// (probably because the subranges are so small).
for ( fs_l = fs_b+FSRT__UNIT; fs_l < fs_e; fs_l += FSRT__UNIT ) {
if ( FSRT__LT( fs_l, fs_l-FSRT__UNIT, FSRT__SIZE, 3 ) ) {
FSRT__COPY( FSRT__TEMP, fs_l, FSRT__SIZE, 5 );
FSRT__COPY( fs_l, fs_l-FSRT__UNIT, FSRT__SIZE, 5 );
for ( fs_r = fs_l-2*FSRT__UNIT;
fs_b <= fs_r && FSRT__LT( FSRT__TEMP, fs_r, FSRT__SIZE, 3 );
fs_r -= FSRT__UNIT ) {
FSRT__COPY( fs_r+FSRT__UNIT, fs_r, FSRT__SIZE, 5 );
}
FSRT__COPY( fs_r+FSRT__UNIT, FSRT__TEMP, FSRT__SIZE, 5 );
}
}
}
#undef FSRT__TYPE
#undef FSRT__UNIT
#undef FSRT__SIZE
#undef FSRT__DIST
#undef FSRT__TEMP
#undef FSRT__LT
#undef FSRT__EQ
#undef FSRT__LEC
#undef FSRT__EQC
#undef FSRT__COPY
#undef FSRT__SWAP
#undef FSRT__INSR
#undef FSRT__THREE
#undef FSRT__NINE
#undef FSRT__EXTRA_ARGS
#undef FSRT__EXTRA_DECL
#undef FSRT__MED3
// #undef FSRT__RAND
#undef FSRT__SORT
#undef FSRT_NAME
#undef FSRT_NAM2
#undef FSRT_LT
#undef FSRT_EQ
#undef FSRT_COMP
#undef FSRT_TYPE
#undef FSRT_COPY
#undef FSRT_UNIQ
#undef FSRT_INSR
#undef FSRT_THREE
#undef FSRT_NINE
#undef FSRT_EXTRA_ARGS
#undef FSRT_EXTRA_DECL
////////////////////////////////////////////////////////////////////////////////
//
// fsrt.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
//
// 0.90 2008-11-20 mschoene initial version
//
// 0.95 2009-03-24 mschoene file is now called fsrt.h
// changed prefix to FSRT_
// parameters and local variables begin with fs_
// changed INSR default to 8
// added description for split-end partitioning
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -57,5 +57,4 @@ avocdb_SOURCES = \
VocBase/simple-collection.c \
VocBase/vocbase.c \
VocBase/voc-shaper.c \
VocBase/write-slots.c \
# end of file list

File diff suppressed because it is too large Load Diff

View File

@ -195,7 +195,7 @@ static v8::Handle<v8::Value> ParseArray (yyscan_t scanner) {
v8::Handle<v8::Object> array = v8::Object::New();
bool comma = false;
char const* name;
char* name;
char const* ptr;
size_t len;
size_t outLength;
@ -270,7 +270,7 @@ static v8::Handle<v8::Value> ParseObject (yyscan_t scanner, int c) {
char buffer[1024];
char* ep;
char const* ptr;
char* ptr;
double d;
size_t outLength;

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,19 @@
#define TRIAGENS_DURHAM_V8_V8_SHELL_H 1
#define TRI_WITHIN_C
#include <Basics/Common.h>
#include <Basics/json.h>
#include <VocBase/simple-collection.h>
#undef TRI_WITHIN_C
#include <string>
#include <v8.h>
// -----------------------------------------------------------------------------
// --SECTION-- CONVERSION FUNCTIONS
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@ -46,29 +52,79 @@
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an object to a string
/// @brief converts a TRI_json_t into a V8 object
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> ObjectJson (TRI_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a TRI_shaped_json_t into a V8 object
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> ObjectShapedJson (TRI_doc_collection_t* collection,
TRI_voc_did_t did,
TRI_shaper_t* shaper,
TRI_shaped_json_t const* shaped);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a TRI_result_set_t into a V8 array
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Array> ArrayResultSet (TRI_result_set_t* rs);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an V8 object to a TRI_shaped_json_t
////////////////////////////////////////////////////////////////////////////////
TRI_shaped_json_t* ShapedJsonV8Object (v8::Handle<v8::Value> object, TRI_shaper_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an V8 object to a string
////////////////////////////////////////////////////////////////////////////////
std::string ObjectToString (v8::Handle<v8::Value> value);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an object to a character
/// @brief converts an V8 object to a character
////////////////////////////////////////////////////////////////////////////////
char ObjectToCharacter (v8::Handle<v8::Value> value, bool& error);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an object to a double
/// @brief converts an V8 object to a double
////////////////////////////////////////////////////////////////////////////////
double ObjectToDouble (v8::Handle<v8::Value> value);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts an object to a double
/// @brief converts an V8 object to a double
////////////////////////////////////////////////////////////////////////////////
double ObjectToDouble (v8::Handle<v8::Value> value, bool& error);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds attributes to array
////////////////////////////////////////////////////////////////////////////////
void AugmentObject (v8::Handle<v8::Value> value, TRI_json_t const* json);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- GENERAL
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup V8Shell V8 Shell
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief stores the V8 shell function inside the global variable
////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,129 @@
#include <v8.h>
////////////////////////////////////////////////////////////////////////////////
/// @page DurhamFluentInterface Fluent Interface
///
/// A fluent interface is implemented by using method chaining to relay the
/// instruction context of a subsequent call. The AvocadoDB provides the
/// following methods:
///
/// - selection by example
/// - field selection (aka projection)
/// - @ref GeoFI "geo coordinates"
/// - sorting
/// - cursors
/// - pagination of the result-set
///
////////////////////////////////////////////////////////////////////////////////
/// @section FirstStepsFI First Steps
////////////////////////////////////////////////////////////////////////////////
///
/// For instance, in order to select all elements of a collection "examples",
/// one can use the "all()" operator.
///
/// @verbinclude fluent1
///
/// This will select all documents and prints the first 20 documents. If there
/// are more than 20 documents, then "...more results..." is printed and you
/// can use the variable "it" to access the next 20 document.
///
/// @verbinclude fluent2
///
/// In the above examples "db.examples.all()" defines a query. Printing
/// that query, executes the query and returns a cursor to the result set.
/// The first 20 documents are printed and the query (resp. cursor) is
/// assigned to the variable "it".
///
/// A cursor can also be queried using "hasNext()" and "next()". Calling
/// either of these functions also executes the query, turning it into
/// a cursor.
///
/// @verbinclude fluent3
///
////////////////////////////////////////////////////////////////////////////////
/// @section GeoFI Geo Coordinates
////////////////////////////////////////////////////////////////////////////////
///
/// The AvocadoDB allows to selects documents based on geographic
/// coordinates. In order for this to work a geo-spatial index must be defined.
/// This index will use a very elaborate algorithm to lookup neighbours that is
/// a magnitude faster than a simple R* index.
///
/// In general a geo coordinate is a pair of latitude and longitude. This can
/// either be an list with two elements like "[ -10, +30 ]" (latitude first,
/// followed by longitude) or an object like "{ lon: -10, lat: +30 }". In order
/// to find all documents within a given radius around a coordinate use the @ref
/// WithinFI "within()" operator. In order to find all documents near a given
/// document use the @ref NearFI "near()" operator.
///
/// It is possible to define more than one geo-spatial index per collection. In
/// this case you must give a hint which of indexes should be used in a query.
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection EnsureGeoIndexFI Create a Geo-Spatial Index
////////////////////////////////////////////////////////////////////////////////
///
/// @copydetails JS_EnsureGeoIndexVocbaseCol
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection NearFI The Near Operator
////////////////////////////////////////////////////////////////////////////////
///
/// @copydetails JS_NearVocbaseCol
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection WithinFI The Within Operator
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
/// @section LimitFI The Limit Operator
////////////////////////////////////////////////////////////////////////////////
///
/// If, for example, you display the result of a user search, then you are in
/// general not interested in the completed result set, but only the first 10
/// documents. In this case, you can the "limit()" operator. This operators
/// works like LIMIT in MySQL, it specifies a maximal number of documents to
/// return.
///
/// @verbinclude fluent4
///
/// Specifying a limit of "0" returns no documents at all. If you do not need
/// a limit, just do not add the limit operator. If you specifiy a negtive
/// limit of -n, this will return the last n documents instead.
///
/// @verbinclude fluent8
///
////////////////////////////////////////////////////////////////////////////////
/// @section SkipFI The Skip Operator
////////////////////////////////////////////////////////////////////////////////
///
/// "skip" used together with "limit" can be used to implement pagination.
/// The "skip" operator skips over the first n documents. So, in order to
/// create result pages with 10 result documents per page, you can use
/// "skip(n * 10).limit(10)" to access the n.th page.
///
/// @verbinclude fluent5
///
////////////////////////////////////////////////////////////////////////////////
/// @section CountFI The Count Operator
////////////////////////////////////////////////////////////////////////////////
///
/// If you are implementation pagination, then you need the total amount of
/// documents a query returned. "count()" just does this. It returns the
/// total amount of documents regardless of any "limit()" and "skip()"
/// operator used before the "count()". If you really want these to be taken
/// into account, use "count(true)".
///
/// @verbinclude fluent6
///
////////////////////////////////////////////////////////////////////////////////
/// @section ExplainFI The Explain Operator
////////////////////////////////////////////////////////////////////////////////
///
/// @copydetails JS_ExplainQuery
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------

View File

@ -249,7 +249,84 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
shaper = geo->base._collection->_shaper;
// lookup latitude and longitude
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
if (geo->_location != 0) {
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
}
else {
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
}
if (! ok) {
return false;
}
// and insert into index
gc.latitude = latitude;
gc.longitude = longitude;
gc.data = doc;
res = GeoIndex_insert(geo->_geoIndex, &gc);
if (res == -1) {
LOG_WARNING("found duplicate entry in geo-index, should not happend");
}
else if (res == -2) {
LOG_WARNING("out-of-memory in geo-index");
}
else if (res == -3) {
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
}
return res == 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document, location is a list
////////////////////////////////////////////////////////////////////////////////
static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
GeoCoordinate gc;
TRI_shaper_t* shaper;
bool ok;
double latitude;
double longitude;
TRI_geo_index_t* geo;
int res;
geo = (TRI_geo_index_t*) idx;
shaper = geo->base._collection->_shaper;
// lookup OLD latitude and longitude
if (geo->_location != 0) {
ok = ExtractDoubleList(shaper, old, geo->_location, &latitude, &longitude);
}
else {
ok = ExtractDoubleArray(shaper, old, geo->_latitude, &latitude);
ok = ok && ExtractDoubleArray(shaper, old, geo->_longitude, &longitude);
}
// and remove old entry
if (ok) {
gc.latitude = latitude;
gc.longitude = longitude;
gc.data = doc;
res = GeoIndex_remove(geo->_geoIndex, &gc);
if (res != 0) {
LOG_WARNING("cannot remove old index entry: %d", res);
}
}
// create new entry with new coordinates
if (geo->_location != 0) {
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
}
else {
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
}
if (! ok) {
return false;
@ -274,19 +351,46 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
return res == 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document, location is a list
////////////////////////////////////////////////////////////////////////////////
static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief erases a document, location is a list
////////////////////////////////////////////////////////////////////////////////
static bool EraseGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
static bool RemoveGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
GeoCoordinate gc;
TRI_shaper_t* shaper;
bool ok;
double latitude;
double longitude;
TRI_geo_index_t* geo;
int res;
geo = (TRI_geo_index_t*) idx;
shaper = geo->base._collection->_shaper;
// lookup OLD latitude and longitude
if (geo->_location != 0) {
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
}
else {
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
}
// and remove old entry
if (ok) {
gc.latitude = latitude;
gc.longitude = longitude;
gc.data = doc;
res = GeoIndex_remove(geo->_geoIndex, &gc);
if (res != 0) {
LOG_WARNING("cannot remove old index entry: %d", res);
}
return res == 0;
}
return true;
}
@ -318,55 +422,6 @@ static TRI_json_t* JsonGeoIndex (TRI_index_t* idx, TRI_doc_collection_t* collect
return json;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts a new document, location is an array
////////////////////////////////////////////////////////////////////////////////
static bool InsertGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
TRI_shaper_t* shaper;
bool ok;
double latitude;
double longitude;
TRI_geo_index_t* geo;
geo = (TRI_geo_index_t*) idx;
shaper = geo->base._collection->_shaper;
// lookup latitude
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
if (! ok) {
return false;
}
// lookup longitude
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
if (! ok) {
return false;
}
printf("%f %f\n", latitude, longitude);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document, location is an array
////////////////////////////////////////////////////////////////////////////////
static bool UpdateGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief erases a document, location is an array
////////////////////////////////////////////////////////////////////////////////
static bool EraseGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief saves the index to file, location is an array
////////////////////////////////////////////////////////////////////////////////
@ -489,7 +544,7 @@ TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s* collection,
geo->base._collection = collection;
geo->base.insert = InsertGeoIndex;
geo->base.erase = EraseGeoIndex;
geo->base.remove = RemoveGeoIndex;
geo->base.update = UpdateGeoIndex;
geo->base.json = JsonGeoIndex;
@ -513,12 +568,13 @@ TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s* collection,
geo = TRI_Allocate(sizeof(TRI_geo_index_t));
geo->base._iid = TRI_NewTickVocBase();
geo->base._type = TRI_IDX_TYPE_GEO_INDEX;
geo->base._collection = collection;
geo->base.insert = InsertGeoIndex2;
geo->base.erase = EraseGeoIndex2;
geo->base.update = UpdateGeoIndex2;
geo->base.insert = InsertGeoIndex;
geo->base.remove = RemoveGeoIndex;
geo->base.update = UpdateGeoIndex;
geo->base.json = JsonGeoIndex2;
geo->_geoIndex = GeoIndex_new();

View File

@ -81,7 +81,7 @@ typedef struct TRI_index_s {
struct TRI_doc_collection_s* _collection;
bool (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
bool (*erase) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
bool (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
bool (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
TRI_json_t* (*json) (struct TRI_index_s*, struct TRI_doc_collection_s*);
}

File diff suppressed because it is too large Load Diff

View File

@ -36,117 +36,6 @@
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////////////
/// @page DurhamFluentInterface Fluent Interface
///
/// A fluent interface is implemented by using method chaining to relay the
/// instruction context of a subsequent call.
///
/// The Durham Storage Engine provides the following methods:
///
/// - selection by example
/// - field selection aka projection
/// - @ref GeoFI "geo coordinates"
/// - sorting
/// - pagination of the result using @ref LimitFI "limit", @ref SkipFI "skip",
/// and @ref CountFI "count".
///
/// @section FirstStepsFI First Steps
///
/// For instance, in order to select all elements of a collection "examples",
/// one can use
///
/// @verbinclude fluent1
///
/// This will select all documents and prints the first 20 documents. If there
/// are more than 20 documents, then "...more results..." is printed and you
/// can use the variable "it" to access the next 20 document.
///
/// @verbinclude fluent2
///
/// In the above examples "db.examples.select()" defines a query. Printing
/// that query, executes the query and returns a cursor to the result set.
/// The first 20 documents are printed and the query (resp. cursor) is
/// assigned to the variable "it".
///
/// A cursor can also be query using "hasNext()" and "next()".
///
/// @verbinclude fluent3
///
/// @section GeoFI Geo Coordinates
///
/// The Storage Engine allows to selects documents based on geographic
/// coordinates. In order for this to work a geo index must be defined. This
/// index will a very elaborate index to lookup neighbours that is magnitudes
/// faster than a simple R* index.
///
/// In generale a geo coordinate is a pair of longitude and latitude. This can
/// either be an list with two elements like "[ -10, +30 ]" or an object like "{
/// lon: -10, lat: +30 }". In order to find all documents within a given radius
/// around a coordinate use the @ref WithinFI "within()" operator. In order to
/// find all documents near a given document use the @ref NearFI "near()"
/// operator.
///
/// @section WithinFI The Within Operator
///
/// @section NearFI The Near Operator
///
/// Assume that the geo coordinate is stored as list of size 2. The first
/// value being the latitude and the second value being the longitude.
///
/// @section LimitFI The Limit Operator
///
/// If, for example, you display the result of a user search, then you are in
/// general not interested in the completed result set, but only the first 10
/// documents. In this case, you can the "limit()" operator. This operators
/// works like LIMIT in MySQL, it specifies a maximal number of documents to
/// return.
///
/// @verbinclude fluent4
///
/// Specifying a limit of "0" returns no documents at all. If you do not need
/// a limit, just do not add the limit operator. If you specifiy a negtive
/// limit of -n, this will return the last n documents instead.
///
/// @verbinclude fluent8
///
/// @section SkipFI The Skip Operator
///
/// "skip" used together with "limit" can be used to implement pagination.
/// The "skip" operator skips over the first n documents. So, in order to
/// create result pages with 10 result documents per page, you can use
/// "skip(n * 10).limit(10)" to access the n.th page.
///
/// @verbinclude fluent5
///
/// @section CountFI The Count Operator
///
/// If you are implementation pagination, then you need the total amount of
/// documents a query returned. "count()" just does this. It returns the
/// total amount of documents regardless of any "limit()" and "skip()"
/// operator used before the "count()". If you really want these to be taken
/// into account, use "count(true)".
///
/// @verbinclude fluent6
///
/// @section ExplainFI The Explain Operator
///
/// In order to optimise queries you need to know how the storage engine
/// executed that type of query. You can use the "explain()" operator to
/// see how a query was executed.
///
/// @verbinclude fluent9
///
/// The "explain()" operator returns an object with the following attributes.
///
/// - cursor: describes how the result set was computed.
/// - scannedIndexEntries: how many index entries were scanned
/// - scannedDocuments: how many documents were scanned
/// - matchedDocuments: the sum of all matched documents in each step
/// - runtime: the runtime in seconds
///
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------
@ -176,13 +65,39 @@ typedef enum {
}
TRI_que_type_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief query result
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_query_result_s {
char* _cursor;
char* _error;
TRI_voc_size_t _length;
TRI_voc_size_t _total;
TRI_voc_size_t _scannedIndexEntries;
TRI_voc_size_t _scannedDocuments;
TRI_voc_size_t _matchedDocuments;
struct TRI_doc_mptr_s const** _documents;
struct TRI_json_s* _augmented;
}
TRI_query_result_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief query
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_query_s {
TRI_que_type_e _type;
struct TRI_doc_collection_s* _collection;
TRI_vocbase_col_t const* _collection;
char* _string;
void (*execute) (struct TRI_query_s*, TRI_query_result_t*);
struct TRI_query_s* (*clone) (struct TRI_query_s*);
void (*free) (struct TRI_query_s*);
}
TRI_query_t;
@ -226,9 +141,14 @@ TRI_limit_query_t;
typedef struct TRI_near_query_s {
TRI_query_t base;
struct TRI_index_s* _index;
TRI_query_t* _operand;
char* _location;
char* _distance;
double _latitude;
double _longitude;
TRI_voc_size_t _count;
}
TRI_near_query_t;
@ -250,7 +170,7 @@ TRI_skip_query_t;
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
@ -262,7 +182,13 @@ TRI_skip_query_t;
/// @brief creates a full scan of a collection
////////////////////////////////////////////////////////////////////////////////
TRI_query_t* TRI_CreateCollectionQuery (struct TRI_doc_collection_s*);
TRI_query_t* TRI_CreateCollectionQuery (TRI_vocbase_col_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds the distance to a query
////////////////////////////////////////////////////////////////////////////////
TRI_query_t* TRI_CreateDistanceQuery (TRI_query_t*, char const* name);
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a document
@ -281,23 +207,10 @@ TRI_query_t* TRI_CreateLimitQuery (TRI_query_t*, TRI_voc_ssize_t);
////////////////////////////////////////////////////////////////////////////////
TRI_query_t* TRI_CreateNearQuery (TRI_query_t*,
char const* location,
double latitude,
double longitude,
TRI_voc_size_t count,
char const** error);
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up documents near a given point
////////////////////////////////////////////////////////////////////////////////
TRI_query_t* TRI_CreateNear2Query (TRI_query_t*,
char const* locLatitude,
double latitude,
char const* locLongitude,
double longitude,
TRI_voc_size_t count,
char const** error);
char const* distance);
////////////////////////////////////////////////////////////////////////////////
/// @brief skips elements of an existing query
@ -305,6 +218,19 @@ TRI_query_t* TRI_CreateNear2Query (TRI_query_t*,
TRI_query_t* TRI_CreateSkipQuery (TRI_query_t*, TRI_voc_size_t);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief executes a query
////////////////////////////////////////////////////////////////////////////////

View File

@ -66,6 +66,7 @@ typedef struct doc_rs_vector_s {
TRI_shaped_json_t* _elements;
TRI_voc_did_t* _dids;
TRI_json_t* _augmented;
TRI_voc_size_t _length;
TRI_voc_size_t _current;
@ -100,9 +101,15 @@ static bool HasNextRSSingle (TRI_result_set_t* rs) {
/// @brief returns the current element of a single result set
////////////////////////////////////////////////////////////////////////////////
static TRI_shaped_json_t* NextRSSingle (TRI_result_set_t* rs, TRI_voc_did_t* did) {
static TRI_shaped_json_t* NextRSSingle (TRI_result_set_t* rs,
TRI_voc_did_t* did,
TRI_json_t const** augmented) {
doc_rs_single_t* rss = (doc_rs_single_t*) rs;
if (augmented != NULL) {
*augmented = NULL;
}
if (rss->_empty) {
*did = 0;
@ -167,12 +174,23 @@ static bool HasNextRSVector (TRI_result_set_t* rs) {
/// @brief returns the current element of a vector result set
////////////////////////////////////////////////////////////////////////////////
static TRI_shaped_json_t* NextRSVector (TRI_result_set_t* rs, TRI_voc_did_t* did) {
static TRI_shaped_json_t* NextRSVector (TRI_result_set_t* rs,
TRI_voc_did_t* did,
TRI_json_t const** augmented) {
doc_rs_vector_t* rss = (doc_rs_vector_t*) rs;
if (rss->_current < rss->_length) {
*did = rss->_dids[rss->_current];
if (augmented != NULL) {
if (rss->_augmented == NULL) {
*augmented = NULL;
}
else {
*augmented = &rss->_augmented[rss->_current];
}
}
return &rss->_elements[rss->_current++];
}
else {
@ -206,13 +224,17 @@ static void FreeRSVector (TRI_result_set_t* rs) {
void* f;
f = TRI_RemoveKeyAssociativeSynced(&rs->_container->_resultSets, &rs->_id);
assert(f != NULL);
if (rss->_elements != NULL) {
TRI_Free(rss->_dids);
TRI_Free(rss->_elements);
}
f = TRI_RemoveKeyAssociativeSynced(&rs->_container->_resultSets, &rs->_id);
assert(f != NULL);
if (rss->_augmented != NULL) {
TRI_Free(rss->_augmented);
}
TRI_Free(rs->_info._cursor);
TRI_Free(rs);
@ -308,6 +330,8 @@ TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection,
rs = TRI_Allocate(sizeof(doc_rs_single_t));
rs->base._error = NULL;
rs->base.hasNext = HasNextRSSingle;
rs->base.next = NextRSSingle;
rs->base.count = CountRSSingle;
@ -338,6 +362,7 @@ TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection,
TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
TRI_doc_mptr_t const** header,
TRI_json_t const* augmented,
TRI_voc_size_t length,
TRI_voc_size_t total) {
doc_rs_vector_t* rs;
@ -348,6 +373,8 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
rs = TRI_Allocate(sizeof(doc_rs_vector_t));
rs->base._error = NULL;
rs->base.hasNext = HasNextRSVector;
rs->base.next = NextRSVector;
rs->base.count = CountRSVector;
@ -361,6 +388,7 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
rs->_current = 0;
rs->_dids = NULL;
rs->_elements = NULL;
rs->_augmented = NULL;
}
else {
rs->_length = length;
@ -377,6 +405,14 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
*wtr = (*qtr)->_did;
*ptr = (*qtr)->_document;
}
if (augmented == NULL) {
rs->_augmented = NULL;
}
else {
rs->_augmented = TRI_Allocate(length * sizeof(TRI_json_t));
memcpy(rs->_augmented, augmented, length * sizeof(TRI_json_t));
}
}
rs->_total = total;

View File

@ -39,8 +39,9 @@ extern "C" {
// -----------------------------------------------------------------------------
struct TRI_doc_collection_s;
struct TRI_shaped_json_s;
struct TRI_doc_mptr_s;
struct TRI_json_s;
struct TRI_shaped_json_s;
// -----------------------------------------------------------------------------
// --SECTION-- public types
@ -92,8 +93,10 @@ typedef struct TRI_result_set_s {
TRI_rs_container_t* _container;
TRI_rs_info_t _info;
char* _error;
bool (*hasNext) (struct TRI_result_set_s*);
struct TRI_shaped_json_s* (*next) (struct TRI_result_set_s*, TRI_voc_did_t*);
struct TRI_shaped_json_s* (*next) (struct TRI_result_set_s*, TRI_voc_did_t*, struct TRI_json_s const**);
TRI_voc_size_t (*count) (struct TRI_result_set_s*, bool current);
void (*free) (struct TRI_result_set_s*);
@ -139,6 +142,7 @@ TRI_result_set_t* TRI_CreateRSSingle (struct TRI_doc_collection_s* collection,
TRI_result_set_t* TRI_CreateRSVector (struct TRI_doc_collection_s* collection,
struct TRI_doc_mptr_s const** header,
struct TRI_json_s const* augmented,
TRI_voc_size_t length,
TRI_voc_size_t total);

View File

@ -55,7 +55,8 @@ static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collection,
char const* location,
char const* latitude,
char const* longitude);
char const* longitude,
TRI_idx_iid iid);
static uint64_t HashKeyHeader (TRI_associative_pointer_t* array, void const* key);
@ -351,8 +352,8 @@ static bool UpdateDocument (TRI_sim_collection_t* collection,
update._rid = marker->_rid;
update._data = *result;
update._document._sid = ((TRI_doc_document_marker_t*) marker)->_shape;
update._document._data.length = ((TRI_df_marker_t const*) (header->_data))->_size - sizeof(TRI_doc_document_marker_t);
update._document._data.data = ((char*) header->_data) + sizeof(TRI_doc_document_marker_t);
update._document._data.length = ((TRI_df_marker_t const*) (update._data))->_size - sizeof(TRI_doc_document_marker_t);
update._document._data.data = ((char*) update._data) + sizeof(TRI_doc_document_marker_t);
UpdateImmediateIndexes(collection, header, &update);
}
@ -650,7 +651,9 @@ static void OpenIterator (TRI_df_marker_t const* marker, void* data, bool journa
}
}
else if (marker->_type == TRI_DOC_MARKER_DELETION) {
TRI_doc_deletion_marker_t const* d = (TRI_doc_deletion_marker_t const*) marker;
TRI_doc_deletion_marker_t const* d;
d = (TRI_doc_deletion_marker_t const*) marker;
LOG_TRACE("deletion did %lu, rid %lu, deletion %lu",
(unsigned long) d->_did,
@ -692,11 +695,13 @@ static void OpenIterator (TRI_df_marker_t const* marker, void* data, bool journa
static void OpenIndex (char const* filename, void* data) {
TRI_sim_collection_t* doc;
TRI_idx_iid iid;
TRI_json_t* json;
TRI_json_t* loc;
TRI_json_t* lat;
TRI_json_t* lon;
TRI_json_t* type;
TRI_json_t* iis;
char const* typeStr;
char* error;
@ -729,12 +734,18 @@ static void OpenIndex (char const* filename, void* data) {
loc = TRI_LookupArrayJson(json, "location");
lat = TRI_LookupArrayJson(json, "latitude");
lon = TRI_LookupArrayJson(json, "longitude");
iis = TRI_LookupArrayJson(json, "iid");
iid = 0;
if (iis != NULL && loc->_type == TRI_JSON_NUMBER) {
iid = loc->_value._number;
}
if (loc != NULL && loc->_type == TRI_JSON_STRING) {
CreateGeoIndexSimCollection(doc, loc->_value._string.data, NULL, NULL);
CreateGeoIndexSimCollection(doc, loc->_value._string.data, NULL, NULL, iid);
}
else if (lat != NULL && lat->_type == TRI_JSON_STRING && lon != NULL && lon ->_type == TRI_JSON_STRING) {
CreateGeoIndexSimCollection(doc, NULL, lat->_value._string.data, lon->_value._string.data);
CreateGeoIndexSimCollection(doc, NULL, lat->_value._string.data, lon->_value._string.data, iid);
}
else {
LOG_WARNING("ignore geo-index, need either 'location' or 'latitude' and 'longitude'");
@ -770,6 +781,7 @@ static void InitSimCollection (TRI_sim_collection_t* collection,
TRI_InitCondition(&collection->_journalsCondition);
TRI_InitVectorPointer(&collection->_indexes);
collection->_geoIndex = NULL;
collection->base.beginRead = BeginRead;
collection->base.endRead = EndRead;
@ -1058,7 +1070,43 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
TRI_doc_mptr_t const* header,
TRI_doc_mptr_t const* update) {
#warning TODO
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
TRI_shaped_json_t old;
bool ok;
bool result;
size_t i;
size_t n;
// get the old document
old = header->_document;
// update all fields, the document identifier stays the same
change.c = header;
change.v->_rid = update->_rid;
change.v->_eid = update->_eid;
change.v->_deletion = update->_deletion;
change.v->_data = update->_data;
change.v->_document = update->_document;
// update all other indexes
n = TRI_SizeVectorPointer(&collection->_indexes);
result = true;
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
idx = TRI_AtVectorPointer(&collection->_indexes, i);
ok = idx->update(idx, header, &old);
if (! ok) {
result = false;
}
}
return true;
}
@ -1069,7 +1117,45 @@ static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
TRI_doc_mptr_t const* header,
TRI_voc_tick_t deletion) {
#warning TODO
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
TRI_doc_mptr_t* found;
size_t n;
size_t i;
bool result;
bool ok;
// set the deletion flag
change.c = header;
change.v->_deletion = deletion;
// remove from main index
found = TRI_RemoveKeyAssociativePointer(&collection->_primaryIndex, &header->_did);
if (found == NULL) {
TRI_set_errno(TRI_VOC_ERROR_DOCUMENT_NOT_FOUND);
return false;
}
// remove all other indexes
n = TRI_SizeVectorPointer(&collection->_indexes);
result = true;
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
idx = TRI_AtVectorPointer(&collection->_indexes, i);
ok = idx->remove(idx, header);
if (! ok) {
result = false;
}
}
// and release the header pointer
collection->_headers->release(collection->_headers, change.v);
// that's it
return true;
}
@ -1176,7 +1262,8 @@ static bool EqualKeyDocument (TRI_associative_pointer_t* array, void const* key,
static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collection,
char const* location,
char const* latitude,
char const* longitude) {
char const* longitude,
TRI_idx_iid iid) {
TRI_index_t* idx;
TRI_shape_pid_t lat;
TRI_shape_pid_t loc;
@ -1204,10 +1291,10 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
// check, if we know the index
if (location != NULL) {
idx = TRI_LookupGeoIndexSimCollection(collection, location);
idx = TRI_LookupGeoIndexSimCollection(collection, loc);
}
else if (longitude != NULL && latitude != NULL) {
idx = TRI_LookupGeoIndex2SimCollection(collection, latitude, longitude);
idx = TRI_LookupGeoIndex2SimCollection(collection, lat, lon);
}
else {
TRI_set_errno(TRI_VOC_ERROR_ILLEGAL_PARAMETER);
@ -1242,12 +1329,23 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
(unsigned long) lon);
}
if (iid) {
idx->_iid = iid;
}
// initialises the index with all existing documents
FillIndex(collection, idx);
// and store index
TRI_PushBackVectorPointer(&collection->_indexes, idx);
if (collection->_geoIndex == NULL) {
collection->_geoIndex = (TRI_geo_index_t*) idx;
}
else if (collection->_geoIndex->base._iid > idx->_iid) {
collection->_geoIndex = (TRI_geo_index_t*) idx;
}
return idx;
}
@ -1269,15 +1367,11 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
char const* location) {
TRI_shape_pid_t loc;
TRI_shaper_t* shaper;
TRI_shape_pid_t location) {
size_t n;
size_t i;
n = TRI_SizeVectorPointer(&collection->_indexes);
shaper = collection->base._shaper;
loc = shaper->findAttributePathByName(shaper, location);
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
@ -1287,7 +1381,7 @@ TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
TRI_geo_index_t* geo = (TRI_geo_index_t*) idx;
if (geo->_location == loc) {
if (geo->_location != 0 && geo->_location == location) {
return idx;
}
}
@ -1301,18 +1395,12 @@ TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection,
char const* latitude,
char const* longitude) {
TRI_shape_pid_t lat;
TRI_shape_pid_t lon;
TRI_shaper_t* shaper;
TRI_shape_pid_t latitude,
TRI_shape_pid_t longitude) {
size_t n;
size_t i;
n = TRI_SizeVectorPointer(&collection->_indexes);
shaper = collection->base._shaper;
lat = shaper->findAttributePathByName(shaper, latitude);
lon = shaper->findAttributePathByName(shaper, longitude);
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
@ -1322,7 +1410,7 @@ TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection,
if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
TRI_geo_index_t* geo = (TRI_geo_index_t*) idx;
if (geo->_latitude == lat && geo->_longitude == lon) {
if (geo->_latitude != 0 && geo->_longitude != 0 && geo->_latitude == latitude && geo->_longitude == longitude) {
return idx;
}
}
@ -1346,7 +1434,7 @@ bool TRI_EnsureGeoIndexSimCollection (TRI_sim_collection_t* collection,
TRI_WriteLockReadWriteLock(&collection->_lock);
idx = CreateGeoIndexSimCollection(collection, location, NULL, NULL);
idx = CreateGeoIndexSimCollection(collection, location, NULL, NULL, 0);
if (idx == NULL) {
TRI_WriteUnlockReadWriteLock(&collection->_lock);
@ -1385,7 +1473,7 @@ bool TRI_EnsureGeoIndex2SimCollection (TRI_sim_collection_t* collection,
TRI_WriteLockReadWriteLock(&collection->_lock);
idx = CreateGeoIndexSimCollection(collection, NULL, latitude, longitude);
idx = CreateGeoIndexSimCollection(collection, NULL, latitude, longitude, 0);
if (idx == NULL) {
TRI_WriteUnlockReadWriteLock(&collection->_lock);

View File

@ -41,6 +41,7 @@ extern "C" {
// -----------------------------------------------------------------------------
struct TRI_index_s;
struct TRI_geo_index_s;
// -----------------------------------------------------------------------------
// --SECTION-- public types
@ -71,6 +72,7 @@ typedef struct TRI_sim_collection_s {
TRI_headers_t* _headers;
TRI_associative_pointer_t _primaryIndex;
TRI_vector_pointer_t _indexes;
struct TRI_geo_index_s* _geoIndex;
// .............................................................................
// this condition variable protects the _journals
@ -176,7 +178,7 @@ bool TRI_CloseSimCollection (TRI_sim_collection_t* collection);
////////////////////////////////////////////////////////////////////////////////
struct TRI_index_s* TRI_LookupGeoIndexSimCollection (struct TRI_sim_collection_s* collection,
char const* location);
TRI_shape_pid_t location);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds a geo index
@ -185,8 +187,8 @@ struct TRI_index_s* TRI_LookupGeoIndexSimCollection (struct TRI_sim_collection_s
////////////////////////////////////////////////////////////////////////////////
struct TRI_index_s* TRI_LookupGeoIndex2SimCollection (struct TRI_sim_collection_s* collection,
char const* latitude,
char const* longitude);
TRI_shape_pid_t latitude,
TRI_shape_pid_t longitude);
////////////////////////////////////////////////////////////////////////////////
/// @brief ensures that a geo index exists

View File

@ -1,192 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief write slots
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2010, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "write-slots.h"
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialses a write slots
////////////////////////////////////////////////////////////////////////////////
void TRI_InitWriteSlots (TRI_col_write_slots_t* slots) {
size_t i;
TRI_col_write_slot_t* next;
TRI_col_write_slot_t* last = NULL;
for (i = 0; i < TRI_COL_WRITE_SLOTS; ++i) {
next = TRI_Allocate(sizeof(TRI_col_write_slot_t));
next->_begin = NULL;
next->_end = NULL;
next->_backward = NULL;
next->_forward = last;
last = next;
}
slots->_free = last;
slots->_used = NULL;
slots->_position = NULL;
slots->_synced = NULL;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the writes slots, but does not free the pointer
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyWriteSlots (TRI_col_write_slots_t* slots) {
TRI_col_write_slot_t* next;
TRI_col_write_slot_t* current;
// clear free list
current = slots->_free;
while (current != NULL) {
next = current->_forward;
TRI_Free(current);
current = next;
}
// clear used list
current = slots->_used;
while (current != 0) {
next = current->_forward;
TRI_Free(current);
current = next;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the writes slots
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeWriteSlots (TRI_col_write_slots_t* slots) {
TRI_DestroyWriteSlots(slots);
TRI_Free(slots);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief acquires a free write slot, returns 0 if none is free
////////////////////////////////////////////////////////////////////////////////
TRI_col_write_slot_t* TRI_AcquireWriteSlots (TRI_col_write_slots_t* slots, void* begin, void* end) {
TRI_col_write_slot_t* slot;
TRI_col_write_slot_t* used;
if (slots->_free == NULL) {
return NULL;
}
slot = slots->_free;
slots->_free = slot->_forward;
slot->_forward = NULL;
slot->_begin = begin;
slot->_end = end;
if (slots->_used == NULL) {
slot->_backward = NULL;
slots->_used = slot;
}
else {
used = slots->_used;
while (used->_forward != NULL) {
used = used->_forward;
}
used->_forward = slot;
slot->_backward = used;
}
if (slots->_synced == NULL) {
slots->_synced = begin;
}
return slot;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief releases a write slot
////////////////////////////////////////////////////////////////////////////////
void* TRI_ReleaseWriteSlots (TRI_col_write_slots_t* slots, TRI_col_write_slot_t* slot) {
void* position;
// correct the predecessor
if (slot->_backward == NULL) {
slots->_used = slot->_forward;
// correct the position
if (slots->_used == NULL) {
slots->_position = slot->_end;
}
else {
slots->_position = slots->_used->_begin;
}
}
else {
slot->_backward->_forward = slot->_forward;
}
// correct the successor
if (slot->_forward != NULL) {
slot->_forward->_backward = slot->_backward;
}
// put back onto free list
slot->_backward = NULL;
slot->_begin = NULL;
slot->_end = NULL;
slot->_forward = slots->_free;
slots->_free = slot;
position = slots->_position;
return position;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -1,148 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief write slots
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2010, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_VOCBASE_WRITE_SLOTS_H
#define TRIAGENS_DURHAM_VOCBASE_WRITE_SLOTS_H 1
#include <Basics/Common.h>
#include <Basics/vector.h>
#include <Basics/locks.h>
#include <VocBase/vocbase.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- public constants
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief default write slots
////////////////////////////////////////////////////////////////////////////////
#define TRI_COL_WRITE_SLOTS (10)
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief single write slot
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_col_write_slot_s {
struct TRI_col_write_slot_s* _forward;
struct TRI_col_write_slot_s* _backward;
void* _begin;
void* _end; // excluding
}
TRI_col_write_slot_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief write slots
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_col_write_slots_s {
TRI_col_write_slot_t* _free;
TRI_col_write_slot_t* _used;
void* _position; // position of finished writes (excluding)
void* _synced; // position of synced writes (excluding)
}
TRI_col_write_slots_t;
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialses a write slots
////////////////////////////////////////////////////////////////////////////////
void TRI_InitWriteSlots (TRI_col_write_slots_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the writes slots, but does not free the pointer
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyWriteSlots (TRI_col_write_slots_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the writes slots
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeWriteSlots (TRI_col_write_slots_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief acquires a free write slot, returns 0 if none is free
////////////////////////////////////////////////////////////////////////////////
TRI_col_write_slot_t* TRI_AcquireWriteSlots (TRI_col_write_slots_t*, void* begin, void* end);
////////////////////////////////////////////////////////////////////////////////
/// @brief releases a write slot
////////////////////////////////////////////////////////////////////////////////
void* TRI_ReleaseWriteSlots (TRI_col_write_slots_t*, TRI_col_write_slot_t*);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -1 +1 @@
#define TRIAGENS_VERSION "0.0.1 (9334:9405)"
#define TRIAGENS_VERSION "0.0.1 (9427)"