From ac7eea770477deda0726f9903493d746794eb346 Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Thu, 22 Mar 2012 10:04:13 +0100 Subject: [PATCH 1/3] index constraint --- BasicsC/voc-errors.c | 3 + BasicsC/voc-errors.h | 6 + Doxygen/avocado.doxy.in | 2 + HashIndex/hashindex.c | 22 +- HashIndex/hashindex.h | 13 +- RestServer/glossary.dox | 3 +- RestServer/rest-document.dox | 11 +- V8/v8-vocbase.cpp | 2 +- VocBase/blob-collection.c | 6 +- VocBase/compactor.c | 22 +- VocBase/datafile.c | 80 ++-- VocBase/datafile.h | 8 +- VocBase/document-collection.c | 6 +- VocBase/index.c | 799 ++++++++++++---------------------- VocBase/index.h | 115 +++-- VocBase/query-join-execute.c | 131 +++--- VocBase/simple-collection.c | 564 ++++++++++++++++++------ VocBase/vocbase.c | 87 +++- 18 files changed, 1013 insertions(+), 867 deletions(-) diff --git a/BasicsC/voc-errors.c b/BasicsC/voc-errors.c index 2e6964f8fd..7b02ca4228 100644 --- a/BasicsC/voc-errors.c +++ b/BasicsC/voc-errors.c @@ -50,7 +50,10 @@ void TRI_InitialiseErrorMessages (void) { REG_ERROR(ERROR_AVOCADO_ILLEGAL_NAME, "illegal name"); REG_ERROR(ERROR_AVOCADO_NO_INDEX, "no index known"); REG_ERROR(ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED, "unique constraint violated"); +<<<<<<< HEAD REG_ERROR(ERROR_AVOCADO_GEO_INDEX_VIOLATED, "geo index violated"); +======= +>>>>>>> index constraint REG_ERROR(ERROR_AVOCADO_DATAFILE_FULL, "datafile full"); REG_ERROR(ERROR_QUERY_KILLED, "query killed"); REG_ERROR(ERROR_QUERY_PARSE, "parse error: %s"); diff --git a/BasicsC/voc-errors.h b/BasicsC/voc-errors.h index b474220ed9..5bbf412a30 100644 --- a/BasicsC/voc-errors.h +++ b/BasicsC/voc-errors.h @@ -98,8 +98,11 @@ extern "C" { /// Will be raised when no index is known. /// - 1210: @CODE{unique constraint violated} /// Will be raised when there is a unique constraint violation. +<<<<<<< HEAD /// - 1211: @CODE{geo index violated} /// Will be raised when a illegale coordinate is used. +======= +>>>>>>> index constraint /// - 1300: @CODE{datafile full} /// Will be raised when the datafile reaches its limit. /// - 1500: @CODE{query killed} @@ -615,6 +618,7 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED (1210) //////////////////////////////////////////////////////////////////////////////// +<<<<<<< HEAD /// @brief 1211: ERROR_AVOCADO_GEO_INDEX_VIOLATED /// /// geo index violated @@ -625,6 +629,8 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED (1211) //////////////////////////////////////////////////////////////////////////////// +======= +>>>>>>> index constraint /// @brief 1300: ERROR_AVOCADO_DATAFILE_FULL /// /// datafile full 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/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..01ec4e094c 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; @@ -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", 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..1c2ca84748 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; @@ -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..9542046371 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_VOC_ERROR_GEO_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_VOC_ERROR_GEO_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,26 +1141,19 @@ 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])); } @@ -1450,10 +1167,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 +1180,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 +1218,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 +1251,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 +1274,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 +1289,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 +1300,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 +1328,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 +1344,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 +1355,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 +1373,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 +1394,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_string_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 +1452,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 +1503,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 +1519,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 +1619,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 +1654,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 +1701,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 +1750,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 +1763,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 +1772,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 +1791,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 +1802,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; } @@ -2111,7 +1845,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 +1854,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); @@ -2149,11 +1883,11 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co } 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])); } @@ -2169,7 +1903,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 +1916,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 +1924,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 +1945,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 +1958,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 +1984,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 +1992,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 +2011,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 +2041,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 +2088,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 +2101,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 +2121,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_string_t* fields, + TRI_vector_t* paths, + bool unique) { TRI_skiplist_index_t* skiplistIndex; size_t j; @@ -2397,28 +2135,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 +2172,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..8dba838119 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,41 @@ 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; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ErrorHandling +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief corrupted primary index +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_VOC_ERROR_PRIMARY_VIOLATED (9000) + +//////////////////////////////////////////////////////////////////////////////// +/// @brief unique constraint violated +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_VOC_ERROR_UNIQUE_VIOLATED (9001) + +//////////////////////////////////////////////////////////////////////////////// +/// @brief geo constraint violated +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_VOC_ERROR_GEO_VIOLATED (9002) //////////////////////////////////////////////////////////////////////////////// /// @} @@ -182,7 +202,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 +216,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 +248,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 +257,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 +330,8 @@ GeoCoordinates* TRI_NearestGeoIndex (TRI_index_t*, //////////////////////////////////////////////////////////////////////////////// TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s*, - TRI_vector_t* shapeList, + TRI_vector_string_t* fields, + TRI_vector_t* paths, bool unique); //////////////////////////////////////////////////////////////////////////////// @@ -392,7 +390,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_string_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..818962b199 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, @@ -134,6 +141,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 +170,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 +191,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 +215,7 @@ static bool WriteElement (TRI_sim_collection_t* collection, journal->_nWritten++; TRI_UnlockCondition(&collection->_journalsCondition); - return true; + return TRI_ERROR_NO_ERROR; } //////////////////////////////////////////////////////////////////////////////// @@ -261,6 +278,11 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection, TRI_voc_size_t total; TRI_doc_datafile_info_t* dfi; bool ok; + int res; + + // ----------------------------------------------------------------------------- + // create header + // ----------------------------------------------------------------------------- // get a new header pointer header = collection->_headers->request(collection->_headers); @@ -283,6 +305,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); @@ -292,6 +318,10 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection, // and write marker and blob ok = WriteElement(collection, journal, &marker->base, markerSize, body, bodySize, *result); + // ----------------------------------------------------------------------------- + // update indexes + // ----------------------------------------------------------------------------- + // generate create header if (ok) { @@ -305,7 +335,40 @@ 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); + + if (res != TRI_ERROR_NO_ERROR) { + TRI_set_errno(res); + } + + // check for constraint error + if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { + TRI_doc_deletion_marker_t markerDel; + + LOG_WARNING("encountered constraint 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()); + } + } + else if (res != TRI_ERROR_NO_ERROR) { + LOG_WARNING("cannot update indices: %s", TRI_last_error()); + } mptr = *header; @@ -368,13 +431,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 res; + originalJson = header->_document; + originalMarker = header->_data; + + // ----------------------------------------------------------------------------- // check the revision + // ----------------------------------------------------------------------------- + if (oldRid != NULL) { *oldRid = header->_rid; } @@ -420,6 +494,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,12 +516,20 @@ 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); + // ----------------------------------------------------------------------------- + // update indexes + // ----------------------------------------------------------------------------- + // update the header if (ok) { TRI_doc_mptr_t update; @@ -467,7 +553,100 @@ 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); + + if (res != TRI_ERROR_NO_ERROR) { + TRI_set_errno(res); + } + + // check for constraint error + if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { + LOG_WARNING("encountered constraint violating during create, rolling back"); + + // ----------------------------------------------------------------------------- + // rollback + // ----------------------------------------------------------------------------- + + if (allowRollback) { + if (originalMarker->_type == TRI_DOC_MARKER_DELETION) { + 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); + } + } + else { + LOG_ERROR("cannot rollback update"); + } + } + else if (res != TRI_ERROR_NO_ERROR) { + LOG_WARNING("cannot update indices: %s", TRI_last_error()); + } mptr = *header; @@ -497,17 +676,17 @@ 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); @@ -519,7 +698,7 @@ static bool DeleteDocument (TRI_sim_collection_t* collection, collection->base.endWrite(&collection->base); } - return false; + return TRI_ERROR_NO_ERROR; } // check the revision @@ -531,13 +710,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 +724,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 +752,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 +797,7 @@ static bool DeleteDocument (TRI_sim_collection_t* collection, LOG_ERROR("cannot delete element"); } - return ok; + return res; } //////////////////////////////////////////////////////////////////////////////// @@ -742,6 +915,8 @@ static TRI_doc_mptr_t const CreateShapedJson (TRI_doc_collection_t* document, TRI_df_marker_t* result; TRI_sim_collection_t* collection; + TRI_set_errno(TRI_ERROR_NO_ERROR); + collection = (TRI_sim_collection_t*) document; if (type == TRI_DOC_MARKER_DOCUMENT) { @@ -834,6 +1009,8 @@ static TRI_doc_mptr_t const UpdateShapedJson (TRI_doc_collection_t* document, TRI_doc_mptr_t const* header; TRI_sim_collection_t* collection; + TRI_set_errno(TRI_ERROR_NO_ERROR); + collection = (TRI_sim_collection_t*) document; // get an existing header pointer @@ -873,7 +1050,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 +1084,8 @@ static TRI_doc_mptr_t const UpdateShapedJson (TRI_doc_collection_t* document, oldRid, policy, &result, - release); + release, + true); } // do not know @@ -932,6 +1111,9 @@ static bool DeleteShapedJson (TRI_doc_collection_t* document, bool release) { TRI_sim_collection_t* collection; TRI_doc_deletion_marker_t marker; + int res; + + TRI_set_errno(TRI_ERROR_NO_ERROR); collection = (TRI_sim_collection_t*) document; @@ -943,7 +1125,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 +1492,7 @@ static bool OpenIndexIterator (char const* filename, void* data) { } TRI_FreeJson(json); + return true; } @@ -1454,14 +1643,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 +1676,25 @@ 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; + + TRI_PushBackVectorPointer(&collection->_indexes, primary); + + // setup methods collection->base.createHeader = CreateHeader; collection->base.updateHeader = UpdateHeader; @@ -1493,6 +1710,8 @@ static void InitSimCollection (TRI_sim_collection_t* collection, collection->base.destroy = DeleteShapedJson; collection->base.size = SizeSimCollection; + + return true; } //////////////////////////////////////////////////////////////////////////////// @@ -1729,14 +1948,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 +1971,18 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection, (unsigned long) header->_rid); collection->_headers->release(collection->_headers, header); - return false; + return TRI_VOC_ERROR_PRIMARY_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 +1995,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_VOC_ERROR_UNIQUE_VIOLATED) { + constraint = true; + } + else if (res != TRI_ERROR_NO_ERROR) { + result = res; + } + } + + if (constraint) { + return TRI_VOC_ERROR_UNIQUE_VIOLATED; } return result; @@ -1840,13 +2091,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 +2105,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 +2120,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_VOC_ERROR_UNIQUE_VIOLATED) { + constraint = true; + } + else if (res != TRI_ERROR_NO_ERROR) { + result = res; + } + } + + if (constraint) { + return TRI_VOC_ERROR_UNIQUE_VIOLATED; } return result; @@ -1888,7 +2160,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 +2169,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 +2244,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; } } @@ -2170,7 +2450,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; @@ -2350,14 +2630,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 +2669,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_string_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_InitVectorString(&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_PushBackVectorString(&fields, path); + TRI_PushBackVector(&paths, &pid); } // ........................................................................... @@ -2418,10 +2701,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_DestroyVectorString(&fields); LOG_TRACE("hash-index already created"); return idx; @@ -2431,13 +2715,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 +2761,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_string_t names; size_t j; - TRI_InitVector(&shapes, sizeof(TRI_shape_pid_t)); - + TRI_InitVector(&paths, sizeof(TRI_shape_pid_t)); + TRI_InitVectorString(&names); // ........................................................................... // 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_PushBackVectorString(&names, path); } @@ -2498,46 +2786,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_DestroyVectorString(&names); + LOG_TRACE("skiplist-index already created"); return idx; } - // ........................................................................... // Create the skiplist index // ........................................................................... - idx = TRI_CreateSkiplistIndex(&collection->base,&shapes, unique); - + + idx = TRI_CreateSkiplistIndex(&collection->base, &names, &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 +2909,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 +2940,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 +2953,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 +2978,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 +3009,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 +3022,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/vocbase.c b/VocBase/vocbase.c index 0b0441c2c3..ed5484be22 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 false; } //////////////////////////////////////////////////////////////////////////////// @@ -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,41 @@ 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; } + TRI_FreeString(lockFile); + // 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 +524,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 +557,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 +661,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 +672,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 +693,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 +742,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 +777,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 +806,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 +816,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); From 1df0e49205d21531a9fc90a0588fce81e93f3cf1 Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Thu, 22 Mar 2012 17:31:28 +0100 Subject: [PATCH 2/3] added constraints --- BasicsC/voc-errors.c | 4 + BasicsC/voc-errors.h | 11 + RestServer/AvocadoServer.cpp | 4 +- VocBase/blob-collection.c | 51 ++--- VocBase/blob-collection.h | 12 +- VocBase/document-collection.c | 4 +- VocBase/index.c | 20 +- VocBase/index.h | 35 +-- VocBase/simple-collection.c | 395 ++++++++++++++++++++-------------- VocBase/voc-shaper.c | 12 +- VocBase/vocbase.c | 4 +- 11 files changed, 295 insertions(+), 257 deletions(-) diff --git a/BasicsC/voc-errors.c b/BasicsC/voc-errors.c index 7b02ca4228..e68e66b093 100644 --- a/BasicsC/voc-errors.c +++ b/BasicsC/voc-errors.c @@ -50,10 +50,14 @@ void TRI_InitialiseErrorMessages (void) { REG_ERROR(ERROR_AVOCADO_ILLEGAL_NAME, "illegal name"); REG_ERROR(ERROR_AVOCADO_NO_INDEX, "no index known"); REG_ERROR(ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED, "unique constraint violated"); +<<<<<<< HEAD <<<<<<< HEAD REG_ERROR(ERROR_AVOCADO_GEO_INDEX_VIOLATED, "geo index violated"); ======= >>>>>>> index constraint +======= + REG_ERROR(ERROR_AVOCADO_GEO_INDEX_VIOLATED, "geo index violated"); +>>>>>>> added constraints REG_ERROR(ERROR_AVOCADO_DATAFILE_FULL, "datafile full"); REG_ERROR(ERROR_QUERY_KILLED, "query killed"); REG_ERROR(ERROR_QUERY_PARSE, "parse error: %s"); diff --git a/BasicsC/voc-errors.h b/BasicsC/voc-errors.h index 5bbf412a30..fbcf33e258 100644 --- a/BasicsC/voc-errors.h +++ b/BasicsC/voc-errors.h @@ -99,10 +99,15 @@ extern "C" { /// - 1210: @CODE{unique constraint violated} /// Will be raised when there is a unique constraint violation. <<<<<<< HEAD +<<<<<<< HEAD /// - 1211: @CODE{geo index violated} /// Will be raised when a illegale coordinate is used. ======= >>>>>>> index constraint +======= +/// - 1211: @CODE{geo index violated} +/// Will be raised when a illegale coordinate is used. +>>>>>>> added constraints /// - 1300: @CODE{datafile full} /// Will be raised when the datafile reaches its limit. /// - 1500: @CODE{query killed} @@ -619,6 +624,9 @@ void TRI_InitialiseErrorMessages (void); //////////////////////////////////////////////////////////////////////////////// <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> added constraints /// @brief 1211: ERROR_AVOCADO_GEO_INDEX_VIOLATED /// /// geo index violated @@ -629,8 +637,11 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED (1211) //////////////////////////////////////////////////////////////////////////////// +<<<<<<< HEAD ======= >>>>>>> index constraint +======= +>>>>>>> added constraints /// @brief 1300: ERROR_AVOCADO_DATAFILE_FULL /// /// datafile full diff --git a/RestServer/AvocadoServer.cpp b/RestServer/AvocadoServer.cpp index 5de35afb30..685fa707f8 100644 --- a/RestServer/AvocadoServer.cpp +++ b/RestServer/AvocadoServer.cpp @@ -315,7 +315,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"] @@ -457,7 +457,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/VocBase/blob-collection.c b/VocBase/blob-collection.c index 01ec4e094c..7e2e074f4f 100644 --- a/VocBase/blob-collection.c +++ b/VocBase/blob-collection.c @@ -96,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", @@ -204,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? @@ -222,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) { @@ -240,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; } @@ -256,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; } //////////////////////////////////////////////////////////////////////////////// @@ -359,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(); @@ -396,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/document-collection.c b/VocBase/document-collection.c index 1c2ca84748..32bf10eef9 100644 --- a/VocBase/document-collection.c +++ b/VocBase/document-collection.c @@ -289,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); diff --git a/VocBase/index.c b/VocBase/index.c index 9542046371..add0bd9b42 100644 --- a/VocBase/index.c +++ b/VocBase/index.c @@ -495,7 +495,7 @@ static int InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { } else if (res == -3) { LOG_DEBUG("illegal geo-coordinates, ignoring entry"); - return TRI_set_errno(TRI_VOC_ERROR_GEO_VIOLATED); + return TRI_set_errno(TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED); } else if (res < 0) { return TRI_set_errno(TRI_ERROR_INTERNAL); @@ -576,7 +576,7 @@ static int UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_sha } else if (res == -3) { LOG_DEBUG("illegal geo-coordinates, ignoring entry"); - return TRI_set_errno(TRI_VOC_ERROR_GEO_VIOLATED); + return TRI_set_errno(TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED); } else if (res < 0) { return TRI_set_errno(TRI_ERROR_INTERNAL); @@ -1158,7 +1158,6 @@ static TRI_json_t* JsonHashIndex (TRI_index_t* idx, TRI_doc_collection_t* collec } TRI_Free(fieldList); - TRI_Free(fieldCounter); return json; } @@ -1394,7 +1393,7 @@ static int UpdateHashIndex (TRI_index_t* idx, //////////////////////////////////////////////////////////////////////////////// TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s* collection, - TRI_vector_string_t* fields, + TRI_vector_pointer_t* fields, TRI_vector_t* paths, bool unique) { TRI_hash_index_t* hashIndex; @@ -1830,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; // .......................................................................... @@ -1874,14 +1873,6 @@ 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->base._unique)); TRI_Insert2ArrayJson(json, "type", TRI_CreateStringCopyJson("skiplist")); @@ -1893,7 +1884,6 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t* idx, TRI_doc_collection_t* co } TRI_Free(fieldList); - TRI_Free(fieldCounter); return json; } @@ -2121,7 +2111,7 @@ static int UpdateSkiplistIndex (TRI_index_t* idx, const TRI_doc_mptr_t* newDoc, //////////////////////////////////////////////////////////////////////////////// TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection, - TRI_vector_string_t* fields, + TRI_vector_pointer_t* fields, TRI_vector_t* paths, bool unique) { TRI_skiplist_index_t* skiplistIndex; diff --git a/VocBase/index.h b/VocBase/index.h index 8dba838119..17d4906a03 100644 --- a/VocBase/index.h +++ b/VocBase/index.h @@ -154,37 +154,6 @@ TRI_skiplist_index_t; /// @} //////////////////////////////////////////////////////////////////////////////// -// ----------------------------------------------------------------------------- -// --SECTION-- public constants -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ErrorHandling -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief corrupted primary index -//////////////////////////////////////////////////////////////////////////////// - -#define TRI_VOC_ERROR_PRIMARY_VIOLATED (9000) - -//////////////////////////////////////////////////////////////////////////////// -/// @brief unique constraint violated -//////////////////////////////////////////////////////////////////////////////// - -#define TRI_VOC_ERROR_UNIQUE_VIOLATED (9001) - -//////////////////////////////////////////////////////////////////////////////// -/// @brief geo constraint violated -//////////////////////////////////////////////////////////////////////////////// - -#define TRI_VOC_ERROR_GEO_VIOLATED (9002) - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- INDEX // ----------------------------------------------------------------------------- @@ -330,7 +299,7 @@ GeoCoordinates* TRI_NearestGeoIndex (TRI_index_t*, //////////////////////////////////////////////////////////////////////////////// TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s*, - TRI_vector_string_t* fields, + TRI_vector_pointer_t* fields, TRI_vector_t* paths, bool unique); @@ -390,7 +359,7 @@ TRI_skiplist_iterator_t* TRI_LookupSkiplistIndex (TRI_index_t*, TRI_sl_operator_ //////////////////////////////////////////////////////////////////////////////// TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s*, - TRI_vector_string_t* fields, + TRI_vector_pointer_t* fields, TRI_vector_t* paths, bool unique); diff --git a/VocBase/simple-collection.c b/VocBase/simple-collection.c index 818962b199..1c0810e228 100644 --- a/VocBase/simple-collection.c +++ b/VocBase/simple-collection.c @@ -81,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 // ----------------------------------------------------------------------------- @@ -105,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; @@ -120,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; } @@ -277,12 +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); @@ -305,9 +310,9 @@ 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); @@ -316,14 +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); @@ -336,20 +341,17 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection, // update immediate indexes res = CreateImmediateIndexes(collection, header); - - if (res != TRI_ERROR_NO_ERROR) { - TRI_set_errno(res); - } + originalRes = res; // check for constraint error - if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { + if (res != TRI_ERROR_NO_ERROR) { TRI_doc_deletion_marker_t markerDel; - LOG_WARNING("encountered constraint violating during create, deleting newly created document"); + LOG_WARNING("encountered index violating during create, deleting newly created document"); - // ----------------------------------------------------------------------------- + // ............................................................................. // rollback - // ----------------------------------------------------------------------------- + // ............................................................................. memset(&markerDel, 0, sizeof(markerDel)); @@ -366,22 +368,36 @@ static TRI_doc_mptr_t CreateDocument (TRI_sim_collection_t* collection, LOG_ERROR("encountered error '%s' during rollback of create", TRI_last_error()); } } - else if (res != TRI_ERROR_NO_ERROR) { - LOG_WARNING("cannot update indices: %s", TRI_last_error()); + + // ............................................................................. + // 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; } - 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) { @@ -439,15 +455,15 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection, 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; @@ -494,9 +510,9 @@ 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(); @@ -516,22 +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; @@ -554,112 +570,118 @@ static TRI_doc_mptr_t const UpdateDocument (TRI_sim_collection_t* collection, // update immediate indexes res = UpdateImmediateIndexes(collection, header, &update); - - if (res != TRI_ERROR_NO_ERROR) { - TRI_set_errno(res); - } + originalRes = res; // check for constraint error - if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { - LOG_WARNING("encountered constraint violating during create, rolling back"); + if (allowRollback && res != TRI_ERROR_NO_ERROR) { + LOG_WARNING("encountered index violating during update, rolling back"); - // ----------------------------------------------------------------------------- + // ............................................................................. // rollback - // ----------------------------------------------------------------------------- + // ............................................................................. - if (allowRollback) { - if (originalMarker->_type == TRI_DOC_MARKER_DELETION) { - 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()); - } + 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); + } + 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("cannot rollback update"); + 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); } } - else if (res != TRI_ERROR_NO_ERROR) { - LOG_WARNING("cannot update indices: %s", TRI_last_error()); + + // ............................................................................. + // 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; } - 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) { @@ -692,13 +714,11 @@ static int DeleteDocument (TRI_sim_collection_t* collection, 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 TRI_ERROR_NO_ERROR; + return TRI_set_errno(TRI_ERROR_AVOCADO_DOCUMENT_NOT_FOUND); } // check the revision @@ -915,8 +935,6 @@ static TRI_doc_mptr_t const CreateShapedJson (TRI_doc_collection_t* document, TRI_df_marker_t* result; TRI_sim_collection_t* collection; - TRI_set_errno(TRI_ERROR_NO_ERROR); - collection = (TRI_sim_collection_t*) document; if (type == TRI_DOC_MARKER_DOCUMENT) { @@ -1009,8 +1027,6 @@ static TRI_doc_mptr_t const UpdateShapedJson (TRI_doc_collection_t* document, TRI_doc_mptr_t const* header; TRI_sim_collection_t* collection; - TRI_set_errno(TRI_ERROR_NO_ERROR); - collection = (TRI_sim_collection_t*) document; // get an existing header pointer @@ -1113,8 +1129,6 @@ static bool DeleteShapedJson (TRI_doc_collection_t* document, TRI_doc_deletion_marker_t marker; int res; - TRI_set_errno(TRI_ERROR_NO_ERROR); - collection = (TRI_sim_collection_t*) document; memset(&marker, 0, sizeof(marker)); @@ -1692,6 +1706,11 @@ static bool InitSimCollection (TRI_sim_collection_t* collection, 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 @@ -1747,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; } @@ -1768,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; } @@ -1971,7 +1990,7 @@ static int CreateImmediateIndexes (TRI_sim_collection_t* collection, (unsigned long) header->_rid); collection->_headers->release(collection->_headers, header); - return TRI_VOC_ERROR_PRIMARY_VIOLATED; + return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED; } // return in case of a delete @@ -2072,7 +2091,7 @@ static int CreateImmediateIndexes (TRI_sim_collection_t* collection, } // "prefer" unique constraint violated - if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { + if (res == TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED) { constraint = true; } else if (res != TRI_ERROR_NO_ERROR) { @@ -2081,7 +2100,7 @@ static int CreateImmediateIndexes (TRI_sim_collection_t* collection, } if (constraint) { - return TRI_VOC_ERROR_UNIQUE_VIOLATED; + return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED; } return result; @@ -2141,7 +2160,7 @@ static int UpdateImmediateIndexes (TRI_sim_collection_t* collection, } // "prefer" unique constraint violated - if (res == TRI_VOC_ERROR_UNIQUE_VIOLATED) { + if (res == TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED) { constraint = true; } else if (res != TRI_ERROR_NO_ERROR) { @@ -2150,7 +2169,7 @@ static int UpdateImmediateIndexes (TRI_sim_collection_t* collection, } if (constraint) { - return TRI_VOC_ERROR_UNIQUE_VIOLATED; + return TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED; } return result; @@ -2416,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; } @@ -2505,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; +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -2669,7 +2734,7 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti bool unique) { TRI_index_t* idx; TRI_shaper_t* shaper; - TRI_vector_string_t fields; + TRI_vector_pointer_t fields; TRI_vector_t paths; bool ok; size_t j; @@ -2678,7 +2743,7 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti shaper = collection->base._shaper; TRI_InitVector(&paths, sizeof(TRI_shape_pid_t)); - TRI_InitVectorString(&fields); + TRI_InitVectorPointer(&fields); // ........................................................................... // Determine the shape ids for the attributes @@ -2691,7 +2756,7 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti path = *((char**)(TRI_AtVector(attributes,j))); pid = shaper->findAttributePathByName(shaper, path); - TRI_PushBackVectorString(&fields, path); + TRI_PushBackVectorPointer(&fields, path); TRI_PushBackVector(&paths, &pid); } @@ -2705,7 +2770,7 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti if (idx != NULL) { TRI_DestroyVector(&paths); - TRI_DestroyVectorString(&fields); + TRI_DestroyVectorPointer(&fields); LOG_TRACE("hash-index already created"); return idx; @@ -2762,11 +2827,11 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll TRI_index_t* idx = NULL; TRI_shaper_t* shaper = collection->base._shaper; TRI_vector_t paths; - TRI_vector_string_t names; + TRI_vector_pointer_t fields; size_t j; TRI_InitVector(&paths, sizeof(TRI_shape_pid_t)); - TRI_InitVectorString(&names); + TRI_InitVectorPointer(&fields); // ........................................................................... // Determine the shape ids for the attributes @@ -2777,7 +2842,7 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll TRI_shape_pid_t shape = shaper->findAttributePathByName(shaper, path); TRI_PushBackVector(&paths, &shape); - TRI_PushBackVectorString(&names, path); + TRI_PushBackVectorPointer(&fields, path); } @@ -2791,7 +2856,7 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll if (idx != NULL) { TRI_DestroyVector(&paths); - TRI_DestroyVectorString(&names); + TRI_DestroyVectorPointer(&fields); LOG_TRACE("skiplist-index already created"); return idx; @@ -2801,7 +2866,7 @@ static TRI_index_t* CreateSkiplistIndexSimCollection (TRI_sim_collection_t* coll // Create the skiplist index // ........................................................................... - idx = TRI_CreateSkiplistIndex(&collection->base, &names, &paths, unique); + idx = TRI_CreateSkiplistIndex(&collection->base, &fields, &paths, unique); // ........................................................................... // If index id given, use it otherwise use the default. 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 ed5484be22..a91af64016 100644 --- a/VocBase/vocbase.c +++ b/VocBase/vocbase.c @@ -289,7 +289,7 @@ static bool ScanPath (TRI_vocbase_t* vocbase, char const* path) { } TRI_DestroyVectorString(&files); - return false; + return true; } //////////////////////////////////////////////////////////////////////////////// @@ -473,8 +473,6 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) { return NULL; } - TRI_FreeString(lockFile); - // setup vocbase structure vocbase = TRI_Allocate(sizeof(TRI_vocbase_t)); From 1c434c064b30205213003cfde6a073df48252efb Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Thu, 22 Mar 2012 17:44:02 +0100 Subject: [PATCH 3/3] errors --- BasicsC/voc-errors.c | 7 ------- BasicsC/voc-errors.h | 17 ----------------- 2 files changed, 24 deletions(-) diff --git a/BasicsC/voc-errors.c b/BasicsC/voc-errors.c index e68e66b093..2e6964f8fd 100644 --- a/BasicsC/voc-errors.c +++ b/BasicsC/voc-errors.c @@ -50,14 +50,7 @@ void TRI_InitialiseErrorMessages (void) { REG_ERROR(ERROR_AVOCADO_ILLEGAL_NAME, "illegal name"); REG_ERROR(ERROR_AVOCADO_NO_INDEX, "no index known"); REG_ERROR(ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED, "unique constraint violated"); -<<<<<<< HEAD -<<<<<<< HEAD REG_ERROR(ERROR_AVOCADO_GEO_INDEX_VIOLATED, "geo index violated"); -======= ->>>>>>> index constraint -======= - REG_ERROR(ERROR_AVOCADO_GEO_INDEX_VIOLATED, "geo index violated"); ->>>>>>> added constraints REG_ERROR(ERROR_AVOCADO_DATAFILE_FULL, "datafile full"); REG_ERROR(ERROR_QUERY_KILLED, "query killed"); REG_ERROR(ERROR_QUERY_PARSE, "parse error: %s"); diff --git a/BasicsC/voc-errors.h b/BasicsC/voc-errors.h index fbcf33e258..b474220ed9 100644 --- a/BasicsC/voc-errors.h +++ b/BasicsC/voc-errors.h @@ -98,16 +98,8 @@ extern "C" { /// Will be raised when no index is known. /// - 1210: @CODE{unique constraint violated} /// Will be raised when there is a unique constraint violation. -<<<<<<< HEAD -<<<<<<< HEAD /// - 1211: @CODE{geo index violated} /// Will be raised when a illegale coordinate is used. -======= ->>>>>>> index constraint -======= -/// - 1211: @CODE{geo index violated} -/// Will be raised when a illegale coordinate is used. ->>>>>>> added constraints /// - 1300: @CODE{datafile full} /// Will be raised when the datafile reaches its limit. /// - 1500: @CODE{query killed} @@ -623,10 +615,6 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED (1210) //////////////////////////////////////////////////////////////////////////////// -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> added constraints /// @brief 1211: ERROR_AVOCADO_GEO_INDEX_VIOLATED /// /// geo index violated @@ -637,11 +625,6 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_AVOCADO_GEO_INDEX_VIOLATED (1211) //////////////////////////////////////////////////////////////////////////////// -<<<<<<< HEAD -======= ->>>>>>> index constraint -======= ->>>>>>> added constraints /// @brief 1300: ERROR_AVOCADO_DATAFILE_FULL /// /// datafile full