diff --git a/Doxygen/avocado.doxy.in b/Doxygen/avocado.doxy.in
index c71d084fcb..9ff5b400cd 100644
--- a/Doxygen/avocado.doxy.in
+++ b/Doxygen/avocado.doxy.in
@@ -202,6 +202,8 @@ ALIASES += FN{1}="\1"
ALIASES += VAR{1}="\1"
ALIASES += LIT{1}="\1"
ALIASES += CODE{1}="\1"
+ALIASES += CODE{2}="\1, \2"
+ALIASES += CODE{3}="\1, \2, \3"
ALIASES += CMDOPT{1}="\1"
ALIASES += CA{1}="\1"
ALIASES += CO{1}="\1"
diff --git a/HashIndex/hashindex.c b/HashIndex/hashindex.c
index 761f05394f..4501f0e0fb 100755
--- a/HashIndex/hashindex.c
+++ b/HashIndex/hashindex.c
@@ -368,10 +368,8 @@ HashIndex* HashIndex_new() {
int HashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
bool result;
result = TRI_InsertElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, false);
- if (result) {
- return 0;
- }
- return -1;
+
+ return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED;
}
@@ -413,11 +411,11 @@ int HashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
// Removes an entry from the associative array
// ...............................................................................
-bool HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
+int HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
bool result;
result = TRI_RemoveElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, NULL);
- return result;
+ return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
}
@@ -426,10 +424,10 @@ bool HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
// then adds the afterElement
// ...............................................................................
-bool HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
+int HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
const HashIndexElement* afterElement) {
assert(false);
- return false;
+ return TRI_ERROR_INTERNAL;
}
//------------------------------------------------------------------------------
@@ -640,10 +638,10 @@ int MultiHashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
// Removes an entry from the associative array
// ...............................................................................
-bool MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
+int MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
bool result;
result = TRI_RemoveElementMultiArray(hashIndex->assocArray.nonUniqueArray, element, NULL);
- return result;
+ return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
}
@@ -652,8 +650,8 @@ bool MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
// then adds the afterElement
// ...............................................................................
-bool MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
+int MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
HashIndexElement* afterElement) {
assert(false);
- return false;
+ return TRI_ERROR_INTERNAL;
}
diff --git a/HashIndex/hashindex.h b/HashIndex/hashindex.h
index f06d053811..aedf46b976 100755
--- a/HashIndex/hashindex.h
+++ b/HashIndex/hashindex.h
@@ -35,6 +35,9 @@
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
+#ifndef TRI_HASH_INDEX_H
+#define TRI_HASH_INDEX_H 1
+
#include
#include
#include
@@ -82,9 +85,9 @@ HashIndexElements* HashIndex_find (HashIndex*, HashIndexElement*);
int HashIndex_insert (HashIndex*, HashIndexElement*);
-bool HashIndex_remove (HashIndex*, HashIndexElement*);
+int HashIndex_remove (HashIndex*, HashIndexElement*);
-bool HashIndex_update (HashIndex*, const HashIndexElement*, const HashIndexElement*);
+int HashIndex_update (HashIndex*, const HashIndexElement*, const HashIndexElement*);
//------------------------------------------------------------------------------
@@ -102,6 +105,8 @@ HashIndexElements* MultiHashIndex_find (HashIndex*, HashIndexElement*);
int MultiHashIndex_insert (HashIndex*, HashIndexElement*);
-bool MultiHashIndex_remove (HashIndex*, HashIndexElement*);
+int MultiHashIndex_remove (HashIndex*, HashIndexElement*);
-bool MultiHashIndex_update (HashIndex*, HashIndexElement*, HashIndexElement*);
+int MultiHashIndex_update (HashIndex*, HashIndexElement*, HashIndexElement*);
+
+#endif
diff --git a/RestServer/AvocadoServer.cpp b/RestServer/AvocadoServer.cpp
index 25754f55db..cc94ce8eb9 100644
--- a/RestServer/AvocadoServer.cpp
+++ b/RestServer/AvocadoServer.cpp
@@ -316,7 +316,7 @@ void AvocadoServer::buildApplicationServer () {
map additional;
additional[ApplicationServer::OPTIONS_CMDLINE]
- ("shell", "do not start as server, start in shell mode instead")
+ ("console", "do not start as server, start an emergency console instead")
;
additional[ApplicationServer::OPTIONS_CMDLINE + ":help-extended"]
@@ -459,7 +459,7 @@ void AvocadoServer::buildApplicationServer () {
// in shell mode ignore the rest
// .............................................................................
- if (_applicationServer->programOptions().has("shell")) {
+ if (_applicationServer->programOptions().has("console")) {
executeShell();
exit(EXIT_SUCCESS);
}
diff --git a/RestServer/glossary.dox b/RestServer/glossary.dox
index 3e1deb3993..ce573a516a 100644
--- a/RestServer/glossary.dox
+++ b/RestServer/glossary.dox
@@ -46,7 +46,8 @@
/// @page GlossaryDocument
///
/// @GE{Document}: Documents in AvocadoDB are JSON objects. These objects can be
-/// nested (to any depth) and may contains lists.
+/// nested (to any depth) and may contains lists. Each document is unique identified
+/// by its document handle.
///
/// @page GlossaryDocumentHandle
///
diff --git a/RestServer/rest-document.dox b/RestServer/rest-document.dox
index c9fe8af017..e2e20518b9 100644
--- a/RestServer/rest-document.dox
+++ b/RestServer/rest-document.dox
@@ -86,9 +86,14 @@
/////////////////////////////////////////////////////////////////
///
/// All documents in AvocadoDB have a document handle. This handle uniquely
-/// defines a document and is managed by AvocadoDB. Assume that the document
-/// handle, which is stored in the @LIT{_id} field of the document, is
-/// @LIT{7254820/362549736}, then the HTTP URI of that document is:
+/// defines a document and is managed by AvocadoDB. All documents are
+/// found under the URI
+///
+/// @LIT{document/@FA{document-handle}}
+///
+/// For exmaple: Assume that the document handle, which is stored in
+/// the @LIT{_id} field of the document, is @LIT{7254820/362549736},
+/// then the URL of that document is:
///
/// @LIT{http://localhost:8529/document/7254820/362549736}
///
diff --git a/V8/v8-vocbase.cpp b/V8/v8-vocbase.cpp
index 164adafc60..f7b7de84d3 100644
--- a/V8/v8-vocbase.cpp
+++ b/V8/v8-vocbase.cpp
@@ -2025,7 +2025,7 @@ static v8::Handle JS_SkiplistSelectAql (v8::Arguments const& argv) {
if (idx == NULL) {
return scope.Close(v8::ThrowException(v8::String::New("invalid index in where statement")));
}
- if (! CheckWhereSkiplistOperators(idx->_shapeList->_length, slWhere->_operator)) {
+ if (! CheckWhereSkiplistOperators(idx->_paths._length, slWhere->_operator)) {
return scope.Close(v8::ThrowException(v8::String::New("One or more operators has invalid number of attributes")));
}
diff --git a/VocBase/blob-collection.c b/VocBase/blob-collection.c
index 54c56399bc..7e2e074f4f 100644
--- a/VocBase/blob-collection.c
+++ b/VocBase/blob-collection.c
@@ -50,6 +50,7 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
TRI_datafile_t* journal;
TRI_df_marker_t* position;
bool ok;
+ int res;
char* filename;
char* jname;
char* number;
@@ -95,9 +96,9 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
TRI_FreeString(filename);
// create a collection header
- ok = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
+ res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
TRI_FreeDatafile(journal);
LOG_ERROR("cannot create document header in journal '%s': %s",
@@ -117,9 +118,10 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
cm._cid = collection->base._cid;
TRI_FillCrcMarkerDatafile(&cm.base, sizeof(cm), 0, 0);
- ok = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
- if (! ok) {
+ res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
+
+ if (res != TRI_ERROR_NO_ERROR) {
TRI_FreeDatafile(journal);
LOG_ERROR("cannot create document header in journal '%s': %s",
@@ -202,6 +204,7 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
TRI_df_marker_t** result) {
TRI_datafile_t* datafile;
bool ok;
+ int res;
size_t n;
// need to create a new journal?
@@ -220,9 +223,9 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
datafile = collection->base._journals._buffer[0];
// try to reserve space
- ok = TRI_ReserveElementDatafile(datafile, size, result);
+ res = TRI_ReserveElementDatafile(datafile, size, result);
- while (! ok && TRI_errno() == TRI_ERROR_AVOCADO_DATAFILE_FULL) {
+ while (res == TRI_ERROR_AVOCADO_DATAFILE_FULL) {
ok = CloseJournal(collection, datafile);
if (! ok) {
@@ -238,10 +241,10 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
datafile = collection->base._journals._buffer[0];
- ok = TRI_ReserveElementDatafile(datafile, size, result);
+ res = TRI_ReserveElementDatafile(datafile, size, result);
}
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
collection->base._state = TRI_COL_STATE_WRITE_ERROR;
return NULL;
}
@@ -254,22 +257,22 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
/// @brief writes an element to a given position
////////////////////////////////////////////////////////////////////////////////
-static bool WriteElement (TRI_blob_collection_t* collection,
- TRI_datafile_t* journal,
- TRI_df_marker_t* position,
- TRI_df_marker_t* marker,
- TRI_voc_size_t markerSize,
+static int WriteElement (TRI_blob_collection_t* collection,
+ TRI_datafile_t* journal,
+ TRI_df_marker_t* position,
+ TRI_df_marker_t* marker,
+ TRI_voc_size_t markerSize,
void const* body,
- size_t bodySize) {
- bool ok;
+ size_t bodySize) {
+ int res;
- ok = TRI_WriteElementDatafile(journal, position, marker, markerSize, body, bodySize, true);
+ res = TRI_WriteElementDatafile(journal, position, marker, markerSize, body, bodySize, true);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
collection->base._state = TRI_COL_STATE_WRITE_ERROR;
}
- return ok;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
@@ -357,14 +360,14 @@ void TRI_FreeBlobCollection (TRI_blob_collection_t* collection) {
/// @brief writes an element splitted into marker and body to file
////////////////////////////////////////////////////////////////////////////////
-bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
- TRI_df_marker_t* marker,
- TRI_voc_size_t markerSize,
- void const* body,
- TRI_voc_size_t bodySize,
- TRI_df_marker_t** result) {
+int TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
+ TRI_df_marker_t* marker,
+ TRI_voc_size_t markerSize,
+ void const* body,
+ TRI_voc_size_t bodySize,
+ TRI_df_marker_t** result) {
TRI_datafile_t* journal;
- bool ok;
+ int res;
// generate a new tick
marker->_tick = TRI_NewTickVocBase();
@@ -394,12 +397,12 @@ bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
}
// and write marker and blob
- ok = WriteElement(collection, journal, *result, marker, markerSize, body, bodySize);
+ res = WriteElement(collection, journal, *result, marker, markerSize, body, bodySize);
// release lock on collection
TRI_UnlockMutex(&collection->_lock);
- return ok;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/VocBase/blob-collection.h b/VocBase/blob-collection.h
index 7c70f06d96..c135c9fa7e 100644
--- a/VocBase/blob-collection.h
+++ b/VocBase/blob-collection.h
@@ -117,12 +117,12 @@ void TRI_FreeBlobCollection (TRI_blob_collection_t* collection);
/// @brief writes an element splitted into marker and body to file
////////////////////////////////////////////////////////////////////////////////
-bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
- TRI_df_marker_t* marker,
- TRI_voc_size_t markerSize,
- void const* body,
- TRI_voc_size_t bodySize,
- TRI_df_marker_t** result);
+int TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
+ TRI_df_marker_t* marker,
+ TRI_voc_size_t markerSize,
+ void const* body,
+ TRI_voc_size_t bodySize,
+ TRI_df_marker_t** result);
////////////////////////////////////////////////////////////////////////////////
/// @brief opens an existing collection
diff --git a/VocBase/compactor.c b/VocBase/compactor.c
index 9c91926ba7..cb3488b6c5 100644
--- a/VocBase/compactor.c
+++ b/VocBase/compactor.c
@@ -112,10 +112,10 @@ static TRI_datafile_t* SelectCompactor (TRI_sim_collection_t* collection,
/// @brief write document to file
////////////////////////////////////////////////////////////////////////////////
-static bool CopyDocument (TRI_sim_collection_t* collection,
- TRI_df_marker_t const* marker,
- TRI_df_marker_t** result,
- TRI_voc_fid_t* fid) {
+static int CopyDocument (TRI_sim_collection_t* collection,
+ TRI_df_marker_t const* marker,
+ TRI_df_marker_t** result,
+ TRI_voc_fid_t* fid) {
TRI_datafile_t* journal;
TRI_voc_size_t total;
@@ -140,6 +140,10 @@ static bool CopyDocument (TRI_sim_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
/// @brief callback to delete datafile
+///
+/// Note that a datafile pointer is never freed. The state of the datafile
+/// will be switch to TRI_DF_STATE_CLOSED - but the datafile pointer is
+/// still valid.
////////////////////////////////////////////////////////////////////////////////
static void RemoveDatafileCallback (TRI_datafile_t* datafile, void* data) {
@@ -189,7 +193,7 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
TRI_doc_mptr_t const* found;
TRI_sim_collection_t* collection;
TRI_voc_fid_t fid;
- bool ok;
+ int res;
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } cnv;
collection = data;
@@ -226,9 +230,9 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
TRI_ReadUnlockReadWriteLock(&collection->_lock);
// write to compactor files
- ok = CopyDocument(collection, marker, &result, &fid);
+ res = CopyDocument(collection, marker, &result, &fid);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
LOG_FATAL("cannot write compactor file: ", TRI_last_error());
return false;
}
@@ -269,9 +273,9 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
// TODO: remove TRI_doc_deletion_marker_t from file
// write to compactor files
- ok = CopyDocument(collection, marker, &result, &fid);
+ res = CopyDocument(collection, marker, &result, &fid);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
LOG_FATAL("cannot write compactor file: ", TRI_last_error());
return false;
}
diff --git a/VocBase/datafile.c b/VocBase/datafile.c
index bfe40ac50b..c2284a9384 100644
--- a/VocBase/datafile.c
+++ b/VocBase/datafile.c
@@ -340,9 +340,9 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
TRI_df_header_marker_t header;
TRI_df_marker_t* position;
TRI_voc_tick_t tick;
- bool ok;
char zero;
int fd;
+ int result;
off_t offset;
ssize_t res;
void* data;
@@ -355,7 +355,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
TRI_set_errno(TRI_ERROR_AVOCADO_MAXIMAL_SIZE_TOO_SMALL);
LOG_ERROR("cannot create datafile '%s', maximal size '%u' is too small", filename, (unsigned int) maximalSize);
-
return NULL;
}
@@ -366,7 +365,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
TRI_set_errno(TRI_ERROR_SYS_ERROR);
LOG_ERROR("cannot create datafile '%s': '%s'", filename, TRI_last_error());
-
return NULL;
}
@@ -378,7 +376,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
close(fd);
LOG_ERROR("cannot seek in datafile '%s': '%s'", filename, TRI_last_error());
-
return NULL;
}
@@ -390,7 +387,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
close(fd);
LOG_ERROR("cannot create sparse datafile '%s': '%s'", filename, TRI_last_error());
-
return NULL;
}
@@ -402,7 +398,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
close(fd);
LOG_ERROR("cannot memory map file '%s': '%s'", filename, TRI_last_error());
-
return NULL;
}
@@ -411,8 +406,13 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
// create datafile structure
datafile = TRI_Allocate(sizeof(TRI_datafile_t));
- if (!datafile) {
- // TODO: FIXME
+
+ if (datafile == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+ close(fd);
+
+ LOG_ERROR("out-of-memory");
+ return NULL;
}
InitDatafile(datafile,
@@ -440,13 +440,13 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
TRI_FillCrcMarkerDatafile(&header.base, sizeof(TRI_df_header_marker_t), 0, 0);
// reserve space and write header to file
- ok = TRI_ReserveElementDatafile(datafile, header.base._size, &position);
+ result = TRI_ReserveElementDatafile(datafile, header.base._size, &position);
- if (ok) {
- ok = TRI_WriteElementDatafile(datafile, position, &header.base, header.base._size, 0, 0, true);
+ if (result == TRI_ERROR_NO_ERROR) {
+ result = TRI_WriteElementDatafile(datafile, position, &header.base, header.base._size, 0, 0, true);
}
- if (! ok) {
+ if (result != TRI_ERROR_NO_ERROR) {
LOG_ERROR("cannot write header to datafile '%s'",
filename);
@@ -555,23 +555,20 @@ void TRI_FillCrcMarkerDatafile (TRI_df_marker_t* marker,
/// @brief reserves room for an element, advances the pointer
////////////////////////////////////////////////////////////////////////////////
-bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
- TRI_voc_size_t size,
- TRI_df_marker_t** position) {
+int TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
+ TRI_voc_size_t size,
+ TRI_df_marker_t** position) {
*position = 0;
size = ((size + TRI_DF_BLOCK_ALIGN - 1) / TRI_DF_BLOCK_ALIGN) * TRI_DF_BLOCK_ALIGN;
if (datafile->_state != TRI_DF_STATE_WRITE) {
if (datafile->_state == TRI_DF_STATE_READ) {
- TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
-
LOG_ERROR("cannot reserve marker, datafile is read-only");
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
}
- TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
}
// add the marker, leave enough room for the footer
@@ -581,7 +578,7 @@ bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
LOG_TRACE("cannot write marker, not enough space");
- return false;
+ return datafile->_lastError;
}
*position = (TRI_df_marker_t*) datafile->_next;
@@ -589,20 +586,20 @@ bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
datafile->_next += size;
datafile->_currentSize += size;
- return true;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief writes a marker and body to the datafile
////////////////////////////////////////////////////////////////////////////////
-bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
- void* position,
- TRI_df_marker_t const* marker,
- TRI_voc_size_t markerSize,
- void const* body,
- TRI_voc_size_t bodySize,
- bool forceSync) {
+int TRI_WriteElementDatafile (TRI_datafile_t* datafile,
+ void* position,
+ TRI_df_marker_t const* marker,
+ TRI_voc_size_t markerSize,
+ void const* body,
+ TRI_voc_size_t bodySize,
+ bool forceSync) {
TRI_voc_size_t size;
size = markerSize + bodySize;
@@ -615,15 +612,12 @@ bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
if (datafile->_state != TRI_DF_STATE_WRITE) {
if (datafile->_state == TRI_DF_STATE_READ) {
- TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
-
LOG_ERROR("cannot write marker, datafile is read-only");
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
}
- TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
}
memcpy(position, marker, markerSize);
@@ -649,14 +643,14 @@ bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
LOG_ERROR("msync failed with: %s", TRI_last_error());
- return false;
+ return datafile->_lastError;
}
else {
LOG_TRACE("msync succeeded %p, size %lu", position, (unsigned long) size);
}
}
- return true;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@@ -849,6 +843,7 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
TRI_df_footer_marker_t footer;
TRI_df_marker_t* position;
bool ok;
+ int res;
if (datafile->_state == TRI_DF_STATE_READ) {
TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
@@ -877,13 +872,14 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
// reserve space and write footer to file
datafile->_footerSize = 0;
- ok = TRI_ReserveElementDatafile(datafile, footer.base._size, &position);
- if (ok) {
- ok = TRI_WriteElementDatafile(datafile, position, &footer.base, footer.base._size, 0, 0, true);
+ res = TRI_ReserveElementDatafile(datafile, footer.base._size, &position);
+
+ if (res == TRI_ERROR_NO_ERROR) {
+ res = TRI_WriteElementDatafile(datafile, position, &footer.base, footer.base._size, 0, 0, true);
}
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
return false;
}
@@ -912,8 +908,6 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
// truncate datafile
if (ok) {
- int res;
-
res = ftruncate(datafile->_fd, datafile->_currentSize);
if (res < 0) {
@@ -925,7 +919,7 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
datafile->_state = TRI_DF_STATE_READ;
}
- return ok;
+ return ok ? TRI_ERROR_NO_ERROR : datafile->_lastError;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/VocBase/datafile.h b/VocBase/datafile.h
index 468fd46b49..8078aee14f 100644
--- a/VocBase/datafile.h
+++ b/VocBase/datafile.h
@@ -431,15 +431,15 @@ void TRI_FillCrcMarkerDatafile (TRI_df_marker_t* marker,
/// @brief reserves room for an element, advances the pointer
////////////////////////////////////////////////////////////////////////////////
-bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
- TRI_voc_size_t size,
- TRI_df_marker_t** position);
+int TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
+ TRI_voc_size_t size,
+ TRI_df_marker_t** position);
////////////////////////////////////////////////////////////////////////////////
/// @brief writes a marker and body to the datafile
////////////////////////////////////////////////////////////////////////////////
-bool TRI_WriteElementDatafile (TRI_datafile_t*,
+int TRI_WriteElementDatafile (TRI_datafile_t*,
void* position,
TRI_df_marker_t const* marker,
TRI_voc_size_t markerSize,
diff --git a/VocBase/document-collection.c b/VocBase/document-collection.c
index 530a066fe8..32bf10eef9 100644
--- a/VocBase/document-collection.c
+++ b/VocBase/document-collection.c
@@ -212,6 +212,7 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
TRI_datafile_t* journal;
TRI_df_marker_t* position;
bool ok;
+ int res;
char* filename;
char* jname;
char* number;
@@ -288,9 +289,9 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
TRI_FreeString(filename);
// create a collection header
- ok = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
+ res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
collection->base._lastError = journal->_lastError;
TRI_FreeDatafile(journal);
@@ -308,9 +309,10 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
cm._cid = collection->base._cid;
TRI_FillCrcMarkerDatafile(&cm.base, sizeof(cm), 0, 0);
- ok = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
- if (! ok) {
+ res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
+
+ if (res != TRI_ERROR_NO_ERROR) {
collection->base._lastError = journal->_lastError;
TRI_FreeDatafile(journal);
diff --git a/VocBase/index.c b/VocBase/index.c
index 505d4e86f6..add0bd9b42 100644
--- a/VocBase/index.c
+++ b/VocBase/index.c
@@ -42,113 +42,6 @@
// --SECTION-- INDEX
// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// --SECTION-- private functions
-// -----------------------------------------------------------------------------
-
-////////////////////////////////////////////////////////////////////////////////
-/// @addtogroup VocBase
-/// @{
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief read the fields of an index from a json structure and return them
-////////////////////////////////////////////////////////////////////////////////
-
-static TRI_vector_string_t* GetFieldsIndex (const TRI_idx_type_e indexType,
- TRI_json_t* json,
- TRI_index_geo_variant_e* geoVariant) {
- TRI_vector_string_t* fields;
- TRI_json_t* strVal;
- TRI_json_t* strVal2;
- char* temp1;
- char* temp2;
- char* temp3;
- uint32_t numFields;
- size_t i;
-
- *geoVariant = INDEX_GEO_NONE;
- fields = (TRI_vector_string_t*) TRI_Allocate(sizeof(TRI_vector_string_t));
- if (!fields) {
- return NULL;
- }
-
- TRI_InitVectorString(fields);
- if (indexType == TRI_IDX_TYPE_GEO_INDEX) {
- strVal = TRI_LookupArrayJson(json, "location");
- if (!strVal || strVal->_type != TRI_JSON_STRING) {
- strVal = TRI_LookupArrayJson(json, "latitude");
- if (!strVal || strVal->_type != TRI_JSON_STRING) {
- return fields;
- }
- strVal2 = TRI_LookupArrayJson(json, "longitude");
- if (!strVal2 || strVal2->_type != TRI_JSON_STRING) {
- return fields;
- }
- temp1 = TRI_DuplicateString(strVal->_value._string.data);
- if (!temp1) {
- return fields;
- }
- TRI_PushBackVectorString(fields, temp1);
-
- temp1 = TRI_DuplicateString(strVal2->_value._string.data);
- if (!temp1) {
- return fields;
- }
- TRI_PushBackVectorString(fields, temp1);
- *geoVariant = INDEX_GEO_INDIVIDUAL_LAT_LON;
- }
- else {
- *geoVariant = INDEX_GEO_COMBINED_LON_LAT;
-
- strVal2 = TRI_LookupArrayJson(json, "geoJson");
- if (strVal2 && strVal2->_type == TRI_JSON_BOOLEAN) {
- if (strVal2->_value._boolean) {
- *geoVariant = INDEX_GEO_COMBINED_LAT_LON;
- }
- }
- TRI_PushBackVectorString(fields, strVal->_value._string.data);
- }
- }
- else {
- // read number of fields
- strVal = TRI_LookupArrayJson(json, "fieldCount");
- if (!strVal || strVal->_type != TRI_JSON_NUMBER) {
- return fields;
- }
-
- numFields = (uint32_t) strVal->_value._number;
- if (numFields == 0) {
- return fields;
- }
-
- // read field names
- for (i = 0; i < numFields ; i++) {
- temp1 = TRI_StringUInt32(i);
- if (temp1) {
- temp2 = TRI_Concatenate2String("field_", temp1);
- if (temp2) {
- strVal = TRI_LookupArrayJson(json, temp2);
- if (strVal && strVal->_type == TRI_JSON_STRING) {
- temp3 = TRI_DuplicateString(strVal->_value._string.data);
- if (temp3) {
- TRI_PushBackVectorString(fields, temp3);
- }
- }
- TRI_FreeString(temp2);
- }
- TRI_FreeString(temp1);
- }
- }
- }
-
- return fields;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// @}
-////////////////////////////////////////////////////////////////////////////////
-
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@@ -162,7 +55,7 @@ static TRI_vector_string_t* GetFieldsIndex (const TRI_idx_type_e indexType,
/// @brief removes an index file
////////////////////////////////////////////////////////////////////////////////
-bool TRI_RemoveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) {
+bool TRI_RemoveIndexFile (TRI_doc_collection_t* collection, TRI_index_t* idx) {
char* filename;
char* name;
char* number;
@@ -171,14 +64,17 @@ bool TRI_RemoveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) {
// construct filename
number = TRI_StringUInt64(idx->_iid);
- if (!number) {
+ if (number == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
LOG_ERROR("out of memory when creating index number");
return false;
}
name = TRI_Concatenate3String("index-", number, ".json");
- if (!name) {
+ if (name == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
TRI_FreeString(number);
LOG_ERROR("out of memory when creating index name");
return false;
@@ -186,7 +82,9 @@ bool TRI_RemoveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) {
filename = TRI_Concatenate2File(collection->base._directory, name);
- if (!filename) {
+ if (filename == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
TRI_FreeString(number);
TRI_FreeString(name);
LOG_ERROR("out of memory when creating index filename");
@@ -222,20 +120,28 @@ bool TRI_SaveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) {
json = idx->json(idx, collection);
if (json == NULL) {
+ TRI_set_errno(TRI_ERROR_INTERNAL);
+
LOG_TRACE("cannot save index definition: index cannot be jsonfied");
return false;
}
// construct filename
number = TRI_StringUInt64(idx->_iid);
- if (!number) {
+
+ if (number == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
LOG_ERROR("out of memory when creating index number");
TRI_FreeJson(json);
return false;
}
name = TRI_Concatenate3String("index-", number, ".json");
- if (!name) {
+
+ if (name == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
LOG_ERROR("out of memory when creating index name");
TRI_FreeJson(json);
TRI_FreeString(number);
@@ -243,18 +149,23 @@ bool TRI_SaveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) {
}
filename = TRI_Concatenate2File(collection->base._directory, name);
- if (!filename) {
+
+ if (filename == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
LOG_ERROR("out of memory when creating index filename");
TRI_FreeJson(json);
TRI_FreeString(number);
TRI_FreeString(name);
return false;
}
+
TRI_FreeString(name);
TRI_FreeString(number);
// and save
ok = TRI_SaveJson(filename, json);
+
TRI_FreeString(filename);
TRI_FreeJson(json);
@@ -276,6 +187,7 @@ TRI_index_t* TRI_LookupIndex (TRI_doc_collection_t* collection, TRI_idx_iid_t ii
size_t i;
if (collection->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE);
return NULL;
}
@@ -289,52 +201,25 @@ TRI_index_t* TRI_LookupIndex (TRI_doc_collection_t* collection, TRI_idx_iid_t ii
}
}
+ TRI_set_errno(TRI_ERROR_AVOCADO_NO_INDEX);
return NULL;
}
-////////////////////////////////////////////////////////////////////////////////
-/// @brief free an existing index definition
-////////////////////////////////////////////////////////////////////////////////
-
-void TRI_FreeIndexDefinition (TRI_index_definition_t* definition) {
- assert(definition->_fields);
- TRI_FreeVectorString(definition->_fields);
- TRI_Free(definition);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief free an existing index definitions vector
-////////////////////////////////////////////////////////////////////////////////
-
-void TRI_FreeIndexDefinitions (TRI_vector_pointer_t* definitions) {
- TRI_index_definition_t* definition;
- size_t i;
-
- if (!definitions) {
- return;
- }
-
- for (i = 0; i < definitions->_length; i++) {
- definition = (TRI_index_definition_t*) definitions->_buffer[i];
- assert(definition);
- TRI_FreeIndexDefinition(definition);
- }
-
- TRI_FreeVectorPointer(definitions);
-}
-
////////////////////////////////////////////////////////////////////////////////
/// @brief gets name of index type
////////////////////////////////////////////////////////////////////////////////
-char* TRI_GetTypeNameIndex (const TRI_index_definition_t* const indexDefinition) {
- switch (indexDefinition->_type) {
+char const* TRI_TypeNameIndex (const TRI_index_t* const idx) {
+ switch (idx->_type) {
case TRI_IDX_TYPE_HASH_INDEX:
return "hash";
+
case TRI_IDX_TYPE_SKIPLIST_INDEX:
return "skiplist";
+
case TRI_IDX_TYPE_GEO_INDEX:
return "geo";
+
case TRI_IDX_TYPE_PRIMARY_INDEX:
return "primary";
}
@@ -342,200 +227,6 @@ char* TRI_GetTypeNameIndex (const TRI_index_definition_t* const indexDefinition)
return "unknown";
}
-////////////////////////////////////////////////////////////////////////////////
-/// @brief gets the definitions of all index files for a collection
-////////////////////////////////////////////////////////////////////////////////
-
-TRI_vector_pointer_t* TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase,
- const char* collectionName) {
- TRI_vector_pointer_t* indexes;
- TRI_index_definition_t* indexDefinition;
- TRI_index_geo_variant_e geoVariant;
- TRI_vector_string_t indexFiles;
- TRI_vector_string_t* fields;
- TRI_json_t* json;
- TRI_json_t* strVal;
- TRI_json_t* numVal;
- char* error;
- char* temp;
- TRI_idx_iid_t indexId;
- TRI_idx_type_e indexType;
- bool indexUnique;
- size_t i;
-
- assert(vocbase);
-
- indexes = (TRI_vector_pointer_t*) TRI_Allocate(sizeof(TRI_vector_pointer_t));
- if (!indexes) {
- return NULL;
- }
- TRI_InitVectorPointer(indexes);
-
- // add "pseudo" primary index
- indexDefinition = (TRI_index_definition_t*) TRI_Allocate(sizeof(TRI_index_definition_t));
- if (indexDefinition) {
- indexDefinition->_fields = TRI_Allocate(sizeof(TRI_vector_string_t));
- if (!indexDefinition->_fields) {
- TRI_Free(indexDefinition);
- return NULL;
- }
-
- TRI_InitVectorString(indexDefinition->_fields);
- indexDefinition->_iid = 0; // note: this id is ignored
- indexDefinition->_type = TRI_IDX_TYPE_PRIMARY_INDEX;
- indexDefinition->_isUnique = true; // primary index is always unique
-
- temp = TRI_DuplicateString("_id");
- if (temp) {
- TRI_PushBackVectorString(indexDefinition->_fields, temp); // name of field
- }
- TRI_PushBackVectorPointer(indexes, indexDefinition);
- }
-
- // get all index filenames
- indexFiles = TRI_GetCollectionIndexFiles(vocbase, collectionName);
- for (i = 0; i < indexFiles._length; ++i) {
- // read JSON data from index file
- json = TRI_JsonFile(indexFiles._buffer[i], &error);
- if (!json) {
- continue;
- }
- if (error) {
- goto NEXT_INDEX;
- }
-
- if (json->_type != TRI_JSON_ARRAY) {
- goto NEXT_INDEX;
- }
-
- // index file contains a JSON array. fine.
-
- // read index id
- indexId = 0;
- numVal = TRI_LookupArrayJson(json, "iid");
- if (!numVal || numVal->_type != TRI_JSON_NUMBER) {
- goto NEXT_INDEX;
- }
- indexId = (uint64_t) numVal->_value._number;
- if (indexId == 0) {
- goto NEXT_INDEX;
- }
-
- // read uniqueness information
- strVal = TRI_LookupArrayJson(json, "unique");
- if (!strVal || strVal->_type != TRI_JSON_BOOLEAN) {
- indexUnique = false; // default is non-unique index
- }
- else {
- indexUnique = strVal->_value._boolean;
- }
-
- // read index type
- strVal = TRI_LookupArrayJson(json, "type");
- if (!strVal || strVal->_type != TRI_JSON_STRING) {
- goto NEXT_INDEX;
- }
-
- if (strcmp(strVal->_value._string.data, "hash") == 0) {
- indexType = TRI_IDX_TYPE_HASH_INDEX;
- }
- else if (strcmp(strVal->_value._string.data, "skiplist") == 0) {
- indexType = TRI_IDX_TYPE_SKIPLIST_INDEX;
- }
- else if (strcmp(strVal->_value._string.data, "geo") == 0) {
- indexType = TRI_IDX_TYPE_GEO_INDEX;
- }
- else {
- // unknown index type
- LOG_ERROR("found unknown index type '%s'", strVal->_value._string.data);
- goto NEXT_INDEX;
- }
-
- fields = GetFieldsIndex(indexType, json, &geoVariant);
- if (!fields) {
- goto NEXT_INDEX;
- }
- if (fields->_length == 0) {
- TRI_DestroyVectorString(fields);
- TRI_Free(fields);
- goto NEXT_INDEX;
- }
-
- // create the index definition
- indexDefinition =
- (TRI_index_definition_t*) TRI_Allocate(sizeof(TRI_index_definition_t));
- if (!indexDefinition) {
- TRI_FreeVectorString(fields);
- goto NEXT_INDEX;
- }
-
- indexDefinition->_iid = indexId;
- indexDefinition->_type = indexType;
- indexDefinition->_isUnique = indexUnique;
- indexDefinition->_fields = fields;
- indexDefinition->_geoVariant = geoVariant;
-
- TRI_PushBackVectorPointer(indexes, indexDefinition);
-
-NEXT_INDEX:
- TRI_FreeJson(json);
- }
- TRI_DestroyVectorString(&indexFiles);
-
- return indexes;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief gets the names of all index files for a collection
-////////////////////////////////////////////////////////////////////////////////
-
-TRI_vector_string_t TRI_GetCollectionIndexFiles(const TRI_vocbase_t* vocbase,
- const char* collectionName) {
- TRI_vector_string_t files;
- TRI_vector_string_t indexFiles;
- char *path;
- size_t i;
- size_t n;
-
- assert(vocbase);
- TRI_InitVectorString(&indexFiles);
-
- path = TRI_Concatenate2File(vocbase->_path, collectionName);
- if (!path) {
- return indexFiles;
- }
-
- files = TRI_FilesDirectory(path);
- n = files._length;
-
- for (i = 0; i < n; ++i) {
- char* name;
- char* file;
-
- name = files._buffer[i];
-
- if (name[0] == '\0' || strncmp(name, "index-", 6) != 0) {
- continue;
- }
-
- file = TRI_Concatenate2File(path, name);
- if (!file) {
- continue;
- }
-
- if (TRI_IsDirectory(file)) {
- continue;
- }
-
- TRI_PushBackVectorString(&indexFiles, file);
- }
-
- TRI_DestroyVectorString(&files);
- TRI_FreeString(path);
-
- return indexFiles;
-}
-
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@@ -755,7 +446,7 @@ static bool ExtractDoubleList (TRI_shaper_t* shaper,
/// @brief inserts a new document, location is a list
////////////////////////////////////////////////////////////////////////////////
-static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
union { void* p; void const* c; } cnv;
GeoCoordinate gc;
TRI_shaper_t* shaper;
@@ -789,7 +480,6 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// and insert into index
gc.latitude = latitude;
gc.longitude = longitude;
-
cnv.c = doc;
gc.data = cnv.p;
@@ -798,22 +488,27 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
if (res == -1) {
LOG_WARNING("found duplicate entry in geo-index, should not happen");
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
else if (res == -2) {
- LOG_WARNING("out-of-memory in geo-index");
+ return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
else if (res == -3) {
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
+ return TRI_set_errno(TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED);
+ }
+ else if (res < 0) {
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
- return res == 0;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document, location is a list
////////////////////////////////////////////////////////////////////////////////
-static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
+static int UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
union { void* p; void const* c; } cnv;
GeoCoordinate gc;
TRI_shaper_t* shaper;
@@ -873,22 +568,28 @@ static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_sha
if (res == -1) {
LOG_WARNING("found duplicate entry in geo-index, should not happen");
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
else if (res == -2) {
LOG_WARNING("out-of-memory in geo-index");
+ return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
else if (res == -3) {
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
+ return TRI_set_errno(TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED);
+ }
+ else if (res < 0) {
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
- return res == 0;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief erases a document, location is a list
////////////////////////////////////////////////////////////////////////////////
-static bool RemoveGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int RemoveGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
union { void* p; void const* c; } cnv;
GeoCoordinate gc;
TRI_shaper_t* shaper;
@@ -922,12 +623,11 @@ static bool RemoveGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
if (res != 0) {
LOG_WARNING("cannot remove old index entry: %d", res);
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
-
- return res == 0;
}
- return true;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@@ -953,7 +653,9 @@ static TRI_json_t* JsonGeoIndex (TRI_index_t* idx, TRI_doc_collection_t* collect
// create json
json = TRI_CreateArrayJson();
- if (!json) {
+
+ if (json == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
@@ -998,7 +700,9 @@ static TRI_json_t* JsonGeoIndex2 (TRI_index_t* idx, TRI_doc_collection_t* collec
// create json
json = TRI_CreateArrayJson();
- if (!json) {
+
+ if (json == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
@@ -1028,26 +732,37 @@ static TRI_json_t* JsonGeoIndex2 (TRI_index_t* idx, TRI_doc_collection_t* collec
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s* collection,
+ char const* locationName,
TRI_shape_pid_t location,
bool geoJson) {
TRI_geo_index_t* geo;
+ char* ln;
geo = TRI_Allocate(sizeof(TRI_geo_index_t));
- if (!geo) {
+ ln = TRI_DuplicateString(locationName);
+
+ if (geo == NULL || ln == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
+ TRI_InitVectorString(&geo->base._fields);
+
geo->base._iid = TRI_NewTickVocBase();
geo->base._type = TRI_IDX_TYPE_GEO_INDEX;
geo->base._collection = collection;
+ geo->base._unique = false;
geo->base.insert = InsertGeoIndex;
geo->base.remove = RemoveGeoIndex;
geo->base.update = UpdateGeoIndex;
geo->base.json = JsonGeoIndex;
+ TRI_PushBackVectorString(&geo->base._fields, ln);
+
geo->_geoIndex = GeoIndex_new();
+ geo->_variant = geoJson ? INDEX_GEO_COMBINED_LAT_LON : INDEX_GEO_COMBINED_LON_LAT;
geo->_location = location;
geo->_latitude = 0;
geo->_longitude = 0;
@@ -1061,26 +776,41 @@ TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s* collection,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s* collection,
+ char const* latitudeName,
TRI_shape_pid_t latitude,
+ char const* longitudeName,
TRI_shape_pid_t longitude) {
TRI_geo_index_t* geo;
+ char* lan;
+ char* lon;
geo = TRI_Allocate(sizeof(TRI_geo_index_t));
- if (!geo) {
+ lan = TRI_DuplicateString(latitudeName);
+ lon = TRI_DuplicateString(longitudeName);
+
+ if (geo == NULL || lan == NULL || lon == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
+ TRI_InitVectorString(&geo->base._fields);
+
geo->base._iid = TRI_NewTickVocBase();
geo->base._type = TRI_IDX_TYPE_GEO_INDEX;
geo->base._collection = collection;
+ geo->base._unique = false;
geo->base.insert = InsertGeoIndex;
geo->base.remove = RemoveGeoIndex;
geo->base.update = UpdateGeoIndex;
geo->base.json = JsonGeoIndex2;
+ TRI_PushBackVectorString(&geo->base._fields, lan);
+ TRI_PushBackVectorString(&geo->base._fields, lon);
+
geo->_geoIndex = GeoIndex_new();
+ geo->_variant = INDEX_GEO_INDIVIDUAL_LAT_LON;
geo->_location = 0;
geo->_latitude = latitude;
geo->_longitude = longitude;
@@ -1095,6 +825,8 @@ TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s* collection,
void TRI_DestroyGeoIndex (TRI_index_t* idx) {
TRI_geo_index_t* geo;
+ TRI_DestroyVectorString(&idx->_fields);
+
geo = (TRI_geo_index_t*) idx;
GeoIndex_free(geo->_geoIndex);
@@ -1180,10 +912,10 @@ GeoCoordinates* TRI_NearestGeoIndex (TRI_index_t* idx,
/// @brief helper for hashing
////////////////////////////////////////////////////////////////////////////////
-static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
- HashIndexElement* hashElement,
- const TRI_doc_mptr_t* document,
- const TRI_shaped_json_t* shapedDoc) {
+static int HashIndexHelper (const TRI_hash_index_t* hashIndex,
+ HashIndexElement* hashElement,
+ 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;
@@ -1199,9 +931,8 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
hashElement->data = NULL;
- for (j = 0; j < hashIndex->_shapeList->_length; ++j) {
-
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(hashIndex->_shapeList,j)));
+ for (j = 0; j < hashIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_paths,j)));
// ..........................................................................
// Determine if document has that particular shape
@@ -1213,8 +944,9 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
if (acc != NULL) {
TRI_FreeShapeAccessor(acc);
}
+
TRI_Free(hashElement->fields);
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
// ..........................................................................
@@ -1225,12 +957,13 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
TRI_FreeShapeAccessor(acc);
TRI_Free(hashElement->fields);
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
// ..........................................................................
// Store the json shaped Object -- this is what will be hashed
// ..........................................................................
+
hashElement->fields[j] = shapedObject;
TRI_FreeShapeAccessor(acc);
} // end of for loop
@@ -1246,8 +979,8 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
cnv.c = document;
hashElement->data = cnv.p;
- for (j = 0; j < hashIndex->_shapeList->_length; ++j) {
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(hashIndex->_shapeList,j)));
+ for (j = 0; j < hashIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_paths,j)));
// ..........................................................................
// Determine if document has that particular shape
@@ -1262,7 +995,7 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
TRI_Free(hashElement->fields);
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
// ..........................................................................
@@ -1273,10 +1006,9 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
TRI_FreeShapeAccessor(acc);
TRI_Free(hashElement->fields);
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
-
// ..........................................................................
// Store the field
// ..........................................................................
@@ -1288,21 +1020,20 @@ static bool HashIndexHelper (const TRI_hash_index_t* hashIndex,
}
else {
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
- return true;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hash indexes a document
////////////////////////////////////////////////////////////////////////////////
-static bool InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
HashIndexElement hashElement;
TRI_hash_index_t* hashIndex;
int res;
- bool ok;
// ............................................................................
// Obtain the hash index structure
@@ -1312,7 +1043,7 @@ static bool InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
if (idx == NULL) {
LOG_WARNING("internal error in InsertHashIndex");
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
// ............................................................................
@@ -1320,25 +1051,25 @@ static bool InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// These will be used for hashing.
// ............................................................................
- hashElement.numFields = hashIndex->_shapeList->_length;
- hashElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * hashElement.numFields);
+ hashElement.numFields = hashIndex->_paths._length;
+ hashElement.fields = TRI_Allocate(sizeof(TRI_shaped_json_t) * hashElement.numFields);
if (hashElement.fields == NULL) {
LOG_WARNING("out-of-memory in InsertHashIndex");
- return false;
+ return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
- ok = HashIndexHelper(hashIndex, &hashElement, doc, NULL);
+ res = HashIndexHelper(hashIndex, &hashElement, doc, NULL);
- if (!ok) {
- return false;
+ if (res != TRI_ERROR_NO_ERROR) {
+ return res;
}
// ............................................................................
// Fill the json field list from the document for unique hash index
// ............................................................................
- if (hashIndex->_unique) {
+ if (hashIndex->base._unique) {
res = HashIndex_insert(hashIndex->_hashIndex, &hashElement);
}
@@ -1350,17 +1081,7 @@ static bool InsertHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
res = MultiHashIndex_insert(hashIndex->_hashIndex, &hashElement);
}
- if (res == -1) {
- LOG_WARNING("found duplicate entry in hash-index, should not happen");
- }
- else if (res == -2) {
- LOG_WARNING("out-of-memory in hash-index");
- }
- else if (res == -99) {
- LOG_DEBUG("unknown error, ignoring entry");
- }
-
- return res == 0;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1372,7 +1093,7 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
const TRI_shape_path_t* path;
TRI_hash_index_t* hashIndex;
char const** fieldList;
- char* fieldCounter;
+ char fieldCounter[64]; // used below to store strings like "field_ddd"
size_t j;
// ..........................................................................
@@ -1382,6 +1103,7 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
hashIndex = (TRI_hash_index_t*) idx;
if (hashIndex == NULL) {
+ TRI_set_errno(TRI_ERROR_INTERNAL);
return NULL;
}
@@ -1389,9 +1111,10 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
// Allocate sufficent memory for the field list
// ..........................................................................
- fieldList = TRI_Allocate( (sizeof(char*) * hashIndex->_shapeList->_length) );
+ fieldList = TRI_Allocate( (sizeof(char*) * hashIndex->_paths._length) );
if (fieldList == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
@@ -1399,11 +1122,12 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
// Convert the attributes (field list of the hash index) into strings
// ..........................................................................
- for (j = 0; j < hashIndex->_shapeList->_length; ++j) {
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(hashIndex->_shapeList,j)));
+ for (j = 0; j < hashIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_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;
}
@@ -1417,31 +1141,23 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
json = TRI_CreateArrayJson();
- if (!json) {
+ if (json == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
TRI_Free(fieldList);
return NULL;
}
- fieldCounter = TRI_Allocate(64); // used below to store strings like "field_ddd"
-
- if (!fieldCounter) {
- TRI_Free(fieldList);
- TRI_FreeJson(json);
- return NULL;
- }
-
TRI_Insert2ArrayJson(json, "iid", TRI_CreateNumberJson(idx->_iid));
- TRI_Insert2ArrayJson(json, "unique", TRI_CreateBooleanJson(hashIndex->_unique));
+ TRI_Insert2ArrayJson(json, "unique", TRI_CreateBooleanJson(hashIndex->base._unique));
TRI_Insert2ArrayJson(json, "type", TRI_CreateStringCopyJson("hash"));
- TRI_Insert2ArrayJson(json, "fieldCount", TRI_CreateNumberJson(hashIndex->_shapeList->_length));
+ TRI_Insert2ArrayJson(json, "fieldCount", TRI_CreateNumberJson(hashIndex->_paths._length));
- for (j = 0; j < hashIndex->_shapeList->_length; ++j) {
- sprintf(fieldCounter,"field_%lu", (unsigned long) j);
+ for (j = 0; j < hashIndex->_paths._length; ++j) {
+ snprintf(fieldCounter, sizeof(fieldCounter), "field_%lu", (unsigned long) j);
TRI_Insert2ArrayJson(json, fieldCounter, TRI_CreateStringCopyJson(fieldList[j]));
}
TRI_Free(fieldList);
- TRI_Free(fieldCounter);
return json;
}
@@ -1450,10 +1166,10 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec
/// @brief removes a document from a hash index
////////////////////////////////////////////////////////////////////////////////
-static bool RemoveHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int RemoveHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
HashIndexElement hashElement;
TRI_hash_index_t* hashIndex;
- bool result;
+ int res;
// ............................................................................
// Obtain the hash index structure
@@ -1463,35 +1179,37 @@ static bool RemoveHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
if (idx == NULL) {
LOG_WARNING("internal error in RemoveHashIndex");
- return false;
+ return TRI_set_errno(TRI_ERROR_INTERNAL);
}
// ............................................................................
// Allocate some memory for the HashIndexElement structure
// ............................................................................
- hashElement.numFields = hashIndex->_shapeList->_length;
+ hashElement.numFields = hashIndex->_paths._length;
hashElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * hashElement.numFields);
if (hashElement.fields == NULL) {
LOG_WARNING("out-of-memory in InsertHashIndex");
- return false;
+ return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
// ..........................................................................
// Fill the json field list from the document
// ..........................................................................
- if (! HashIndexHelper(hashIndex, &hashElement, doc, NULL)) {
- return false;
+ res = HashIndexHelper(hashIndex, &hashElement, doc, NULL);
+
+ if (res != TRI_ERROR_NO_ERROR) {
+ return res;
}
// ............................................................................
// Attempt the removal for unique hash indexes
// ............................................................................
- if (hashIndex->_unique) {
- result = HashIndex_remove(hashIndex->_hashIndex, &hashElement);
+ if (hashIndex->base._unique) {
+ res = HashIndex_remove(hashIndex->_hashIndex, &hashElement);
}
// ............................................................................
@@ -1499,19 +1217,19 @@ static bool RemoveHashIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// ............................................................................
else {
- result = MultiHashIndex_remove(hashIndex->_hashIndex, &hashElement);
+ res = MultiHashIndex_remove(hashIndex->_hashIndex, &hashElement);
}
- return result;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document from a hash index
////////////////////////////////////////////////////////////////////////////////
-static bool UpdateHashIndex (TRI_index_t* idx,
- const TRI_doc_mptr_t* newDoc,
- const TRI_shaped_json_t* oldDoc) {
+static int UpdateHashIndex (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
@@ -1532,19 +1250,19 @@ static bool UpdateHashIndex (TRI_index_t* idx,
if (idx == NULL) {
LOG_WARNING("internal error in UpdateHashIndex");
- return false;
+ return TRI_ERROR_INTERNAL;
}
// ............................................................................
// Allocate some memory for the HashIndexElement structure
// ............................................................................
- hashElement.numFields = hashIndex->_shapeList->_length;
- hashElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * hashElement.numFields);
+ hashElement.numFields = hashIndex->_paths._length;
+ hashElement.fields = TRI_Allocate(sizeof(TRI_shaped_json_t) * hashElement.numFields);
if (hashElement.fields == NULL) {
LOG_WARNING("out-of-memory in UpdateHashIndex");
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
// ............................................................................
@@ -1555,7 +1273,7 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Fill in the fields with the values from oldDoc
// ............................................................................
- if (hashIndex->_unique) {
+ if (hashIndex->base._unique) {
if (HashIndexHelper(hashIndex, &hashElement, NULL, oldDoc)) {
// ............................................................................
@@ -1570,7 +1288,9 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Remove the hash index entry and return.
// ............................................................................
- if (!HashIndex_remove(hashIndex->_hashIndex, &hashElement)) {
+ res = HashIndex_remove(hashIndex->_hashIndex, &hashElement);
+
+ if (res != TRI_ERROR_NO_ERROR) {
LOG_WARNING("could not remove old document from hash index in UpdateHashIndex");
}
}
@@ -1579,17 +1299,21 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Fill the json simple list from the document
// ............................................................................
- if (! HashIndexHelper(hashIndex, &hashElement, newDoc, NULL)) {
+ res = HashIndexHelper(hashIndex, &hashElement, newDoc, NULL);
+
+ if (res != TRI_ERROR_NO_ERROR) {
// ..........................................................................
// probably fields do not match
// ..........................................................................
- return false;
+
+ return res;
}
// ............................................................................
// Attempt to add the hash entry from the new doc
// ............................................................................
+
res = HashIndex_insert(hashIndex->_hashIndex, &hashElement);
}
@@ -1603,7 +1327,9 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Fill in the fields with the values from oldDoc
// ............................................................................
- if (HashIndexHelper(hashIndex, &hashElement, NULL, oldDoc)) {
+ res = HashIndexHelper(hashIndex, &hashElement, NULL, oldDoc);
+
+ if (res != TRI_ERROR_NO_ERROR) {
// ............................................................................
// We must fill the hashElement with the value of the document shape -- this
@@ -1617,7 +1343,9 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Remove the hash index entry and return.
// ............................................................................
- if (! MultiHashIndex_remove(hashIndex->_hashIndex, &hashElement)) {
+ res = MultiHashIndex_remove(hashIndex->_hashIndex, &hashElement);
+
+ if (res != TRI_ERROR_NO_ERROR) {
LOG_WARNING("could not remove old document from hash index in UpdateHashIndex");
}
}
@@ -1626,13 +1354,15 @@ static bool UpdateHashIndex (TRI_index_t* idx,
// Fill the shaped json simple list from the document
// ............................................................................
- if (!HashIndexHelper(hashIndex, &hashElement, newDoc, NULL)) {
+ res = HashIndexHelper(hashIndex, &hashElement, newDoc, NULL);
+
+ if (res != TRI_ERROR_NO_ERROR) {
// ..........................................................................
// probably fields do not match
// ..........................................................................
- return false;
+ return res;
}
// ............................................................................
@@ -1642,17 +1372,7 @@ static bool UpdateHashIndex (TRI_index_t* idx,
res = MultiHashIndex_insert(hashIndex->_hashIndex, &hashElement);
}
- if (res == -1) {
- LOG_WARNING("found duplicate entry in hash-index, should not happen");
- }
- else if (res == -2) {
- LOG_WARNING("out-of-memory in hash-index");
- }
- else if (res == -99) {
- LOG_DEBUG("unknown error, ignoring entry");
- }
-
- return res == 0;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1673,45 +1393,49 @@ static bool UpdateHashIndex (TRI_index_t* idx,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s* collection,
- TRI_vector_t* shapeList,
+ TRI_vector_pointer_t* fields,
+ TRI_vector_t* paths,
bool unique) {
TRI_hash_index_t* hashIndex;
size_t j;
hashIndex = TRI_Allocate(sizeof(TRI_hash_index_t));
- if (!hashIndex) {
+
+ if (hashIndex == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
hashIndex->base._iid = TRI_NewTickVocBase();
hashIndex->base._type = TRI_IDX_TYPE_HASH_INDEX;
hashIndex->base._collection = collection;
+ hashIndex->base._unique = unique;
hashIndex->base.insert = InsertHashIndex;
hashIndex->base.json = JsonHashIndex;
hashIndex->base.remove = RemoveHashIndex;
hashIndex->base.update = UpdateHashIndex;
- hashIndex->_unique = unique;
-
+
// ...........................................................................
- // Copy the contents of the shape list vector into a new vector and store this
+ // Copy the contents of the path list vector into a new vector and store this
// ...........................................................................
- hashIndex->_shapeList = TRI_Allocate(sizeof(TRI_vector_t));
+ TRI_InitVector(&hashIndex->_paths, sizeof(TRI_shape_pid_t));
- if (!hashIndex->_shapeList) {
- TRI_Free(hashIndex);
- return NULL;
- }
+ for (j = 0; j < paths->_length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths,j)));
- TRI_InitVector(hashIndex->_shapeList, sizeof(TRI_shape_pid_t));
-
- for (j = 0; j < shapeList->_length; ++j) {
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(shapeList,j)));
-
- TRI_PushBackVector(hashIndex->_shapeList,&shape);
+ TRI_PushBackVector(&hashIndex->_paths, &shape);
}
+ TRI_InitVectorString(&hashIndex->base._fields);
+
+ for (j = 0; j < fields->_length; ++j) {
+ char const* name = fields->_buffer[j];
+
+ TRI_PushBackVectorString(&hashIndex->base._fields, TRI_DuplicateString(name));
+ }
+
if (unique) {
hashIndex->_hashIndex = HashIndex_new();
}
@@ -1727,7 +1451,15 @@ TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s* collection,
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyHashIndex (TRI_index_t* idx) {
- LOG_ERROR("TRI_DestroyHashIndex not implemented");
+ TRI_hash_index_t* hash;
+
+ TRI_DestroyVectorString(&idx->_fields);
+
+ hash = (TRI_hash_index_t*) idx;
+
+ TRI_DestroyVector(&hash->_paths);
+
+ LOG_ERROR("TRI_DestroyHashIndex not implemented TODO oreste");
}
////////////////////////////////////////////////////////////////////////////////
@@ -1770,6 +1502,7 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi
element.fields = TRI_Allocate( sizeof(TRI_json_t) * element.numFields);
if (element.fields == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
LOG_WARNING("out-of-memory in LookupHashIndex");
return NULL;
}
@@ -1785,7 +1518,7 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi
TRI_Free(shapedObject);
}
- if (hashIndex->_unique) {
+ if (hashIndex->base._unique) {
result = HashIndex_find(hashIndex->_hashIndex, &element);
}
else {
@@ -1885,11 +1618,11 @@ TRI_skiplist_iterator_t* TRI_LookupSkiplistIndex(TRI_index_t* idx, TRI_sl_operat
FillLookupSLOperator(slOperator, skiplistIndex->base._collection);
- if (skiplistIndex->_unique) {
- result = SkiplistIndex_find(skiplistIndex->_skiplistIndex, skiplistIndex->_shapeList, slOperator);
+ if (skiplistIndex->base._unique) {
+ result = SkiplistIndex_find(skiplistIndex->_skiplistIndex, &skiplistIndex->_paths, slOperator);
}
else {
- result = MultiSkiplistIndex_find(skiplistIndex->_skiplistIndex, skiplistIndex->_shapeList, slOperator);
+ result = MultiSkiplistIndex_find(skiplistIndex->_skiplistIndex, &skiplistIndex->_paths, slOperator);
}
return result;
@@ -1920,9 +1653,8 @@ static bool SkiplistIndexHelper(const TRI_skiplist_index_t* skiplistIndex,
skiplistElement->data = NULL;
- for (j = 0; j < skiplistIndex->_shapeList->_length; ++j) {
-
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(skiplistIndex->_shapeList,j)));
+ for (j = 0; j < skiplistIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&skiplistIndex->_paths,j)));
// ..........................................................................
// Determine if document has that particular shape
@@ -1968,9 +1700,8 @@ static bool SkiplistIndexHelper(const TRI_skiplist_index_t* skiplistIndex,
skiplistElement->data = cnv.p;
- for (j = 0; j < skiplistIndex->_shapeList->_length; ++j) {
-
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(skiplistIndex->_shapeList,j)));
+ for (j = 0; j < skiplistIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&skiplistIndex->_paths,j)));
// ..........................................................................
// Determine if document has that particular shape
@@ -2018,7 +1749,7 @@ static bool SkiplistIndexHelper(const TRI_skiplist_index_t* skiplistIndex,
/// @brief inserts a document into a skip list index
////////////////////////////////////////////////////////////////////////////////
-static bool InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
SkiplistIndexElement skiplistElement;
TRI_skiplist_index_t* skiplistIndex;
@@ -2031,7 +1762,7 @@ static bool InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
skiplistIndex = (TRI_skiplist_index_t*) idx;
if (idx == NULL) {
LOG_WARNING("internal error in InsertSkiplistIndex");
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2040,18 +1771,18 @@ static bool InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// These will be used for comparisions
// ............................................................................
- skiplistElement.numFields = skiplistIndex->_shapeList->_length;
+ skiplistElement.numFields = skiplistIndex->_paths._length;
skiplistElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * skiplistElement.numFields);
skiplistElement.collection = skiplistIndex->base._collection;
if (skiplistElement.fields == NULL) {
LOG_WARNING("out-of-memory in InsertSkiplistIndex");
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
ok = SkiplistIndexHelper(skiplistIndex, &skiplistElement, doc, NULL);
if (!ok) {
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2059,7 +1790,7 @@ static bool InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// Fill the json field list from the document for unique skiplist index
// ............................................................................
- if (skiplistIndex->_unique) {
+ if (skiplistIndex->base._unique) {
res = SkiplistIndex_insert(skiplistIndex->_skiplistIndex, &skiplistElement);
}
@@ -2070,19 +1801,21 @@ static bool InsertSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
else {
res = MultiSkiplistIndex_insert(skiplistIndex->_skiplistIndex, &skiplistElement);
}
-
if (res == -1) {
LOG_WARNING("found duplicate entry in skiplist-index, should not happen");
+ return TRI_ERROR_INTERNAL;
}
else if (res == -2) {
LOG_WARNING("out-of-memory in skiplist-index");
+ return TRI_ERROR_OUT_OF_MEMORY;
}
- else if (res == -99) {
+ else if (res < 0) {
LOG_DEBUG("unknown error, ignoring entry");
+ return TRI_ERROR_INTERNAL;
}
- return res == 0;
+ return TRI_ERROR_NO_ERROR;
}
@@ -2096,7 +1829,7 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co
const TRI_shape_path_t* path;
TRI_skiplist_index_t* skiplistIndex;
char const** fieldList;
- char* fieldCounter;
+ char fieldCounter[64];
size_t j;
// ..........................................................................
@@ -2111,7 +1844,7 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co
// ..........................................................................
// Allocate sufficent memory for the field list
// ..........................................................................
- fieldList = TRI_Allocate( (sizeof(char*) * skiplistIndex->_shapeList->_length) );
+ fieldList = TRI_Allocate( (sizeof(char*) * skiplistIndex->_paths._length) );
if (fieldList == NULL) {
return NULL;
}
@@ -2120,8 +1853,8 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co
// ..........................................................................
// Convert the attributes (field list of the skiplist index) into strings
// ..........................................................................
- for (j = 0; j < skiplistIndex->_shapeList->_length; ++j) {
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(skiplistIndex->_shapeList,j)));
+ for (j = 0; j < skiplistIndex->_paths._length; ++j) {
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(&skiplistIndex->_paths,j)));
path = collection->_shaper->lookupAttributePathByPid(collection->_shaper, shape);
if (path == NULL) {
TRI_Free(fieldList);
@@ -2140,26 +1873,17 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co
return NULL;
}
- fieldCounter = TRI_Allocate(64);
-
- if (!fieldCounter) {
- TRI_Free(fieldList);
- TRI_FreeJson(json);
- return NULL;
- }
-
TRI_Insert2ArrayJson(json, "iid", TRI_CreateNumberJson(idx->_iid));
- TRI_Insert2ArrayJson(json, "unique", TRI_CreateBooleanJson(skiplistIndex->_unique));
+ TRI_Insert2ArrayJson(json, "unique", TRI_CreateBooleanJson(skiplistIndex->base._unique));
TRI_Insert2ArrayJson(json, "type", TRI_CreateStringCopyJson("skiplist"));
- TRI_Insert2ArrayJson(json, "fieldCount", TRI_CreateNumberJson(skiplistIndex->_shapeList->_length));
+ TRI_Insert2ArrayJson(json, "fieldCount", TRI_CreateNumberJson(skiplistIndex->_paths._length));
- for (j = 0; j < skiplistIndex->_shapeList->_length; ++j) {
+ for (j = 0; j < skiplistIndex->_paths._length; ++j) {
sprintf(fieldCounter,"field_%lu", (unsigned long) j);
TRI_Insert2ArrayJson(json, fieldCounter, TRI_CreateStringCopyJson(fieldList[j]));
}
TRI_Free(fieldList);
- TRI_Free(fieldCounter);
return json;
}
@@ -2169,7 +1893,7 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co
/// @brief removes a document from a skiplist index
////////////////////////////////////////////////////////////////////////////////
-static bool RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+static int RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
SkiplistIndexElement skiplistElement;
TRI_skiplist_index_t* skiplistIndex;
@@ -2182,7 +1906,7 @@ static bool RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
skiplistIndex = (TRI_skiplist_index_t*) idx;
if (idx == NULL) {
LOG_WARNING("internal error in RemoveHashIndex");
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2190,20 +1914,20 @@ static bool RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// Allocate some memory for the SkiplistIndexElement structure
// ............................................................................
- skiplistElement.numFields = skiplistIndex->_shapeList->_length;
+ skiplistElement.numFields = skiplistIndex->_paths._length;
skiplistElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * skiplistElement.numFields);
skiplistElement.collection = skiplistIndex->base._collection;
if (skiplistElement.fields == NULL) {
LOG_WARNING("out-of-memory in InsertSkiplistIndex");
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
// ..........................................................................
// Fill the json field list from the document
// ..........................................................................
if (!SkiplistIndexHelper(skiplistIndex, &skiplistElement, doc, NULL)) {
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2211,7 +1935,7 @@ static bool RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
// Attempt the removal for unique skiplist indexes
// ............................................................................
- if (skiplistIndex->_unique) {
+ if (skiplistIndex->base._unique) {
result = SkiplistIndex_remove(skiplistIndex->_skiplistIndex, &skiplistElement);
}
@@ -2224,11 +1948,11 @@ static bool RemoveSkiplistIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
}
- return result;
+ return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
}
-static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
+static int UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
const TRI_shaped_json_t* oldDoc) {
// ..........................................................................
@@ -2250,7 +1974,7 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
skiplistIndex = (TRI_skiplist_index_t*) idx;
if (idx == NULL) {
LOG_WARNING("internal error in UpdateSkiplistIndex");
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2258,13 +1982,13 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
// Allocate some memory for the SkiplistIndexElement structure
// ............................................................................
- skiplistElement.numFields = skiplistIndex->_shapeList->_length;
+ skiplistElement.numFields = skiplistIndex->_paths._length;
skiplistElement.fields = TRI_Allocate( sizeof(TRI_shaped_json_t) * skiplistElement.numFields);
skiplistElement.collection = skiplistIndex->base._collection;
if (skiplistElement.fields == NULL) {
LOG_WARNING("out-of-memory in UpdateHashIndex");
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
@@ -2277,7 +2001,7 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
// Fill in the fields with the values from oldDoc
// ............................................................................
- if (skiplistIndex->_unique) {
+ if (skiplistIndex->base._unique) {
if (SkiplistIndexHelper(skiplistIndex, &skiplistElement, NULL, oldDoc)) {
@@ -2307,7 +2031,7 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
// ..........................................................................
// probably fields do not match
// ..........................................................................
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2354,7 +2078,7 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
// ..........................................................................
// probably fields do not match
// ..........................................................................
- return false;
+ return TRI_ERROR_INTERNAL;
}
@@ -2367,15 +2091,18 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
if (res == -1) {
LOG_WARNING("found duplicate entry in skiplist-index, should not happen");
+ return TRI_ERROR_INTERNAL;
}
else if (res == -2) {
LOG_WARNING("out-of-memory in skiplist-index");
+ return TRI_ERROR_OUT_OF_MEMORY;
}
- else if (res == -99) {
+ else if (res < 0) {
LOG_DEBUG("unknown error, ignoring entry");
+ return TRI_ERROR_INTERNAL;
}
- return res == 0;
+ return TRI_ERROR_NO_ERROR;
}
@@ -2384,8 +2111,9 @@ static bool UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection,
- TRI_vector_t* shapeList,
- bool unique) {
+ TRI_vector_pointer_t* fields,
+ TRI_vector_t* paths,
+ bool unique) {
TRI_skiplist_index_t* skiplistIndex;
size_t j;
@@ -2397,28 +2125,32 @@ TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection,
skiplistIndex->base._iid = TRI_NewTickVocBase();
skiplistIndex->base._type = TRI_IDX_TYPE_SKIPLIST_INDEX;
skiplistIndex->base._collection = collection;
+ skiplistIndex->base._unique = unique;
skiplistIndex->base.insert = InsertSkiplistIndex;
skiplistIndex->base.json = JsonSkiplistIndex;
skiplistIndex->base.remove = RemoveSkiplistIndex;
skiplistIndex->base.update = UpdateSkiplistIndex;
- skiplistIndex->_unique = unique;
// ...........................................................................
// Copy the contents of the shape list vector into a new vector and store this
// ...........................................................................
- skiplistIndex->_shapeList = TRI_Allocate(sizeof(TRI_vector_t));
- if (!skiplistIndex->_shapeList) {
- TRI_Free(skiplistIndex);
- return NULL;
+
+ TRI_InitVector(&skiplistIndex->_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(&skiplistIndex->_paths, &shape);
}
- TRI_InitVector(skiplistIndex->_shapeList, sizeof(TRI_shape_pid_t));
- for (j = 0; j < shapeList->_length; ++j) {
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(shapeList,j)));
- TRI_PushBackVector(skiplistIndex->_shapeList,&shape);
- }
+ TRI_InitVectorString(&skiplistIndex->base._fields);
+ for (j = 0; j < fields->_length; ++j) {
+ char const* name = fields->_buffer[j];
+
+ TRI_PushBackVectorString(&skiplistIndex->base._fields, TRI_DuplicateString(name));
+ }
if (unique) {
skiplistIndex->_skiplistIndex = SkiplistIndex_new();
@@ -2430,6 +2162,31 @@ TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection,
return &skiplistIndex->base;
}
+////////////////////////////////////////////////////////////////////////////////
+/// @brief frees the memory allocated, but does not free the pointer
+////////////////////////////////////////////////////////////////////////////////
+
+void TRI_DestroySkiplistIndex (TRI_index_t* idx) {
+ TRI_skiplist_index_t* sl;
+
+ TRI_DestroyVectorString(&idx->_fields);
+
+ sl = (TRI_skiplist_index_t*) idx;
+
+ TRI_DestroyVector(&sl->_paths);
+
+ LOG_ERROR("TRI_DestroyHashIndex not implemented TODO oreste");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// @brief frees the memory allocated and frees the pointer
+////////////////////////////////////////////////////////////////////////////////
+
+void TRI_FreeSkiplistIndex (TRI_index_t* idx) {
+ TRI_DestroySkiplistIndex(idx);
+ TRI_Free(idx);
+}
+
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
diff --git a/VocBase/index.h b/VocBase/index.h
index 9bc2c103da..17d4906a03 100644
--- a/VocBase/index.h
+++ b/VocBase/index.h
@@ -5,7 +5,7 @@
///
/// DISCLAIMER
///
-/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
+/// Copyright 2011-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
-/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany
+/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_VOC_BASE_INDEX_H
@@ -89,19 +89,6 @@ typedef enum {
}
TRI_index_geo_variant_e;
-////////////////////////////////////////////////////////////////////////////////
-/// @brief index definition struct as used by the query optimizer
-////////////////////////////////////////////////////////////////////////////////
-
-typedef struct TRI_index_definition_s {
- TRI_idx_iid_t _iid;
- TRI_idx_type_e _type;
- TRI_vector_string_t* _fields;
- bool _isUnique;
- TRI_index_geo_variant_e _geoVariant;
-}
-TRI_index_definition_t;
-
////////////////////////////////////////////////////////////////////////////////
/// @brief index base class
////////////////////////////////////////////////////////////////////////////////
@@ -111,9 +98,12 @@ typedef struct TRI_index_s {
TRI_idx_type_e _type;
struct TRI_doc_collection_s* _collection;
- bool (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
- bool (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
- bool (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
+ bool _unique;
+ TRI_vector_string_t _fields;
+
+ int (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
+ int (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
+ int (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
TRI_json_t* (*json) (struct TRI_index_s*, struct TRI_doc_collection_s*);
}
TRI_index_t;
@@ -124,6 +114,7 @@ TRI_index_t;
typedef struct TRI_geo_index_s {
TRI_index_t base;
+ TRI_index_geo_variant_e _variant;
GeoIndex* _geoIndex;
@@ -135,7 +126,6 @@ typedef struct TRI_geo_index_s {
}
TRI_geo_index_t;
-
////////////////////////////////////////////////////////////////////////////////
/// @brief hash index
////////////////////////////////////////////////////////////////////////////////
@@ -143,11 +133,10 @@ TRI_geo_index_t;
typedef struct TRI_hash_index_s {
TRI_index_t base;
- HashIndex* _hashIndex; // effectively the associative array
- TRI_vector_t* _shapeList; // a list of shape pid which identifies the fields of the index
- bool _unique;
-} TRI_hash_index_t;
-
+ HashIndex* _hashIndex; // effectively the associative array
+ TRI_vector_t _paths; // a list of shape pid which identifies the fields of the index
+}
+TRI_hash_index_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief skiplist index
@@ -156,10 +145,10 @@ typedef struct TRI_hash_index_s {
typedef struct TRI_skiplist_index_s {
TRI_index_t base;
- SkiplistIndex* _skiplistIndex; // effectively the skiplist
- TRI_vector_t* _shapeList; // a list of shape pid which identifies the fields of the index
- bool _unique;
-} TRI_skiplist_index_t;
+ SkiplistIndex* _skiplistIndex; // effectively the skiplist
+ TRI_vector_t _paths; // a list of shape pid which identifies the fields of the index
+}
+TRI_skiplist_index_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
@@ -182,7 +171,7 @@ typedef struct TRI_skiplist_index_s {
/// @brief removes an index file
////////////////////////////////////////////////////////////////////////////////
-bool TRI_RemoveIndex (struct TRI_doc_collection_s* collection, TRI_index_t* idx);
+bool TRI_RemoveIndexFile (struct TRI_doc_collection_s* collection, TRI_index_t* idx);
////////////////////////////////////////////////////////////////////////////////
/// @brief saves an index
@@ -196,37 +185,11 @@ bool TRI_SaveIndex (struct TRI_doc_collection_s*, TRI_index_t*);
TRI_index_t* TRI_LookupIndex (struct TRI_doc_collection_s*, TRI_idx_iid_t);
-////////////////////////////////////////////////////////////////////////////////
-/// @brief free an existing index definition
-////////////////////////////////////////////////////////////////////////////////
-
-void TRI_FreeIndexDefinition (TRI_index_definition_t*);
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief free an existing index definitions vector
-////////////////////////////////////////////////////////////////////////////////
-
-void TRI_FreeIndexDefinitions (TRI_vector_pointer_t*);
-
////////////////////////////////////////////////////////////////////////////////
/// @brief gets name of index type
////////////////////////////////////////////////////////////////////////////////
-char* TRI_GetTypeNameIndex (const TRI_index_definition_t* const);
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief gets the definitions of all index files for a collection
-////////////////////////////////////////////////////////////////////////////////
-
-TRI_vector_pointer_t* TRI_GetCollectionIndexes (const TRI_vocbase_t* vocbase,
- const char* collectionName);
-
-////////////////////////////////////////////////////////////////////////////////
-/// @brief gets the names of all index files for a collection
-////////////////////////////////////////////////////////////////////////////////
-
-TRI_vector_string_t TRI_GetCollectionIndexFiles (const TRI_vocbase_t* vocbase,
- const char* collectionName);
+char const* TRI_TypeNameIndex (const TRI_index_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
@@ -254,6 +217,7 @@ TRI_vector_string_t TRI_GetCollectionIndexFiles (const TRI_vocbase_t* vocbase,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s*,
+ char const* locationName,
TRI_shape_pid_t,
bool geoJson);
@@ -262,7 +226,9 @@ TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s*,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s*,
+ char const* latitudeName,
TRI_shape_pid_t,
+ char const* longitudeName,
TRI_shape_pid_t);
////////////////////////////////////////////////////////////////////////////////
@@ -333,7 +299,8 @@ GeoCoordinates* TRI_NearestGeoIndex (TRI_index_t*,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s*,
- TRI_vector_t* shapeList,
+ TRI_vector_pointer_t* fields,
+ TRI_vector_t* paths,
bool unique);
////////////////////////////////////////////////////////////////////////////////
@@ -392,7 +359,8 @@ TRI_skiplist_iterator_t* TRI_LookupSkiplistIndex (TRI_index_t*, TRI_sl_operator_
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s*,
- TRI_vector_t* shapeList,
+ TRI_vector_pointer_t* fields,
+ TRI_vector_t* paths,
bool unique);
diff --git a/VocBase/query-join-execute.c b/VocBase/query-join-execute.c
index 366cc889ea..b1b278d8df 100644
--- a/VocBase/query-join-execute.c
+++ b/VocBase/query-join-execute.c
@@ -25,10 +25,11 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
-#include
-#include
+#include "query-join-execute.h"
-#include "VocBase/query-join-execute.h"
+#include "BasicsC/logging.h"
+#include "BasicsC/string-buffer.h"
+#include "BasicsC/strings.h"
#include "VocBase/query-join.h"
////////////////////////////////////////////////////////////////////////////////
@@ -40,25 +41,25 @@
/// @brief log information about the used index
////////////////////////////////////////////////////////////////////////////////
-static void LogIndexString(const TRI_index_definition_t* const indexDefinition,
- const char* const collectionName) {
-
+static void LogIndexString(TRI_index_t const* idx,
+ char const* collectionName) {
TRI_string_buffer_t* buffer = TRI_CreateStringBuffer();
size_t i;
- if (!buffer) {
+ if (buffer == NULL) {
return;
}
- for (i = 0; i < indexDefinition->_fields->_length; i++) {
+ for (i = 0; i < idx->_fields._length; i++) {
if (i > 0) {
TRI_AppendStringStringBuffer(buffer, ", ");
}
- TRI_AppendStringStringBuffer(buffer, indexDefinition->_fields->_buffer[i]);
+
+ TRI_AppendStringStringBuffer(buffer, idx->_fields._buffer[i]);
}
LOG_DEBUG("using %s index (%s) for '%s'",
- TRI_GetTypeNameIndex(indexDefinition),
+ TRI_TypeNameIndex(idx),
buffer->_buffer,
collectionName);
@@ -74,6 +75,9 @@ static TRI_data_feeder_t* DetermineGeoIndexUsageX (const TRI_vocbase_t* vocbase,
const TRI_select_join_t* join,
const size_t level,
const TRI_join_part_t* part) {
+ assert(false);
+
+#if 0
TRI_vector_pointer_t* indexDefinitions;
TRI_index_definition_t* indexDefinition;
TRI_data_feeder_t* feeder = NULL;
@@ -125,6 +129,7 @@ static TRI_data_feeder_t* DetermineGeoIndexUsageX (const TRI_vocbase_t* vocbase,
TRI_FreeIndexDefinitions(indexDefinitions);
return feeder;
+#endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -135,6 +140,9 @@ static TRI_data_feeder_t* DetermineIndexUsageX (const TRI_vocbase_t* vocbase,
const TRI_select_join_t* join,
const size_t level,
const TRI_join_part_t* part) {
+ assert(false);
+
+#if 0
TRI_vector_pointer_t* indexDefinitions;
TRI_index_definition_t* indexDefinition;
TRI_data_feeder_t* feeder = NULL;
@@ -310,50 +318,51 @@ EXIT2:
}
return feeder;
+#endif
}
////////////////////////////////////////////////////////////////////////////////
-/// @brief Determine which geo indexes to use in a query
+/// @brief determines which geo indexes to use in a query
////////////////////////////////////////////////////////////////////////////////
static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const instance,
const size_t level,
const TRI_join_part_t* part) {
- TRI_vector_pointer_t* indexDefinitions;
+ TRI_vector_pointer_t* indexes;
TRI_data_feeder_t* feeder = NULL;
size_t i;
assert(part->_geoRestriction);
- indexDefinitions = TRI_GetCollectionIndexes(instance->_template->_vocbase,
- part->_collectionName);
- if (!indexDefinitions) {
- TRI_RegisterErrorQueryInstance(instance, TRI_ERROR_OUT_OF_MEMORY, NULL);
+ if (part->_collection->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
+ TRI_RegisterErrorQueryInstance(instance,
+ TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE,
+ part->_alias);
return NULL;
}
-
+
+ indexes = & ((TRI_sim_collection_t*) part->_collection)->_indexes;
+
// enum all indexes
- for (i = 0; i < indexDefinitions->_length; i++) {
- TRI_index_definition_t* indexDefinition;
+ for (i = 0; i < indexes->_length; i++) {
+ TRI_index_t* idx;
- indexDefinition = (TRI_index_definition_t*) indexDefinitions->_buffer[i];
+ idx = (TRI_index_t*) indexes->_buffer[i];
- if (indexDefinition->_type != TRI_IDX_TYPE_GEO_INDEX) {
+ if (idx->_type != TRI_IDX_TYPE_GEO_INDEX) {
// ignore all indexes except geo indexes here
continue;
}
- if (indexDefinition->_fields->_length != 2) {
+ if (idx->_fields._length != 2) {
continue;
}
- if (strcmp(indexDefinition->_fields->_buffer[0],
- part->_geoRestriction->_compareLat._field) != 0) {
+ if (! TRI_EqualString(idx->_fields._buffer[0], part->_geoRestriction->_compareLat._field)) {
continue;
}
- if (strcmp(indexDefinition->_fields->_buffer[1],
- part->_geoRestriction->_compareLon._field) != 0) {
+ if (! TRI_EqualString(idx->_fields._buffer[1], part->_geoRestriction->_compareLon._field)) {
continue;
}
@@ -361,16 +370,14 @@ static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const in
TRI_CreateDataFeederGeoLookup(instance,
(TRI_doc_collection_t*) part->_collection,
level,
- indexDefinition->_iid,
+ idx->_iid,
part->_geoRestriction);
- LogIndexString(indexDefinition, part->_alias);
+ LogIndexString(idx, part->_alias);
break;
}
- TRI_FreeIndexDefinitions(indexDefinitions);
-
- if (!feeder) {
+ if (feeder == NULL) {
TRI_RegisterErrorQueryInstance(instance,
TRI_ERROR_QUERY_GEO_INDEX_MISSING,
part->_alias);
@@ -386,7 +393,7 @@ static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const in
static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const instance,
const size_t level,
const TRI_join_part_t* part) {
- TRI_vector_pointer_t* indexDefinitions;
+ TRI_vector_pointer_t* indexes;
TRI_data_feeder_t* feeder = NULL;
size_t i;
@@ -400,21 +407,24 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
size_t numConsts;
TRI_InitVectorPointer(&matches);
- indexDefinitions = TRI_GetCollectionIndexes(instance->_template->_vocbase,
- part->_collectionName);
- if (!indexDefinitions) {
- TRI_RegisterErrorQueryInstance(instance, TRI_ERROR_OUT_OF_MEMORY, NULL);
- goto EXIT2;
+ if (part->_collection->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
+ TRI_RegisterErrorQueryInstance(instance,
+ TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE,
+ part->_alias);
+ return NULL;
}
-
+
+ indexes = & ((TRI_sim_collection_t*) part->_collection)->_indexes;
+
// enum all indexes
- for (i = 0; i < indexDefinitions->_length; i++) {
- TRI_index_definition_t* indexDefinition;
+ for (i = 0; i < indexes->_length; i++) {
+ TRI_index_t* idx;
size_t j;
- indexDefinition = (TRI_index_definition_t*) indexDefinitions->_buffer[i];
- if (indexDefinition->_type == TRI_IDX_TYPE_GEO_INDEX) {
+ idx = (TRI_index_t*) indexes->_buffer[i];
+
+ if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
// ignore all geo indexes here
continue;
}
@@ -424,11 +434,13 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
TRI_DestroyVectorPointer(&matches);
TRI_InitVectorPointer(&matches);
}
+
numFields = 0;
numConsts = 0;
- numFieldsDefined = indexDefinition->_fields->_length;
- for (j = 0 ; j < numFieldsDefined; j++) {
+ numFieldsDefined = idx->_fields._length;
+
+ for (j = 0; j < numFieldsDefined; j++) {
size_t k;
// enumerate all fields from the index definition and
@@ -437,6 +449,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
QL_optimize_range_t* range;
range = (QL_optimize_range_t*) part->_ranges->_buffer[k];
+
if (!range) {
continue;
}
@@ -446,18 +459,17 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
assert(part->_alias);
// check if collection name matches
- if (strcmp(range->_collection, part->_alias) != 0) {
+ if (! TRI_EqualString(range->_collection, part->_alias)) {
continue;
}
// check if field names match
- if (strcmp(indexDefinition->_fields->_buffer[j],
- range->_field) != 0) {
+ if (! TRI_EqualString(idx->_fields._buffer[j], range->_field)) {
continue;
}
- if (indexDefinition->_type == TRI_IDX_TYPE_PRIMARY_INDEX ||
- indexDefinition->_type == TRI_IDX_TYPE_HASH_INDEX) {
+ if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX ||
+ idx->_type == TRI_IDX_TYPE_HASH_INDEX) {
// check if index can be used
// (primary and hash index only support equality comparisons)
if (range->_minStatus == RANGE_VALUE_INFINITE ||
@@ -504,7 +516,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
// we have found as many matches as defined in the index definition
// that means the index is fully covered in the condition
- if (indexDefinition->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
+ if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
// use the collection's primary index
if (feeder) {
// free any other feeder previously set up
@@ -519,7 +531,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
if (feeder) {
// we always exit if we can use the primary index
// the primary index guarantees uniqueness
- LogIndexString(indexDefinition, part->_alias);
+ LogIndexString(idx, part->_alias);
goto EXIT;
}
}
@@ -528,33 +540,33 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
// if the index found contains more fields than the one we previously found,
// we use the new one
// (assumption: the more fields index, the less selective is the index)
- if (indexDefinition->_type == TRI_IDX_TYPE_HASH_INDEX ||
- indexDefinition->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
+ if (idx->_type == TRI_IDX_TYPE_HASH_INDEX ||
+ idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
// use a hash index defined for the collection
if (feeder) {
// free any other feeder previously set up
feeder->free(feeder);
}
- if (indexDefinition->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
+ if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
feeder =
TRI_CreateDataFeederSkiplistLookup(instance,
(TRI_doc_collection_t*) part->_collection,
level,
- indexDefinition->_iid,
+ idx->_iid,
TRI_CopyVectorPointer(&matches));
- LogIndexString(indexDefinition, part->_alias);
+ LogIndexString(idx, part->_alias);
}
else {
feeder =
TRI_CreateDataFeederHashLookup(instance,
(TRI_doc_collection_t*) part->_collection,
level,
- indexDefinition->_iid,
+ idx->_iid,
TRI_CopyVectorPointer(&matches));
- LogIndexString(indexDefinition, part->_alias);
+ LogIndexString(idx, part->_alias);
}
if (!feeder) {
@@ -571,12 +583,9 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
}
EXIT:
- TRI_FreeIndexDefinitions(indexDefinitions);
TRI_DestroyVectorPointer(&matches);
}
-EXIT2:
-
if (!feeder) {
// if no index can be used, we'll do a full table scan
feeder = TRI_CreateDataFeederTableScan(instance,
diff --git a/VocBase/simple-collection.c b/VocBase/simple-collection.c
index 12c564f000..1c0810e228 100644
--- a/VocBase/simple-collection.c
+++ b/VocBase/simple-collection.c
@@ -40,16 +40,23 @@
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------
-static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
- TRI_doc_mptr_t* header);
+static int CreateImmediateIndexes (TRI_sim_collection_t* collection,
+ TRI_doc_mptr_t* header);
-static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
- TRI_doc_mptr_t const* header,
- TRI_doc_mptr_t const* update);
+static int UpdateImmediateIndexes (TRI_sim_collection_t* collection,
+ TRI_doc_mptr_t const* header,
+ TRI_doc_mptr_t const* update);
-static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
- TRI_doc_mptr_t const* header,
- TRI_voc_tick_t);
+static int DeleteImmediateIndexes (TRI_sim_collection_t* collection,
+ TRI_doc_mptr_t const* header,
+ TRI_voc_tick_t);
+
+static int DeleteDocument (TRI_sim_collection_t* collection,
+ TRI_doc_deletion_marker_t* marker,
+ TRI_voc_rid_t rid,
+ TRI_voc_rid_t* oldRid,
+ TRI_doc_update_policy_e policy,
+ bool release);
static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collection,
char const* location,
@@ -74,6 +81,11 @@ static uint64_t HashElementDocument (TRI_associative_pointer_t* array, void cons
static bool IsEqualKeyDocument (TRI_associative_pointer_t* array, void const* key, void const* element);
+static int InsertPrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc);
+static int UpdatePrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old);
+static int RemovePrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc);
+static TRI_json_t* JsonPrimary (TRI_index_t* idx, TRI_doc_collection_t* collection);
+
// -----------------------------------------------------------------------------
// --SECTION-- JOURNALS
// -----------------------------------------------------------------------------
@@ -98,7 +110,7 @@ static TRI_datafile_t* SelectJournal (TRI_sim_collection_t* collection,
TRI_voc_size_t size,
TRI_df_marker_t** result) {
TRI_datafile_t* datafile;
- bool ok;
+ int res;
size_t i;
size_t n;
@@ -113,14 +125,14 @@ static TRI_datafile_t* SelectJournal (TRI_sim_collection_t* collection,
datafile = collection->base.base._journals._buffer[i];
// try to reserve space
- ok = TRI_ReserveElementDatafile(datafile, size, result);
+ res = TRI_ReserveElementDatafile(datafile, size, result);
// in case of full datafile, try next
- if (ok) {
+ if (res == TRI_ERROR_NO_ERROR) {
TRI_UnlockCondition(&collection->_journalsCondition);
return datafile;
}
- else if (! ok && TRI_errno() != TRI_ERROR_AVOCADO_DATAFILE_FULL) {
+ else if (res != TRI_ERROR_AVOCADO_DATAFILE_FULL) {
TRI_UnlockCondition(&collection->_journalsCondition);
return NULL;
}
@@ -134,6 +146,11 @@ static TRI_datafile_t* SelectJournal (TRI_sim_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
/// @brief waits for synchronisation
+///
+/// Note that a datafile is never freed. If the datafile is closed the state
+/// is set to TRI_DF_STATE_CLOSED - but the datafile pointer is still valid.
+/// If a datafile is closed - then the data has been copied to some other
+/// datafile and has been synced.
////////////////////////////////////////////////////////////////////////////////
static void WaitSync (TRI_sim_collection_t* collection,
@@ -158,6 +175,11 @@ static void WaitSync (TRI_sim_collection_t* collection,
break;
}
+ // check for close
+ if (journal->_state == TRI_DF_STATE_CLOSED) {
+ break;
+ }
+
// always sync
if (position <= journal->_synced) {
break;
@@ -174,23 +196,23 @@ static void WaitSync (TRI_sim_collection_t* collection,
/// @brief writes data to the journal and updates the barriers
////////////////////////////////////////////////////////////////////////////////
-static bool WriteElement (TRI_sim_collection_t* collection,
- TRI_datafile_t* journal,
- TRI_df_marker_t* marker,
- TRI_voc_size_t markerSize,
- void const* body,
- TRI_voc_size_t bodySize,
- TRI_df_marker_t* result) {
- bool ok;
+static int WriteElement (TRI_sim_collection_t* collection,
+ TRI_datafile_t* journal,
+ TRI_df_marker_t* marker,
+ TRI_voc_size_t markerSize,
+ void const* body,
+ TRI_voc_size_t bodySize,
+ TRI_df_marker_t* result) {
+ int res;
- ok = TRI_WriteElementDatafile(journal,
- result,
- marker, markerSize,
- body, bodySize,
- false);
+ res = TRI_WriteElementDatafile(journal,
+ result,
+ marker, markerSize,
+ body, bodySize,
+ false);
- if (! ok) {
- return false;
+ if (res != TRI_ERROR_NO_ERROR) {
+ return res;
}
TRI_LockCondition(&collection->_journalsCondition);
@@ -198,7 +220,7 @@ static bool WriteElement (TRI_sim_collection_t* collection,
journal->_nWritten++;
TRI_UnlockCondition(&collection->_journalsCondition);
- return true;
+ return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@@ -260,7 +282,12 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection,
TRI_doc_mptr_t mptr;
TRI_voc_size_t total;
TRI_doc_datafile_info_t* dfi;
- bool ok;
+ int res;
+ int originalRes;
+
+ // .............................................................................
+ // create header
+ // .............................................................................
// get a new header pointer
header = collection->_headers->request(collection->_headers);
@@ -283,6 +310,10 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection,
return mptr;
}
+ // .............................................................................
+ // write document blob
+ // .............................................................................
+
// verify the header pointer
header = collection->_headers->verify(collection->_headers, header);
@@ -290,10 +321,14 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection,
TRI_FillCrcMarkerDatafile(&marker->base, markerSize, body, bodySize);
// and write marker and blob
- ok = WriteElement(collection, journal, &marker->base, markerSize, body, bodySize, *result);
+ res = WriteElement(collection, journal, &marker->base, markerSize, body, bodySize, *result);
+
+ // .............................................................................
+ // update indexes
+ // .............................................................................
// generate create header
- if (ok) {
+ if (res == TRI_ERROR_NO_ERROR) {
// fill the header
collection->base.createHeader(&collection->base, journal, *result, markerSize, header, 0);
@@ -305,20 +340,64 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection,
dfi->_sizeAlive += header->_document._data.length;
// update immediate indexes
- CreateImmediateIndexes(collection, header);
+ res = CreateImmediateIndexes(collection, header);
+ originalRes = res;
- mptr = *header;
+ // check for constraint error
+ if (res != TRI_ERROR_NO_ERROR) {
+ TRI_doc_deletion_marker_t markerDel;
- // release lock, header might be invalid after this
- if (release) {
- collection->base.endWrite(&collection->base);
+ LOG_WARNING("encountered index violating during create, deleting newly created document");
+
+ // .............................................................................
+ // rollback
+ // .............................................................................
+
+ memset(&markerDel, 0, sizeof(markerDel));
+
+ markerDel.base._size = sizeof(markerDel);
+ markerDel.base._type = TRI_DOC_MARKER_DELETION;
+
+ markerDel._did = header->_did;
+ markerDel._sid = 0;
+
+ // ignore any additional errors
+ res = DeleteDocument(collection, &markerDel, header->_rid, NULL, TRI_DOC_UPDATE_LAST_WRITE, false);
+
+ if (res != TRI_ERROR_NO_ERROR) {
+ LOG_ERROR("encountered error '%s' during rollback of create", TRI_last_error());
+ }
}
- // wait for sync
- WaitSync(collection, journal, ((char const*) *result) + markerSize + bodySize);
+ // .............................................................................
+ // create result
+ // .............................................................................
+
+ if (res == TRI_ERROR_NO_ERROR) {
+ mptr = *header;
+
+ // release lock, header might be invalid after this
+ if (release) {
+ collection->base.endWrite(&collection->base);
+ }
+
+ // wait for sync
+ WaitSync(collection, journal, ((char const*) *result) + markerSize + bodySize);
+
+ // and return
+ return mptr;
+ }
+ else {
+ if (release) {
+ collection->base.endWrite(&collection->base);
+ }
+
+ TRI_set_errno(originalRes);
+
+ mptr._did = 0;
+ return mptr;
+ }
- // and return
- return mptr;
}
else {
if (release) {
@@ -368,13 +447,24 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection,
TRI_voc_rid_t* oldRid,
TRI_doc_update_policy_e policy,
TRI_df_marker_t** result,
- bool release) {
+ bool release,
+ bool allowRollback) {
TRI_doc_mptr_t mptr;
TRI_datafile_t* journal;
+ TRI_df_marker_t const* originalMarker;
+ TRI_doc_mptr_t resUpd;
+ TRI_shaped_json_t originalJson;
TRI_voc_size_t total;
- bool ok;
+ int originalRes;
+ int res;
+ originalJson = header->_document;
+ originalMarker = header->_data;
+
+ // .............................................................................
// check the revision
+ // .............................................................................
+
if (oldRid != NULL) {
*oldRid = header->_rid;
}
@@ -420,6 +510,10 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection,
return mptr;
}
+ // .............................................................................
+ // update header
+ // .............................................................................
+
// generate a new tick
marker->_rid = marker->base._tick = TRI_NewTickVocBase();
@@ -438,14 +532,22 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection,
return mptr;
}
+ // .............................................................................
+ // write document blob
+ // .............................................................................
+
// generate crc
TRI_FillCrcMarkerDatafile(&marker->base, markerSize, body, bodySize);
// and write marker and blob
- ok = WriteElement(collection, journal, &marker->base, markerSize, body, bodySize, *result);
+ res = WriteElement(collection, journal, &marker->base, markerSize, body, bodySize, *result);
+
+ // .............................................................................
+ // update indexes
+ // .............................................................................
// update the header
- if (ok) {
+ if (res == TRI_ERROR_NO_ERROR) {
TRI_doc_mptr_t update;
TRI_doc_datafile_info_t* dfi;
@@ -467,20 +569,119 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection,
dfi->_sizeAlive += update._document._data.length;
// update immediate indexes
- UpdateImmediateIndexes(collection, header, &update);
+ res = UpdateImmediateIndexes(collection, header, &update);
+ originalRes = res;
- mptr = *header;
+ // check for constraint error
+ if (allowRollback && res != TRI_ERROR_NO_ERROR) {
+ LOG_WARNING("encountered index violating during update, rolling back");
- // release lock, header might be invalid after this
- if (release) {
- collection->base.endWrite(&collection->base);
+ // .............................................................................
+ // rollback
+ // .............................................................................
+
+ if (originalMarker->_type == TRI_DOC_MARKER_DOCUMENT) {
+ TRI_doc_document_marker_t markerUpd;
+
+ // create an update
+ memset(&markerUpd, 0, sizeof(markerUpd));
+
+ markerUpd.base._size = sizeof(markerUpd) + originalJson._data.length;
+ markerUpd.base._type = originalMarker->_type;
+
+ markerUpd._did = header->_did;
+ markerUpd._sid = 0;
+ markerUpd._shape = originalJson._sid;
+
+ resUpd = UpdateDocument(collection,
+ header,
+ &markerUpd, sizeof(markerUpd),
+ originalJson._data.data, originalJson._data.length,
+ header->_rid,
+ NULL,
+ TRI_DOC_UPDATE_LAST_WRITE,
+ result,
+ false,
+ false);
+
+ if (resUpd._did == 0) {
+ LOG_ERROR("encountered error '%s' during rollback of update", TRI_last_error());
+ }
+ }
+ else if (originalMarker->_type == TRI_DOC_MARKER_EDGE) {
+ TRI_doc_edge_marker_t markerUpd;
+ TRI_doc_edge_marker_t const* originalEdge;
+
+ originalEdge = (TRI_doc_edge_marker_t*) originalMarker;
+
+ // create an update
+ memset(&markerUpd, 0, sizeof(markerUpd));
+
+ markerUpd.base.base._size = sizeof(markerUpd) + originalJson._data.length;
+ markerUpd.base.base._type = originalMarker->_type;
+
+ markerUpd.base._did = header->_did;
+ markerUpd.base._sid = 0;
+ markerUpd.base._shape = originalJson._sid;
+
+ markerUpd._fromCid = originalEdge->_fromCid;
+ markerUpd._fromDid = originalEdge->_fromDid;
+ markerUpd._toCid = originalEdge->_toCid;
+ markerUpd._toDid = originalEdge->_toDid;
+
+ resUpd = UpdateDocument(collection,
+ header,
+ &markerUpd.base, sizeof(markerUpd),
+ originalJson._data.data, originalJson._data.length,
+ header->_rid,
+ NULL,
+ TRI_DOC_UPDATE_LAST_WRITE,
+ result,
+ false,
+ false);
+
+ if (resUpd._did == 0) {
+ LOG_ERROR("encountered error '%s' during rollback of update", TRI_last_error());
+ }
+ }
+ else {
+ LOG_ERROR("unknown document marker type '%lu' in document '%lu:%lu' revision '%lu'",
+ (unsigned long) originalMarker->_type,
+ (unsigned long) collection->base.base._cid,
+ (unsigned long) header->_did,
+ (unsigned long) header->_rid);
+ }
}
- // wait for sync
- WaitSync(collection, journal, ((char const*) *result) + markerSize + bodySize);
+ // .............................................................................
+ // create result
+ // .............................................................................
+
+ if (originalRes == TRI_ERROR_NO_ERROR) {
+ mptr = *header;
+
+ // release lock, header might be invalid after this
+ if (release) {
+ collection->base.endWrite(&collection->base);
+ }
+
+ // wait for sync
+ WaitSync(collection, journal, ((char const*) *result) + markerSize + bodySize);
+
+ // and return
+ return mptr;
+ }
+ else {
+ if (release) {
+ collection->base.endWrite(&collection->base);
+ }
+
+ TRI_set_errno(originalRes);
+
+ mptr._did = 0;
+ return mptr;
+ }
- // and return
- return mptr;
}
else {
if (release) {
@@ -497,29 +698,27 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection,
/// @brief deletes an element and removes it from the index
////////////////////////////////////////////////////////////////////////////////
-static bool DeleteDocument (TRI_sim_collection_t* collection,
- TRI_doc_deletion_marker_t* marker,
- TRI_voc_rid_t rid,
- TRI_voc_rid_t* oldRid,
- TRI_doc_update_policy_e policy,
- bool release) {
+static int DeleteDocument (TRI_sim_collection_t* collection,
+ TRI_doc_deletion_marker_t* marker,
+ TRI_voc_rid_t rid,
+ TRI_voc_rid_t* oldRid,
+ TRI_doc_update_policy_e policy,
+ bool release) {
TRI_datafile_t* journal;
TRI_df_marker_t* result;
TRI_doc_mptr_t const* header;
TRI_voc_size_t total;
- bool ok;
+ int res;
// get an existing header pointer
header = TRI_LookupByKeyAssociativePointer(&collection->_primaryIndex, &marker->_did);
if (header == NULL || header->_deletion != 0) {
- TRI_set_errno(TRI_ERROR_AVOCADO_DOCUMENT_NOT_FOUND);
-
if (release) {
collection->base.endWrite(&collection->base);
}
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_DOCUMENT_NOT_FOUND);
}
// check the revision
@@ -531,13 +730,11 @@ static bool DeleteDocument (TRI_sim_collection_t* collection,
case TRI_DOC_UPDATE_ERROR:
if (rid != 0) {
if (rid != header->_rid) {
- TRI_set_errno(TRI_ERROR_AVOCADO_CONFLICT);
-
if (release) {
collection->base.endWrite(&collection->base);
}
- return NULL;
+ return TRI_ERROR_AVOCADO_CONFLICT;
}
}
@@ -547,22 +744,18 @@ static bool DeleteDocument (TRI_sim_collection_t* collection,
break;
case TRI_DOC_UPDATE_CONFLICT:
- TRI_set_errno(TRI_ERROR_NOT_IMPLEMENTED);
-
if (release) {
collection->base.endWrite(&collection->base);
}
- return NULL;
+ return TRI_ERROR_NOT_IMPLEMENTED;
case TRI_DOC_UPDATE_ILLEGAL:
- TRI_set_errno(TRI_ERROR_INTERNAL);
-
if (release) {
collection->base.endWrite(&collection->base);
}
- return NULL;
+ return TRI_ERROR_INTERNAL;
}
// generate a new tick
@@ -579,17 +772,17 @@ static bool DeleteDocument (TRI_sim_collection_t* collection,
collection->base.endWrite(&collection->base);
}
- return false;
+ return TRI_ERROR_AVOCADO_NO_JOURNAL;
}
// generate crc
TRI_FillCrcMarkerDatafile(&marker->base, sizeof(TRI_doc_deletion_marker_t), 0, 0);
// and write marker and blob
- ok = WriteElement(collection, journal, &marker->base, sizeof(TRI_doc_deletion_marker_t), 0, 0, result);
+ res = WriteElement(collection, journal, &marker->base, sizeof(TRI_doc_deletion_marker_t), 0, 0, result);
// update the header
- if (ok) {
+ if (res == TRI_ERROR_NO_ERROR) {
TRI_doc_datafile_info_t* dfi;
// update the datafile info
@@ -624,7 +817,7 @@ static bool DeleteDocument (TRI_sim_collection_t* collection,
LOG_ERROR("cannot delete element");
}
- return ok;
+ return res;
}
////////////////////////////////////////////////////////////////////////////////
@@ -873,7 +1066,8 @@ static TRI_doc_mptr_t const UpdateShapedJson (TRI_doc_collection_t* document,
oldRid,
policy,
&result,
- release);
+ release,
+ true);
}
// the original is an edge
@@ -906,7 +1100,8 @@ static TRI_doc_mptr_t const UpdateShapedJson (TRI_doc_collection_t* document,
oldRid,
policy,
&result,
- release);
+ release,
+ true);
}
// do not know
@@ -932,6 +1127,7 @@ static bool DeleteShapedJson (TRI_doc_collection_t* document,
bool release) {
TRI_sim_collection_t* collection;
TRI_doc_deletion_marker_t marker;
+ int res;
collection = (TRI_sim_collection_t*) document;
@@ -943,7 +1139,13 @@ static bool DeleteShapedJson (TRI_doc_collection_t* document,
marker._did = did;
marker._sid = 0;
- return DeleteDocument(collection, &marker, rid, oldRid, policy, release);
+ res = DeleteDocument(collection, &marker, rid, oldRid, policy, release);
+
+ if (res != TRI_ERROR_NO_ERROR) {
+ TRI_set_errno(res);
+ }
+
+ return res == TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1304,6 +1506,7 @@ static bool OpenIndexIterator (char const* filename, void* data) {
}
TRI_FreeJson(json);
+
return true;
}
@@ -1454,14 +1657,23 @@ static bool IsEqualElementEdge (TRI_multi_pointer_t* array, void const* left, vo
/// @brief initialises a document collection
////////////////////////////////////////////////////////////////////////////////
-static void InitSimCollection (TRI_sim_collection_t* collection,
+static bool InitSimCollection (TRI_sim_collection_t* collection,
TRI_shaper_t* shaper) {
+ TRI_index_t* primary;
+ char* id;
+
TRI_InitDocCollection(&collection->base, shaper);
TRI_InitReadWriteLock(&collection->_lock);
collection->_headers = TRI_CreateSimpleHeaders(sizeof(TRI_doc_mptr_t));
+ if (collection->_headers == NULL) {
+ TRI_DestroyDocCollection(&collection->base);
+ TRI_DestroyReadWriteLock(&collection->_lock);
+ return false;
+ }
+
TRI_InitAssociativePointer(&collection->_primaryIndex,
HashKeyHeader,
HashElementDocument,
@@ -1478,6 +1690,30 @@ static void InitSimCollection (TRI_sim_collection_t* collection,
TRI_InitVectorPointer(&collection->_indexes);
+ // create primary index
+ primary = TRI_Allocate(sizeof(TRI_index_t));
+ id = TRI_DuplicateString("_id");
+
+ if (primary == NULL || id == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+ return false;
+ }
+
+ TRI_InitVectorString(&primary->_fields);
+ TRI_PushBackVectorString(&primary->_fields, id);
+
+ primary->_iid = 0;
+ primary->_type = TRI_IDX_TYPE_PRIMARY_INDEX;
+ primary->_unique = true;
+
+ primary->insert = InsertPrimary;
+ primary->remove = RemovePrimary;
+ primary->update = UpdatePrimary;
+ primary->json = JsonPrimary;
+
+ TRI_PushBackVectorPointer(&collection->_indexes, primary);
+
+ // setup methods
collection->base.createHeader = CreateHeader;
collection->base.updateHeader = UpdateHeader;
@@ -1493,6 +1729,8 @@ static void InitSimCollection (TRI_sim_collection_t* collection,
collection->base.destroy = DeleteShapedJson;
collection->base.size = SizeSimCollection;
+
+ return true;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1528,7 +1766,8 @@ TRI_sim_collection_t* TRI_CreateSimCollection (char const* path, TRI_col_paramet
// first create the document collection
doc = TRI_Allocate(sizeof(TRI_sim_collection_t));
- if (!doc) {
+
+ if (doc == NULL) {
LOG_ERROR("cannot create document");
return NULL;
}
@@ -1549,9 +1788,8 @@ TRI_sim_collection_t* TRI_CreateSimCollection (char const* path, TRI_col_paramet
LOG_ERROR("cannot create shapes collection");
TRI_CloseCollection(collection);
- TRI_FreeCollection(collection);
+ TRI_FreeCollection(collection); // will free doc
- TRI_Free(doc);
return NULL;
}
@@ -1729,14 +1967,18 @@ bool TRI_CloseSimCollection (TRI_sim_collection_t* collection) {
/// @brief creates a new entry in the immediate indexes
////////////////////////////////////////////////////////////////////////////////
-static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
- TRI_doc_mptr_t* header) {
+static int CreateImmediateIndexes (TRI_sim_collection_t* collection,
+ TRI_doc_mptr_t* header) {
TRI_df_marker_t const* marker;
TRI_doc_mptr_t* found;
size_t n;
size_t i;
- bool ok;
- bool result;
+ int result;
+ bool constraint;
+
+ // .............................................................................
+ // update primary index
+ // .............................................................................
// add a new header
found = TRI_InsertKeyAssociativePointer(&collection->_primaryIndex, &header->_did, header, false);
@@ -1748,14 +1990,18 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
(unsigned long) header->_rid);
collection->_headers->release(collection->_headers, header);
- return false;
+ return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED;
}
// return in case of a delete
if (header->_deletion != 0) {
- return true;
+ return TRI_ERROR_NO_ERROR;
}
+ // .............................................................................
+ // update edges index
+ // .............................................................................
+
// check the document type
marker = header->_data;
@@ -1768,69 +2014,93 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
// IN
entry = TRI_Allocate(sizeof(TRI_edge_header_t));
+
if (!entry) {
- // TODO: what to do in this case?
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
+
entry->_mptr = header;
entry->_direction = TRI_EDGE_IN;
entry->_cid = edge->_toCid;
entry->_did = edge->_toDid;
+
TRI_InsertElementMultiPointer(&collection->_edgesIndex, entry, true);
// OUT
entry = TRI_Allocate(sizeof(TRI_edge_header_t));
+
if (!entry) {
- // TODO: what to do in this case?
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
+
entry->_mptr = header;
entry->_direction = TRI_EDGE_OUT;
entry->_cid = edge->_fromCid;
entry->_did = edge->_fromDid;
+
TRI_InsertElementMultiPointer(&collection->_edgesIndex, entry, true);
// ANY
entry = TRI_Allocate(sizeof(TRI_edge_header_t));
+
if (!entry) {
- // TODO: what to do in this case?
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
+
entry->_mptr = header;
entry->_direction = TRI_EDGE_ANY;
entry->_cid = edge->_toCid;
entry->_did = edge->_toDid;
+
TRI_InsertElementMultiPointer(&collection->_edgesIndex, entry, true);
if (edge->_toCid != edge->_fromCid || edge->_toDid != edge->_fromDid) {
entry = TRI_Allocate(sizeof(TRI_edge_header_t));
+
if (!entry) {
- // TODO: what to do in this case?
- return false;
+ return TRI_ERROR_OUT_OF_MEMORY;
}
+
entry->_mptr = header;
entry->_direction = TRI_EDGE_ANY;
entry->_cid = edge->_fromCid;
entry->_did = edge->_fromDid;
+
TRI_InsertElementMultiPointer(&collection->_edgesIndex, entry, true);
}
}
+ // .............................................................................
// update all the other indices
+ // .............................................................................
+
n = collection->_indexes._length;
- result = true;
+ result = TRI_ERROR_NO_ERROR;
+ constraint = false;
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
+ int res;
idx = collection->_indexes._buffer[i];
+ res = idx->insert(idx, header);
- ok = idx->insert(idx, header);
-
- // i < n ? idx : NULL;
- if (! ok) {
- result = false;
+ // in case of no-memory, return immediately
+ if (res == TRI_ERROR_OUT_OF_MEMORY) {
+ return res;
}
+
+ // "prefer" unique constraint violated
+ if (res == TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED) {
+ constraint = true;
+ }
+ else if (res != TRI_ERROR_NO_ERROR) {
+ result = res;
+ }
+ }
+
+ if (constraint) {
+ return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED;
}
return result;
@@ -1840,13 +2110,13 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
/// @brief updates the immediate indexes
////////////////////////////////////////////////////////////////////////////////
-static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
- TRI_doc_mptr_t const* header,
- TRI_doc_mptr_t const* update) {
+static int UpdateImmediateIndexes (TRI_sim_collection_t* collection,
+ TRI_doc_mptr_t const* header,
+ TRI_doc_mptr_t const* update) {
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
TRI_shaped_json_t old;
- bool ok;
+ bool constraint;
bool result;
size_t i;
size_t n;
@@ -1854,6 +2124,10 @@ static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
// get the old document
old = header->_document;
+ // .............................................................................
+ // update primary index
+ // .............................................................................
+
// update all fields, the document identifier stays the same
change.c = header;
@@ -1865,20 +2139,37 @@ static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
change.v->_data = update->_data;
change.v->_document = update->_document;
- // update all other indexes
+ // .............................................................................
+ // update all the other indices
+ // .............................................................................
+
n = collection->_indexes._length;
- result = true;
+ result = TRI_ERROR_NO_ERROR;
+ constraint = false;
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
+ int res;
idx = collection->_indexes._buffer[i];
+ res = idx->update(idx, header, &old);
- ok = idx->update(idx, header, &old);
-
- if (! ok) {
- result = false;
+ // in case of no-memory, return immediately
+ if (res == TRI_ERROR_OUT_OF_MEMORY) {
+ return res;
}
+
+ // "prefer" unique constraint violated
+ if (res == TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED) {
+ constraint = true;
+ }
+ else if (res != TRI_ERROR_NO_ERROR) {
+ result = res;
+ }
+ }
+
+ if (constraint) {
+ return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED;
}
return result;
@@ -1888,7 +2179,7 @@ static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
/// @brief deletes an entry from the immediate indexes
////////////////////////////////////////////////////////////////////////////////
-static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
+static int DeleteImmediateIndexes (TRI_sim_collection_t* collection,
TRI_doc_mptr_t const* header,
TRI_voc_tick_t deletion) {
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
@@ -1897,20 +2188,25 @@ static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
size_t n;
size_t i;
bool result;
- bool ok;
// set the deletion flag
change.c = header;
change.v->_deletion = deletion;
+ // .............................................................................
// remove from main index
+ // .............................................................................
+
found = TRI_RemoveKeyAssociativePointer(&collection->_primaryIndex, &header->_did);
if (found == NULL) {
- TRI_set_errno(TRI_ERROR_AVOCADO_DOCUMENT_NOT_FOUND);
- return false;
+ return TRI_set_errno(TRI_ERROR_AVOCADO_DOCUMENT_NOT_FOUND);
}
+ // .............................................................................
+ // update edges index
+ // .............................................................................
+
// check the document type
marker = header->_data;
@@ -1967,19 +2263,22 @@ static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
}
}
- // remove all other indexes
+ // .............................................................................
+ // remove from all other indexes
+ // .............................................................................
+
n = collection->_indexes._length;
- result = true;
+ result = TRI_ERROR_NO_ERROR;
for (i = 0; i < n; ++i) {
TRI_index_t* idx;
+ int res;
idx = collection->_indexes._buffer[i];
+ res = idx->remove(idx, header);
- ok = idx->remove(idx, header);
-
- if (! ok) {
- result = false;
+ if (res != TRI_ERROR_NO_ERROR) {
+ result = res;
}
}
@@ -2136,7 +2435,12 @@ bool TRI_DropIndexSimCollection (TRI_sim_collection_t* collection, TRI_idx_iid_t
size_t n;
size_t i;
+ if (iid == 0) {
+ return true;
+ }
+
vector = TRI_Allocate(sizeof(TRI_vector_pointer_t));
+
if (!vector) {
return false;
}
@@ -2170,7 +2474,7 @@ bool TRI_DropIndexSimCollection (TRI_sim_collection_t* collection, TRI_idx_iid_t
// .............................................................................
if (found != NULL) {
- return TRI_RemoveIndex(&collection->base, found);
+ return TRI_RemoveIndexFile(&collection->base, found);
}
else {
return false;
@@ -2225,6 +2529,47 @@ static bool IsEqualKeyDocument (TRI_associative_pointer_t* array, void const* ke
return *k == e->_did;
}
+////////////////////////////////////////////////////////////////////////////////
+/// @brief insert methods does nothing
+////////////////////////////////////////////////////////////////////////////////
+
+static int InsertPrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+ return TRI_ERROR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// @brief update methods does nothing
+////////////////////////////////////////////////////////////////////////////////
+
+static int UpdatePrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
+ return TRI_ERROR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// @brief remove methods does nothing
+////////////////////////////////////////////////////////////////////////////////
+
+static int RemovePrimary (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
+ return TRI_ERROR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// @brief JSON description of a geo index, location is a list
+////////////////////////////////////////////////////////////////////////////////
+
+static TRI_json_t* JsonPrimary (TRI_index_t* idx, TRI_doc_collection_t* collection) {
+ TRI_json_t* json;
+
+ json = TRI_CreateArrayJson();
+
+ TRI_Insert2ArrayJson(json, "iid", TRI_CreateNumberJson(0));
+ TRI_Insert2ArrayJson(json, "type", TRI_CreateStringCopyJson("primary"));
+ TRI_Insert2ArrayJson(json, "fieldCount", TRI_CreateNumberJson(1));
+ TRI_Insert2ArrayJson(json, "field_0", TRI_CreateStringCopyJson("_id"));
+
+ return json;
+}
+
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@@ -2350,14 +2695,14 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
// create a new index
if (location != NULL) {
- idx = TRI_CreateGeoIndex(&collection->base, loc, geoJson);
+ idx = TRI_CreateGeoIndex(&collection->base, location, loc, geoJson);
LOG_TRACE("created geo-index for location '%s': %d",
location,
(unsigned long) loc);
}
else if (longitude != NULL && latitude != NULL) {
- idx = TRI_CreateGeoIndex2(&collection->base, lat, lon);
+ idx = TRI_CreateGeoIndex2(&collection->base, latitude, lat, longitude, lon);
LOG_TRACE("created geo-index for location '%s': %d, %d",
location,
@@ -2389,27 +2734,30 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti
bool unique) {
TRI_index_t* idx;
TRI_shaper_t* shaper;
- TRI_vector_t shapes;
+ TRI_vector_pointer_t fields;
+ TRI_vector_t paths;
bool ok;
size_t j;
idx = NULL;
shaper = collection->base._shaper;
- TRI_InitVector(&shapes, sizeof(TRI_shape_pid_t));
+ 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* shapeString;
- TRI_shape_pid_t shape;
+ char* path;
+ TRI_shape_pid_t pid;
- shapeString = *((char**)(TRI_AtVector(attributes,j)));
- shape = shaper->findAttributePathByName(shaper, shapeString);
+ path = *((char**)(TRI_AtVector(attributes,j)));
+ pid = shaper->findAttributePathByName(shaper, path);
- TRI_PushBackVector(&shapes, &shape);
+ TRI_PushBackVectorPointer(&fields, path);
+ TRI_PushBackVector(&paths, &pid);
}
// ...........................................................................
@@ -2418,10 +2766,11 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti
// a new one.
// ...........................................................................
- idx = TRI_LookupHashIndexSimCollection(collection, &shapes);
+ idx = TRI_LookupHashIndexSimCollection(collection, &paths);
if (idx != NULL) {
- TRI_DestroyVector(&shapes);
+ TRI_DestroyVector(&paths);
+ TRI_DestroyVectorPointer(&fields);
LOG_TRACE("hash-index already created");
return idx;
@@ -2431,13 +2780,13 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti
// Create the hash index
// ...........................................................................
- idx = TRI_CreateHashIndex(&collection->base, &shapes, unique);
+ idx = TRI_CreateHashIndex(&collection->base, &fields, &paths, unique);
// ...........................................................................
// release memory allocated to vector
// ...........................................................................
- TRI_DestroyVector(&shapes);
+ TRI_DestroyVector(&paths);
// ...........................................................................
// If index id given, use it otherwise use the default.
@@ -2477,19 +2826,23 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll
bool unique) {
TRI_index_t* idx = NULL;
TRI_shaper_t* shaper = collection->base._shaper;
- TRI_vector_t shapes;
+ TRI_vector_t paths;
+ TRI_vector_pointer_t fields;
size_t j;
- TRI_InitVector(&shapes, sizeof(TRI_shape_pid_t));
-
+ 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* shapeString = *((char**)(TRI_AtVector(attributes,j)));
- TRI_shape_pid_t shape = shaper->findAttributePathByName(shaper, shapeString);
- TRI_PushBackVector(&shapes,&shape);
+
+ 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);
}
@@ -2498,46 +2851,48 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll
// If a suitable index is found, return that one otherwise we need to create
// a new one.
// ...........................................................................
- idx = TRI_LookupSkiplistIndexSimCollection(collection, &shapes);
-
+
+ idx = TRI_LookupSkiplistIndexSimCollection(collection, &paths);
if (idx != NULL) {
- TRI_DestroyVector(&shapes);
+ TRI_DestroyVector(&paths);
+ TRI_DestroyVectorPointer(&fields);
+
LOG_TRACE("skiplist-index already created");
return idx;
}
-
// ...........................................................................
// Create the skiplist index
// ...........................................................................
- idx = TRI_CreateSkiplistIndex(&collection->base,&shapes, unique);
-
+
+ idx = TRI_CreateSkiplistIndex(&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
// ...........................................................................
- FillIndex(collection, idx);
+ FillIndex(collection, idx);
// ...........................................................................
// store index
// ...........................................................................
- TRI_PushBackVectorPointer(&collection->_indexes, idx);
+ TRI_PushBackVectorPointer(&collection->_indexes, idx);
// ...........................................................................
// release memory allocated to vector
// ...........................................................................
- TRI_DestroyVector(&shapes);
+
+ TRI_DestroyVector(&paths);
return idx;
}
@@ -2619,14 +2974,14 @@ TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection,
- const TRI_vector_t* shapes) {
+ 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
// hash indexes. The first hash index which matches the attributes
- // (shapes parameter) will be returned.
+ // (paths parameter) will be returned.
// ...........................................................................
@@ -2650,11 +3005,11 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection,
// .........................................................................
- // check that the number of shapes (fields) in the hash index matches that
+ // check that the number of paths (fields) in the hash index matches that
// of the number of attributes
// .........................................................................
- if (shapes->_length != hashIndex->_shapeList->_length) {
+ if (paths->_length != hashIndex->_paths._length) {
continue;
}
@@ -2663,9 +3018,9 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection,
// Go through all the attributes and see if they match
// .........................................................................
- for (k = 0; k < shapes->_length; ++k) {
- TRI_shape_pid_t field = *((TRI_shape_pid_t*)(TRI_AtVector(hashIndex->_shapeList,k)));
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(shapes,k)));
+ for (k = 0; k < paths->_length; ++k) {
+ TRI_shape_pid_t field = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_paths,k)));
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths,k)));
if (field != shape) {
found = false;
break;
@@ -2688,14 +3043,14 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
TRI_index_t* TRI_LookupSkiplistIndexSimCollection (TRI_sim_collection_t* collection,
- const TRI_vector_t* shapes) {
+ 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
- // (shapes parameter) will be returned.
+ // (paths parameter) will be returned.
// ...........................................................................
@@ -2719,11 +3074,11 @@ TRI_index_t* TRI_LookupSkiplistIndexSimCollection (TRI_sim_collection_t* collect
// .........................................................................
- // check that the number of shapes (fields) in the index matches that
+ // check that the number of paths (fields) in the index matches that
// of the number of attributes
// .........................................................................
- if (shapes->_length != skiplistIndex->_shapeList->_length) {
+ if (paths->_length != skiplistIndex->_paths._length) {
continue;
}
@@ -2732,9 +3087,9 @@ TRI_index_t* TRI_LookupSkiplistIndexSimCollection (TRI_sim_collection_t* collect
// Go through all the attributes and see if they match
// .........................................................................
- for (k = 0; k < shapes->_length; ++k) {
- TRI_shape_pid_t field = *((TRI_shape_pid_t*)(TRI_AtVector(skiplistIndex->_shapeList,k)));
- TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(shapes,k)));
+ for (k = 0; k < paths->_length; ++k) {
+ TRI_shape_pid_t field = *((TRI_shape_pid_t*)(TRI_AtVector(&skiplistIndex->_paths,k)));
+ TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths,k)));
if (field != shape) {
found = false;
break;
diff --git a/VocBase/voc-shaper.c b/VocBase/voc-shaper.c
index b11e738e0d..911230ac9f 100644
--- a/VocBase/voc-shaper.c
+++ b/VocBase/voc-shaper.c
@@ -138,7 +138,7 @@ static bool EqualKeyAttributeName (TRI_associative_synced_t* array, void const*
static TRI_shape_aid_t FindAttributeName (TRI_shaper_t* shaper, char const* name) {
TRI_df_attribute_marker_t marker;
TRI_df_marker_t* result;
- bool ok;
+ int res;
size_t n;
voc_shaper_t* s;
void const* p;
@@ -175,9 +175,9 @@ static TRI_shape_aid_t FindAttributeName (TRI_shaper_t* shaper, char const* name
marker._size = n;
// write into the shape collection
- ok = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_attribute_marker_t), name, n, &result);
+ res = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_attribute_marker_t), name, n, &result);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
TRI_UnlockMutex(&s->_attributeLock);
return 0;
}
@@ -283,7 +283,7 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_shape_t* shape) {
TRI_df_shape_marker_t marker;
TRI_shape_t const* found;
TRI_shape_t* l;
- bool ok;
+ int res;
voc_shaper_t* s;
void* f;
@@ -317,9 +317,9 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_shape_t* shape) {
shape->_sid = s->_nextSid++;
// write into the shape collection
- ok = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_shape_marker_t), shape, shape->_size, &result);
+ res = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_shape_marker_t), shape, shape->_size, &result);
- if (! ok) {
+ if (res != TRI_ERROR_NO_ERROR) {
TRI_UnlockMutex(&s->_shapeLock);
return NULL;
}
diff --git a/VocBase/vocbase.c b/VocBase/vocbase.c
index 0b0441c2c3..a91af64016 100644
--- a/VocBase/vocbase.c
+++ b/VocBase/vocbase.c
@@ -196,17 +196,24 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
if (found != NULL) {
TRI_Free(col);
+
LOG_ERROR("duplicate entry for name '%s'", name);
+ TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_NAME);
+
return NULL;
}
- // check collection identifier
+ // check collection identifier (unknown for new born collections)
if (cid != 0) {
found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsById, &cid, col, false);
if (found != NULL) {
+ TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
TRI_Free(col);
+
LOG_ERROR("duplicate collection identifier '%lu' for name '%s'", (unsigned long) cid, name);
+ TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_IDENTIFIER);
+
return NULL;
}
}
@@ -219,7 +226,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
/// @brief scans a directory and loads all collections
////////////////////////////////////////////////////////////////////////////////
-static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
+static bool ScanPath (TRI_vocbase_t* vocbase, char const* path) {
TRI_vector_string_t files;
TRI_col_type_e type;
size_t n;
@@ -239,8 +246,10 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
}
file = TRI_Concatenate2File(path, name);
- if (!file) {
- continue;
+
+ if (file == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+ return false;
}
if (TRI_IsDirectory(file)) {
@@ -256,7 +265,15 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
type = info._type;
if (type == TRI_COL_TYPE_SIMPLE_DOCUMENT) {
- AddCollection(vocbase, type, info._name, info._cid, file);
+ TRI_vocbase_col_t* c;
+
+ c = AddCollection(vocbase, type, info._name, info._cid, file);
+
+ if (c == NULL) {
+ LOG_FATAL("failed to add simple document collection from '%s'", file);
+ return false;
+ }
+
LOG_DEBUG("added simple document collection from '%s'", file);
}
else {
@@ -272,6 +289,7 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
}
TRI_DestroyVectorString(&files);
+ return true;
}
////////////////////////////////////////////////////////////////////////////////
@@ -308,6 +326,8 @@ size_t PageSize;
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a collection is allowed
+///
+/// Returns 0 for success or the offending character.
////////////////////////////////////////////////////////////////////////////////
char TRI_IsAllowedCollectionName (char const* name) {
@@ -414,6 +434,7 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
TRI_vocbase_t* vocbase;
char* lockFile;
int lockCheck;
+ bool ok;
if (! TRI_IsDirectory(path)) {
LOG_ERROR("database path '%s' is not a directory", path);
@@ -422,9 +443,18 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
// check if the database is locked
lockFile = TRI_Concatenate2File(path, "lock");
+
+ if (lockFile == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+ LOG_ERROR("out of memory when opening database");
+ return NULL;
+ }
+
lockCheck = TRI_VerifyLockFile(lockFile);
if (lockCheck) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_DATABASE_LOCKED);
+
LOG_FATAL("database is locked, please check the lock file '%s'", lockFile);
TRI_FreeString(lockFile);
return NULL;
@@ -439,32 +469,39 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
if (! lockCheck) {
LOG_FATAL("cannot lock the database, please check the lock file '%s': %s", lockFile, TRI_last_error());
TRI_FreeString(lockFile);
+
return NULL;
}
// setup vocbase structure
vocbase = TRI_Allocate(sizeof(TRI_vocbase_t));
- if (!vocbase) {
- LOG_ERROR("out of memory when opening vocbase");
+ if (vocbase == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+ LOG_ERROR("out of memory when opening database");
return NULL;
}
vocbase->_cursors = TRI_CreateShadowsQueryCursor();
- if (!vocbase->_cursors) {
+
+ if (vocbase->_cursors == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
TRI_FreeShadowStore(vocbase->_cursors);
TRI_Free(vocbase);
- LOG_ERROR("out of memory when opening vocbase");
+ LOG_ERROR("out of memory when opening database");
return NULL;
}
vocbase->_lockFile = lockFile;
vocbase->_path = TRI_DuplicateString(path);
- if (!vocbase->_path) {
+ if (vocbase->_path == NULL) {
+ TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
+
TRI_FreeShadowStore(vocbase->_cursors);
TRI_Free(vocbase);
- LOG_ERROR("out of memory when opening vocbase");
+ LOG_ERROR("out of memory when opening database");
return NULL;
}
@@ -485,7 +522,11 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
NULL);
// scan directory for collections
- ScanPath(vocbase, vocbase->_path);
+ ok = ScanPath(vocbase, vocbase->_path);
+
+ if (! ok) {
+ return NULL;
+ }
// vocbase is now active
vocbase->_active = 1;
@@ -514,9 +555,8 @@ void TRI_CloseVocBase (TRI_vocbase_t* vocbase) {
TRI_JoinThread(&vocbase->_synchroniser);
TRI_JoinThread(&vocbase->_compactor);
- // Free shadows
+ // cursors
if (vocbase->_cursors) {
- // cursors
TRI_FreeShadowStore(vocbase->_cursors);
}
@@ -619,6 +659,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
found = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name);
if (found != NULL) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_NAME);
+
LOG_ERROR("collection named '%s' already exists", name);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -628,6 +670,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
wrong = TRI_IsAllowedCollectionName(name);
if (wrong != 0) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_NAME);
+
LOG_ERROR("found illegal character in name: %c", wrong);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -647,6 +691,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
}
}
else {
+ TRI_set_errno(TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE);
+
LOG_ERROR("unknown collection type: %d", parameter->_type);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -694,6 +740,8 @@ TRI_vocbase_col_t const* TRI_LoadCollectionVocBase (TRI_vocbase_t* vocbase, char
found.c = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name);
if (found.c == NULL) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_COLLECTION_NOT_FOUND);
+
LOG_ERROR("unknown collection '%s'", name);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -727,6 +775,8 @@ TRI_vocbase_col_t const* TRI_LoadCollectionVocBase (TRI_vocbase_t* vocbase, char
return found.c;
}
else {
+ TRI_set_errno(TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE);
+
LOG_ERROR("unknown collection type %d for '%s'", (int) found.c->_type, name);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -754,6 +804,8 @@ TRI_vocbase_col_t const* TRI_BearCollectionVocBase (TRI_vocbase_t* vocbase, char
wrong = TRI_IsAllowedCollectionName(name);
if (wrong != 0) {
+ TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_NAME);
+
LOG_ERROR("found illegal character in name: %c", wrong);
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
return NULL;
@@ -762,6 +814,11 @@ TRI_vocbase_col_t const* TRI_BearCollectionVocBase (TRI_vocbase_t* vocbase, char
// check if the collection is not already loaded
found.v = AddCollection(vocbase, TRI_COL_TYPE_SIMPLE_DOCUMENT, name, 0, NULL);
+ if (found.v == NULL) {
+ TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
+ return NULL;
+ }
+
found.v->_newBorn = 1;
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);