mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'master' of github.com:triAGENS/AvocadoDB
This commit is contained in:
commit
00355fccf4
|
@ -107,6 +107,8 @@ void TRI_InitialiseErrorMessages (void) {
|
|||
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_WRITE, "could not write to server");
|
||||
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_READ, "could not read from server");
|
||||
REG_ERROR(ERROR_AVOCADO_INDEX_PQ_INSERT_FAILED, "priority queue insert failure");
|
||||
REG_ERROR(ERROR_AVOCADO_INDEX_PQ_REMOVE_FAILED, "priority queue remove failure");
|
||||
REG_ERROR(ERROR_AVOCADO_INDEX_PQ_REMOVE_ITEM_MISSING, "priority queue remove failure - item missing in index");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -232,6 +232,12 @@ extern "C" {
|
|||
/// - 3100: @CODE{priority queue insert failure}
|
||||
/// Will be raised when an attempt to insert a document into a priority queue
|
||||
/// index fails for some reason.
|
||||
/// - 3110: @CODE{priority queue remove failure}
|
||||
/// Will be raised when an attempt to remove a document from a priority queue
|
||||
/// index fails for some reason.
|
||||
/// - 3111: @CODE{priority queue remove failure - item missing in index}
|
||||
/// Will be raised when an attempt to remove a document from a priority queue
|
||||
/// index fails when document can not be located within the index.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1234,6 +1240,28 @@ void TRI_InitialiseErrorMessages (void);
|
|||
|
||||
#define TRI_ERROR_AVOCADO_INDEX_PQ_INSERT_FAILED (3100)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 3110: ERROR_AVOCADO_INDEX_PQ_REMOVE_FAILED
|
||||
///
|
||||
/// priority queue remove failure
|
||||
///
|
||||
/// Will be raised when an attempt to remove a document from a priority queue
|
||||
/// index fails for some reason.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_ERROR_AVOCADO_INDEX_PQ_REMOVE_FAILED (3110)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 3111: ERROR_AVOCADO_INDEX_PQ_REMOVE_ITEM_MISSING
|
||||
///
|
||||
/// priority queue remove failure - item missing in index
|
||||
///
|
||||
/// Will be raised when an attempt to remove a document from a priority queue
|
||||
/// index fails when document can not be located within the index.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_ERROR_AVOCADO_INDEX_PQ_REMOVE_ITEM_MISSING (3111)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
> curl --data @- -X PUT --dump - http://localhost:8529/_api/collection/70109828/parameter
|
||||
> curl --data @- -X PUT --dump - http://localhost:8529/_api/collection/70109828/properties
|
||||
{ "waitForSync" : true }
|
||||
|
||||
HTTP/1.1 200 OK
|
|
@ -1,4 +1,4 @@
|
|||
avocado> db.examples.parameter();
|
||||
avocado> db.examples.properties();
|
||||
{
|
||||
"waitForSync" : false,
|
||||
"journalSize" : 134217728
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
avocado> db.examples.parameter({ waitForSync : true });
|
||||
avocado> db.examples.properties({ waitForSync : true });
|
||||
{
|
||||
"waitForSync" : true,
|
||||
"journalSize" : 134217728
|
||||
|
|
|
@ -135,6 +135,8 @@ avocado_SOURCES = \
|
|||
HttpsServer/HttpsAsyncCommTask.cpp \
|
||||
HttpsServer/HttpsServer.cpp \
|
||||
HttpsServer/HttpsServerImpl.cpp \
|
||||
PriorityQueue/pqueueindex.c \
|
||||
PriorityQueue/priorityqueue.c \
|
||||
QL/ast-query.c \
|
||||
QL/formatter.c \
|
||||
QL/optimize.c \
|
||||
|
|
26
Makefile.in
26
Makefile.in
|
@ -239,7 +239,9 @@ am_avocado_OBJECTS = Admin/ApplicationAdminServer.$(OBJEXT) \
|
|||
HttpsServer/ApplicationHttpsServerImpl.$(OBJEXT) \
|
||||
HttpsServer/HttpsAsyncCommTask.$(OBJEXT) \
|
||||
HttpsServer/HttpsServer.$(OBJEXT) \
|
||||
HttpsServer/HttpsServerImpl.$(OBJEXT) QL/ast-query.$(OBJEXT) \
|
||||
HttpsServer/HttpsServerImpl.$(OBJEXT) \
|
||||
PriorityQueue/pqueueindex.$(OBJEXT) \
|
||||
PriorityQueue/priorityqueue.$(OBJEXT) QL/ast-query.$(OBJEXT) \
|
||||
QL/formatter.$(OBJEXT) QL/optimize.$(OBJEXT) \
|
||||
QL/parser.$(OBJEXT) QL/tokens.$(OBJEXT) \
|
||||
RestHandler/RestActionHandler.$(OBJEXT) \
|
||||
|
@ -688,6 +690,8 @@ avocado_SOURCES = \
|
|||
HttpsServer/HttpsAsyncCommTask.cpp \
|
||||
HttpsServer/HttpsServer.cpp \
|
||||
HttpsServer/HttpsServerImpl.cpp \
|
||||
PriorityQueue/pqueueindex.c \
|
||||
PriorityQueue/priorityqueue.c \
|
||||
QL/ast-query.c \
|
||||
QL/formatter.c \
|
||||
QL/optimize.c \
|
||||
|
@ -1448,6 +1452,16 @@ HttpsServer/HttpsServer.$(OBJEXT): HttpsServer/$(am__dirstamp) \
|
|||
HttpsServer/$(DEPDIR)/$(am__dirstamp)
|
||||
HttpsServer/HttpsServerImpl.$(OBJEXT): HttpsServer/$(am__dirstamp) \
|
||||
HttpsServer/$(DEPDIR)/$(am__dirstamp)
|
||||
PriorityQueue/$(am__dirstamp):
|
||||
@$(MKDIR_P) PriorityQueue
|
||||
@: > PriorityQueue/$(am__dirstamp)
|
||||
PriorityQueue/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) PriorityQueue/$(DEPDIR)
|
||||
@: > PriorityQueue/$(DEPDIR)/$(am__dirstamp)
|
||||
PriorityQueue/pqueueindex.$(OBJEXT): PriorityQueue/$(am__dirstamp) \
|
||||
PriorityQueue/$(DEPDIR)/$(am__dirstamp)
|
||||
PriorityQueue/priorityqueue.$(OBJEXT): PriorityQueue/$(am__dirstamp) \
|
||||
PriorityQueue/$(DEPDIR)/$(am__dirstamp)
|
||||
QL/$(am__dirstamp):
|
||||
@$(MKDIR_P) QL
|
||||
@: > QL/$(am__dirstamp)
|
||||
|
@ -1744,6 +1758,8 @@ mostlyclean-compile:
|
|||
-rm -f Logger/LoggerInfo.$(OBJEXT)
|
||||
-rm -f Logger/LoggerStream.$(OBJEXT)
|
||||
-rm -f Logger/LoggerTiming.$(OBJEXT)
|
||||
-rm -f PriorityQueue/pqueueindex.$(OBJEXT)
|
||||
-rm -f PriorityQueue/priorityqueue.$(OBJEXT)
|
||||
-rm -f ProgramOptions/program-options.$(OBJEXT)
|
||||
-rm -f QL/ast-query.$(OBJEXT)
|
||||
-rm -f QL/formatter.$(OBJEXT)
|
||||
|
@ -1944,6 +1960,8 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@Logger/$(DEPDIR)/LoggerInfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@Logger/$(DEPDIR)/LoggerStream.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@Logger/$(DEPDIR)/LoggerTiming.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@PriorityQueue/$(DEPDIR)/pqueueindex.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@PriorityQueue/$(DEPDIR)/priorityqueue.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@ProgramOptions/$(DEPDIR)/program-options.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@QL/$(DEPDIR)/ast-query.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@QL/$(DEPDIR)/formatter.Po@am__quote@
|
||||
|
@ -2371,6 +2389,8 @@ distclean-generic:
|
|||
-rm -f JsonParserX/$(am__dirstamp)
|
||||
-rm -f Logger/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f Logger/$(am__dirstamp)
|
||||
-rm -f PriorityQueue/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f PriorityQueue/$(am__dirstamp)
|
||||
-rm -f ProgramOptions/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f ProgramOptions/$(am__dirstamp)
|
||||
-rm -f QL/$(DEPDIR)/$(am__dirstamp)
|
||||
|
@ -2419,7 +2439,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-local \
|
|||
|
||||
distclean: distclean-am
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR)
|
||||
-rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-tags
|
||||
|
@ -2467,7 +2487,7 @@ installcheck-am:
|
|||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR)
|
||||
-rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,189 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief priority queue index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright by triAGENS GmbH - All rights reserved.
|
||||
///
|
||||
/// The Programs (which include both the software and documentation)
|
||||
/// contain proprietary information of triAGENS GmbH; they are
|
||||
/// provided under a license agreement containing restrictions on use and
|
||||
/// disclosure and are also protected by copyright, patent and other
|
||||
/// intellectual and industrial property laws. Reverse engineering,
|
||||
/// disassembly or decompilation of the Programs, except to the extent
|
||||
/// required to obtain interoperability with other independently created
|
||||
/// software or as specified by law, is prohibited.
|
||||
///
|
||||
/// The Programs are not intended for use in any nuclear, aviation, mass
|
||||
/// transit, medical, or other inherently dangerous applications. It shall
|
||||
/// be the licensee's responsibility to take all appropriate fail-safe,
|
||||
/// backup, redundancy, and other measures to ensure the safe use of such
|
||||
/// applications if the Programs are used for such purposes, and triAGENS
|
||||
/// GmbH disclaims liability for any damages caused by such use of
|
||||
/// the Programs.
|
||||
///
|
||||
/// This software is the confidential and proprietary information of
|
||||
/// triAGENS GmbH. You shall not disclose such confidential and
|
||||
/// proprietary information and shall use it only in accordance with the
|
||||
/// terms of the license agreement you entered into with triAGENS GmbH.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. O
|
||||
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_VOC_BASE_PRIORITY_QUEUE_INDEX_H
|
||||
#define TRIAGENS_DURHAM_VOC_BASE_PRIORITY_QUEUE_INDEX_H 1
|
||||
|
||||
#include <BasicsC/common.h>
|
||||
#include "PriorityQueue/priorityqueue.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- priority queue index public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueueIndex
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Define the structure of a priority queue index
|
||||
// Currently the priority queue defines its own storage for the position integer
|
||||
// into the priority queue array. That is, we do not store a 'hidden' attribute
|
||||
// in the doc.
|
||||
// ...............................................................................
|
||||
|
||||
typedef struct {
|
||||
TRI_pqueue_t* _pq; // the actual priority queue
|
||||
TRI_associative_array_t* _aa; // storage for the pointer into the pq array
|
||||
} PQIndex;
|
||||
|
||||
// ...............................................................................
|
||||
// Currently only support one shaped_json field (attribute) of the type 'number'
|
||||
// Can extend later
|
||||
// ...............................................................................
|
||||
|
||||
typedef struct {
|
||||
size_t numFields; // the number of fields
|
||||
TRI_shaped_json_t* fields; // list of shaped json objects which the collection should know about
|
||||
void* data; // master document pointer
|
||||
void* collection; // pointer to the collection;
|
||||
uint64_t pqSlot; // int pointer to the position in the pq array
|
||||
} PQIndexElement;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t _numElements;
|
||||
PQIndexElement* _elements; // simple list of elements
|
||||
} PQIndexElements;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Priority Queue Index constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueueIndex
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reclaims memory allocated for the index, releasing the Priority
|
||||
/// Queue storage and Associative Array storage.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PQueueIndex_destroy (PQIndex*);
|
||||
|
||||
void PQueueIndex_free (PQIndex*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PQIndex* PQueueIndex_new (void);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Priority Queue Index public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueueIndex
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts an item into a priority queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int PQIndex_add (PQIndex*, PQIndexElement*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts an item into a priority queue (same as add method above)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int PQIndex_insert (PQIndex*, PQIndexElement*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an item from the priority queue (not necessarily the top most)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int PQIndex_remove (PQIndex*, PQIndexElement*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the top most item without removing it from the queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PQIndexElements* PQIndex_top (PQIndex*, uint64_t);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an item and inserts a new item
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool PQIndex_update (PQIndex*, const PQIndexElement*, const PQIndexElement*);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -0,0 +1,584 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief priorty queue
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright by triAGENS GmbH - All rights reserved.
|
||||
///
|
||||
/// The Programs (which include both the software and documentation)
|
||||
/// contain proprietary information of triAGENS GmbH; they are
|
||||
/// provided under a license agreement containing restrictions on use and
|
||||
/// disclosure and are also protected by copyright, patent and other
|
||||
/// intellectual and industrial property laws. Reverse engineering,
|
||||
/// disassembly or decompilation of the Programs, except to the extent
|
||||
/// required to obtain interoperability with other independently created
|
||||
/// software or as specified by law, is prohibited.
|
||||
///
|
||||
/// The Programs are not intended for use in any nuclear, aviation, mass
|
||||
/// transit, medical, or other inherently dangerous applications. It shall
|
||||
/// be the licensee's responsibility to take all appropriate fail-safe,
|
||||
/// backup, redundancy, and other measures to ensure the safe use of such
|
||||
/// applications if the Programs are used for such purposes, and triAGENS
|
||||
/// GmbH disclaims liability for any damages caused by such use of
|
||||
/// the Programs.
|
||||
///
|
||||
/// This software is the confidential and proprietary information of
|
||||
/// triAGENS GmbH. You shall not disclose such confidential and
|
||||
/// proprietary information and shall use it only in accordance with the
|
||||
/// terms of the license agreement you entered into with triAGENS GmbH.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Dr. O
|
||||
/// @author Martin Schoenert
|
||||
/// @author Copyright 2009-2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "priorityqueue.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include <BasicsC/logging.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- useful forward declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
oreste's debug only
|
||||
typedef struct {
|
||||
size_t numFields; // the number of fields
|
||||
TRI_shaped_json_t* fields; // list of shaped json objects which the collection should know about
|
||||
void* data; // master document pointer
|
||||
void* collection; // pointer to the collection;
|
||||
uint64_t pqSlot; // int pointer to the position in the pq array
|
||||
} xx;
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool AddPQueue (TRI_pqueue_t*, void*);
|
||||
static bool CheckPQSize (TRI_pqueue_t*);
|
||||
static bool CompareIsLess (TRI_pqueue_t*, void*, void*);
|
||||
static bool FixPQ (TRI_pqueue_t*, uint64_t);
|
||||
static char* GetItemAddress (TRI_pqueue_t*, uint64_t);
|
||||
static bool RemovePQueue (TRI_pqueue_t*, uint64_t, bool);
|
||||
static void* TopPQueue (TRI_pqueue_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- priority queue constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a priority queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InitPQueue (TRI_pqueue_t* pq, size_t initialCapacity, size_t itemSize, bool reverse,
|
||||
void (*clearStorage) (struct TRI_pqueue_s*, void*),
|
||||
uint64_t (*getStorage) (struct TRI_pqueue_s*, void*),
|
||||
bool (*isLess) (struct TRI_pqueue_s*, void*, void*),
|
||||
void (*updateStorage) (struct TRI_pqueue_s*, void*, uint64_t pos)) {
|
||||
|
||||
if (pq == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Assign the call back functions
|
||||
// ..........................................................................
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// This callback is used to remove any memory which may be used as part of
|
||||
// the storage within the array _items. Callback required since we do not
|
||||
// know if there is any internal structure.
|
||||
// ..........................................................................
|
||||
pq->clearStoragePQ = clearStorage;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Returns the position within the _items array the element is.
|
||||
// Currently this simply is used to perform a consistency check.
|
||||
// ..........................................................................
|
||||
pq->getStoragePQ = getStorage;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// The actual comparison function which returns true if left item is
|
||||
// less than right item (otherwise false).
|
||||
// ..........................................................................
|
||||
pq->isLessPQ = isLess;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Stores the position of the element within the _items array. Its purpose
|
||||
// is to allow the storage position to be located independent of the
|
||||
// priority queue _items array.
|
||||
// ..........................................................................
|
||||
pq->updateStoragePQ = updateStorage;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Assign the element size
|
||||
// ..........................................................................
|
||||
pq->_base._itemSize = itemSize;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Initialise invalid access counters
|
||||
// ..........................................................................
|
||||
pq->_base._nrFalseRemoves = 0;
|
||||
pq->_base._nrFalseAdds = 0;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Set the capacity and assign memeory for storage
|
||||
// ..........................................................................
|
||||
pq->_base._capacity = initialCapacity;
|
||||
pq->_base._items = TRI_Allocate(pq->_base._itemSize * pq->_base._capacity);
|
||||
if (pq->_base._items == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
LOG_ERROR("out of memory when creating priority queue storage");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Initialise the memory allcoated for the storage of pq (0 filled)
|
||||
// ..........................................................................
|
||||
|
||||
memset(pq->_base._items, 0, pq->_base._itemSize * pq->_base._capacity);
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// initialise the number of items stored
|
||||
// ..........................................................................
|
||||
pq->_base._count = 0;
|
||||
|
||||
// ..........................................................................
|
||||
// Determines if the pq should be reversed
|
||||
// ..........................................................................
|
||||
pq->_base._reverse = reverse;
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// The static call back functions to query, modifiy the pq
|
||||
// ..........................................................................
|
||||
pq->add = AddPQueue;
|
||||
pq->remove = RemovePQueue;
|
||||
pq->top = TopPQueue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a priority queue, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyPQueue(TRI_pqueue_t* pq) {
|
||||
size_t j;
|
||||
void* thisItem;
|
||||
|
||||
if (pq == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < pq->_base._count; ++j) {
|
||||
thisItem = (j * pq->_base._itemSize) + pq->_base._items;
|
||||
pq->clearStoragePQ(pq,thisItem);
|
||||
}
|
||||
TRI_Free(pq->_base._items);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a priority queue and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePQueue(TRI_pqueue_t* pq) {
|
||||
if (pq == NULL) {
|
||||
return;
|
||||
}
|
||||
TRI_DestroyPQueue(pq);
|
||||
TRI_Free(pq);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- priority queue callback functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts an item into the priority queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool AddPQueue(TRI_pqueue_t* pq, void* item) {
|
||||
size_t k;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Some basic checks for consistency
|
||||
// ...........................................................................
|
||||
|
||||
if (pq == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pq->getStoragePQ(pq,item) != 0) {
|
||||
pq->_base._nrFalseAdds++;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// handle case that pq is too small
|
||||
// ...........................................................................
|
||||
|
||||
if (!CheckPQSize(pq)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// increase the number of items in the queue
|
||||
// ...........................................................................
|
||||
|
||||
pq->_base._count++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// add the item to the end
|
||||
// ...........................................................................
|
||||
k = (pq->_base._count - 1) * pq->_base._itemSize;
|
||||
memcpy( k + pq->_base._items, item, pq->_base._itemSize);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// call back so that the item can store the position of the entry into the
|
||||
// pq array back into the document (row, whatever).
|
||||
// ...........................................................................
|
||||
pq->updateStoragePQ(pq, k + pq->_base._items, pq->_base._count);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// and fix the priority queue (re-sort)
|
||||
// ...........................................................................
|
||||
FixPQ(pq, pq->_base._count);
|
||||
|
||||
/*
|
||||
for (k = 0; k < pq->_base._count; ++k) {
|
||||
tt = (xx*)( (k * pq->_base._itemSize) + pq->_base._items);
|
||||
printf("%s:%u:zzzzzzzzzzzzzzzzzzzzzz:%f:%u;%u\n",__FILE__,__LINE__,
|
||||
*((double*)((tt->fields)->_data.data)),
|
||||
tt->pqSlot,
|
||||
tt->numFields);
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief rmeoves an item from the pq -- needs the position
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool RemovePQueue(TRI_pqueue_t* pq, uint64_t position, bool destroyItem) {
|
||||
|
||||
char* lastItem;
|
||||
char* thisItem;
|
||||
|
||||
if (pq == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Check that the position sent is valid
|
||||
// ...........................................................................
|
||||
|
||||
if (position == 0 || position > pq->_base._count) {
|
||||
pq->_base._nrFalseRemoves++;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// obtain the pointer positions
|
||||
// ...........................................................................
|
||||
|
||||
thisItem = ((position - 1) * pq->_base._itemSize) + pq->_base._items;
|
||||
lastItem = ((pq->_base._count - 1) * pq->_base._itemSize) + pq->_base._items;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Set the position in the priority queue array back in the document
|
||||
// ...........................................................................
|
||||
|
||||
pq->updateStoragePQ(pq, thisItem, 0);
|
||||
if (destroyItem) {
|
||||
pq->clearStoragePQ(pq,thisItem);
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// perhaps we are lucky and the item to be removed is at the end of queue?
|
||||
// ...........................................................................
|
||||
|
||||
if (position == pq->_base._count) {
|
||||
memset(thisItem, 0, pq->_base._itemSize);
|
||||
pq->_base._count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// No such luck - so work a little harder.
|
||||
// ...........................................................................
|
||||
|
||||
memcpy(thisItem, lastItem, pq->_base._itemSize);
|
||||
memset(lastItem, 0, pq->_base._itemSize);
|
||||
pq->_base._count--;
|
||||
FixPQ(pq,position);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the top most item in the priority queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void* TopPQueue(TRI_pqueue_t* pq) {
|
||||
|
||||
if ( (pq == NULL) || (pq->_base._count == 0) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (pq->_base._items);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- priority queue helper functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if additional capacity is required and extends if so
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool CheckPQSize(TRI_pqueue_t* pq) {
|
||||
char* newItems;
|
||||
|
||||
if (pq == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pq->_base._capacity > (pq->_base._count + 1) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pq->_base._capacity = pq->_base._capacity * 2;
|
||||
newItems = TRI_Allocate(pq->_base._capacity * pq->_base._itemSize);
|
||||
if (newItems == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(newItems, 0, pq->_base._itemSize * pq->_base._capacity);
|
||||
memcpy(newItems, pq->_base._items, (pq->_base._count * pq->_base._itemSize) );
|
||||
|
||||
TRI_Free(pq->_base._items);
|
||||
pq->_base._items = newItems;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief rebalances the heap (priority queue storage) using partial order
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool FixPQ(TRI_pqueue_t* pq, uint64_t position) {
|
||||
|
||||
char* currentItem; // the element which may be out of place in the heap
|
||||
uint64_t currentPos; // the current item we are checking against.
|
||||
char* parentItem;
|
||||
char* itemAddress;
|
||||
char* leftChildItem;
|
||||
char* rightChildItem;
|
||||
|
||||
currentPos = position;
|
||||
currentItem = (char*)(TRI_Allocate(pq->_base._itemSize));
|
||||
if (currentItem == NULL) { // out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
if (itemAddress == NULL) {
|
||||
TRI_Free(currentItem);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Temporarily save our item just changed (via removal or addition)
|
||||
// ...........................................................................
|
||||
|
||||
memcpy(currentItem,itemAddress,pq->_base._itemSize);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Remember that given position m, it's parent in the heap is given by m/2
|
||||
// Remember that the item we have to fix can be in the wrong place either because
|
||||
// it is less than it's parent or because it is greater than its children.
|
||||
// ...........................................................................
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// item is moved up if the item is LESS than its parent.
|
||||
// ...........................................................................
|
||||
|
||||
while ((currentPos / 2) >= 1) {
|
||||
parentItem = GetItemAddress(pq, currentPos / 2);
|
||||
if (!pq->isLessPQ(pq,currentItem,parentItem)) {
|
||||
break;
|
||||
}
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
memcpy(itemAddress,parentItem,pq->_base._itemSize);
|
||||
pq->updateStoragePQ(pq, itemAddress, currentPos);
|
||||
currentPos = currentPos / 2;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// If the position has changed, then we moved the item up somewhere
|
||||
// ...........................................................................
|
||||
|
||||
if (currentPos != position) {
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
memcpy(itemAddress,currentItem,pq->_base._itemSize);
|
||||
pq->updateStoragePQ(pq, itemAddress, currentPos);
|
||||
TRI_Free(currentItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// ok perhaps item has to move down the heap since it is too heavy
|
||||
// ...........................................................................
|
||||
|
||||
while (pq->_base._count >= (2 * currentPos)) {
|
||||
leftChildItem = GetItemAddress(pq, (currentPos * 2));
|
||||
rightChildItem = GetItemAddress(pq, (currentPos * 2) + 1);
|
||||
|
||||
// this is to keep the heap balanced
|
||||
if ( (pq->_base._count > (2 * currentPos)) &&
|
||||
(pq->isLessPQ(pq, rightChildItem,leftChildItem)) &&
|
||||
(pq->isLessPQ(pq, rightChildItem, currentItem))
|
||||
) {
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
memcpy(itemAddress,rightChildItem,pq->_base._itemSize);
|
||||
pq->updateStoragePQ(pq, itemAddress, currentPos);
|
||||
currentPos = (2 * currentPos) + 1;
|
||||
}
|
||||
|
||||
// move item down
|
||||
else if (pq->isLessPQ(pq, leftChildItem, currentItem)) {
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
memcpy(itemAddress,leftChildItem,pq->_base._itemSize);
|
||||
pq->updateStoragePQ(pq, itemAddress, currentPos);
|
||||
currentPos = 2 * currentPos;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
itemAddress = GetItemAddress(pq,currentPos);
|
||||
memcpy(itemAddress,currentItem,pq->_base._itemSize);
|
||||
pq->updateStoragePQ(pq, itemAddress, currentPos);
|
||||
TRI_Free(currentItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool CompareIsLess(TRI_pqueue_t* pq, void* leftItem, void* rightItem) {
|
||||
if (pq->_base._reverse) {
|
||||
return !pq->isLessPQ(pq, leftItem, rightItem);
|
||||
}
|
||||
return pq->isLessPQ(pq, leftItem, rightItem);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief given a position returns the element stored in the priorty queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static char* GetItemAddress(TRI_pqueue_t* pq, uint64_t position) {
|
||||
if (position < 1 || position > pq->_base._count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((position - 1) * pq->_base._itemSize) + pq->_base._items;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -0,0 +1,204 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief priorty queue
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright by triAGENS GmbH - All rights reserved.
|
||||
///
|
||||
/// The Programs (which include both the software and documentation)
|
||||
/// contain proprietary information of triAGENS GmbH; they are
|
||||
/// provided under a license agreement containing restrictions on use and
|
||||
/// disclosure and are also protected by copyright, patent and other
|
||||
/// intellectual and industrial property laws. Reverse engineering,
|
||||
/// disassembly or decompilation of the Programs, except to the extent
|
||||
/// required to obtain interoperability with other independently created
|
||||
/// software or as specified by law, is prohibited.
|
||||
///
|
||||
/// The Programs are not intended for use in any nuclear, aviation, mass
|
||||
/// transit, medical, or other inherently dangerous applications. It shall
|
||||
/// be the licensee's responsibility to take all appropriate fail-safe,
|
||||
/// backup, redundancy, and other measures to ensure the safe use of such
|
||||
/// applications if the Programs are used for such purposes, and triAGENS
|
||||
/// GmbH disclaims liability for any damages caused by such use of
|
||||
/// the Programs.
|
||||
///
|
||||
/// This software is the confidential and proprietary information of
|
||||
/// triAGENS GmbH. You shall not disclose such confidential and
|
||||
/// proprietary information and shall use it only in accordance with the
|
||||
/// terms of the license agreement you entered into with triAGENS GmbH.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Dr. O
|
||||
/// @author Martin Schoenert
|
||||
/// @author Copyright 2009-2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_BASICS_C_PRIORITY_QUEUE_H
|
||||
#define TRIAGENS_BASICS_C_PRIORITY_QUEUE_H 1
|
||||
|
||||
#include "BasicsC/common.h"
|
||||
#include "BasicsC/locks.h"
|
||||
#include "BasicsC/vector.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Currently only double values are supported.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- skiplist public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief The base structure of a priority queue (pq)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_pqueue_base_s {
|
||||
// ...........................................................................
|
||||
// The current storage allocated to the pq. This is NOT the number of items
|
||||
// in the queue.
|
||||
// ...........................................................................
|
||||
size_t _capacity;
|
||||
|
||||
// ...........................................................................
|
||||
// The storage of the items as an array of element size
|
||||
// ...........................................................................
|
||||
char* _items;
|
||||
|
||||
// ...........................................................................
|
||||
// Size of each item (element)
|
||||
// ...........................................................................
|
||||
uint32_t _itemSize;
|
||||
|
||||
// ...........................................................................
|
||||
// The number of actual elements in the pq
|
||||
// ...........................................................................
|
||||
size_t _count;
|
||||
|
||||
// ...........................................................................
|
||||
// A counter which indicates the number of removals which are invalid.
|
||||
// ...........................................................................
|
||||
size_t _nrFalseRemoves;
|
||||
|
||||
// ...........................................................................
|
||||
// A counter which indicates the number of inserts which are invalid.
|
||||
// ...........................................................................
|
||||
size_t _nrFalseAdds;
|
||||
|
||||
// ...........................................................................
|
||||
// by default (reverse = false), items are stored from lowest to highest
|
||||
// so that the items which sort lowest are the ones which are removed first.
|
||||
// When this is set to true, the ... reverse is true ...eh? This can also
|
||||
// be achieved by the call back comparision function
|
||||
// ...........................................................................
|
||||
bool _reverse;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Additional hidden extenral structure used outside this priority queue
|
||||
// This hidden structure is not available within this priority queue
|
||||
// ...........................................................................
|
||||
// char[n]
|
||||
|
||||
}
|
||||
TRI_pqueue_base_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief The structure of a priority queue (pq)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct TRI_pqueue_s {
|
||||
TRI_pqueue_base_t _base;
|
||||
void (*clearStoragePQ) (struct TRI_pqueue_s*, void*);
|
||||
uint64_t (*getStoragePQ) (struct TRI_pqueue_s*, void*);
|
||||
bool (*isLessPQ) (struct TRI_pqueue_s*, void*, void*);
|
||||
void (*updateStoragePQ) (struct TRI_pqueue_s*, void*, uint64_t pos);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// default pq add, remove ,top methods
|
||||
// ...........................................................................
|
||||
|
||||
bool (*add) (struct TRI_pqueue_s*, void*);
|
||||
bool (*remove) (struct TRI_pqueue_s*, uint64_t, bool);
|
||||
void* (*top) (struct TRI_pqueue_s*);
|
||||
|
||||
}
|
||||
TRI_pqueue_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Priority Queue constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup PriorityQueue
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a priority queue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InitPQueue (TRI_pqueue_t*, size_t, size_t, bool,
|
||||
void (*clearStoragePQ) (struct TRI_pqueue_s*, void*),
|
||||
uint64_t (*getStoragePQ) (struct TRI_pqueue_s*, void*),
|
||||
bool (*isLessPQ) (struct TRI_pqueue_s*, void*, void*),
|
||||
void (*updateStoragePQ) (struct TRI_pqueue_s*, void*, uint64_t pos));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a skip list, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyPQueue (TRI_pqueue_t*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a skip list and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePQueue (TRI_pqueue_t*);
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -140,7 +140,7 @@ static uint64_t HashNameKeyAttributePath (TRI_associative_synced_t* array, void
|
|||
char const* k;
|
||||
|
||||
k = (char const*) key;
|
||||
|
||||
|
||||
return TRI_FnvHashString(k);
|
||||
}
|
||||
|
||||
|
@ -171,10 +171,13 @@ static bool EqualNameKeyAttributePath (TRI_associative_synced_t* array, void con
|
|||
k = (char const*) key;
|
||||
e = (char const*) element;
|
||||
ee = (TRI_shape_path_t const*) element;
|
||||
|
||||
|
||||
return TRI_EqualString(k,e + sizeof(TRI_shape_path_t) + ee->_aidLength * sizeof(TRI_shape_aid_t));
|
||||
/*
|
||||
return TRI_EqualString2(k,
|
||||
e + sizeof(TRI_shape_path_t) + ee->_aidLength * sizeof(TRI_shape_aid_t),
|
||||
ee->_nameLength - 1);
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -195,7 +198,7 @@ static TRI_shape_pid_t FindNameAttributePath (TRI_shaper_t* shaper, char const*
|
|||
void const* p;
|
||||
|
||||
p = TRI_LookupByKeyAssociativeSynced(&shaper->_attributePathsByName, name);
|
||||
|
||||
|
||||
if (p != NULL) {
|
||||
return ((TRI_shape_path_t const*) p)->_pid;
|
||||
}
|
||||
|
|
|
@ -580,11 +580,6 @@ TRI_long_string_shape_t;
|
|||
/// <td>number of variable attributes</td>
|
||||
/// </tr>
|
||||
/// <tr>
|
||||
/// <td>@c TRI_shape_size_t</td>
|
||||
/// <td>_variableEntries</td>
|
||||
/// <td>number of variable attributes</td>
|
||||
/// </tr>
|
||||
/// <tr>
|
||||
/// <td>@c TRI_shape_sid_t</td>
|
||||
/// <td>_sids[_fixedEntries + _variableEntries]</td>
|
||||
/// <td>shape identifier of the corresponding attribute</td>
|
||||
|
|
|
@ -213,9 +213,9 @@ describe AvocadoDB do
|
|||
end
|
||||
|
||||
# get count
|
||||
it "checks the parameter of a collection" do
|
||||
cmd = api + "/" + String(@cid) + "/parameter"
|
||||
doc = AvocadoDB.log_get("#{prefix}-get-collection-parameter", cmd)
|
||||
it "checks the properties of a collection" do
|
||||
cmd = api + "/" + String(@cid) + "/properties"
|
||||
doc = AvocadoDB.log_get("#{prefix}-get-collection-properties", cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json")
|
||||
|
@ -226,7 +226,7 @@ describe AvocadoDB do
|
|||
doc.parsed_response['status'].should eq(3)
|
||||
doc.parsed_response['waitForSync'].should eq(true)
|
||||
doc.parsed_response['journalSize'].should be_kind_of(Integer)
|
||||
doc.headers['location'].should eq(api + "/" + String(@cid) + "/parameter")
|
||||
doc.headers['location'].should eq(api + "/" + String(@cid) + "/properties")
|
||||
end
|
||||
|
||||
# get figures
|
||||
|
@ -654,11 +654,11 @@ describe AvocadoDB do
|
|||
end
|
||||
|
||||
################################################################################
|
||||
## parameter a collection
|
||||
## properties of a collection
|
||||
################################################################################
|
||||
|
||||
context "parameter:" do
|
||||
it "changing the parameter of a collection by identifier" do
|
||||
context "properties:" do
|
||||
it "changing the properties of a collection by identifier" do
|
||||
cn = "UnitTestsCollectionBasics"
|
||||
AvocadoDB.drop_collection(cn)
|
||||
cid = AvocadoDB.create_collection(cn)
|
||||
|
@ -673,9 +673,9 @@ describe AvocadoDB do
|
|||
AvocadoDB.size_collection(cid).should eq(10)
|
||||
AvocadoDB.size_collection(cn).should eq(10)
|
||||
|
||||
cmd = api + "/" + String(cid) + "/parameter"
|
||||
cmd = api + "/" + String(cid) + "/properties"
|
||||
body = "{ \"waitForSync\" : true }"
|
||||
doc = AvocadoDB.log_put("#{prefix}-identifier-parameter-sync", cmd, :body => body)
|
||||
doc = AvocadoDB.log_put("#{prefix}-identifier-properties-sync", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json")
|
||||
|
@ -686,9 +686,9 @@ describe AvocadoDB do
|
|||
doc.parsed_response['status'].should eq(3)
|
||||
doc.parsed_response['waitForSync'].should eq(true)
|
||||
|
||||
cmd = api + "/" + String(cid) + "/parameter"
|
||||
cmd = api + "/" + String(cid) + "/properties"
|
||||
body = "{ \"waitForSync\" : false }"
|
||||
doc = AvocadoDB.log_put("#{prefix}-identifier-parameter-no-sync", cmd, :body => body)
|
||||
doc = AvocadoDB.log_put("#{prefix}-identifier-properties-no-sync", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json")
|
||||
|
|
|
@ -2165,6 +2165,70 @@ static v8::Handle<v8::Value> JS_WhereHashConstAql (const v8::Arguments& argv) {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_WherePQConstAql (const v8::Arguments& argv) {
|
||||
v8::HandleScope scope;
|
||||
TRI_json_t* parameterList;
|
||||
|
||||
if (argv.Length() > 2 || argv.Length() == 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: AQL_WHERE_PQ_CONST(<index-identifier> {,<value 1>})")));
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// check that the first parameter sent is a double value -- the index id
|
||||
// ..........................................................................
|
||||
|
||||
bool inValidType = true;
|
||||
TRI_idx_iid_t iid = TRI_ObjectToDouble(argv[0], inValidType);
|
||||
|
||||
if (inValidType || iid == 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("<index-identifier> must be an positive integer")));
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Store the index field parameters in a json object -- there is only one
|
||||
// possible parameter to be sent - the number of top documents to query.
|
||||
// ..........................................................................
|
||||
|
||||
parameterList = TRI_CreateListJson();
|
||||
if (!parameterList) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("out of memory in JS_WherePQConstAql")));
|
||||
}
|
||||
|
||||
|
||||
if (argv.Length() == 1) {
|
||||
TRI_json_t* jsonParameter = TRI_CreateNumberJson(1);
|
||||
if (jsonParameter == NULL) { // failure of some sort
|
||||
return scope.Close(v8::ThrowException(v8::String::New("internal error in JS_WherePQConstAql")));
|
||||
}
|
||||
TRI_PushBackListJson(parameterList, jsonParameter);
|
||||
}
|
||||
|
||||
else {
|
||||
for (int j = 1; j < argv.Length(); ++j) {
|
||||
v8::Handle<v8::Value> parameter = argv[j];
|
||||
TRI_json_t* jsonParameter = ConvertHelper(parameter);
|
||||
if (jsonParameter == NULL) { // NOT the null json value!
|
||||
return scope.Close(v8::ThrowException(v8::String::New("type value not currently supported for priority queue index")));
|
||||
}
|
||||
TRI_PushBackListJson(parameterList, jsonParameter);
|
||||
}
|
||||
}
|
||||
|
||||
// build document priority queue access
|
||||
TRI_qry_where_t* where = TRI_CreateQueryWherePQConstant(iid, parameterList);
|
||||
|
||||
// wrap it up
|
||||
return scope.Close(WrapWhere(where));
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2391,6 +2455,79 @@ static v8::Handle<v8::Value> JS_HashSelectAql (v8::Arguments const& argv) {
|
|||
return scope.Close(WrapQuery(query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static v8::Handle<v8::Value> JS_PQSelectAql (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() != 2) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: AQL_PQ_SELECT(collection, where)")));
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// extract the primary collection
|
||||
// ...........................................................................
|
||||
v8::Handle<v8::Value> collectionArg = argv[0];
|
||||
if (! collectionArg->IsObject()) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("expecting a COLLECTION as first argument")));
|
||||
}
|
||||
v8::Handle<v8::Object> collectionObj = collectionArg->ToObject();
|
||||
|
||||
v8::Handle<v8::Object> err;
|
||||
const TRI_vocbase_col_t* collection = UseCollection(collectionObj, &err);
|
||||
|
||||
if (collection == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Extract the where clause
|
||||
// ...........................................................................
|
||||
v8::Handle<v8::Value> whereArg = argv[1];
|
||||
TRI_qry_where_t* where = 0;
|
||||
if (whereArg->IsNull()) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("expecting a WHERE object as second argument")));
|
||||
}
|
||||
v8::Handle<v8::Object> whereObj = whereArg->ToObject();
|
||||
where = UnwrapClass<TRI_qry_where_t>(whereObj, WRP_QRY_WHERE_TYPE);
|
||||
if (where == 0) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted WHERE")));
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Check the operators
|
||||
// ...........................................................................
|
||||
TRI_qry_where_priorityqueue_const_t* pqWhere = (TRI_qry_where_priorityqueue_const_t*)(where);
|
||||
TRI_priorityqueue_index_t* idx = (TRI_priorityqueue_index_t*)(TRI_LookupIndex(collection->_collection, pqWhere->_iid));
|
||||
if (idx == NULL) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("invalid index in where statement")));
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Create the skiplist query
|
||||
// ...........................................................................
|
||||
TRI_query_t* query = TRI_CreatePriorityQueueQuery(where, collection->_collection);
|
||||
if (!query) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("could not create query object")));
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// wrap it up
|
||||
// ...........................................................................
|
||||
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(WrapQuery(query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructs a new query from given parts - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3882,6 +4019,179 @@ static v8::Handle<v8::Value> JS_EnsureHashIndexVocbaseCol (v8::Arguments const&
|
|||
return EnsureHashSkipListIndex("ensureHashIndex", argv, false, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a priority queue index exists
|
||||
///
|
||||
/// @FUN{ensureSLIndex(@FA{field1})}
|
||||
///
|
||||
/// Creates a priority queue index on all documents using attributes as paths to
|
||||
/// the fields. Currently only supports one attribute of the type double.
|
||||
/// All documents, which do not have the attribute path are ignored.
|
||||
///
|
||||
/// In case that the index was successfully created, the index indetifier
|
||||
/// is returned.
|
||||
///
|
||||
/// @verbinclude fluent14
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_EnsurePriorityQueueIndexVocbaseCol (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
bool created = false;
|
||||
TRI_index_t* idx;
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Check that we have a valid collection
|
||||
// .............................................................................
|
||||
|
||||
v8::Handle<v8::Object> err;
|
||||
TRI_vocbase_col_t const* collection = UseCollection(argv.Holder(), &err);
|
||||
|
||||
if (collection == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// Check collection type
|
||||
// .............................................................................
|
||||
|
||||
TRI_doc_collection_t* doc = collection->_collection;
|
||||
|
||||
if (doc->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("unknown collection type")));
|
||||
}
|
||||
|
||||
TRI_sim_collection_t* sim = (TRI_sim_collection_t*) doc;
|
||||
|
||||
// .............................................................................
|
||||
// Return string when there is an error of some sort.
|
||||
// .............................................................................
|
||||
|
||||
string errorString;
|
||||
|
||||
// .............................................................................
|
||||
// Ensure that there is at least one string parameter sent to this method
|
||||
// .............................................................................
|
||||
|
||||
if (argv.Length() != 1) {
|
||||
ReleaseCollection(collection);
|
||||
|
||||
errorString = "one string parameter required for the ensurePQIndex(...) command";
|
||||
return scope.Close(v8::String::New(errorString.c_str(),errorString.length()));
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Create a list of paths, these will be used to create a list of shapes
|
||||
// which will be used by the priority queue index.
|
||||
// .............................................................................
|
||||
|
||||
TRI_vector_t attributes;
|
||||
TRI_InitVector(&attributes,sizeof(char*));
|
||||
|
||||
bool ok = true;
|
||||
|
||||
for (int j = 0; j < argv.Length(); ++j) {
|
||||
|
||||
v8::Handle<v8::Value> argument = argv[j];
|
||||
if (! argument->IsString() ) {
|
||||
errorString = "invalid parameter passed to ensurePQIndex(...) command";
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// convert the argument into a "C" string
|
||||
// ...........................................................................
|
||||
|
||||
v8::String::Utf8Value argumentString(argument);
|
||||
char* cArgument = (char*) (TRI_Allocate(argumentString.length() + 1));
|
||||
if (cArgument == NULL) {
|
||||
errorString = "insuffient memory to complete ensurePQIndex(...) command";
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(cArgument, *argumentString, argumentString.length());
|
||||
TRI_PushBackVector(&attributes,&cArgument);
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// Check that each parameter is unique
|
||||
// .............................................................................
|
||||
|
||||
for (size_t j = 0; j < attributes._length; ++j) {
|
||||
char* left = *((char**) (TRI_AtVector(&attributes, j)));
|
||||
for (size_t k = j + 1; k < attributes._length; ++k) {
|
||||
char* right = *((char**) (TRI_AtVector(&attributes, k)));
|
||||
if (strcmp(left,right) == 0) {
|
||||
errorString = "duplicate parameters sent to ensurePQIndex(...) command";
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// Some sort of error occurred -- display error message and abort index creation
|
||||
// (or index retrieval).
|
||||
// .............................................................................
|
||||
|
||||
if (!ok) {
|
||||
// ...........................................................................
|
||||
// Remove the memory allocated to the list of attributes used for the hash index
|
||||
// ...........................................................................
|
||||
for (size_t j = 0; j < attributes._length; ++j) {
|
||||
char* cArgument = *((char**) (TRI_AtVector(&attributes, j)));
|
||||
TRI_Free(cArgument);
|
||||
}
|
||||
TRI_DestroyVector(&attributes);
|
||||
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::String::New(errorString.c_str(),errorString.length()));
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// Actually create the index here. Note that priority queue is never unique.
|
||||
// .............................................................................
|
||||
|
||||
idx = TRI_EnsurePriorityQueueIndexSimCollection(sim, &attributes, false, &created);
|
||||
|
||||
// .............................................................................
|
||||
// Remove the memory allocated to the list of attributes used for the hash index
|
||||
// .............................................................................
|
||||
|
||||
for (size_t j = 0; j < attributes._length; ++j) {
|
||||
char* cArgument = *((char**) (TRI_AtVector(&attributes, j)));
|
||||
TRI_Free(cArgument);
|
||||
}
|
||||
|
||||
TRI_DestroyVector(&attributes);
|
||||
|
||||
if (idx == NULL) {
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(v8::String::New("Priority Queue index could not be created"));
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// Return the newly assigned index identifier
|
||||
// .............................................................................
|
||||
|
||||
TRI_json_t* json = idx->json(idx, collection->_collection);
|
||||
v8::Handle<v8::Value> index = TRI_ObjectJson(json);
|
||||
|
||||
if (index->IsObject()) {
|
||||
index->ToObject()->Set(v8::String::New("isNewlyCreated"), created ? v8::True() : v8::False());
|
||||
}
|
||||
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a skiplist index exists
|
||||
///
|
||||
|
@ -3902,6 +4212,8 @@ static v8::Handle<v8::Value> JS_EnsureUniqueSkiplistVocbaseCol (v8::Arguments co
|
|||
return EnsureHashSkipListIndex("ensureUniqueSkipList", argv, true, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a multi skiplist index exists
|
||||
///
|
||||
|
@ -4058,32 +4370,32 @@ static v8::Handle<v8::Value> JS_NameVocbaseCol (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets or sets the parameters of a collection
|
||||
/// @brief gets or sets the properties of a collection
|
||||
///
|
||||
/// @FUN{parameter()}
|
||||
/// @FUN{properties()}
|
||||
///
|
||||
/// Returns an object containing all collection parameters.
|
||||
/// Returns an object containing all collection properties.
|
||||
///
|
||||
/// - @LIT{waitForSync}: If @LIT{true} creating a document will only return
|
||||
/// after the data was synced to disk.
|
||||
/// - @LIT{journalSize} : The size of the journal in bytes.
|
||||
///
|
||||
/// @FUN{parameter(@FA{parameter-array})}
|
||||
/// @FUN{properties(@FA{properties-array})}
|
||||
///
|
||||
/// Changes the collection parameters.
|
||||
/// Changes the collection properties.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Read all parameters
|
||||
/// Read all properties
|
||||
///
|
||||
/// @verbinclude admin1
|
||||
///
|
||||
/// Change a parameter
|
||||
/// Change a property
|
||||
///
|
||||
/// @verbinclude admin2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ParameterVocbaseCol (v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> JS_PropertiesVocbaseCol (v8::Arguments const& argv) {
|
||||
TRI_v8_global_t* v8g;
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
@ -5367,10 +5679,18 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8::Handle<v8::String> DropIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("dropIndex"));
|
||||
v8::Handle<v8::String> EdgesFuncName = v8::Persistent<v8::String>::New(v8::String::New("edges"));
|
||||
v8::Handle<v8::String> EnsureGeoIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureGeoIndex"));
|
||||
/*
|
||||
oreste:
|
||||
v8::Handle<v8::String> EnsureMultiHashIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureMultiHashIndex"));
|
||||
v8::Handle<v8::String> EnsureMultiSkiplistIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureMultiSLIndex"));
|
||||
v8::Handle<v8::String> EnsureSkiplistIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureSLIndex"));
|
||||
*/
|
||||
v8::Handle<v8::String> EnsureHashIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureHashIndex"));
|
||||
v8::Handle<v8::String> EnsurePriorityQueueIndexFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensurePQIndex"));
|
||||
v8::Handle<v8::String> EnsureSkiplistFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureSkiplist"));
|
||||
v8::Handle<v8::String> EnsureUniqueConstraintFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureUniqueConstraint"));
|
||||
v8::Handle<v8::String> EnsureUniqueSkiplistFuncName = v8::Persistent<v8::String>::New(v8::String::New("ensureUniqueSkiplist"));
|
||||
|
||||
v8::Handle<v8::String> ExecuteFuncName = v8::Persistent<v8::String>::New(v8::String::New("execute"));
|
||||
v8::Handle<v8::String> FiguresFuncName = v8::Persistent<v8::String>::New(v8::String::New("figures"));
|
||||
v8::Handle<v8::String> GetBatchSizeFuncName = v8::Persistent<v8::String>::New(v8::String::New("getBatchSize"));
|
||||
|
@ -5385,8 +5705,8 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8::Handle<v8::String> NextFuncName = v8::Persistent<v8::String>::New(v8::String::New("next"));
|
||||
v8::Handle<v8::String> NextRefFuncName = v8::Persistent<v8::String>::New(v8::String::New("nextRef"));
|
||||
v8::Handle<v8::String> OutEdgesFuncName = v8::Persistent<v8::String>::New(v8::String::New("outEdges"));
|
||||
v8::Handle<v8::String> ParameterFuncName = v8::Persistent<v8::String>::New(v8::String::New("parameter"));
|
||||
v8::Handle<v8::String> PersistFuncName = v8::Persistent<v8::String>::New(v8::String::New("persist"));
|
||||
v8::Handle<v8::String> PropertiesFuncName = v8::Persistent<v8::String>::New(v8::String::New("properties"));
|
||||
v8::Handle<v8::String> RenameFuncName = v8::Persistent<v8::String>::New(v8::String::New("rename"));
|
||||
v8::Handle<v8::String> ReplaceFuncName = v8::Persistent<v8::String>::New(v8::String::New("replace"));
|
||||
v8::Handle<v8::String> SaveFuncName = v8::Persistent<v8::String>::New(v8::String::New("save"));
|
||||
|
@ -5544,16 +5864,25 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
rt->Set(DropFuncName, v8::FunctionTemplate::New(JS_DropVocbaseCol));
|
||||
rt->Set(DropIndexFuncName, v8::FunctionTemplate::New(JS_DropIndexVocbaseCol));
|
||||
rt->Set(EnsureGeoIndexFuncName, v8::FunctionTemplate::New(JS_EnsureGeoIndexVocbaseCol));
|
||||
|
||||
/* oreste:
|
||||
rt->Set(EnsureMultiHashIndexFuncName, v8::FunctionTemplate::New(JS_EnsureMultiHashIndexVocbaseCol));
|
||||
rt->Set(EnsureMultiSkiplistIndexFuncName, v8::FunctionTemplate::New(JS_EnsureMultiSkiplistIndexVocbaseCol));
|
||||
rt->Set(EnsureSkiplistIndexFuncName, v8::FunctionTemplate::New(JS_EnsureSkiplistIndexVocbaseCol));
|
||||
*/
|
||||
|
||||
rt->Set(EnsureHashIndexFuncName, v8::FunctionTemplate::New(JS_EnsureHashIndexVocbaseCol));
|
||||
rt->Set(EnsurePriorityQueueIndexFuncName, v8::FunctionTemplate::New(JS_EnsurePriorityQueueIndexVocbaseCol));
|
||||
rt->Set(EnsureSkiplistFuncName, v8::FunctionTemplate::New(JS_EnsureSkiplistVocbaseCol));
|
||||
rt->Set(EnsureUniqueSkiplistFuncName, v8::FunctionTemplate::New(JS_EnsureUniqueSkiplistVocbaseCol));
|
||||
rt->Set(EnsureUniqueConstraintFuncName, v8::FunctionTemplate::New(JS_EnsureUniqueConstraintVocbaseCol));
|
||||
|
||||
rt->Set(FiguresFuncName, v8::FunctionTemplate::New(JS_FiguresVocbaseCol));
|
||||
rt->Set(GetIndexesFuncName, v8::FunctionTemplate::New(JS_GetIndexesVocbaseCol));
|
||||
rt->Set(LoadFuncName, v8::FunctionTemplate::New(JS_LoadVocbaseCol));
|
||||
rt->Set(NameFuncName, v8::FunctionTemplate::New(JS_NameVocbaseCol));
|
||||
rt->Set(NearFuncName, v8::FunctionTemplate::New(JS_NearQuery));
|
||||
rt->Set(ParameterFuncName, v8::FunctionTemplate::New(JS_ParameterVocbaseCol));
|
||||
rt->Set(PropertiesFuncName, v8::FunctionTemplate::New(JS_PropertiesVocbaseCol));
|
||||
rt->Set(RenameFuncName, v8::FunctionTemplate::New(JS_RenameVocbaseCol));
|
||||
rt->Set(StatusFuncName, v8::FunctionTemplate::New(JS_StatusVocbaseCol));
|
||||
rt->Set(UnloadFuncName, v8::FunctionTemplate::New(JS_UnloadVocbaseCol));
|
||||
|
@ -5583,16 +5912,23 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
rt->Set(DropFuncName, v8::FunctionTemplate::New(JS_DropVocbaseCol));
|
||||
rt->Set(DropIndexFuncName, v8::FunctionTemplate::New(JS_DropIndexVocbaseCol));
|
||||
rt->Set(EnsureGeoIndexFuncName, v8::FunctionTemplate::New(JS_EnsureGeoIndexVocbaseCol));
|
||||
/* oreste
|
||||
rt->Set(EnsureMultiHashIndexFuncName, v8::FunctionTemplate::New(JS_EnsureMultiHashIndexVocbaseCol));
|
||||
rt->Set(EnsureMultiSkiplistIndexFuncName, v8::FunctionTemplate::New(JS_EnsureMultiSkiplistIndexVocbaseCol));
|
||||
rt->Set(EnsureSkiplistIndexFuncName, v8::FunctionTemplate::New(JS_EnsureSkiplistIndexVocbaseCol));
|
||||
*/
|
||||
rt->Set(EnsureHashIndexFuncName, v8::FunctionTemplate::New(JS_EnsureHashIndexVocbaseCol));
|
||||
rt->Set(EnsurePriorityQueueIndexFuncName, v8::FunctionTemplate::New(JS_EnsurePriorityQueueIndexVocbaseCol));
|
||||
rt->Set(EnsureSkiplistFuncName, v8::FunctionTemplate::New(JS_EnsureSkiplistVocbaseCol));
|
||||
rt->Set(EnsureUniqueConstraintFuncName, v8::FunctionTemplate::New(JS_EnsureUniqueConstraintVocbaseCol));
|
||||
rt->Set(EnsureUniqueSkiplistFuncName, v8::FunctionTemplate::New(JS_EnsureUniqueSkiplistVocbaseCol));
|
||||
|
||||
rt->Set(FiguresFuncName, v8::FunctionTemplate::New(JS_FiguresVocbaseCol));
|
||||
rt->Set(GetIndexesFuncName, v8::FunctionTemplate::New(JS_GetIndexesVocbaseCol));
|
||||
rt->Set(LoadFuncName, v8::FunctionTemplate::New(JS_LoadVocbaseCol));
|
||||
rt->Set(NameFuncName, v8::FunctionTemplate::New(JS_NameVocbaseCol));
|
||||
rt->Set(NearFuncName, v8::FunctionTemplate::New(JS_NearQuery));
|
||||
rt->Set(ParameterFuncName, v8::FunctionTemplate::New(JS_ParameterVocbaseCol));
|
||||
rt->Set(PropertiesFuncName, v8::FunctionTemplate::New(JS_PropertiesVocbaseCol));
|
||||
rt->Set(RenameFuncName, v8::FunctionTemplate::New(JS_RenameVocbaseCol));
|
||||
rt->Set(ReplaceFuncName, v8::FunctionTemplate::New(JS_ReplaceVocbaseCol));
|
||||
rt->Set(StatusFuncName, v8::FunctionTemplate::New(JS_StatusVocbaseCol));
|
||||
|
@ -5742,6 +6078,10 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8::FunctionTemplate::New(JS_WhereHashConstAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AQL_WHERE_PQ_CONST"),
|
||||
v8::FunctionTemplate::New(JS_WherePQConstAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AQL_WHERE_SL_CONST"),
|
||||
v8::FunctionTemplate::New(JS_WhereSkiplistConstAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
@ -5762,6 +6102,10 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8::FunctionTemplate::New(JS_HashSelectAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AQL_PQ_SELECT"),
|
||||
v8::FunctionTemplate::New(JS_PQSelectAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AQL_SL_SELECT"),
|
||||
v8::FunctionTemplate::New(JS_SkiplistSelectAql)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
|
|
@ -161,6 +161,11 @@ namespace triagens {
|
|||
if (!_httpResult->isComplete()) {
|
||||
// not complete
|
||||
_lastErrorMessage = _client->getErrorMessage();
|
||||
|
||||
if (_lastErrorMessage == "") {
|
||||
_lastErrorMessage = "Unknown error";
|
||||
}
|
||||
|
||||
_lastHttpReturnCode = SimpleHttpResult::HTTP_STATUS_SERVER_ERROR;
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
|
|
|
@ -206,7 +206,7 @@ static v8::Handle<v8::Value> JS_PagerOutput (v8::Arguments const& argv) {
|
|||
/// @brief starts the output pager
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_StartOutputPager (v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> JS_StartOutputPager (v8::Arguments const& ) {
|
||||
if (usePager) {
|
||||
internalPrint("Using pager already.\n");
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ static v8::Handle<v8::Value> JS_StartOutputPager (v8::Arguments const& argv) {
|
|||
/// @brief stops the output pager
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_StopOutputPager (v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> JS_StopOutputPager (v8::Arguments const& ) {
|
||||
if (usePager) {
|
||||
internalPrint("Stopping pager.\n");
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ enum WRAP_CLASS_TYPES {WRAP_TYPE_CONNECTION = 1};
|
|||
/// @brief weak reference callback for queries (call the destructor here)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ClientConnection_DestructorCallback (v8::Persistent<v8::Value> object, void* parameter) {
|
||||
static void ClientConnection_DestructorCallback (v8::Persistent<v8::Value> , void* parameter) {
|
||||
V8ClientConnection* client = (V8ClientConnection*) parameter;
|
||||
delete(client);
|
||||
}
|
||||
|
|
790
VocBase/index.c
790
VocBase/index.c
|
@ -215,6 +215,9 @@ char const* TRI_TypeNameIndex (const TRI_index_t* const idx) {
|
|||
case TRI_IDX_TYPE_HASH_INDEX:
|
||||
return "hash";
|
||||
|
||||
case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX:
|
||||
return "priorityqueue";
|
||||
|
||||
case TRI_IDX_TYPE_SKIPLIST_INDEX:
|
||||
return "skiplist";
|
||||
|
||||
|
@ -1005,7 +1008,7 @@ static int HashIndexHelper (const TRI_hash_index_t* hashIndex,
|
|||
}
|
||||
|
||||
TRI_Free(hashElement->fields);
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
|
@ -1043,6 +1046,7 @@ static int HashIndexHelper (const TRI_hash_index_t* hashIndex,
|
|||
|
||||
// ..........................................................................
|
||||
// Determine if document has that particular shape
|
||||
// It is not an error if the document DOES NOT have the particular shape
|
||||
// ..........................................................................
|
||||
|
||||
acc = TRI_ShapeAccessor(hashIndex->base._collection->_shaper, document->_document._sid, shape);
|
||||
|
@ -1054,7 +1058,7 @@ static int HashIndexHelper (const TRI_hash_index_t* hashIndex,
|
|||
|
||||
TRI_Free(hashElement->fields);
|
||||
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
|
@ -1119,8 +1123,17 @@ static int InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
|||
}
|
||||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, doc, NULL);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that this document does not have the necessary attributes
|
||||
// (keys) to participate in this index.
|
||||
// ............................................................................
|
||||
|
||||
if (res == -1) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1260,7 +1273,18 @@ static int RemoveHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
|||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, doc, NULL);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
||||
// ..........................................................................
|
||||
// It may happen that the document does not have attributes which match
|
||||
// For now return internal error, there needs to be its own error number
|
||||
// and the appropriate action needs to be taken by the calling function in
|
||||
// such cases.
|
||||
// ..........................................................................
|
||||
|
||||
if (res == -1) {
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1334,7 +1358,9 @@ static int UpdateHashIndex (TRI_index_t* idx,
|
|||
// ............................................................................
|
||||
|
||||
if (hashIndex->base._unique) {
|
||||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, NULL, oldDoc);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
||||
// ............................................................................
|
||||
|
@ -1366,12 +1392,16 @@ static int UpdateHashIndex (TRI_index_t* idx,
|
|||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, newDoc, NULL);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
||||
if (res == -1) {
|
||||
|
||||
// ..........................................................................
|
||||
// probably fields do not match
|
||||
// probably fields do not match. For now just return internal error
|
||||
// ..........................................................................
|
||||
|
||||
return TRI_ERROR_INTERNAL;
|
||||
|
||||
}
|
||||
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1394,7 +1424,7 @@ static int UpdateHashIndex (TRI_index_t* idx,
|
|||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, NULL, oldDoc);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
||||
// ............................................................................
|
||||
// We must fill the hashElement with the value of the document shape -- this
|
||||
|
@ -1415,18 +1445,26 @@ static int UpdateHashIndex (TRI_index_t* idx,
|
|||
}
|
||||
}
|
||||
|
||||
else {
|
||||
LOG_WARNING("existing document could not be removed");
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Fill the shaped json simple list from the document
|
||||
// ............................................................................
|
||||
|
||||
res = HashIndexHelper(hashIndex, &hashElement, newDoc, NULL);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (res == -1) {
|
||||
|
||||
// ..........................................................................
|
||||
// probably fields do not match
|
||||
// probably fields do not match -- report internal error for now
|
||||
// ..........................................................................
|
||||
|
||||
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1605,6 +1643,732 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PRIORITY QUEUE INDEX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PRIVATE FUNCTIONS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief helper for priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int PriorityQueueIndexHelper (const TRI_priorityqueue_index_t* pqIndex,
|
||||
PQIndexElement* pqElement,
|
||||
const TRI_doc_mptr_t* document,
|
||||
const TRI_shaped_json_t* shapedDoc) {
|
||||
union { void* p; void const* c; } cnv;
|
||||
TRI_shaped_json_t shapedObject;
|
||||
TRI_shape_access_t* acc;
|
||||
size_t j;
|
||||
|
||||
// ............................................................................
|
||||
// TODO: allow documents to be indexed on other keys (attributes) besides
|
||||
// doubles. For now, documents which do have an attribute of double, will be
|
||||
// be skipped. We return -2 to indicate this.
|
||||
// ............................................................................
|
||||
|
||||
if (shapedDoc != NULL) {
|
||||
|
||||
// ..........................................................................
|
||||
// Attempting to locate a priority queue entry using TRI_shaped_json_t object.
|
||||
// Use this when we wish to remove a priority queue entry and we only have
|
||||
// the "keys" rather than having the document (from which the keys would follow).
|
||||
// ..........................................................................
|
||||
|
||||
pqElement->data = NULL;
|
||||
|
||||
|
||||
|
||||
for (j = 0; j < pqIndex->_paths._length; ++j) {
|
||||
TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&pqIndex->_paths,j)));
|
||||
|
||||
// ..........................................................................
|
||||
// Determine if document has that particular shape
|
||||
// ..........................................................................
|
||||
|
||||
acc = TRI_ShapeAccessor(pqIndex->base._collection->_shaper, shapedDoc->_sid, shape);
|
||||
|
||||
if (acc == NULL || acc->_shape == NULL) {
|
||||
if (acc != NULL) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
}
|
||||
|
||||
TRI_Free(pqElement->fields);
|
||||
// the attribute does not exist in the document
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Determine if the attribute is of the type double -- if not for now
|
||||
// ignore this document
|
||||
// ..........................................................................
|
||||
|
||||
if (acc->_shape->_type != TRI_SHAPE_NUMBER) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
TRI_Free(pqElement->fields);
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Extract the field
|
||||
// ..........................................................................
|
||||
|
||||
if (! TRI_ExecuteShapeAccessor(acc, shapedDoc, &shapedObject)) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
TRI_Free(pqElement->fields);
|
||||
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Store the json shaped Object -- this is what will be hashed
|
||||
// ..........................................................................
|
||||
|
||||
pqElement->fields[j] = shapedObject;
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
} // end of for loop
|
||||
}
|
||||
|
||||
else if (document != NULL) {
|
||||
|
||||
// ..........................................................................
|
||||
// Assign the document to the PQIndexElement structure - so that it can later
|
||||
// be retreived.
|
||||
// ..........................................................................
|
||||
|
||||
cnv.c = document;
|
||||
pqElement->data = cnv.p;
|
||||
|
||||
for (j = 0; j < pqIndex->_paths._length; ++j) {
|
||||
TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&pqIndex->_paths,j)));
|
||||
|
||||
// ..........................................................................
|
||||
// Determine if document has that particular shape
|
||||
// It is not an error if the document DOES NOT have the particular shape
|
||||
// ..........................................................................
|
||||
|
||||
acc = TRI_ShapeAccessor(pqIndex->base._collection->_shaper, document->_document._sid, shape);
|
||||
|
||||
if (acc == NULL || acc->_shape == NULL) {
|
||||
if (acc != NULL) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
}
|
||||
|
||||
TRI_Free(pqElement->fields);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Determine if the attribute is of the type double -- if not for now
|
||||
// ignore this document
|
||||
// ..........................................................................
|
||||
|
||||
if (acc->_shape->_type != TRI_SHAPE_NUMBER) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
TRI_Free(pqElement->fields);
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
// Extract the field
|
||||
// ..........................................................................
|
||||
|
||||
if (! TRI_ExecuteShapeAccessor(acc, &(document->_document), &shapedObject)) {
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
TRI_Free(pqElement->fields);
|
||||
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Store the field
|
||||
// ..........................................................................
|
||||
|
||||
pqElement->fields[j] = shapedObject;
|
||||
|
||||
TRI_FreeShapeAccessor(acc);
|
||||
} // end of for loop
|
||||
}
|
||||
|
||||
else {
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief attempts to add a document to a priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int InsertPriorityQueueIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
PQIndexElement pqElement;
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
int res;
|
||||
|
||||
// ............................................................................
|
||||
// Obtain the priority queue index structure
|
||||
// ............................................................................
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
if (idx == NULL) {
|
||||
LOG_WARNING("internal error in InsertPriorityQueueIndex");
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Allocate storage to shaped json objects stored as a simple list.
|
||||
// These will be used for adding the document to the priority queue
|
||||
// ............................................................................
|
||||
|
||||
pqElement.numFields = pqIndex->_paths._length;
|
||||
pqElement.fields = TRI_Allocate(sizeof(TRI_shaped_json_t) * pqElement.numFields);
|
||||
pqElement.collection = pqIndex->base._collection;
|
||||
|
||||
|
||||
if (pqElement.fields == NULL) {
|
||||
LOG_WARNING("out-of-memory in InsertPriorityQueueIndex");
|
||||
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
res = PriorityQueueIndexHelper(pqIndex, &pqElement, doc, NULL);
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that this document does not have the necessary attributes
|
||||
// (keys) to participate in this index. Skip this document for now.
|
||||
// ............................................................................
|
||||
|
||||
if (res == -1) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that while we have the correct attribute name, the type is
|
||||
// not double. Skip this document for now.
|
||||
// ............................................................................
|
||||
|
||||
else if (res == -2) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// Some other error has occurred - report this error to the calling function
|
||||
// ............................................................................
|
||||
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Attempt to insert document into priority queue index
|
||||
// ............................................................................
|
||||
|
||||
res = PQIndex_insert(pqIndex->_pqIndex, &pqElement);
|
||||
|
||||
if (res == TRI_ERROR_AVOCADO_INDEX_PQ_INSERT_FAILED) {
|
||||
LOG_WARNING("priority queue insert failure");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief describes a priority queue index as a json object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_json_t* JsonPriorityQueueIndex (TRI_index_t* idx, TRI_doc_collection_t const* collection) {
|
||||
TRI_json_t* json;
|
||||
TRI_json_t* fields;
|
||||
const TRI_shape_path_t* path;
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
char const** fieldList;
|
||||
size_t j;
|
||||
|
||||
// ..........................................................................
|
||||
// Recast as a priority queue index
|
||||
// ..........................................................................
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
if (pqIndex == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Allocate sufficent memory for the field list
|
||||
// ..........................................................................
|
||||
|
||||
fieldList = TRI_Allocate( (sizeof(char*) * pqIndex->_paths._length) );
|
||||
|
||||
if (fieldList == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Convert the attributes (field list of the hash index) into strings
|
||||
// ..........................................................................
|
||||
|
||||
for (j = 0; j < pqIndex->_paths._length; ++j) {
|
||||
TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&pqIndex->_paths,j)));
|
||||
path = collection->_shaper->lookupAttributePathByPid(collection->_shaper, shape);
|
||||
|
||||
if (path == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
TRI_Free(fieldList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fieldList[j] = ((const char*) path) + sizeof(TRI_shape_path_t) + path->_aidLength * sizeof(TRI_shape_aid_t);
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// create json object and fill it
|
||||
// ..........................................................................
|
||||
|
||||
json = TRI_CreateArrayJson();
|
||||
|
||||
if (json == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
TRI_Free(fieldList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fields = TRI_CreateListJson();
|
||||
|
||||
for (j = 0; j < pqIndex->_paths._length; ++j) {
|
||||
TRI_PushBack3ListJson(fields, TRI_CreateStringCopyJson(fieldList[j]));
|
||||
}
|
||||
|
||||
TRI_Insert3ArrayJson(json, "id", TRI_CreateNumberJson(idx->_iid));
|
||||
TRI_Insert3ArrayJson(json, "unique", TRI_CreateBooleanJson(pqIndex->base._unique));
|
||||
TRI_Insert3ArrayJson(json, "type", TRI_CreateStringCopyJson(TRI_TypeNameIndex(idx)));
|
||||
TRI_Insert3ArrayJson(json, "fields", fields);
|
||||
|
||||
TRI_Free(fieldList);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes a document from a priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int RemovePriorityQueueIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
PQIndexElement pqElement;
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
int res;
|
||||
|
||||
// ............................................................................
|
||||
// Obtain the priority queue index structure
|
||||
// ............................................................................
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
if (idx == NULL) {
|
||||
LOG_WARNING("internal error in RemovePriorityQueueIndex");
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Allocate some memory for the PQIndexElement structure
|
||||
// ............................................................................
|
||||
|
||||
pqElement.numFields = pqIndex->_paths._length;
|
||||
pqElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * pqElement.numFields);
|
||||
pqElement.collection = pqIndex->base._collection;
|
||||
|
||||
if (pqElement.fields == NULL) {
|
||||
LOG_WARNING("out-of-memory in RemovePriorityQueueIndex");
|
||||
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// ..........................................................................
|
||||
// Fill the json field list from the document
|
||||
// ..........................................................................
|
||||
|
||||
res = PriorityQueueIndexHelper(pqIndex, &pqElement, doc, NULL);
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that this document does not have the necessary attributes
|
||||
// (keys) to participate in this index. For now report this as an error. Todo,
|
||||
// add its own unique error code so that the calling function can take the
|
||||
// appropriate action.
|
||||
// ............................................................................
|
||||
|
||||
if (res == -1) {
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that while we have the correct attribute name, the type is
|
||||
// not double. Skip this document for now.
|
||||
// ............................................................................
|
||||
|
||||
else if (res == -2) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Attempt the removal for unique/non-unique priority queue indexes
|
||||
// ............................................................................
|
||||
|
||||
res = PQIndex_remove(pqIndex->_pqIndex, &pqElement);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates a document from a priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int UpdatePriorityQueueIndex (TRI_index_t* idx,
|
||||
const TRI_doc_mptr_t* newDoc,
|
||||
const TRI_shaped_json_t* oldDoc) {
|
||||
|
||||
// ..........................................................................
|
||||
// Note: The oldDoc is represented by the TRI_shaped_json_t rather than by
|
||||
// a TRI_doc_mptr_t object. However for non-unique indexes (such as this
|
||||
// one) we must pass the document shape to the hash remove function.
|
||||
// ..........................................................................
|
||||
|
||||
union { void* p; void const* c; } cnv;
|
||||
PQIndexElement pqElement;
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
int res;
|
||||
|
||||
// ............................................................................
|
||||
// Obtain the priority queue index structure
|
||||
// ............................................................................
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
if (idx == NULL) {
|
||||
LOG_WARNING("internal error in UpdatePriorityQueueIndex");
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Allocate some memory for the HashIndexElement structure
|
||||
// ............................................................................
|
||||
|
||||
pqElement.numFields = pqIndex->_paths._length;
|
||||
pqElement.fields = TRI_Allocate(sizeof(TRI_shaped_json_t) * pqElement.numFields);
|
||||
pqElement.collection = pqIndex->base._collection;
|
||||
|
||||
if (pqElement.fields == NULL) {
|
||||
LOG_WARNING("out-of-memory in UpdatePriorityQueueIndex");
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
// ............................................................................
|
||||
// Fill in the fields with the values from oldDoc
|
||||
// ............................................................................
|
||||
|
||||
res = PriorityQueueIndexHelper(pqIndex, &pqElement, NULL, oldDoc);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
||||
cnv.c = newDoc;
|
||||
pqElement.data = cnv.p;
|
||||
|
||||
// ............................................................................
|
||||
// Remove the priority queue index entry and return.
|
||||
// ............................................................................
|
||||
|
||||
res = PQIndex_remove(pqIndex->_pqIndex, &pqElement);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG_WARNING("could not remove old document from priority queue index in UpdatePriorityQueueIndex");
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
LOG_WARNING("could not remove old document from priority queue index in UpdatePriorityQueueIndex");
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Fill the shaped json simple list from the document
|
||||
// ............................................................................
|
||||
|
||||
res = PriorityQueueIndexHelper(pqIndex, &pqElement, newDoc, NULL);
|
||||
|
||||
if (res == -1) {
|
||||
|
||||
// ..........................................................................
|
||||
// probably fields do not match
|
||||
// ..........................................................................
|
||||
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// It is possible that while we have the correct attribute name, the type is
|
||||
// not double. Skip this document for now.
|
||||
// ............................................................................
|
||||
|
||||
else if (res == -2) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
else if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
// Attempt to add the priority queue entry from the new doc
|
||||
// ............................................................................
|
||||
|
||||
res = PQIndex_insert(pqIndex->_pqIndex, &pqElement);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreatePriorityQueueIndex (struct TRI_doc_collection_s* collection,
|
||||
TRI_vector_pointer_t* fields,
|
||||
TRI_vector_t* paths,
|
||||
bool unique) {
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
size_t j;
|
||||
|
||||
if (paths == NULL) {
|
||||
LOG_WARNING("Internal error in TRI_CreatePriorityQueueIndex. PriorityQueue index creation failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// TODO: Allow priority queue index to be indexed on more than one field. For
|
||||
// now report an error.
|
||||
// ...........................................................................
|
||||
|
||||
if (paths->_length != 1) {
|
||||
LOG_WARNING("Currently only one attribute of the tye 'double' can be used for an index. PriorityQueue index creation failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pqIndex = TRI_Allocate(sizeof(TRI_priorityqueue_index_t));
|
||||
|
||||
if (pqIndex == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pqIndex->base._iid = TRI_NewTickVocBase();
|
||||
pqIndex->base._type = TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX;
|
||||
pqIndex->base._collection = collection;
|
||||
pqIndex->base._unique = unique;
|
||||
|
||||
pqIndex->base.insert = InsertPriorityQueueIndex;
|
||||
pqIndex->base.json = JsonPriorityQueueIndex;
|
||||
pqIndex->base.remove = RemovePriorityQueueIndex;
|
||||
pqIndex->base.update = UpdatePriorityQueueIndex;
|
||||
|
||||
// ...........................................................................
|
||||
// Copy the contents of the path list vector into a new vector and store this
|
||||
// ...........................................................................
|
||||
|
||||
TRI_InitVector(&pqIndex->_paths, sizeof(TRI_shape_pid_t));
|
||||
|
||||
for (j = 0; j < paths->_length; ++j) {
|
||||
TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths,j)));
|
||||
|
||||
TRI_PushBackVector(&pqIndex->_paths, &shape);
|
||||
}
|
||||
|
||||
TRI_InitVectorString(&pqIndex->base._fields);
|
||||
|
||||
for (j = 0; j < fields->_length; ++j) {
|
||||
char const* name = fields->_buffer[j];
|
||||
|
||||
TRI_PushBackVectorString(&pqIndex->base._fields, TRI_DuplicateString(name));
|
||||
}
|
||||
|
||||
if (!unique) {
|
||||
pqIndex->_pqIndex = PQueueIndex_new();
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return &pqIndex->base;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees the memory allocated, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyPriorityQueueIndex(TRI_index_t* idx) {
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
|
||||
if (idx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_DestroyVectorString(&idx->_fields);
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
TRI_DestroyVector(&pqIndex->_paths);
|
||||
|
||||
PQueueIndex_free(pqIndex->_pqIndex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees the memory allocated and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePriorityQueueIndex(TRI_index_t* idx) {
|
||||
if (idx == NULL) {
|
||||
return;
|
||||
}
|
||||
TRI_DestroyPriorityQueueIndex(idx);
|
||||
TRI_Free(idx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief attempts to locate an entry in the priority queue index
|
||||
/// A priority queue index lookup however only allows the 'top' most element
|
||||
/// of the queue to be located.
|
||||
///
|
||||
/// @warning who ever calls this function is responsible for destroying
|
||||
/// PQIndexElement* result (which could be null)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PQIndexElements* TRI_LookupPriorityQueueIndex(TRI_index_t* idx, TRI_json_t* parameterList) {
|
||||
|
||||
TRI_priorityqueue_index_t* pqIndex;
|
||||
PQIndexElements* result;
|
||||
TRI_shaper_t* shaper;
|
||||
size_t j;
|
||||
uint64_t numElements;
|
||||
TRI_json_t* jsonObject;
|
||||
|
||||
|
||||
if (idx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
|
||||
|
||||
// ..............................................................................
|
||||
// The parameter list should consist of exactly one parameter of the type number
|
||||
// which represents the first 'n' elements on the priority queue. If the
|
||||
// parameter list is empty, then 'n' defaults to 1.
|
||||
// ..............................................................................
|
||||
|
||||
if (parameterList == NULL) {
|
||||
result = PQIndex_top(pqIndex->_pqIndex,1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if (parameterList->_value._objects._length == 0) {
|
||||
result = PQIndex_top(pqIndex->_pqIndex,1);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (parameterList->_value._objects._length != 1) {
|
||||
TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
LOG_WARNING("invalid parameter sent to LookupPriorityQueueIndex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
shaper = pqIndex->base._collection->_shaper;
|
||||
numElements = 0;
|
||||
|
||||
for (j = 0; j < parameterList->_value._objects._length; ++j) {
|
||||
jsonObject = (TRI_json_t*) (TRI_AtVector(&(parameterList->_value._objects),j));
|
||||
if (jsonObject->_type == TRI_JSON_NUMBER) {
|
||||
numElements = jsonObject->_value._number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numElements == 0) {
|
||||
TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
LOG_WARNING("invalid parameter sent to LookupPriorityQueueIndex - request ignored");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PQIndex_top(pqIndex->_pqIndex,numElements);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SKIPLIST INDEX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "ShapedJson/shaped-json.h"
|
||||
#include "GeoIndex/GeoIndex.h"
|
||||
#include "HashIndex/hashindex.h"
|
||||
#include "PriorityQueue/pqueueindex.h"
|
||||
#include "SkipLists/skiplistIndex.h"
|
||||
#include "SkipLists/sl-operator.h"
|
||||
|
||||
|
@ -73,6 +74,7 @@ typedef enum {
|
|||
TRI_IDX_TYPE_PRIMARY_INDEX,
|
||||
TRI_IDX_TYPE_GEO_INDEX,
|
||||
TRI_IDX_TYPE_HASH_INDEX,
|
||||
TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX,
|
||||
TRI_IDX_TYPE_SKIPLIST_INDEX
|
||||
}
|
||||
TRI_idx_type_e;
|
||||
|
@ -138,6 +140,19 @@ typedef struct TRI_hash_index_s {
|
|||
}
|
||||
TRI_hash_index_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skiplist index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_priorityqueue_index_s {
|
||||
TRI_index_t base;
|
||||
PQIndex* _pqIndex;
|
||||
TRI_vector_t _paths; // a list of shape pid which identifies the fields of the index
|
||||
}
|
||||
TRI_priorityqueue_index_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skiplist index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -369,6 +384,59 @@ HashIndexElements* TRI_LookupHashIndex (TRI_index_t*, TRI_json_t*);
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PRIORITY QUEUE INDEX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PQIndexElements* TRI_LookupPriorityQueueIndex (TRI_index_t*, TRI_json_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a priority queue index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreatePriorityQueueIndex (struct TRI_doc_collection_s*,
|
||||
TRI_vector_pointer_t*,
|
||||
TRI_vector_t*,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees the memory allocated, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyPriorityQueueIndex (TRI_index_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees the memory allocated and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePriorityQueueIndex (TRI_index_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SKIPLIST INDEX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
|||
TRI_QRY_WHERE_BOOLEAN,
|
||||
TRI_QRY_WHERE_GENERAL,
|
||||
TRI_QRY_WHERE_HASH_CONSTANT,
|
||||
TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT,
|
||||
TRI_QRY_WHERE_SKIPLIST_CONSTANT,
|
||||
TRI_QRY_WHERE_WITHIN_CONSTANT,
|
||||
TRI_QRY_WHERE_PRIMARY_CONSTANT
|
||||
|
@ -162,6 +163,19 @@ typedef struct TRI_qry_where_hash_const_s {
|
|||
TRI_qry_where_hash_const_t;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skiplist index where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_qry_where_priorityqueue_const_s {
|
||||
TRI_qry_where_t base;
|
||||
TRI_idx_iid_t _iid;
|
||||
TRI_json_t* _parameters;
|
||||
}
|
||||
TRI_qry_where_priorityqueue_const_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skiplist index where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
217
VocBase/query.c
217
VocBase/query.c
|
@ -352,6 +352,45 @@ static TRI_rc_result_t* NextHashCollectionCursor (TRI_rc_cursor_t* c) {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool ToJavaScriptPQDocument (TRI_qry_select_t* s,
|
||||
TRI_rc_result_t* result,
|
||||
void* storage) {
|
||||
|
||||
TRI_doc_mptr_t* document;
|
||||
TRI_doc_collection_t* collection;
|
||||
|
||||
collection = result->_context->_primary;
|
||||
|
||||
document = (TRI_doc_mptr_t*) result->_dataPtr;
|
||||
return TRI_ObjectDocumentPointer(collection, document, storage);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_rc_result_t* NextPQCollectionCursor (TRI_rc_cursor_t* c) {
|
||||
collection_cursor_t* cursor;
|
||||
|
||||
cursor = (collection_cursor_t*) c;
|
||||
|
||||
if (cursor->_currentRow == cursor->_length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor->_current = &(cursor->_documents[cursor->_currentRow]);
|
||||
cursor->_result._dataPtr = (TRI_sr_documents_t*) (cursor->_current);
|
||||
++(cursor->_currentRow);
|
||||
|
||||
return &cursor->_result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// For a collection, advances a given cursor by one. Cursor is associated with
|
||||
// a skip list index. Note: for now the <void* _iterator> field will store
|
||||
|
@ -762,6 +801,18 @@ static TRI_qry_where_t* CloneQueryWhereHashConstant (const TRI_qry_where_t* w) {
|
|||
return TRI_CreateQueryWhereHashConstant(whereClause->_iid, whereClause->_parameters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clones a query condition - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_qry_where_t* CloneQueryWherePQConstant (const TRI_qry_where_t* w) {
|
||||
TRI_qry_where_priorityqueue_const_t* whereClause;
|
||||
|
||||
whereClause = (TRI_qry_where_priorityqueue_const_t*) w;
|
||||
|
||||
return TRI_CreateQueryWherePQConstant(whereClause->_iid, whereClause->_parameters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -801,6 +852,17 @@ static void FreeQueryWhereHashConstant (TRI_qry_where_t* w) {
|
|||
TRI_Free(whereClause);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees a query condition priority queue - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FreeQueryWherePQConstant (TRI_qry_where_t* w) {
|
||||
TRI_qry_where_priorityqueue_const_t* whereClause;
|
||||
whereClause = (TRI_qry_where_priorityqueue_const_t*) w;
|
||||
TRI_FreeJson(whereClause->_parameters);
|
||||
TRI_Free(whereClause);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -903,7 +965,23 @@ TRI_qry_where_t* TRI_CreateQueryWhereHashConstant (TRI_idx_iid_t iid, TRI_json_t
|
|||
result = TRI_Allocate(sizeof(TRI_qry_where_hash_const_t));
|
||||
result->base._type = TRI_QRY_WHERE_HASH_CONSTANT;
|
||||
result->base.clone = CloneQueryWhereHashConstant;
|
||||
result->base.free = FreeQueryWhereHashConstant;
|
||||
result->base.free = FreeQueryWhereHashConstant;
|
||||
result->_iid = iid;
|
||||
result->_parameters = TRI_CopyJson(parameters);
|
||||
return &result->base;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a query condition for priority queue index - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_where_t* TRI_CreateQueryWherePQConstant (TRI_idx_iid_t iid, TRI_json_t* parameters) {
|
||||
TRI_qry_where_priorityqueue_const_t* result;
|
||||
result = TRI_Allocate(sizeof(TRI_qry_where_priorityqueue_const_t));
|
||||
result->base._type = TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT;
|
||||
result->base.clone = CloneQueryWherePQConstant;
|
||||
result->base.free = FreeQueryWherePQConstant;
|
||||
result->_iid = iid;
|
||||
result->_parameters = TRI_CopyJson(parameters);
|
||||
return &result->base;
|
||||
|
@ -1004,6 +1082,28 @@ TRI_query_t* TRI_CreateHashQuery(const TRI_qry_where_t* whereStmt,
|
|||
return query;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a priority queue query - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_t* TRI_CreatePriorityQueueQuery(const TRI_qry_where_t* whereStmt,
|
||||
TRI_doc_collection_t* collection) {
|
||||
TRI_query_t* query;
|
||||
|
||||
query = TRI_Allocate(sizeof(TRI_query_t));
|
||||
if (!query) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
query->_where = ( whereStmt == NULL ? NULL : whereStmt->clone(whereStmt));
|
||||
query->_skip = TRI_QRY_NO_SKIP;
|
||||
query->_limit = TRI_QRY_NO_LIMIT;
|
||||
query->_primary = collection;
|
||||
query->_joins = NULL;
|
||||
query->_select = TRI_CreateQuerySelectDocument();
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a skiplist query - DEPRECATED
|
||||
|
@ -1339,6 +1439,105 @@ static void FilterDataHashQuery(collection_cursor_t* cursor,TRI_query_t* query,
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a query - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FilterDataPQQuery(collection_cursor_t* cursor,TRI_query_t* query,
|
||||
TRI_rc_context_t* context) {
|
||||
|
||||
bool ok;
|
||||
TRI_index_t* idx;
|
||||
TRI_qry_where_priorityqueue_const_t* where;
|
||||
TRI_sim_collection_t* collection;
|
||||
PQIndexElements* pqElements;
|
||||
TRI_doc_mptr_t* wtr;
|
||||
TRI_doc_mptr_t* doc;
|
||||
size_t j;
|
||||
|
||||
cursor->base._context = context;
|
||||
cursor->base._select = query->_select->clone(query->_select);
|
||||
|
||||
cursor->base.next = NextPQCollectionCursor;
|
||||
cursor->base.hasNext = HasNextCollectionCursor;
|
||||
cursor->base.free = FreeCollectionCursor;
|
||||
cursor->_result._selectResult = NULL;
|
||||
|
||||
cursor->_result._context = context;
|
||||
cursor->_result._dataPtr = NULL;
|
||||
|
||||
cursor->base._select->toJavaScript = ToJavaScriptPQDocument;
|
||||
|
||||
TRI_InitVectorPointer(&cursor->base._containers);
|
||||
|
||||
TRI_ReadLockCollectionsQuery(query);
|
||||
|
||||
TRI_AddCollectionsCursor(&cursor->base, query);
|
||||
|
||||
|
||||
ok = (query->_primary->base._type == TRI_COL_TYPE_SIMPLE_DOCUMENT);
|
||||
|
||||
if (ok) {
|
||||
where = (TRI_qry_where_priorityqueue_const_t*)(query->_where);
|
||||
ok = (where->base._type == TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
collection = (TRI_sim_collection_t*) query->_primary;
|
||||
idx = TRI_IndexSimCollection(collection, where->_iid);
|
||||
ok = (idx != NULL);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
pqElements = TRI_LookupPriorityQueueIndex(idx,where->_parameters);
|
||||
ok = (pqElements != NULL);
|
||||
}
|
||||
|
||||
|
||||
if (ok) {
|
||||
cursor->_documents = (TRI_doc_mptr_t*) (TRI_Allocate(sizeof(TRI_doc_mptr_t) * pqElements->_numElements));
|
||||
|
||||
wtr = cursor->_documents;
|
||||
cursor->_length = 0;
|
||||
cursor->base._matchedDocuments = 0;
|
||||
cursor->_current = 0;
|
||||
cursor->_currentRow = 0;
|
||||
|
||||
for (j = 0; j < pqElements->_numElements; ++j) {
|
||||
// should not be necessary to check that documents have not been deleted
|
||||
doc = (TRI_doc_mptr_t*)((pqElements->_elements[j]).data);
|
||||
if (doc->_deletion) {
|
||||
continue;
|
||||
}
|
||||
if (cursor->_current == 0) {
|
||||
cursor->_current = wtr;
|
||||
}
|
||||
++cursor->base._matchedDocuments;
|
||||
++cursor->_length;
|
||||
*wtr = *doc;
|
||||
++wtr;
|
||||
}
|
||||
|
||||
|
||||
if (pqElements->_elements != NULL) {
|
||||
TRI_Free(pqElements->_elements);
|
||||
TRI_Free(pqElements);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_ReadUnlockCollectionsQuery(query);
|
||||
|
||||
if (!ok) {
|
||||
cursor->_length = 0;
|
||||
cursor->_currentRow = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1424,7 +1623,6 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
|
|||
limit = query->_limit;
|
||||
applyPostSkipLimit = false;
|
||||
|
||||
|
||||
if (limit < 0) {
|
||||
limit = TRI_QRY_NO_LIMIT;
|
||||
skip = 0;
|
||||
|
@ -1436,7 +1634,9 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
|
|||
where = 0;
|
||||
|
||||
if (query->_where != NULL) {
|
||||
|
||||
where = query->_where;
|
||||
|
||||
if (where->_type == TRI_QRY_WHERE_BOOLEAN) {
|
||||
TRI_qry_where_boolean_t* b;
|
||||
b = (TRI_qry_where_boolean_t*) where;
|
||||
|
@ -1445,12 +1645,15 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
|
|||
}
|
||||
where = NULL;
|
||||
}
|
||||
|
||||
else if (where->_type == TRI_QRY_WHERE_PRIMARY_CONSTANT) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
else if (where->_type == TRI_QRY_WHERE_WITHIN_CONSTANT) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
else if (where->_type == TRI_QRY_WHERE_HASH_CONSTANT) {
|
||||
cursor = TRI_Allocate(sizeof(collection_cursor_t));
|
||||
if (cursor == NULL) {
|
||||
|
@ -1459,6 +1662,16 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
|
|||
FilterDataHashQuery(cursor,query,context);
|
||||
return &cursor->base;
|
||||
}
|
||||
|
||||
else if (where->_type == TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT) {
|
||||
cursor = TRI_Allocate(sizeof(collection_cursor_t));
|
||||
if (cursor == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
FilterDataPQQuery(cursor,query,context);
|
||||
return &cursor->base;
|
||||
}
|
||||
|
||||
else if (where->_type == TRI_QRY_WHERE_SKIPLIST_CONSTANT) {
|
||||
cursor = TRI_Allocate(sizeof(collection_cursor_t));
|
||||
if (cursor == NULL) {
|
||||
|
|
|
@ -316,6 +316,8 @@ TRI_rc_cursor_t;
|
|||
|
||||
TRI_query_t* TRI_CreateHashQuery (const TRI_qry_where_t*, TRI_doc_collection_t*);
|
||||
|
||||
TRI_query_t* TRI_CreatePriorityQueueQuery (const TRI_qry_where_t*, TRI_doc_collection_t*);
|
||||
|
||||
TRI_query_t* TRI_CreateSkiplistQuery (const TRI_qry_where_t*, TRI_doc_collection_t*);
|
||||
|
||||
TRI_query_t* TRI_CreateQuery (TRI_vocbase_t*,
|
||||
|
@ -374,6 +376,12 @@ TRI_qry_where_t* TRI_CreateQueryWhereGeneral (char const*);
|
|||
|
||||
TRI_qry_where_t* TRI_CreateQueryWhereHashConstant (TRI_idx_iid_t, TRI_json_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a query condition for a priority queue with constant parameters - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_where_t* TRI_CreateQueryWherePQConstant (TRI_idx_iid_t, TRI_json_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a query condition for a hash with constant parameters - DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -92,6 +92,12 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti
|
|||
bool unique,
|
||||
bool* created);
|
||||
|
||||
static TRI_index_t* CreatePriorityQueueIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
const TRI_vector_t* attributes,
|
||||
TRI_idx_iid_t iid,
|
||||
bool unique,
|
||||
bool* created);
|
||||
|
||||
static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
const TRI_vector_t* attributes,
|
||||
TRI_idx_iid_t iid,
|
||||
|
@ -1537,7 +1543,9 @@ static bool OpenIndexIterator (char const* filename, void* data) {
|
|||
// HASH INDEX OR SKIPLIST INDEX
|
||||
// ...........................................................................
|
||||
|
||||
else if (TRI_EqualString(typeStr, "hash") || TRI_EqualString(typeStr, "skiplist")) {
|
||||
else if (TRI_EqualString(typeStr, "hash") || TRI_EqualString(typeStr, "skiplist") ||
|
||||
TRI_EqualString(typeStr, "priorityqueue")
|
||||
) {
|
||||
|
||||
// Determine if the hash index is unique or non-unique
|
||||
gjs = TRI_LookupArrayJson(json, "unique");
|
||||
|
@ -1578,6 +1586,9 @@ static bool OpenIndexIterator (char const* filename, void* data) {
|
|||
if (TRI_EqualString(typeStr, "hash")) {
|
||||
idx = CreateHashIndexSimCollection(doc, &attributes, iid, uniqueIndex, NULL);
|
||||
}
|
||||
else if (TRI_EqualString(typeStr, "priorityqueue")) {
|
||||
idx = CreatePriorityQueueIndexSimCollection(doc, &attributes, iid, uniqueIndex, NULL);
|
||||
}
|
||||
else if (TRI_EqualString(typeStr, "skiplist")) {
|
||||
idx = CreateSkiplistIndexSimCollection(doc, &attributes, iid, uniqueIndex, NULL);
|
||||
}
|
||||
|
@ -1597,8 +1608,9 @@ static bool OpenIndexIterator (char const* filename, void* data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
// .........................................................................
|
||||
// ups, unknown index type
|
||||
// oops, unknown index type
|
||||
// .........................................................................
|
||||
|
||||
else {
|
||||
|
@ -2841,6 +2853,104 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti
|
|||
return idx;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a priroity queue index to the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_index_t* CreatePriorityQueueIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
const TRI_vector_t* attributes,
|
||||
TRI_idx_iid_t iid,
|
||||
bool unique,
|
||||
bool* created) {
|
||||
TRI_index_t* idx = NULL;
|
||||
TRI_shaper_t* shaper = collection->base._shaper;
|
||||
TRI_vector_t paths;
|
||||
TRI_vector_pointer_t fields;
|
||||
bool ok;
|
||||
size_t j;
|
||||
|
||||
|
||||
TRI_InitVector(&paths, sizeof(TRI_shape_pid_t));
|
||||
TRI_InitVectorPointer(&fields);
|
||||
|
||||
// ...........................................................................
|
||||
// Determine the shape ids for the attributes
|
||||
// ...........................................................................
|
||||
|
||||
for (j = 0; j < attributes->_length; ++j) {
|
||||
char* path = *((char**)(TRI_AtVector(attributes,j)));
|
||||
TRI_shape_pid_t shape = shaper->findAttributePathByName(shaper, path);
|
||||
TRI_PushBackVector(&paths, &shape);
|
||||
TRI_PushBackVectorPointer(&fields, path);
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Attempt to find an existing index which matches the attributes above.
|
||||
// If a suitable index is found, return that one otherwise we need to create
|
||||
// a new one.
|
||||
// ...........................................................................
|
||||
|
||||
idx = TRI_LookupPriorityQueueIndexSimCollection(collection, &paths);
|
||||
|
||||
if (idx != NULL) {
|
||||
TRI_DestroyVector(&paths);
|
||||
TRI_DestroyVectorPointer(&fields);
|
||||
|
||||
LOG_TRACE("priority queue index already created");
|
||||
|
||||
if (created != NULL) {
|
||||
*created = false;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Create the priority queue index
|
||||
// ...........................................................................
|
||||
|
||||
idx = TRI_CreatePriorityQueueIndex(&collection->base, &fields, &paths, unique);
|
||||
|
||||
// ...........................................................................
|
||||
// If index id given, use it otherwise use the default.
|
||||
// ...........................................................................
|
||||
|
||||
if (iid) {
|
||||
idx->_iid = iid;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// initialises the index with all existing documents
|
||||
// ...........................................................................
|
||||
|
||||
ok = FillIndex(collection, idx);
|
||||
|
||||
if (! ok) {
|
||||
TRI_FreeSkiplistIndex(idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// store index
|
||||
// ...........................................................................
|
||||
|
||||
TRI_PushBackVectorPointer(&collection->_indexes, idx);
|
||||
|
||||
// ...........................................................................
|
||||
// release memory allocated to vector
|
||||
// ...........................................................................
|
||||
|
||||
TRI_DestroyVector(&paths);
|
||||
|
||||
if (created != NULL) {
|
||||
*created = true;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a skiplist index to the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2935,6 +3045,7 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll
|
|||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -3074,6 +3185,75 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection,
|
|||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finds a priority queue index (non-unique)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_LookupPriorityQueueIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
const TRI_vector_t* paths) {
|
||||
TRI_index_t* matchedIndex = NULL;
|
||||
size_t j, k;
|
||||
|
||||
// ...........................................................................
|
||||
// Note: This function does NOT differentiate between non-unique and unique
|
||||
// skiplist indexes. The first index which matches the attributes
|
||||
// (paths parameter) will be returned.
|
||||
// ...........................................................................
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// go through every index and see if we have a match
|
||||
// ...........................................................................
|
||||
|
||||
for (j = 0; j < collection->_indexes._length; ++j) {
|
||||
TRI_index_t* idx = collection->_indexes._buffer[j];
|
||||
TRI_priorityqueue_index_t* pqIndex = (TRI_priorityqueue_index_t*) idx;
|
||||
bool found = true;
|
||||
|
||||
// .........................................................................
|
||||
// check that the type of the index is in fact a skiplist index
|
||||
// .........................................................................
|
||||
|
||||
if (idx->_type != TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// .........................................................................
|
||||
// check that the number of paths (fields) in the index matches that
|
||||
// of the number of attributes
|
||||
// .........................................................................
|
||||
|
||||
if (paths->_length != pqIndex->_paths._length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// .........................................................................
|
||||
// Go through all the attributes and see if they match
|
||||
// .........................................................................
|
||||
|
||||
for (k = 0; k < paths->_length; ++k) {
|
||||
TRI_shape_pid_t field = *((TRI_shape_pid_t*)(TRI_AtVector(&pqIndex->_paths,k)));
|
||||
TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths,k)));
|
||||
|
||||
if (field != shape) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (found) {
|
||||
matchedIndex = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedIndex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finds a skiplist index (unique or non-unique)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3250,6 +3430,47 @@ TRI_index_t* TRI_EnsureHashIndexSimCollection(TRI_sim_collection_t* sim,
|
|||
return res == TRI_ERROR_NO_ERROR ? idx : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a priority queue index exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_EnsurePriorityQueueIndexSimCollection(TRI_sim_collection_t* sim,
|
||||
const TRI_vector_t* attributes,
|
||||
bool unique,
|
||||
bool* created) {
|
||||
TRI_index_t* idx;
|
||||
int res;
|
||||
|
||||
// .............................................................................
|
||||
// inside write-lock
|
||||
// .............................................................................
|
||||
|
||||
TRI_WRITE_LOCK_DOCUMENTS_INDEXES_SIM_COLLECTION(sim);
|
||||
|
||||
// .............................................................................
|
||||
// Given the list of attributes (as strings)
|
||||
// .............................................................................
|
||||
|
||||
idx = CreatePriorityQueueIndexSimCollection(sim, attributes, 0, unique, created);
|
||||
|
||||
if (idx == NULL) {
|
||||
TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_SIM_COLLECTION(sim);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_SIM_COLLECTION(sim);
|
||||
|
||||
// .............................................................................
|
||||
// outside write-lock
|
||||
// .............................................................................
|
||||
|
||||
res = TRI_SaveIndex(&sim->base, idx);
|
||||
|
||||
return res == TRI_ERROR_NO_ERROR ? idx : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a skiplist index exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -432,6 +432,16 @@ struct TRI_index_s* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t*,
|
|||
TRI_vector_t const*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finds a priority queue index
|
||||
///
|
||||
/// Note that the caller must hold at least a read-lock.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_index_s* TRI_LookupPriorityQueueIndexSimCollection (TRI_sim_collection_t*,
|
||||
TRI_vector_t const*);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finds a skiplist index
|
||||
///
|
||||
|
@ -468,8 +478,19 @@ struct TRI_index_s* TRI_EnsureHashIndexSimCollection (TRI_sim_collection_t* coll
|
|||
bool unique,
|
||||
bool* created);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds or returns an existing hash index to a collection
|
||||
/// @brief adds or returns an existing priority queue index to a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_index_s* TRI_EnsurePriorityQueueIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
const TRI_vector_t* attributes,
|
||||
bool unique,
|
||||
bool* created);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds or returns an existing skiplist index to a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_index_s* TRI_EnsureSkiplistIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
|
|
|
@ -41,17 +41,17 @@ var API = "_api/collection";
|
|||
/// @brief collection representation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function CollectionRepresentation (collection, showParameter, showCount, showFigures) {
|
||||
function CollectionRepresentation (collection, showProperties, showCount, showFigures) {
|
||||
var result = {};
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection.name();
|
||||
|
||||
if (showParameter) {
|
||||
var parameter = collection.parameter();
|
||||
if (showProperties) {
|
||||
var properties = collection.properties();
|
||||
|
||||
result.waitForSync = parameter.waitForSync;
|
||||
result.journalSize = parameter.journalSize;
|
||||
result.waitForSync = properties.waitForSync;
|
||||
result.journalSize = properties.journalSize;
|
||||
}
|
||||
|
||||
if (showCount) {
|
||||
|
@ -224,11 +224,12 @@ function GET_api_collections (req, res) {
|
|||
/// response will contain a field "Location" which contains the correct
|
||||
/// location.
|
||||
///
|
||||
/// @REST{GET /_api/collection/@FA{collection-identifier}/parameter}
|
||||
/// @REST{GET /_api/collection/@FA{collection-identifier}/properties}
|
||||
/// DEPRECATED: @REST{GET /_api/collection/@FA{collection-identifier}/parameter}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// In addition to the above, the result will always contain the
|
||||
/// @LIT{waitForSync} and the @LIT{journalSize} parameters. This is
|
||||
/// @LIT{waitForSync} and the @LIT{journalSize} properties. This is
|
||||
/// achieved by forcing a load of the underlying collection.
|
||||
///
|
||||
/// @LIT{waitForSync}: If @LIT{true} then creating or changing a document will
|
||||
|
@ -342,7 +343,18 @@ function GET_api_collection (req, res) {
|
|||
}
|
||||
|
||||
// .............................................................................
|
||||
// /_api/collection/<identifier>/parameter
|
||||
// /_api/collection/<identifier>/properties
|
||||
// .............................................................................
|
||||
|
||||
else if (sub == "properties") {
|
||||
var result = CollectionRepresentation(collection, true, false, false);
|
||||
var headers = { location : "/" + API + "/" + collection._id + "/properties" };
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// /_api/collection/<identifier>/parameter (DEPRECATED)
|
||||
// .............................................................................
|
||||
|
||||
else if (sub == "parameter") {
|
||||
|
@ -353,7 +365,7 @@ function GET_api_collection (req, res) {
|
|||
}
|
||||
|
||||
else {
|
||||
actions.resultNotFound(req, res, "expecting one of the resources 'count', 'figures', 'parameter'");
|
||||
actions.resultNotFound(req, res, "expecting one of the resources 'count', 'figures', 'properties', 'parameter'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -468,9 +480,10 @@ function PUT_api_collection_truncate (req, res, collection) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief changes a collection
|
||||
///
|
||||
/// @REST{PUT /_api/collection/@FA{collection-identifier}/parameter}
|
||||
/// @REST{PUT /_api/collection/@FA{collection-identifier}/properties}
|
||||
/// DEPRECATED: @REST{PUT /_api/collection/@FA{collection-identifier}/parameter}
|
||||
///
|
||||
/// Changes the parameter of a collection. Expects an object with the
|
||||
/// Changes the properties of a collection. Expects an object with the
|
||||
/// attribute(s)
|
||||
///
|
||||
/// @LIT{waitForSync}: If @LIT{true} then creating or changing a document will
|
||||
|
@ -486,10 +499,10 @@ function PUT_api_collection_truncate (req, res, collection) {
|
|||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// @verbinclude api-collection-identifier-parameter-sync
|
||||
/// @verbinclude api-collection-identifier-properties-sync
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function PUT_api_collection_parameter (req, res, collection) {
|
||||
function PUT_api_collection_properties (req, res, collection) {
|
||||
var body;
|
||||
|
||||
try {
|
||||
|
@ -501,7 +514,7 @@ function PUT_api_collection_parameter (req, res, collection) {
|
|||
}
|
||||
|
||||
try {
|
||||
collection.parameter(body);
|
||||
collection.properties(body);
|
||||
|
||||
var result = CollectionRepresentation(collection, true);
|
||||
|
||||
|
@ -595,14 +608,17 @@ function PUT_api_collection (req, res) {
|
|||
else if (sub == "truncate") {
|
||||
PUT_api_collection_truncate(req, res, collection);
|
||||
}
|
||||
else if (sub == "parameter") {
|
||||
PUT_api_collection_parameter(req, res, collection);
|
||||
else if (sub == "properties") {
|
||||
PUT_api_collection_properties(req, res, collection);
|
||||
}
|
||||
else if (sub == "parameter") { /* DEPRECATED */
|
||||
PUT_api_collection_properties(req, res, collection);
|
||||
}
|
||||
else if (sub == "rename") {
|
||||
PUT_api_collection_rename(req, res, collection);
|
||||
}
|
||||
else {
|
||||
actions.resultNotFound(req, res, "expecting one of the actions 'load', 'unload', 'truncate', 'parameter', 'rename'");
|
||||
actions.resultNotFound(req, res, "expecting one of the actions 'load', 'unload', 'truncate', 'properties', 'parameter', 'rename'");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,21 +296,25 @@ function AvocadoError (error) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoError.prototype._PRINT = function() {
|
||||
print(this.toString());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief toString function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoError.prototype.toString = function() {
|
||||
var result = "";
|
||||
if (typeof(COLOR_BRIGHT) != "undefined") {
|
||||
internal.output(COLOR_BRIGHT);
|
||||
internal.output("Error: ");
|
||||
internal.output(COLOR_OUTPUT_RESET);
|
||||
result = COLOR_BRIGHT + "Error: " + COLOR_OUTPUT_RESET;
|
||||
}
|
||||
else {
|
||||
internal.output("Error: ");
|
||||
result = "Error: ";
|
||||
}
|
||||
|
||||
internal.output("[");
|
||||
internal.output(this.code);
|
||||
internal.output(":");
|
||||
internal.output(this.errorNum);
|
||||
internal.output("] ");
|
||||
print(this.errorMessage);
|
||||
result += "[" + this.code + ":" + this.errorNum + "] " + this.errorMessage;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1049,7 +1053,7 @@ try {
|
|||
print(HELP);
|
||||
}
|
||||
catch (err) {
|
||||
print(COLOR_RED + "connection failure: " + err + COLOR_BLACK);
|
||||
print(err);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -297,21 +297,25 @@ static string JS_client_client =
|
|||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoError.prototype._PRINT = function() {\n"
|
||||
" print(this.toString());\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief toString function\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoError.prototype.toString = function() {\n"
|
||||
" var result = \"\";\n"
|
||||
" if (typeof(COLOR_BRIGHT) != \"undefined\") {\n"
|
||||
" internal.output(COLOR_BRIGHT);\n"
|
||||
" internal.output(\"Error: \");\n"
|
||||
" internal.output(COLOR_OUTPUT_RESET);\n"
|
||||
" result = COLOR_BRIGHT + \"Error: \" + COLOR_OUTPUT_RESET;\n"
|
||||
" }\n"
|
||||
" else {\n"
|
||||
" internal.output(\"Error: \"); \n"
|
||||
" result = \"Error: \";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" internal.output(\"[\"); \n"
|
||||
" internal.output(this.code); \n"
|
||||
" internal.output(\":\"); \n"
|
||||
" internal.output(this.errorNum); \n"
|
||||
" internal.output(\"] \"); \n"
|
||||
" print(this.errorMessage);\n"
|
||||
" result += \"[\" + this.code + \":\" + this.errorNum + \"] \" + this.errorMessage;\n"
|
||||
" \n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
|
@ -1050,7 +1054,7 @@ static string JS_client_client =
|
|||
" print(HELP);\n"
|
||||
"}\n"
|
||||
"catch (err) {\n"
|
||||
" print(COLOR_RED + \"connection failure: \" + err + COLOR_BLACK);\n"
|
||||
" print(err);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
|
|
|
@ -101,5 +101,7 @@ ModuleCache["/internal"].exports.errors = {
|
|||
"SIMPLE_CLIENT_COULD_NOT_WRITE" : { "code" : 2002, "message" : "could not write to server" },
|
||||
"SIMPLE_CLIENT_COULD_NOT_READ" : { "code" : 2003, "message" : "could not read from server" },
|
||||
"ERROR_AVOCADO_INDEX_PQ_INSERT_FAILED" : { "code" : 3100, "message" : "priority queue insert failure" },
|
||||
"ERROR_AVOCADO_INDEX_PQ_REMOVE_FAILED" : { "code" : 3110, "message" : "priority queue remove failure" },
|
||||
"ERROR_AVOCADO_INDEX_PQ_REMOVE_ITEM_MISSING" : { "code" : 3111, "message" : "priority queue remove failure - item missing in index" },
|
||||
};
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ static string JS_common_bootstrap_errors =
|
|||
" \"SIMPLE_CLIENT_COULD_NOT_WRITE\" : { \"code\" : 2002, \"message\" : \"could not write to server\" }, \n"
|
||||
" \"SIMPLE_CLIENT_COULD_NOT_READ\" : { \"code\" : 2003, \"message\" : \"could not read from server\" }, \n"
|
||||
" \"ERROR_AVOCADO_INDEX_PQ_INSERT_FAILED\" : { \"code\" : 3100, \"message\" : \"priority queue insert failure\" }, \n"
|
||||
" \"ERROR_AVOCADO_INDEX_PQ_REMOVE_FAILED\" : { \"code\" : 3110, \"message\" : \"priority queue remove failure\" }, \n"
|
||||
" \"ERROR_AVOCADO_INDEX_PQ_REMOVE_ITEM_MISSING\" : { \"code\" : 3111, \"message\" : \"priority queue remove failure - item missing in index\" }, \n"
|
||||
"};\n"
|
||||
"\n"
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue