1
0
Fork 0

Merge branch 'master' of github.com:triAGENS/AvocadoDB

This commit is contained in:
Frank Celler 2012-04-10 13:50:09 +02:00
commit 00355fccf4
29 changed files with 3871 additions and 96 deletions

View File

@ -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");
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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)
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -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

View File

@ -1,4 +1,4 @@
avocado> db.examples.parameter();
avocado> db.examples.properties();
{
"waitForSync" : false,
"journalSize" : 134217728

View File

@ -1,4 +1,4 @@
avocado> db.examples.parameter({ waitForSync : true });
avocado> db.examples.properties({ waitForSync : true });
{
"waitForSync" : true,
"journalSize" : 134217728

View File

@ -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 \

View File

@ -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

1062
PriorityQueue/pqueueindex.c Executable file

File diff suppressed because it is too large Load Diff

189
PriorityQueue/pqueueindex.h Executable file
View File

@ -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:

584
PriorityQueue/priorityqueue.c Executable file
View File

@ -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:

204
PriorityQueue/priorityqueue.h Executable file
View File

@ -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:

View File

@ -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;
}

View File

@ -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>

View File

@ -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")

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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) {

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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,

View File

@ -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'");
}
}

View File

@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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"

View File

@ -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" },
};

View File

@ -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"
;