diff --git a/arangod/HashIndex/hash-array.cpp b/arangod/HashIndex/hash-array.cpp index 999d2c1cbb..98b5a3fcd9 100644 --- a/arangod/HashIndex/hash-array.cpp +++ b/arangod/HashIndex/hash-array.cpp @@ -50,17 +50,6 @@ static void DestroyElement (TRI_hash_array_t* array, element->_document = nullptr; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief determines if two elements are equal -/// -/// Two elements are 'equal' if the document pointer is the same. -//////////////////////////////////////////////////////////////////////////////// - -static inline bool IsEqualElementElement (TRI_hash_index_element_t* left, - TRI_hash_index_element_t* right) { - return (left->_document != nullptr && left->_document == right->_document); -} - //////////////////////////////////////////////////////////////////////////////// /// @brief determines if a key corresponds to an element //////////////////////////////////////////////////////////////////////////////// @@ -459,9 +448,9 @@ int TRI_RemoveElementHashArray (TRI_hash_array_t* array, i = k = HashElement(array, element) % n; - for (; i < n && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (; i < n && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); if (i == n) { - for (i = 0; i < k && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (i = 0; i < k && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); } TRI_ASSERT_EXPENSIVE(i < n); @@ -572,9 +561,9 @@ int TRI_InsertElementHashArrayMulti (TRI_hash_array_t* array, i = k = HashElement(array, element) % n; - for (; i < n && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (; i < n && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); if (i == n) { - for (i = 0; i < k && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (i = 0; i < k && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); } TRI_ASSERT_EXPENSIVE(i < n); @@ -625,9 +614,9 @@ int TRI_RemoveElementHashArrayMulti (TRI_hash_array_t* array, i = k = HashElement(array, element) % n; - for (; i < n && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (; i < n && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); if (i == n) { - for (i = 0; i < k && array->_table[i]._document != nullptr && ! IsEqualElementElement(element, &array->_table[i]); ++i); + for (i = 0; i < k && array->_table[i]._document != nullptr && element->_document != array->_table[i]._document; ++i); } TRI_ASSERT_EXPENSIVE(i < n); diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 1bfa039081..8033efdf83 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -6730,11 +6730,30 @@ static v8::Handle JS_PropertiesVocbaseCol (v8::Arguments const& argv) } TRI_json_t* json = TRI_CreateJsonCollectionInfo(&base->_info); - TRI_LogChangePropertiesCollectionReplication(base->_vocbase, - base->_info._cid, - base->_info._name, - json, - TRI_GetIdServer()); + + // now log the property changes + res = TRI_ERROR_NO_ERROR; + + try { + triagens::wal::ChangeCollectionMarker marker(base->_vocbase->_id, base->_info._cid, JsonHelper::toString(json)); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } + + if (res != TRI_ERROR_NO_ERROR) { + // TODO: what to do here + LOG_WARNING("could not save collection change marker in log: %s", TRI_errno_string(res)); + } + TRI_FreeJson(TRI_CORE_MEM_ZONE, json); } } diff --git a/arangod/VocBase/datafile.cpp b/arangod/VocBase/datafile.cpp index bef77bb7f4..d81f765d9e 100644 --- a/arangod/VocBase/datafile.cpp +++ b/arangod/VocBase/datafile.cpp @@ -1141,6 +1141,10 @@ char const* TRI_NameMarkerDatafile (TRI_df_marker_t const* marker) { return "rename collection (wal)"; case TRI_WAL_MARKER_CHANGE_COLLECTION: return "change collection (wal)"; + case TRI_WAL_MARKER_CREATE_INDEX: + return "create index (wal)"; + case TRI_WAL_MARKER_DROP_INDEX: + return "drop index (wal)"; case TRI_WAL_MARKER_CREATE_DATABASE: return "create database (wal)"; case TRI_WAL_MARKER_DROP_DATABASE: diff --git a/arangod/VocBase/datafile.h b/arangod/VocBase/datafile.h index e83d608816..56043e21f7 100644 --- a/arangod/VocBase/datafile.h +++ b/arangod/VocBase/datafile.h @@ -171,6 +171,8 @@ typedef enum { TRI_WAL_MARKER_DROP_COLLECTION = 4031, TRI_WAL_MARKER_RENAME_COLLECTION = 4032, TRI_WAL_MARKER_CHANGE_COLLECTION = 4033, + TRI_WAL_MARKER_CREATE_INDEX = 4035, + TRI_WAL_MARKER_DROP_INDEX = 4036, TRI_WAL_MARKER_CREATE_DATABASE = 4040, TRI_WAL_MARKER_DROP_DATABASE = 4041, diff --git a/arangod/VocBase/document-collection.cpp b/arangod/VocBase/document-collection.cpp index 76bbe97248..462c4345a7 100644 --- a/arangod/VocBase/document-collection.cpp +++ b/arangod/VocBase/document-collection.cpp @@ -232,16 +232,12 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document, if (document->_info._isVolatile) { // in-memory collection - journal = TRI_CreateDatafile(NULL, fid, maximalSize, true); + journal = TRI_CreateDatafile(nullptr, fid, maximalSize, true); } else { - char* jname; - char* number; - char* filename; - - number = TRI_StringUInt64(fid); - jname = TRI_Concatenate3String("compaction-", number, ".db"); - filename = TRI_Concatenate2File(document->_directory, jname); + char* number = TRI_StringUInt64(fid); + char* jname = TRI_Concatenate3String("compaction-", number, ".db"); + char* filename = TRI_Concatenate2File(document->_directory, jname); TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, jname); @@ -255,7 +251,7 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document, TRI_FreeString(TRI_CORE_MEM_ZONE, filename); } - if (journal == NULL) { + if (journal == nullptr) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { document->_lastError = TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY_MMAP); } @@ -263,7 +259,7 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document, document->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL); } - return NULL; + return nullptr; } LOG_TRACE("created new compactor '%s'", journal->getName(journal)); @@ -279,7 +275,7 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document, TRI_FreeDatafile(journal); - return NULL; + return nullptr; } @@ -297,7 +293,7 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document, TRI_FreeDatafile(journal); - return NULL; + return nullptr; } TRI_ASSERT(fid == journal->_fid); @@ -666,10 +662,10 @@ static int AddIndex (TRI_document_collection_t* document, static void RebuildIndexInfo (TRI_document_collection_t* document) { bool result = false; - size_t const n = document->_allIndexes._length; + for (size_t i = 0 ; i < n ; ++i) { - TRI_index_t* idx = (TRI_index_t*) document->_allIndexes._buffer[i]; + TRI_index_t* idx = static_cast(document->_allIndexes._buffer[i]); if (idx->cleanup != nullptr) { result = true; @@ -2181,13 +2177,8 @@ static int IterateMarkersCollection (TRI_collection_t* collection) { TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, char const* path, - TRI_col_info_t* parameter, + TRI_col_info_t* parameters, TRI_voc_cid_t cid) { - TRI_collection_t* collection; - TRI_shaper_t* shaper; - TRI_document_collection_t* document; - int res; - if (cid > 0) { TRI_UpdateTickServer(cid); } @@ -2195,10 +2186,10 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, cid = TRI_NewTickServer(); } - parameter->_cid = cid; + parameters->_cid = cid; // check if we can generate the key generator - KeyGenerator* keyGenerator = KeyGenerator::factory(parameter->_keyOptions); + KeyGenerator* keyGenerator = KeyGenerator::factory(parameters->_keyOptions); if (keyGenerator == nullptr) { TRI_set_errno(TRI_ERROR_ARANGO_INVALID_KEY_GENERATOR); @@ -2206,6 +2197,7 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, } // first create the document collection + TRI_document_collection_t* document; try { document = new TRI_document_collection_t(); } @@ -2222,7 +2214,8 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, } document->_keyGenerator = keyGenerator; - collection = TRI_CreateCollection(vocbase, document, path, parameter); + + TRI_collection_t* collection = TRI_CreateCollection(vocbase, document, path, parameters); if (collection == nullptr) { delete document; @@ -2231,9 +2224,9 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, return nullptr; } - shaper = TRI_CreateVocShaper(vocbase, document); + TRI_shaper_t* shaper = TRI_CreateVocShaper(vocbase, document); - if (shaper == NULL) { + if (shaper == nullptr) { LOG_ERROR("cannot create shaper"); TRI_CloseCollection(collection); @@ -2256,7 +2249,7 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, document->_keyGenerator = keyGenerator; // save the parameter block (within create, no need to lock) - res = TRI_SaveCollectionInfo(collection->_directory, parameter, vocbase->_settings.forceSyncProperties); + int res = TRI_SaveCollectionInfo(collection->_directory, parameters, false); if (res != TRI_ERROR_NO_ERROR) { // TODO: shouldn't we destroy &document->_allIndexes, free document->_headersPtr etc.? @@ -2559,31 +2552,27 @@ size_t TRI_DocumentIteratorDocumentCollection (TransactionBase const*, int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, TRI_json_t const* json, TRI_index_t** idx) { - TRI_json_t const* type; - TRI_json_t const* iis; - char const* typeStr; - TRI_idx_iid_t iid; - - TRI_ASSERT(json != NULL); + TRI_ASSERT(json != nullptr); TRI_ASSERT(json->_type == TRI_JSON_ARRAY); - if (idx != NULL) { - *idx = NULL; + if (idx != nullptr) { + *idx = nullptr; } // extract the type - type = TRI_LookupArrayJson(json, "type"); + TRI_json_t const* type = TRI_LookupArrayJson(json, "type"); if (! TRI_IsStringJson(type)) { return TRI_ERROR_INTERNAL; } - typeStr = type->_value._string.data; + char const* typeStr = type->_value._string.data; // extract the index identifier - iis = TRI_LookupArrayJson(json, "id"); + TRI_json_t const* iis = TRI_LookupArrayJson(json, "id"); - if (iis != NULL && iis->_type == TRI_JSON_NUMBER) { + TRI_idx_iid_t iid; + if (iis != nullptr && iis->_type == TRI_JSON_NUMBER) { iid = (TRI_idx_iid_t) iis->_value._number; } else if (TRI_IsStringJson(iis)) { @@ -2603,9 +2592,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... if (TRI_EqualString(typeStr, "cap")) { - int res = CapConstraintFromJson(document, json, iid, idx); - - return res; + return CapConstraintFromJson(document, json, iid, idx); } // ........................................................................... @@ -2613,9 +2600,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... else if (TRI_EqualString(typeStr, "bitarray")) { - int res = BitarrayIndexFromJson(document, json, iid, idx); - - return res; + return BitarrayIndexFromJson(document, json, iid, idx); } // ........................................................................... @@ -2623,9 +2608,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... else if (TRI_EqualString(typeStr, "geo1") || TRI_EqualString(typeStr, "geo2")) { - int res = GeoIndexFromJson(document, json, iid, idx); - - return res; + return GeoIndexFromJson(document, json, iid, idx); } // ........................................................................... @@ -2633,9 +2616,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... else if (TRI_EqualString(typeStr, "hash")) { - int res = HashIndexFromJson(document, json, iid, idx); - - return res; + return HashIndexFromJson(document, json, iid, idx); } // ........................................................................... @@ -2643,9 +2624,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... else if (TRI_EqualString(typeStr, "skiplist")) { - int res = SkiplistIndexFromJson(document, json, iid, idx); - - return res; + return SkiplistIndexFromJson(document, json, iid, idx); } // ........................................................................... @@ -2653,9 +2632,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, // ........................................................................... else if (TRI_EqualString(typeStr, "fulltext")) { - int res = FulltextIndexFromJson(document, json, iid, idx); - - return res; + return FulltextIndexFromJson(document, json, iid, idx); } // ........................................................................... @@ -2665,8 +2642,6 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, else if (TRI_EqualString(typeStr, "edge")) { // we should never get here, as users cannot create their own edge indexes LOG_ERROR("logic error. there should never be a JSON file describing an edges index"); - - return TRI_ERROR_INTERNAL; } // ......................................................................... @@ -2677,9 +2652,9 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document, LOG_ERROR("ignoring unknown index type '%s' for index %llu", typeStr, (unsigned long long) iid); - - return TRI_ERROR_INTERNAL; } + + return TRI_ERROR_INTERNAL; } //////////////////////////////////////////////////////////////////////////////// @@ -2738,10 +2713,6 @@ bool TRI_CloseJournalDocumentCollection (TRI_document_collection_t* document, TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* col) { - TRI_collection_t* collection; - TRI_shaper_t* shaper; - int res; - char const* path = col->_path; // first open the document collection @@ -2757,7 +2728,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase, return nullptr; } - collection = TRI_OpenCollection(vocbase, document, path); + TRI_collection_t* collection = TRI_OpenCollection(vocbase, document, path); if (collection == nullptr) { delete document; @@ -2766,7 +2737,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase, return nullptr; } - shaper = TRI_CreateVocShaper(vocbase, document); + TRI_shaper_t* shaper = TRI_CreateVocShaper(vocbase, document); if (shaper == nullptr) { LOG_ERROR("cannot create shaper"); @@ -2803,7 +2774,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase, TransactionBase trx(true); // iterate over all markers of the collection - res = IterateMarkersCollection(collection); + int res = IterateMarkersCollection(collection); if (res != TRI_ERROR_NO_ERROR) { if (document->_failedTransactions != nullptr) { @@ -2880,28 +2851,25 @@ pid_name_t; static TRI_json_t* ExtractFields (TRI_json_t const* json, size_t* fieldCount, TRI_idx_iid_t iid) { - TRI_json_t* fld; - size_t j; + TRI_json_t* fld = TRI_LookupArrayJson(json, "fields"); - fld = TRI_LookupArrayJson(json, "fields"); - - if (fld == NULL || fld->_type != TRI_JSON_LIST) { + if (! TRI_IsListJson(fld)) { LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } *fieldCount = fld->_value._objects._length; - for (j = 0; j < *fieldCount; ++j) { + for (size_t j = 0; j < *fieldCount; ++j) { TRI_json_t* sub = static_cast(TRI_AtVector(&fld->_value._objects, j)); if (! TRI_IsStringJson(sub)) { LOG_ERROR("ignoring index %llu, 'fields' must be a list of attribute paths", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } } @@ -2920,16 +2888,13 @@ static TRI_json_t* ExtractFields (TRI_json_t const* json, static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, size_t* fieldCount, TRI_idx_iid_t iid) { - TRI_json_t* keyValues; - size_t j; + TRI_json_t* keyValues = TRI_LookupArrayJson(jsonIndex, "fields"); - keyValues = TRI_LookupArrayJson(jsonIndex, "fields"); - - if (keyValues == NULL || keyValues->_type != TRI_JSON_LIST) { + if (! TRI_IsListJson(keyValues)) { LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } @@ -2940,7 +2905,7 @@ static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, // Some simple checks // ........................................................................... - for (j = 0; j < *fieldCount; ++j) { + for (size_t j = 0; j < *fieldCount; ++j) { // ......................................................................... // Extract the jth key value pair @@ -2952,10 +2917,10 @@ static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, // The length of this key value pair must be two // ......................................................................... - if (keyValue == NULL || keyValue->_value._objects._length != 2) { + if (keyValue == nullptr || keyValue->_value._objects._length != 2) { LOG_ERROR("ignoring index %llu, 'fields' must be a list of key value pairs", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } @@ -2968,7 +2933,7 @@ static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, if (! TRI_IsStringJson(key)) { LOG_ERROR("ignoring index %llu, key in 'fields' pair must be an attribute (string)", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } @@ -2978,10 +2943,10 @@ static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, TRI_json_t* value = static_cast(TRI_AtVector(&keyValue->_value._objects, 1)); - if (value == NULL || value->_type != TRI_JSON_LIST) { + if (! TRI_IsListJson(value)) { LOG_ERROR("ignoring index %llu, value in 'fields' pair must be a list ([...])", (unsigned long long) iid); TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return NULL; + return nullptr; } } @@ -2989,84 +2954,6 @@ static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex, return keyValues; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief drops an index -//////////////////////////////////////////////////////////////////////////////// - -static bool DropIndex (TRI_document_collection_t* document, - TRI_idx_iid_t iid, - TRI_server_id_t generatingServer, - bool full) { - if (iid == 0) { - // invalid index id or primary index - return true; - } - - TRI_index_t* found = nullptr; - - TRI_vocbase_t* vocbase = document->_vocbase; - TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock); - - // ............................................................................. - // inside write-lock - // ............................................................................. - - TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); - - size_t const n = document->_allIndexes._length; - for (size_t i = 0; i < n; ++i) { - TRI_index_t* idx = static_cast(document->_allIndexes._buffer[i]); - - if (idx->_iid == iid) { - if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX || - idx->_type == TRI_IDX_TYPE_EDGE_INDEX) { - // cannot remove these index types - break; - } - - found = static_cast(TRI_RemoveVectorPointer(&document->_allIndexes, i)); - - if (found != nullptr && found->removeIndex != nullptr) { - // notify the index about its removal - found->removeIndex(found, document); - } - - break; - } - } - - RebuildIndexInfo(document); - - TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); - - TRI_ReadUnlockReadWriteLock(&vocbase->_inventoryLock); - - // ............................................................................. - // outside write-lock - // ............................................................................. - - if (found != nullptr) { - bool result = true; - - if (full) { - result = TRI_RemoveIndexFile(document, found); - - // it is safe to use _name as we hold a read-lock on the collection status - TRI_LogDropIndexReplication(vocbase, - document->_info._cid, - document->_info._name, - iid, - generatingServer); - } - - TRI_FreeIndex(found); - - return result; - } - - return false; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief initialises an index with all existing documents //////////////////////////////////////////////////////////////////////////////// @@ -3124,31 +3011,20 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t TRI_idx_type_e type, bool unique, bool allowAnyAttributeOrder) { - TRI_vector_t* indexPaths = NULL; - size_t j; + TRI_vector_t* indexPaths = nullptr; // ........................................................................... // go through every index and see if we have a match // ........................................................................... - for (j = 0; j < collection->_allIndexes._length; ++j) { + for (size_t j = 0; j < collection->_allIndexes._length; ++j) { TRI_index_t* idx = static_cast(collection->_allIndexes._buffer[j]); - bool found; - size_t k; // ......................................................................... // check if the type of the index matches // ......................................................................... - if (idx->_type != type) { - continue; - } - - // ......................................................................... - // check if uniqueness matches - // ......................................................................... - - if (idx->_unique != unique) { + if (idx->_type != type || idx->_unique != unique) { continue; } @@ -3182,9 +3058,9 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t } - if (indexPaths == NULL) { + if (indexPaths == nullptr) { // this may actually happen if compiled with -DNDEBUG - return NULL; + return nullptr; } // ......................................................................... @@ -3200,17 +3076,16 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t // go through all the attributes and see if they match // ......................................................................... - found = true; + bool found = true; if (allowAnyAttributeOrder) { // any permutation of attributes is allowed - for (k = 0; k < paths->_length; ++k) { + for (size_t k = 0; k < paths->_length; ++k) { TRI_shape_pid_t indexShape = *((TRI_shape_pid_t*) TRI_AtVector(indexPaths, k)); - size_t l; found = false; - for (l = 0; l < paths->_length; ++l) { + for (size_t l = 0; l < paths->_length; ++l) { TRI_shape_pid_t givenShape = *((TRI_shape_pid_t*) TRI_AtVector(paths, l)); if (indexShape == givenShape) { @@ -3226,7 +3101,7 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t } else { // attributes need to present in a given order - for (k = 0; k < paths->_length; ++k) { + for (size_t k = 0; k < paths->_length; ++k) { TRI_shape_pid_t indexShape = *((TRI_shape_pid_t*) TRI_AtVector(indexPaths, k)); TRI_shape_pid_t givenShape = *((TRI_shape_pid_t*) TRI_AtVector(paths, k)); @@ -3243,7 +3118,7 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t } } - return NULL; + return nullptr; } //////////////////////////////////////////////////////////////////////////////// @@ -3401,22 +3276,19 @@ static int PathBasedIndexFromJson (TRI_document_collection_t* document, bool, bool*), TRI_index_t** dst) { - TRI_index_t* idx; TRI_json_t* bv; - TRI_json_t* fld; TRI_vector_pointer_t attributes; bool unique; size_t fieldCount; - size_t j; - if (dst != NULL) { - *dst = NULL; + if (dst != nullptr) { + *dst = nullptr; } // extract fields - fld = ExtractFields(definition, &fieldCount, iid); + TRI_json_t* fld = ExtractFields(definition, &fieldCount, iid); - if (fld == NULL) { + if (fld == nullptr) { return TRI_errno(); } @@ -3430,7 +3302,7 @@ static int PathBasedIndexFromJson (TRI_document_collection_t* document, // determine if the hash index is unique or non-unique bv = TRI_LookupArrayJson(definition, "unique"); - if (bv == NULL || bv->_type != TRI_JSON_BOOLEAN) { + if (! TRI_IsBooleanJson(bv)) { LOG_ERROR("ignoring index %llu, could not determine if unique or non-unique", (unsigned long long) iid); return TRI_set_errno(TRI_ERROR_BAD_PARAMETER); } @@ -3442,24 +3314,24 @@ static int PathBasedIndexFromJson (TRI_document_collection_t* document, TRI_InitVectorPointer(&attributes, TRI_CORE_MEM_ZONE); // find fields - for (j = 0; j < fieldCount; ++j) { + for (size_t j = 0; j < fieldCount; ++j) { TRI_json_t* fieldStr = static_cast(TRI_AtVector(&fld->_value._objects, j)); TRI_PushBackVectorPointer(&attributes, fieldStr->_value._string.data); } // create the index - idx = creator(document, &attributes, iid, unique, NULL); + TRI_index_t* idx = creator(document, &attributes, iid, unique, nullptr); - if (dst != NULL) { + if (dst != nullptr) { *dst = idx; } // cleanup TRI_DestroyVectorPointer(&attributes); - if (idx == NULL) { - LOG_ERROR("cannot create hash index %llu", (unsigned long long) iid); + if (idx == nullptr) { + LOG_ERROR("cannot create index %llu", (unsigned long long) iid); return TRI_errno(); } @@ -3544,17 +3416,87 @@ TRI_vector_pointer_t* TRI_IndexesDocumentCollection (TRI_document_collection_t* bool TRI_DropIndexDocumentCollection (TRI_document_collection_t* document, TRI_idx_iid_t iid, TRI_server_id_t generatingServer) { - return DropIndex(document, iid, generatingServer, true); -} + if (iid == 0) { + // invalid index id or primary index + return true; + } -//////////////////////////////////////////////////////////////////////////////// -/// @brief drops an index, without index file removal and replication -//////////////////////////////////////////////////////////////////////////////// + TRI_index_t* found = nullptr; + TRI_vocbase_t* vocbase = document->_vocbase; -bool TRI_DropIndex2DocumentCollection (TRI_document_collection_t* document, - TRI_idx_iid_t iid, - TRI_server_id_t generatingServer) { - return DropIndex(document, iid, generatingServer, false); + TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock); + + // ............................................................................. + // inside write-lock + // ............................................................................. + + TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); + + size_t const n = document->_allIndexes._length; + + for (size_t i = 0; i < n; ++i) { + TRI_index_t* idx = static_cast(document->_allIndexes._buffer[i]); + + if (idx->_iid == iid) { + if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX || + idx->_type == TRI_IDX_TYPE_EDGE_INDEX) { + // cannot remove these index types + break; + } + + found = static_cast(TRI_RemoveVectorPointer(&document->_allIndexes, i)); + + if (found != nullptr && found->removeIndex != nullptr) { + // notify the index about its removal + found->removeIndex(found, document); + } + break; + } + } + + if (found != nullptr) { + RebuildIndexInfo(document); + } + + TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); + + TRI_ReadUnlockReadWriteLock(&vocbase->_inventoryLock); + + // ............................................................................. + // outside write-lock + // ............................................................................. + + if (found != nullptr) { + bool result = TRI_RemoveIndexFile(document, found); + + TRI_FreeIndex(found); + + int res = TRI_ERROR_NO_ERROR; + + try { + triagens::wal::DropIndexMarker marker(vocbase->_id, document->_info._cid, iid); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + return true; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } + + LOG_WARNING("could not save index drop marker in log: %s", TRI_errno_string(res)); + + // TODO: what to do here? + return result; + } + + return false; } //////////////////////////////////////////////////////////////////////////////// @@ -3571,7 +3513,6 @@ static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes, bool sorted, bool create) { pid_name_t* pidnames; - size_t j; // ............................................................................. // sorted case @@ -3586,7 +3527,7 @@ static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes, return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); } - for (j = 0; j < attributes->_length; ++j) { + for (size_t j = 0; j < attributes->_length; ++j) { pidnames[j]._name = static_cast(attributes->_buffer[j]); if (create) { @@ -3610,7 +3551,7 @@ static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes, TRI_InitVector(pids, TRI_CORE_MEM_ZONE, sizeof(TRI_shape_pid_t)); TRI_InitVectorPointer(names, TRI_CORE_MEM_ZONE); - for (j = 0; j < attributes->_length; ++j) { + for (size_t j = 0; j < attributes->_length; ++j) { TRI_PushBackVector(pids, &pidnames[j]._pid); TRI_PushBackVectorPointer(names, pidnames[j]._name); } @@ -3626,7 +3567,7 @@ static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes, TRI_InitVector(pids, TRI_CORE_MEM_ZONE, sizeof(TRI_shape_pid_t)); TRI_InitVectorPointer(names, TRI_CORE_MEM_ZONE); - for (j = 0; j < attributes->_length; ++j) { + for (size_t j = 0; j < attributes->_length; ++j) { char* name = static_cast(attributes->_buffer[j]); TRI_shape_pid_t pid; @@ -3732,34 +3673,29 @@ static int CapConstraintFromJson (TRI_document_collection_t* document, TRI_json_t const* definition, TRI_idx_iid_t iid, TRI_index_t** dst) { - TRI_json_t* val1; - TRI_json_t* val2; TRI_index_t* idx; - size_t count; - int64_t size; - if (dst != NULL) { - *dst = NULL; + if (dst != nullptr) { + *dst = nullptr; } - val1 = TRI_LookupArrayJson(definition, "size"); - val2 = TRI_LookupArrayJson(definition, "byteSize"); + TRI_json_t* val1 = TRI_LookupArrayJson(definition, "size"); + TRI_json_t* val2 = TRI_LookupArrayJson(definition, "byteSize"); - if ((val1 == NULL || val1->_type != TRI_JSON_NUMBER) && - (val2 == NULL || val2->_type != TRI_JSON_NUMBER)) { + if (! TRI_IsNumberJson(val1) && ! TRI_IsNumberJson(val2)) { LOG_ERROR("ignoring cap constraint %llu, 'size' and 'byteSize' missing", (unsigned long long) iid); return TRI_set_errno(TRI_ERROR_BAD_PARAMETER); } - count = 0; - if (val1 != NULL && val1->_value._number > 0.0) { + size_t count = 0; + if (TRI_IsNumberJson(val1) && val1->_value._number > 0.0) { count = (size_t) val1->_value._number; } - size = 0; - if (val2 != NULL && val2->_value._number > (double) TRI_CAP_CONSTRAINT_MIN_SIZE) { + int64_t size = 0; + if (TRI_IsNumberJson(val2) && val2->_value._number > (double) TRI_CAP_CONSTRAINT_MIN_SIZE) { size = (int64_t) val2->_value._number; } @@ -3772,12 +3708,12 @@ static int CapConstraintFromJson (TRI_document_collection_t* document, return TRI_set_errno(TRI_ERROR_BAD_PARAMETER); } - idx = CreateCapConstraintDocumentCollection(document, count, size, iid, NULL); - if (dst != NULL) { + idx = CreateCapConstraintDocumentCollection(document, count, size, iid, nullptr); + if (dst != nullptr) { *dst = idx; } - return idx == NULL ? TRI_errno() : TRI_ERROR_NO_ERROR; + return idx == nullptr ? TRI_errno() : TRI_ERROR_NO_ERROR; } // ----------------------------------------------------------------------------- diff --git a/arangod/VocBase/document-collection.h b/arangod/VocBase/document-collection.h index bfdbc8388f..d811d64d58 100644 --- a/arangod/VocBase/document-collection.h +++ b/arangod/VocBase/document-collection.h @@ -771,14 +771,6 @@ bool TRI_DropIndexDocumentCollection (TRI_document_collection_t*, TRI_idx_iid_t, TRI_server_id_t); -//////////////////////////////////////////////////////////////////////////////// -/// @brief drops an index, without index file removal and replication -//////////////////////////////////////////////////////////////////////////////// - -bool TRI_DropIndex2DocumentCollection (TRI_document_collection_t*, - TRI_idx_iid_t, - TRI_server_id_t); - // ----------------------------------------------------------------------------- // --SECTION-- CAP CONSTRAINT // ----------------------------------------------------------------------------- diff --git a/arangod/VocBase/index.cpp b/arangod/VocBase/index.cpp index d689eae2e4..dbcf10c001 100644 --- a/arangod/VocBase/index.cpp +++ b/arangod/VocBase/index.cpp @@ -37,7 +37,7 @@ #include "BasicsC/tri-strings.h" #include "BasicsC/utf8-helper.h" #include "BasicsC/fasthash.h" -#include "BasicsC/xxhash.h" +#include "Basics/JsonHelper.h" #include "CapConstraint/cap-constraint.h" #include "GeoIndex/geo-index.h" #include "FulltextIndex/fulltext-index.h" @@ -46,11 +46,14 @@ #include "HashIndex/hash-index.h" #include "ShapedJson/shape-accessor.h" #include "ShapedJson/shaped-json.h" +#include "Utils/Exception.h" #include "VocBase/document-collection.h" #include "VocBase/edge-collection.h" #include "VocBase/replication-logger.h" #include "VocBase/server.h" #include "VocBase/voc-shaper.h" +#include "Wal/LogfileManager.h" +#include "Wal/Marker.h" // ----------------------------------------------------------------------------- // --SECTION-- INDEX @@ -117,8 +120,7 @@ bool TRI_NeedsFullCoverageIndex (TRI_idx_type_e type) { case TRI_IDX_TYPE_CAP_CONSTRAINT: return true; case TRI_IDX_TYPE_BITARRAY_INDEX: - return false; - case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX: + case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX: // removed case TRI_IDX_TYPE_UNKNOWN: return false; } @@ -317,23 +319,18 @@ void TRI_FreeIndex (TRI_index_t* idx) { //////////////////////////////////////////////////////////////////////////////// bool TRI_RemoveIndexFile (TRI_document_collection_t* collection, TRI_index_t* idx) { - char* filename; - char* name; - char* number; - int res; - // construct filename - number = TRI_StringUInt64(idx->_iid); + char* number = TRI_StringUInt64(idx->_iid); - if (number == NULL) { + if (number == nullptr) { 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"); + char* name = TRI_Concatenate3String("index-", number, ".json"); - if (name == NULL) { + if (name == nullptr) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); TRI_FreeString(TRI_CORE_MEM_ZONE, number); @@ -341,9 +338,9 @@ bool TRI_RemoveIndexFile (TRI_document_collection_t* collection, TRI_index_t* id return false; } - filename = TRI_Concatenate2File(collection->_directory, name); + char* filename = TRI_Concatenate2File(collection->_directory, name); - if (filename == NULL) { + if (filename == nullptr) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); TRI_FreeString(TRI_CORE_MEM_ZONE, number); @@ -355,7 +352,7 @@ bool TRI_RemoveIndexFile (TRI_document_collection_t* collection, TRI_index_t* id TRI_FreeString(TRI_CORE_MEM_ZONE, name); TRI_FreeString(TRI_CORE_MEM_ZONE, number); - res = TRI_UnlinkFile(filename); + int res = TRI_UnlinkFile(filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (res != TRI_ERROR_NO_ERROR) { @@ -373,33 +370,26 @@ bool TRI_RemoveIndexFile (TRI_document_collection_t* collection, TRI_index_t* id int TRI_SaveIndex (TRI_document_collection_t* document, TRI_index_t* idx, TRI_server_id_t generatingServer) { - TRI_json_t* json; - TRI_vocbase_t* vocbase; - char* filename; - char* name; - char* number; - bool ok; - // convert into JSON - json = idx->json(idx); + TRI_json_t* json = idx->json(idx); - if (json == NULL) { + if (json == nullptr) { LOG_TRACE("cannot save index definition: index cannot be jsonified"); return TRI_set_errno(TRI_ERROR_INTERNAL); } // construct filename - number = TRI_StringUInt64(idx->_iid); - name = TRI_Concatenate3String("index-", number, ".json"); - filename = TRI_Concatenate2File(document->_directory, name); + char* number = TRI_StringUInt64(idx->_iid); + char* name = TRI_Concatenate3String("index-", number, ".json"); + char* filename = TRI_Concatenate2File(document->_directory, name); TRI_FreeString(TRI_CORE_MEM_ZONE, name); TRI_FreeString(TRI_CORE_MEM_ZONE, number); - vocbase = document->_vocbase; + TRI_vocbase_t* vocbase = document->_vocbase; // and save - ok = TRI_SaveJson(filename, json, vocbase->_settings.forceSyncProperties); + bool ok = TRI_SaveJson(filename, json, vocbase->_settings.forceSyncProperties); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); @@ -410,16 +400,29 @@ int TRI_SaveIndex (TRI_document_collection_t* document, return TRI_errno(); } - // it is safe to use _name as we hold a read-lock on the collection status - TRI_LogCreateIndexReplication(vocbase, - document->_info._cid, - document->_info._name, - idx->_iid, - json, - generatingServer); + int res = TRI_ERROR_NO_ERROR; + + try { + triagens::wal::CreateIndexMarker marker(vocbase->_id, document->_info._cid, idx->_iid, triagens::basics::JsonHelper::toString(json)); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + TRI_FreeJson(TRI_CORE_MEM_ZONE, json); + return TRI_ERROR_NO_ERROR; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } TRI_FreeJson(TRI_CORE_MEM_ZONE, json); + // TODO: what to do here? return TRI_ERROR_NO_ERROR; } @@ -429,7 +432,9 @@ int TRI_SaveIndex (TRI_document_collection_t* document, TRI_index_t* TRI_LookupIndex (TRI_document_collection_t* document, TRI_idx_iid_t iid) { - for (size_t i = 0; i < document->_allIndexes._length; ++i) { + size_t const n = document->_allIndexes._length; + + for (size_t i = 0; i < n; ++i) { TRI_index_t* idx = static_cast(document->_allIndexes._buffer[i]); if (idx->_iid == iid) { @@ -439,7 +444,7 @@ TRI_index_t* TRI_LookupIndex (TRI_document_collection_t* document, TRI_set_errno(TRI_ERROR_ARANGO_NO_INDEX); - return NULL; + return nullptr; } //////////////////////////////////////////////////////////////////////////////// @@ -454,7 +459,7 @@ TRI_json_t* TRI_JsonIndex (TRI_memory_zone_t* zone, json = TRI_CreateArrayJson(zone); - if (json != NULL) { + if (json != nullptr) { char* number; number = TRI_StringUInt64(idx->_iid); @@ -473,7 +478,7 @@ TRI_json_t* TRI_JsonIndex (TRI_memory_zone_t* zone, //////////////////////////////////////////////////////////////////////////////// void TRI_DestroyIndexResult (TRI_index_result_t* result) { - if (result->_documents != NULL) { + if (result->_documents != nullptr) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, result->_documents); } } @@ -483,11 +488,9 @@ void TRI_DestroyIndexResult (TRI_index_result_t* result) { //////////////////////////////////////////////////////////////////////////////// void TRI_CopyPathVector (TRI_vector_t* dst, TRI_vector_t* src) { - size_t j; - TRI_InitVector(dst, TRI_CORE_MEM_ZONE, sizeof(TRI_shape_pid_t)); - for (j = 0; j < src->_length; ++j) { + for (size_t j = 0; j < src->_length; ++j) { TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(src,j))); TRI_PushBackVector(dst, &shape); @@ -517,10 +520,10 @@ char const** TRI_FieldListByPathList (TRI_shaper_t const* shaper, TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths, j))); TRI_shape_path_t const* path = shaper->lookupAttributePathByPid(const_cast(shaper), shape); - if (path == NULL) { + if (path == nullptr) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); TRI_Free(TRI_CORE_MEM_ZONE, (void*) fieldList); - return NULL; + return nullptr; } fieldList[j] = ((const char*) path) + sizeof(TRI_shape_path_t) + path->_aidLength * sizeof(TRI_shape_aid_t); @@ -1056,9 +1059,7 @@ TRI_index_t* TRI_CreateEdgeIndex (TRI_document_collection_t* document, //////////////////////////////////////////////////////////////////////////////// void TRI_DestroyEdgeIndex (TRI_index_t* idx) { - TRI_edge_index_t* edgesIndex; - - edgesIndex = (TRI_edge_index_t*) idx; + TRI_edge_index_t* edgesIndex = (TRI_edge_index_t*) idx; LOG_TRACE("destroying edge index"); @@ -1121,7 +1122,7 @@ static int FillLookupSLOperator (TRI_index_operator_t* slOperator, relationOperator->_numFields = relationOperator->_parameters->_value._objects._length; relationOperator->_fields = static_cast(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_shaped_json_t) * relationOperator->_numFields, false)); - if (relationOperator->_fields != NULL) { + if (relationOperator->_fields != nullptr) { for (size_t j = 0; j < relationOperator->_numFields; ++j) { TRI_json_t* jsonObject = (TRI_json_t*) TRI_AtVector(&(relationOperator->_parameters->_value._objects), j); @@ -1133,7 +1134,7 @@ static int FillLookupSLOperator (TRI_index_operator_t* slOperator, TRI_shaped_json_t* shapedObject = TRI_ShapedJsonJson(document->getShaper(), jsonObject, false, false); // ONLY IN INDEX, PROTECTED by RUNTIME - if (shapedObject != NULL) { + if (shapedObject != nullptr) { relationOperator->_fields[j] = *shapedObject; // shallow copy here is ok TRI_Free(TRI_UNKNOWN_MEM_ZONE, shapedObject); // don't require storage anymore } @@ -1212,7 +1213,7 @@ static int SkiplistIndexHelper (const TRI_skiplist_index_t* skiplistIndex, TRI_shaped_json_t shapedJson; TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->getDataPtr()); // ONLY IN INDEX, PROTECTED by RUNTIME - if (shapedJson._sid == 0) { + if (shapedJson._sid == TRI_SHAPE_ILLEGAL) { LOG_WARNING("encountered invalid marker with shape id 0"); return TRI_ERROR_INTERNAL; @@ -1382,7 +1383,7 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t const* idx) { if (path == nullptr) { TRI_Free(TRI_CORE_MEM_ZONE, (void*) fieldList); - return NULL; + return nullptr; } fieldList[j] = ((const char*) path) + sizeof(TRI_shape_path_t) + path->_aidLength * sizeof(TRI_shape_aid_t); } @@ -1970,14 +1971,14 @@ TRI_index_iterator_t* TRI_LookupBitarrayIndex (TRI_index_t* idx, errorResult = FillLookupBitarrayOperator(indexOperator, baIndex->base._collection); if (errorResult != TRI_ERROR_NO_ERROR) { - return NULL; + return nullptr; } iteratorResult = BitarrayIndex_find(baIndex->_bitarrayIndex, indexOperator, &baIndex->_paths, baIndex, - NULL); + nullptr); TRI_FreeIndexOperator(indexOperator); diff --git a/arangod/VocBase/replication-logger.cpp b/arangod/VocBase/replication-logger.cpp index f9df881464..7d813d4e02 100644 --- a/arangod/VocBase/replication-logger.cpp +++ b/arangod/VocBase/replication-logger.cpp @@ -213,9 +213,10 @@ static void FreeCap (TRI_replication_logger_t* logger) { TRI_document_collection_t* document = logger->_trxCollection->_collection->_collection; TRI_ASSERT(document != NULL); - TRI_DropIndex2DocumentCollection(document, - logger->_cap->_iid, - TRI_GetIdServer()); + // TODO: this wont work anymore - remove function altogether + TRI_DropIndexDocumentCollection(document, + logger->_cap->_iid, + TRI_GetIdServer()); logger->_cap = NULL; } @@ -468,26 +469,6 @@ static int LogEvent (TRI_replication_logger_t* logger, return TRI_ERROR_NO_ERROR; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a collection context -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyCollection (TRI_string_buffer_t* buffer, - const TRI_voc_cid_t cid, - char const* name) { - if (buffer == NULL) { - return false; - } - - APPEND_STRING(buffer, "\"cid\":\""); - APPEND_UINT64(buffer, (uint64_t) cid); - APPEND_STRING(buffer, "\",\"cname\":\""); - APPEND_STRING(buffer, name); - APPEND_CHAR(buffer, '"'); - - return true; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief stringify a "replication" operation with a tick //////////////////////////////////////////////////////////////////////////////// @@ -505,128 +486,6 @@ static bool StringifyTickReplication (TRI_string_buffer_t* buffer, return true; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a "create collection" operation -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyCreateCollection (TRI_string_buffer_t* buffer, - TRI_voc_cid_t cid, - char const* name, - TRI_json_t const* json) { - if (buffer == NULL) { - return false; - } - - APPEND_STRING(buffer, "{\"cid\":\""); - APPEND_UINT64(buffer, (uint64_t) cid); - APPEND_STRING(buffer, "\",\"cname\":\""); - APPEND_STRING(buffer, name); - APPEND_STRING(buffer, "\",\"collection\":"); - APPEND_JSON(buffer, json); - APPEND_CHAR(buffer, '}'); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a "drop collection" operation -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyDropCollection (TRI_string_buffer_t* buffer, - TRI_voc_cid_t cid, - char const* name) { - if (buffer == NULL) { - return false; - } - - APPEND_CHAR(buffer, '{'); - - if (! StringifyCollection(buffer, cid, name)) { - return false; - } - - APPEND_CHAR(buffer, '}'); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a "rename collection" operation -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyRenameCollection (TRI_string_buffer_t* buffer, - TRI_voc_cid_t cid, - char const* name, - char const* newName) { - - if (buffer == NULL) { - return false; - } - - APPEND_CHAR(buffer, '{'); - - if (! StringifyCollection(buffer, cid, name)) { - return false; - } - - APPEND_STRING(buffer, ",\"collection\":{\"name\":\""); - // name is user-defined, but does not need escaping as collection names are "safe" - APPEND_STRING(buffer, newName); - APPEND_STRING(buffer, "\"}}"); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a "create index" operation -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyCreateIndex (TRI_string_buffer_t* buffer, - TRI_voc_cid_t cid, - char const* name, - TRI_json_t const* json) { - if (buffer == NULL) { - return false; - } - - APPEND_CHAR(buffer, '{'); - - if (! StringifyCollection(buffer, cid, name)) { - return false; - } - - APPEND_STRING(buffer, ",\"index\":"); - APPEND_JSON(buffer, json); - APPEND_CHAR(buffer, '}'); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief stringify a "drop index" operation -//////////////////////////////////////////////////////////////////////////////// - -static bool StringifyDropIndex (TRI_string_buffer_t* buffer, - TRI_voc_cid_t cid, - char const* name, - TRI_idx_iid_t iid) { - if (buffer == NULL) { - return false; - } - - APPEND_CHAR(buffer, '{'); - - if (! StringifyCollection(buffer, cid, name)) { - return false; - } - - APPEND_STRING(buffer, ",\"id\":\""); - APPEND_UINT64(buffer, (uint64_t) iid); - APPEND_STRING(buffer, "\"}"); - - return true; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief get current state from the replication logger /// note: must hold the lock when calling this @@ -911,37 +770,6 @@ static int InitBuffers (TRI_replication_logger_t* logger) { return TRI_ERROR_NO_ERROR; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief lock the logger and check for inclusion of an event -/// if this function returns true, it has acquired a read-lock that the caller -/// must unlock! -//////////////////////////////////////////////////////////////////////////////// - -static bool CheckAndLock (TRI_replication_logger_t* logger, - TRI_server_id_t generatingServer) { - // acquire read-lock - TRI_ReadLockReadWriteLock(&logger->_statusLock); - - if (! logger->_state._active) { - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return false; - } - - if (generatingServer != 0 && - generatingServer != logger->_localServerId && - ! logger->_configuration._logRemoteChanges) { - // read-unlock the read-lock - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return false; - } - - // we'll keep the lock!! - - return true; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief get the filename of the replication logger configuration file //////////////////////////////////////////////////////////////////////////////// @@ -1448,262 +1276,6 @@ TRI_json_t* TRI_JsonReplicationLogger (TRI_replication_logger_t* logger) { return json; } -// ----------------------------------------------------------------------------- -// --SECTION-- public log functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "create collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogCreateCollectionReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* name, - TRI_json_t const* json, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(name)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyCreateCollection(buffer, cid, name, json)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, COLLECTION_CREATE, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "drop collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogDropCollectionReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* name, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(name)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyDropCollection(buffer, cid, name)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, COLLECTION_DROP, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "rename collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogRenameCollectionReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* oldName, - char const* newName, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(oldName)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyRenameCollection(buffer, cid, oldName, newName)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, COLLECTION_RENAME, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "change collection properties" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogChangePropertiesCollectionReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* name, - TRI_json_t const* json, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(name)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyCreateCollection(buffer, cid, name, json)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, COLLECTION_CHANGE, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "create index" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogCreateIndexReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* name, - TRI_idx_iid_t iid, - TRI_json_t const* json, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(name)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyCreateIndex(buffer, cid, name, json)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, INDEX_CREATE, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "drop index" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogDropIndexReplication (TRI_vocbase_t* vocbase, - TRI_voc_cid_t cid, - char const* name, - TRI_idx_iid_t iid, - TRI_server_id_t generatingServer) { - TRI_string_buffer_t* buffer; - TRI_replication_logger_t* logger; - int res; - - if (TRI_ExcludeCollectionReplication(name)) { - return TRI_ERROR_NO_ERROR; - } - - if (vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) { - return TRI_ERROR_NO_ERROR; - } - - logger = vocbase->_replicationLogger; - - if (! CheckAndLock(logger, generatingServer)) { - return TRI_ERROR_NO_ERROR; - } - - buffer = GetBuffer(logger); - - if (! StringifyDropIndex(buffer, cid, name, iid)) { - ReturnBuffer(logger, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return TRI_ERROR_OUT_OF_MEMORY; - } - - res = LogEvent(logger, 0, true, INDEX_DROP, buffer); - TRI_ReadUnlockReadWriteLock(&logger->_statusLock); - - return res; -} - // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" diff --git a/arangod/VocBase/replication-logger.h b/arangod/VocBase/replication-logger.h index 32dfaff3a6..85eee26049 100644 --- a/arangod/VocBase/replication-logger.h +++ b/arangod/VocBase/replication-logger.h @@ -199,70 +199,6 @@ struct TRI_json_s* TRI_JsonStateReplicationLogger (TRI_replication_logger_state_ struct TRI_json_s* TRI_JsonReplicationLogger (TRI_replication_logger_t*); -// ----------------------------------------------------------------------------- -// --SECTION-- public log functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "create collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogCreateCollectionReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - struct TRI_json_s const*, - TRI_server_id_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "drop collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogDropCollectionReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - TRI_server_id_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "rename collection" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogRenameCollectionReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - char const*, - TRI_server_id_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "change collection properties" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogChangePropertiesCollectionReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - struct TRI_json_s const*, - TRI_server_id_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "create index" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogCreateIndexReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - TRI_idx_iid_t, - struct TRI_json_s const*, - TRI_server_id_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief replicate a "drop index" operation -//////////////////////////////////////////////////////////////////////////////// - -int TRI_LogDropIndexReplication (struct TRI_vocbase_s*, - TRI_voc_cid_t, - char const*, - TRI_idx_iid_t iid, - TRI_server_id_t); - #endif // Local Variables: diff --git a/arangod/VocBase/voc-shaper.cpp b/arangod/VocBase/voc-shaper.cpp index 7637bfed4b..944e3ff9d5 100644 --- a/arangod/VocBase/voc-shaper.cpp +++ b/arangod/VocBase/voc-shaper.cpp @@ -36,6 +36,7 @@ #include "BasicsC/logging.h" #include "BasicsC/tri-strings.h" #include "BasicsC/utf8-helper.h" +#include "Utils/Exception.h" #include "VocBase/document-collection.h" #include "Wal/LogfileManager.h" @@ -178,36 +179,50 @@ static TRI_shape_aid_t FindOrCreateAttributeByName (TRI_shaper_t* shaper, TRI_document_collection_t* document = s->_collection; - triagens::wal::AttributeMarker marker(document->_vocbase->_id, document->_info._cid, aid, std::string(name)); + int res = TRI_ERROR_NO_ERROR; + + try { + triagens::wal::AttributeMarker marker(document->_vocbase->_id, document->_info._cid, aid, std::string(name)); - // lock the index and check that the element is still missing - { - MUTEX_LOCKER(s->_attributeLock); + // lock the index and check that the element is still missing + { + MUTEX_LOCKER(s->_attributeLock); - void const* p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name); + void const* p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name); - // if the element appeared, return the aid - if (p != nullptr) { - return GetAttributeId(p); + // if the element appeared, return the aid + if (p != nullptr) { + return GetAttributeId(p); + } + + // write marker into wal + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + // throw an exception which is caught at the end of this function + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + void* f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast(slotInfo.mem), false); + TRI_ASSERT(f == nullptr); + + // enter into the dictionaries + f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, const_cast(slotInfo.mem), false); + TRI_ASSERT(f == nullptr); } - // write marker into wal - triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker.mem(), marker.size(), false); - - if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { - LOG_WARNING("could not save attribute marker in log: %s", TRI_errno_string(slotInfo.errorCode)); - return 0; - } - - void* f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast(slotInfo.mem), false); - TRI_ASSERT(f == nullptr); - - // enter into the dictionaries - f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, const_cast(slotInfo.mem), false); - TRI_ASSERT(f == nullptr); + return aid; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; } - return aid; + LOG_WARNING("could not save attribute marker in log: %s", TRI_errno_string(res)); + + return 0; } //////////////////////////////////////////////////////////////////////////////// @@ -321,15 +336,15 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, // get next shape id TRI_shape_sid_t const sid = s->_nextSid++; shape->_sid = sid; - - TRI_document_collection_t* document = s->_collection; - triagens::wal::ShapeMarker marker(document->_vocbase->_id, document->_info._cid, shape); + TRI_document_collection_t* document = s->_collection; - TRI_shape_t const* result; + int res = TRI_ERROR_NO_ERROR; - // lock the index and check the element is still missing - { + try { + triagens::wal::ShapeMarker marker(document->_vocbase->_id, document->_info._cid, shape); + + // lock the index and check the element is still missing MUTEX_LOCKER(s->_shapeLock); found = static_cast(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape)); @@ -341,26 +356,35 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, } // write marker into wal - triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker.mem(), marker.size(), false); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { - LOG_WARNING("could not save shape marker in log: %s", TRI_errno_string(slotInfo.errorCode)); - return nullptr; + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } char const* m = static_cast(slotInfo.mem) + sizeof(triagens::wal::shape_marker_t); - result = reinterpret_cast(m); + TRI_shape_t const* result = reinterpret_cast(m); void* f = TRI_InsertKeyAssociativeSynced(&s->_shapeIds, &sid, (void*) m, false); TRI_ASSERT(f == nullptr); f = TRI_InsertElementAssociativeSynced(&s->_shapeDictionary, (void*) m, false); TRI_ASSERT(f == nullptr); + + TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape); + return result; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; } TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape); + LOG_WARNING("could not save shape marker in log: %s", TRI_errno_string(res)); - return result; + return nullptr; } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/vocbase.cpp b/arangod/VocBase/vocbase.cpp index 28b76f4e5c..af670294bd 100644 --- a/arangod/VocBase/vocbase.cpp +++ b/arangod/VocBase/vocbase.cpp @@ -43,6 +43,7 @@ #include "BasicsC/tri-strings.h" #include "BasicsC/threads.h" +#include "Utils/Exception.h" #include "Utils/transactions.h" #include "VocBase/auth.h" #include "VocBase/barrier.h" @@ -55,6 +56,7 @@ #include "VocBase/server.h" #include "VocBase/transaction.h" #include "VocBase/vocbase-defaults.h" +#include "Wal/LogfileManager.h" #include "Ahuacatl/ahuacatl-functions.h" @@ -187,15 +189,32 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase, } // post-condition - TRI_ASSERT(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); + TRI_ASSERT_EXPENSIVE(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); - TRI_LogDropCollectionReplication(vocbase, - collection->_cid, - collection->_name, - generatingServer); + int res = TRI_ERROR_NO_ERROR; + try { + triagens::wal::DropCollectionMarker marker(vocbase->_id, collection->_cid); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + return true; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } + + LOG_WARNING("could not save collection drop marker in log: %s", TRI_errno_string(res)); + + // TODO: what to do here return true; } @@ -443,9 +462,6 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, char const* name, TRI_voc_cid_t cid, char const* path) { - void const* found; - int res; - // create the init object TRI_vocbase_col_t init; @@ -455,7 +471,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, init._type = static_cast(type); init._status = TRI_VOC_COL_STATUS_CORRUPTED; - init._collection = NULL; + init._collection = nullptr; // default flags: everything is allowed init._canDrop = true; @@ -481,7 +497,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_CopyString(init._dbName, vocbase->_name, strlen(vocbase->_name)); TRI_CopyString(init._name, name, sizeof(init._name) - 1); - if (path == NULL) { + if (path == nullptr) { init._path[0] = '\0'; } else { @@ -491,18 +507,19 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, // create a new proxy TRI_vocbase_col_t* collection = static_cast(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vocbase_col_t), false)); - if (collection == NULL) { + if (collection == nullptr) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); - return NULL; + return nullptr; } memcpy(collection, &init, sizeof(TRI_vocbase_col_t)); collection->_isLocal = true; // check name - res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found); + void const* found; + int res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found); - if (found != NULL) { + if (found != nullptr) { LOG_ERROR("duplicate entry for collection name '%s'", name); LOG_ERROR("collection id %llu has same name as already added collection %llu", (unsigned long long) cid, @@ -511,7 +528,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection); TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_NAME); - return NULL; + return nullptr; } if (res != TRI_ERROR_NO_ERROR) { @@ -520,14 +537,14 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection); TRI_set_errno(res); - return NULL; + return nullptr; } // check collection identifier TRI_ASSERT(collection->_cid == cid); res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found); - if (found != NULL) { + if (found != nullptr) { TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name); LOG_ERROR("duplicate collection identifier %llu for name '%s'", @@ -536,7 +553,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection); TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_IDENTIFIER); - return NULL; + return nullptr; } if (res != TRI_ERROR_NO_ERROR) { @@ -546,10 +563,10 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection); TRI_set_errno(res); - return NULL; + return nullptr; } - TRI_ASSERT(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); + TRI_ASSERT_EXPENSIVE(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); TRI_InitReadWriteLock(&collection->_lock); @@ -566,13 +583,7 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase, TRI_col_info_t* parameter, TRI_voc_cid_t cid, TRI_server_id_t generatingServer) { - TRI_vocbase_col_t* collection; - TRI_collection_t* col; - TRI_json_t* json; - char const* name; - void const* found; - - name = parameter->_name; + char const* name = parameter->_name; TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase); @@ -580,15 +591,15 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase, // check that we have a new name // ............................................................................. - found = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name); + void const* found = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name); - if (found != NULL) { + if (found != nullptr) { TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); LOG_DEBUG("collection named '%s' already exists", name); TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_NAME); - return NULL; + return nullptr; } // ............................................................................. @@ -597,20 +608,20 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase, TRI_document_collection_t* document = TRI_CreateDocumentCollection(vocbase, vocbase->_path, parameter, cid); - if (document == NULL) { + if (document == nullptr) { TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); - return NULL; + return nullptr; } - col = document; + TRI_collection_t* col = document; // add collection container - collection = AddCollection(vocbase, - col->_info._type, - col->_info._name, - col->_info._cid, - col->_directory); + TRI_vocbase_col_t* collection = AddCollection(vocbase, + col->_info._type, + col->_info._name, + col->_info._cid, + col->_directory); if (collection == nullptr) { TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); @@ -635,19 +646,35 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase, document->_directory, sizeof(collection->_path) - 1); - json = TRI_CreateJsonCollectionInfo(&col->_info); + TRI_json_t* json = TRI_CreateJsonCollectionInfo(&col->_info); // release the lock on the list of collections TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); - // replicate and finally unlock the collection - TRI_LogCreateCollectionReplication(vocbase, - cid, - name, - json, - generatingServer); - TRI_FreeJson(TRI_CORE_MEM_ZONE, json); + int res = TRI_ERROR_NO_ERROR; + try { + triagens::wal::CreateCollectionMarker marker(vocbase->_id, cid, triagens::basics::JsonHelper::toString(json)); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + TRI_FreeJson(TRI_CORE_MEM_ZONE, json); + return collection; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } + + TRI_FreeJson(TRI_CORE_MEM_ZONE, json); + LOG_WARNING("could not save collection create marker in log: %s", TRI_errno_string(res)); + + // TODO: what to do here? return collection; } @@ -688,7 +715,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase, // check if the new name is unused found = (void*) TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, newName); - if (found != NULL) { + if (found != nullptr) { TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); @@ -761,18 +788,39 @@ static int RenameCollection (TRI_vocbase_t* vocbase, // this shouldn't fail, as we removed an element above so adding one should be ok found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, newName, CONST_CAST(collection), false); - TRI_ASSERT(found == NULL); + TRI_ASSERT(found == nullptr); - TRI_ASSERT(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); + TRI_ASSERT_EXPENSIVE(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); - - // stay inside the outer lock to protect against unloading - TRI_LogRenameCollectionReplication(vocbase, collection->_cid, oldName, newName, generatingServer); - + TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); - return TRI_ERROR_NO_ERROR; + // now log the operation + res = TRI_ERROR_NO_ERROR; + + try { + triagens::wal::RenameCollectionMarker marker(vocbase->_id, collection->_cid, std::string(newName)); + triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + + return TRI_ERROR_NO_ERROR; + } + catch (triagens::arango::Exception const& ex) { + res = ex.code(); + } + catch (...) { + res = TRI_ERROR_INTERNAL; + } + + if (res != TRI_ERROR_NO_ERROR) { + LOG_WARNING("could not save collection rename marker in log: %s", TRI_errno_string(res)); + } + + return res; } //////////////////////////////////////////////////////////////////////////////// @@ -1913,25 +1961,21 @@ TRI_vocbase_col_t* TRI_FindCollectionByNameOrCreateVocBase (TRI_vocbase_t* vocba //////////////////////////////////////////////////////////////////////////////// TRI_vocbase_col_t* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, - TRI_col_info_t* parameter, + TRI_col_info_t* parameters, TRI_voc_cid_t cid, TRI_server_id_t generatingServer) { - TRI_vocbase_col_t* collection; - char* name; - - TRI_ASSERT(parameter != NULL); - name = parameter->_name; + TRI_ASSERT(parameters != nullptr); // check that the name does not contain any strange characters - if (! TRI_IsAllowedNameCollection(parameter->_isSystem, name)) { + if (! TRI_IsAllowedNameCollection(parameters->_isSystem, parameters->_name)) { TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_NAME); - return NULL; + return nullptr; } TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock); - collection = CreateCollection(vocbase, parameter, cid, generatingServer); + TRI_vocbase_col_t* collection = CreateCollection(vocbase, parameters, cid, generatingServer); TRI_ReadUnlockReadWriteLock(&vocbase->_inventoryLock); diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index 4d14b09a24..27c8786de8 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -739,6 +739,16 @@ SlotInfoCopy LogfileManager::allocateAndWrite (void* src, } } +//////////////////////////////////////////////////////////////////////////////// +/// @brief write data into the logfile +/// this is a convenience function that combines allocate, memcpy and finalise +//////////////////////////////////////////////////////////////////////////////// + +SlotInfoCopy LogfileManager::allocateAndWrite (Marker const& marker, + bool waitForSync) { + return allocateAndWrite(marker.mem(), marker.size(), waitForSync); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief set all open logfiles to status sealed //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Wal/LogfileManager.h b/arangod/Wal/LogfileManager.h index 87daeb1b13..080fe2a8bd 100644 --- a/arangod/Wal/LogfileManager.h +++ b/arangod/Wal/LogfileManager.h @@ -295,6 +295,14 @@ struct RecoverState { uint32_t, bool); +//////////////////////////////////////////////////////////////////////////////// +/// @brief write data into the logfile +/// this is a convenience function that combines allocate, memcpy and finalise +//////////////////////////////////////////////////////////////////////////////// + + SlotInfoCopy allocateAndWrite (Marker const&, + bool); + //////////////////////////////////////////////////////////////////////////////// /// @brief set all open logfiles to status sealed //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Wal/Marker.cpp b/arangod/Wal/Marker.cpp index 7654ade415..6a066d6101 100644 --- a/arangod/Wal/Marker.cpp +++ b/arangod/Wal/Marker.cpp @@ -583,6 +583,120 @@ void ChangeCollectionMarker::dump () const { } #endif +// ----------------------------------------------------------------------------- +// --SECTION-- CreateIndexMarker +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create marker +//////////////////////////////////////////////////////////////////////////////// + +CreateIndexMarker::CreateIndexMarker (TRI_voc_tick_t databaseId, + TRI_voc_cid_t collectionId, + TRI_idx_iid_t indexId, + string const& properties) + : Marker(TRI_WAL_MARKER_CREATE_INDEX, sizeof(index_create_marker_t) + alignedSize(properties.size() + 1)) { + + index_create_marker_t* m = reinterpret_cast(begin()); + + m->_databaseId = databaseId; + m->_collectionId = collectionId; + m->_indexId = indexId; + + storeSizedString(sizeof(index_create_marker_t), properties); + +#ifdef DEBUG_WAL + dump(); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroy marker +//////////////////////////////////////////////////////////////////////////////// + +CreateIndexMarker::~CreateIndexMarker () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief dump marker +//////////////////////////////////////////////////////////////////////////////// + +#ifdef DEBUG_WAL +void CreateIndexMarker::dump () const { + index_create_marker_t* m = reinterpret_cast(begin()); + + std::cout << "WAL CREATE INDEX MARKER FOR DB " << m->_databaseId + << ", COLLECTION " << m->_collectionId + << ", INDEX " << m->_indexId + << ", PROPERTIES " << properties() + << ", SIZE: " << size() + << "\n"; + +#ifdef DEBUG_WAL_DETAIL + dumpBinary(); +#endif +} +#endif + +// ----------------------------------------------------------------------------- +// --SECTION-- DropIndexMarker +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create marker +//////////////////////////////////////////////////////////////////////////////// + +DropIndexMarker::DropIndexMarker (TRI_voc_tick_t databaseId, + TRI_voc_cid_t collectionId, + TRI_idx_iid_t indexId) + : Marker(TRI_WAL_MARKER_DROP_INDEX, sizeof(index_drop_marker_t)) { + + index_drop_marker_t* m = reinterpret_cast(begin()); + + m->_databaseId = databaseId; + m->_collectionId = collectionId; + m->_indexId = indexId; + +#ifdef DEBUG_WAL + dump(); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroy marker +//////////////////////////////////////////////////////////////////////////////// + +DropIndexMarker::~DropIndexMarker () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief dump marker +//////////////////////////////////////////////////////////////////////////////// + +#ifdef DEBUG_WAL +void DropIndexMarker::dump () const { + index_drop_marker_t* m = reinterpret_cast(begin()); + + std::cout << "WAL DROP INDEX MARKER FOR DB " << m->_databaseId + << ", COLLECTION " << m->_collectionId + << ", INDEX " << m->_indexId + << ", SIZE: " << size() + << "\n"; + +#ifdef DEBUG_WAL_DETAIL + dumpBinary(); +#endif +} +#endif + // ----------------------------------------------------------------------------- // --SECTION-- BeginTransactionMarker // ----------------------------------------------------------------------------- @@ -807,7 +921,7 @@ void DocumentMarker::dump () const { std::cout << "WAL DOCUMENT MARKER FOR DB " << m->_databaseId << ", COLLECTION " << m->_collectionId - << ", REV: " << m->_rid + << ", REV: " << m->_revisionId << ", TRX: " << m->_transactionId << ", KEY: " << key() << ", OFFSETKEY: " << m->_offsetKey @@ -946,8 +1060,8 @@ void EdgeMarker::dump () const { std::cout << "WAL EDGE MARKER FOR DB " << m->_databaseId << ", COLLECTION " << m->_collectionId - << ", REV: " << rid() - << ", TRX: " << tid() + << ", REV: " << m->_revisionId + << ", TRX: " << m->_transactionId << ", KEY: " << key() << ", FROMCID " << m->_fromCid << ", TOCID " << m->_toCid @@ -1076,7 +1190,7 @@ void RemoveMarker::dump () const { std::cout << "WAL REMOVE MARKER FOR DB " << m->_databaseId << ", COLLECTION " << m->_collectionId - << ", REV: " << m->_rid + << ", REV: " << m->_revisionId << ", TRX: " << m->_transactionId << ", KEY: " << key() << "\n"; diff --git a/arangod/Wal/Marker.h b/arangod/Wal/Marker.h index 8475dc552f..218b1847c8 100644 --- a/arangod/Wal/Marker.h +++ b/arangod/Wal/Marker.h @@ -123,6 +123,27 @@ namespace triagens { // char* properties }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief wal create index marker +//////////////////////////////////////////////////////////////////////////////// + + struct index_create_marker_t : TRI_df_marker_t { + TRI_voc_tick_t _databaseId; + TRI_voc_cid_t _collectionId; + TRI_idx_iid_t _indexId; + // char* properties + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief wal drop index marker +//////////////////////////////////////////////////////////////////////////////// + + struct index_drop_marker_t : TRI_df_marker_t { + TRI_voc_tick_t _databaseId; + TRI_voc_cid_t _collectionId; + TRI_idx_iid_t _indexId; + }; + //////////////////////////////////////////////////////////////////////////////// /// @brief wal transaction begin marker //////////////////////////////////////////////////////////////////////////////// @@ -502,6 +523,50 @@ namespace triagens { void dump () const; }; +// ----------------------------------------------------------------------------- +// --SECTION-- CreateIndexMarker +// ----------------------------------------------------------------------------- + + class CreateIndexMarker : public Marker { + + public: + + CreateIndexMarker (TRI_voc_tick_t, + TRI_voc_cid_t, + TRI_idx_iid_t, + std::string const&); + + ~CreateIndexMarker (); + + public: + + inline char* properties () const { + return begin() + sizeof(index_create_marker_t); + } + + void dump () const; + }; + + +// ----------------------------------------------------------------------------- +// --SECTION-- DropIndexMarker +// ----------------------------------------------------------------------------- + + class DropIndexMarker : public Marker { + + public: + + DropIndexMarker (TRI_voc_tick_t, + TRI_voc_cid_t, + TRI_idx_iid_t); + + ~DropIndexMarker (); + + public: + + void dump () const; + }; + // ----------------------------------------------------------------------------- // --SECTION-- BeginTransactionMarker // ----------------------------------------------------------------------------- diff --git a/js/common/tests/shell-edge.js b/js/common/tests/shell-edge.js index f2b82ba2e3..56e8270f0e 100644 --- a/js/common/tests/shell-edge.js +++ b/js/common/tests/shell-edge.js @@ -34,6 +34,7 @@ var ArangoCollection = arangodb.ArangoCollection; var db = arangodb.db; var ERRORS = arangodb.errors; var wait = require("internal").wait; +var testHelper = require("org/arangodb/test-helper").Helper; // ----------------------------------------------------------------------------- // --SECTION-- collection methods @@ -253,20 +254,17 @@ function CollectionEdgeSuite () { assertEqual("vx2", k2._key); assertEqual(vn + "/vx2", k2._id); - vertex.unload(); - edge.unload(); - - console.log("waiting for collections to unload"); - wait(4); + testHelper.waitUnload(vertex); + testHelper.waitUnload(edge); var e1 = edge.save(vn + "/vx1", vn + "/vx2", { _key: "ex1", connect: "vx1->vx2" }); var e2 = edge.save(vn + "/vx2", vn + "/vx1", { _key: "ex2", connect: "vx2->vx1" }); + testHelper.waitUnload(vertex); + testHelper.waitUnload(edge); vertex.unload(); edge.unload(); - console.log("waiting for collections to unload"); - wait(4); var e3 = edge.save(k1, k2, { _key: "ex3", connect: "vx1->vx2" }); d1 = edge.document("ex1"); diff --git a/js/server/version-check.js b/js/server/version-check.js index 3c2b50f3aa..80e8b3b84d 100755 --- a/js/server/version-check.js +++ b/js/server/version-check.js @@ -62,6 +62,9 @@ error: function (msg) { console.error("In database '%s': %s", db._name(), msg); }, + warn: function (msg) { + console.warn("In database '%s': %s", db._name(), msg); + }, log: function (msg) { this.info(msg); }