1
0
Fork 0

WAL DDL markers

This commit is contained in:
Jan Steemann 2014-06-19 14:33:38 +02:00
parent d266bedd38
commit 6c0dcf85c4
17 changed files with 635 additions and 918 deletions

View File

@ -50,17 +50,6 @@ static void DestroyElement (TRI_hash_array_t* array,
element->_document = nullptr; 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 /// @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; 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) { 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); TRI_ASSERT_EXPENSIVE(i < n);
@ -572,9 +561,9 @@ int TRI_InsertElementHashArrayMulti (TRI_hash_array_t* array,
i = k = HashElement(array, element) % n; 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) { 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); TRI_ASSERT_EXPENSIVE(i < n);
@ -625,9 +614,9 @@ int TRI_RemoveElementHashArrayMulti (TRI_hash_array_t* array,
i = k = HashElement(array, element) % n; 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) { 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); TRI_ASSERT_EXPENSIVE(i < n);

View File

@ -6730,11 +6730,30 @@ static v8::Handle<v8::Value> JS_PropertiesVocbaseCol (v8::Arguments const& argv)
} }
TRI_json_t* json = TRI_CreateJsonCollectionInfo(&base->_info); TRI_json_t* json = TRI_CreateJsonCollectionInfo(&base->_info);
TRI_LogChangePropertiesCollectionReplication(base->_vocbase,
base->_info._cid, // now log the property changes
base->_info._name, res = TRI_ERROR_NO_ERROR;
json,
TRI_GetIdServer()); 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); TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
} }
} }

View File

@ -1141,6 +1141,10 @@ char const* TRI_NameMarkerDatafile (TRI_df_marker_t const* marker) {
return "rename collection (wal)"; return "rename collection (wal)";
case TRI_WAL_MARKER_CHANGE_COLLECTION: case TRI_WAL_MARKER_CHANGE_COLLECTION:
return "change collection (wal)"; 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: case TRI_WAL_MARKER_CREATE_DATABASE:
return "create database (wal)"; return "create database (wal)";
case TRI_WAL_MARKER_DROP_DATABASE: case TRI_WAL_MARKER_DROP_DATABASE:

View File

@ -171,6 +171,8 @@ typedef enum {
TRI_WAL_MARKER_DROP_COLLECTION = 4031, TRI_WAL_MARKER_DROP_COLLECTION = 4031,
TRI_WAL_MARKER_RENAME_COLLECTION = 4032, TRI_WAL_MARKER_RENAME_COLLECTION = 4032,
TRI_WAL_MARKER_CHANGE_COLLECTION = 4033, 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_CREATE_DATABASE = 4040,
TRI_WAL_MARKER_DROP_DATABASE = 4041, TRI_WAL_MARKER_DROP_DATABASE = 4041,

View File

@ -232,16 +232,12 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document,
if (document->_info._isVolatile) { if (document->_info._isVolatile) {
// in-memory collection // in-memory collection
journal = TRI_CreateDatafile(NULL, fid, maximalSize, true); journal = TRI_CreateDatafile(nullptr, fid, maximalSize, true);
} }
else { else {
char* jname; char* number = TRI_StringUInt64(fid);
char* number; char* jname = TRI_Concatenate3String("compaction-", number, ".db");
char* filename; char* filename = TRI_Concatenate2File(document->_directory, jname);
number = TRI_StringUInt64(fid);
jname = TRI_Concatenate3String("compaction-", number, ".db");
filename = TRI_Concatenate2File(document->_directory, jname);
TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, number);
TRI_FreeString(TRI_CORE_MEM_ZONE, jname); 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); TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
} }
if (journal == NULL) { if (journal == nullptr) {
if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) { if (TRI_errno() == TRI_ERROR_OUT_OF_MEMORY_MMAP) {
document->_lastError = TRI_set_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); document->_lastError = TRI_set_errno(TRI_ERROR_ARANGO_NO_JOURNAL);
} }
return NULL; return nullptr;
} }
LOG_TRACE("created new compactor '%s'", journal->getName(journal)); 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); TRI_FreeDatafile(journal);
return NULL; return nullptr;
} }
@ -297,7 +293,7 @@ static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document,
TRI_FreeDatafile(journal); TRI_FreeDatafile(journal);
return NULL; return nullptr;
} }
TRI_ASSERT(fid == journal->_fid); 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) { static void RebuildIndexInfo (TRI_document_collection_t* document) {
bool result = false; bool result = false;
size_t const n = document->_allIndexes._length; size_t const n = document->_allIndexes._length;
for (size_t i = 0 ; i < n ; ++i) { 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<TRI_index_t*>(document->_allIndexes._buffer[i]);
if (idx->cleanup != nullptr) { if (idx->cleanup != nullptr) {
result = true; result = true;
@ -2181,13 +2177,8 @@ static int IterateMarkersCollection (TRI_collection_t* collection) {
TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase, TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
char const* path, char const* path,
TRI_col_info_t* parameter, TRI_col_info_t* parameters,
TRI_voc_cid_t cid) { TRI_voc_cid_t cid) {
TRI_collection_t* collection;
TRI_shaper_t* shaper;
TRI_document_collection_t* document;
int res;
if (cid > 0) { if (cid > 0) {
TRI_UpdateTickServer(cid); TRI_UpdateTickServer(cid);
} }
@ -2195,10 +2186,10 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
cid = TRI_NewTickServer(); cid = TRI_NewTickServer();
} }
parameter->_cid = cid; parameters->_cid = cid;
// check if we can generate the key generator // check if we can generate the key generator
KeyGenerator* keyGenerator = KeyGenerator::factory(parameter->_keyOptions); KeyGenerator* keyGenerator = KeyGenerator::factory(parameters->_keyOptions);
if (keyGenerator == nullptr) { if (keyGenerator == nullptr) {
TRI_set_errno(TRI_ERROR_ARANGO_INVALID_KEY_GENERATOR); 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 // first create the document collection
TRI_document_collection_t* document;
try { try {
document = new TRI_document_collection_t(); document = new TRI_document_collection_t();
} }
@ -2222,7 +2214,8 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
} }
document->_keyGenerator = keyGenerator; document->_keyGenerator = keyGenerator;
collection = TRI_CreateCollection(vocbase, document, path, parameter);
TRI_collection_t* collection = TRI_CreateCollection(vocbase, document, path, parameters);
if (collection == nullptr) { if (collection == nullptr) {
delete document; delete document;
@ -2231,9 +2224,9 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
return nullptr; 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"); LOG_ERROR("cannot create shaper");
TRI_CloseCollection(collection); TRI_CloseCollection(collection);
@ -2256,7 +2249,7 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
document->_keyGenerator = keyGenerator; document->_keyGenerator = keyGenerator;
// save the parameter block (within create, no need to lock) // 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) { if (res != TRI_ERROR_NO_ERROR) {
// TODO: shouldn't we destroy &document->_allIndexes, free document->_headersPtr etc.? // 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, int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
TRI_json_t const* json, TRI_json_t const* json,
TRI_index_t** idx) { TRI_index_t** idx) {
TRI_json_t const* type; TRI_ASSERT(json != nullptr);
TRI_json_t const* iis;
char const* typeStr;
TRI_idx_iid_t iid;
TRI_ASSERT(json != NULL);
TRI_ASSERT(json->_type == TRI_JSON_ARRAY); TRI_ASSERT(json->_type == TRI_JSON_ARRAY);
if (idx != NULL) { if (idx != nullptr) {
*idx = NULL; *idx = nullptr;
} }
// extract the type // extract the type
type = TRI_LookupArrayJson(json, "type"); TRI_json_t const* type = TRI_LookupArrayJson(json, "type");
if (! TRI_IsStringJson(type)) { if (! TRI_IsStringJson(type)) {
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
typeStr = type->_value._string.data; char const* typeStr = type->_value._string.data;
// extract the index identifier // 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; iid = (TRI_idx_iid_t) iis->_value._number;
} }
else if (TRI_IsStringJson(iis)) { else if (TRI_IsStringJson(iis)) {
@ -2603,9 +2592,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
if (TRI_EqualString(typeStr, "cap")) { if (TRI_EqualString(typeStr, "cap")) {
int res = CapConstraintFromJson(document, json, iid, idx); return CapConstraintFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2613,9 +2600,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
else if (TRI_EqualString(typeStr, "bitarray")) { else if (TRI_EqualString(typeStr, "bitarray")) {
int res = BitarrayIndexFromJson(document, json, iid, idx); return BitarrayIndexFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2623,9 +2608,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
else if (TRI_EqualString(typeStr, "geo1") || TRI_EqualString(typeStr, "geo2")) { else if (TRI_EqualString(typeStr, "geo1") || TRI_EqualString(typeStr, "geo2")) {
int res = GeoIndexFromJson(document, json, iid, idx); return GeoIndexFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2633,9 +2616,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
else if (TRI_EqualString(typeStr, "hash")) { else if (TRI_EqualString(typeStr, "hash")) {
int res = HashIndexFromJson(document, json, iid, idx); return HashIndexFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2643,9 +2624,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
else if (TRI_EqualString(typeStr, "skiplist")) { else if (TRI_EqualString(typeStr, "skiplist")) {
int res = SkiplistIndexFromJson(document, json, iid, idx); return SkiplistIndexFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2653,9 +2632,7 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
// ........................................................................... // ...........................................................................
else if (TRI_EqualString(typeStr, "fulltext")) { else if (TRI_EqualString(typeStr, "fulltext")) {
int res = FulltextIndexFromJson(document, json, iid, idx); return FulltextIndexFromJson(document, json, iid, idx);
return res;
} }
// ........................................................................... // ...........................................................................
@ -2665,8 +2642,6 @@ int TRI_FromJsonIndexDocumentCollection (TRI_document_collection_t* document,
else if (TRI_EqualString(typeStr, "edge")) { else if (TRI_EqualString(typeStr, "edge")) {
// we should never get here, as users cannot create their own edge indexes // 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"); 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", LOG_ERROR("ignoring unknown index type '%s' for index %llu",
typeStr, typeStr,
(unsigned long long) iid); (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_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase,
TRI_vocbase_col_t* col) { TRI_vocbase_col_t* col) {
TRI_collection_t* collection;
TRI_shaper_t* shaper;
int res;
char const* path = col->_path; char const* path = col->_path;
// first open the document collection // first open the document collection
@ -2757,7 +2728,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase,
return nullptr; return nullptr;
} }
collection = TRI_OpenCollection(vocbase, document, path); TRI_collection_t* collection = TRI_OpenCollection(vocbase, document, path);
if (collection == nullptr) { if (collection == nullptr) {
delete document; delete document;
@ -2766,7 +2737,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase,
return nullptr; return nullptr;
} }
shaper = TRI_CreateVocShaper(vocbase, document); TRI_shaper_t* shaper = TRI_CreateVocShaper(vocbase, document);
if (shaper == nullptr) { if (shaper == nullptr) {
LOG_ERROR("cannot create shaper"); LOG_ERROR("cannot create shaper");
@ -2803,7 +2774,7 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase,
TransactionBase trx(true); TransactionBase trx(true);
// iterate over all markers of the collection // iterate over all markers of the collection
res = IterateMarkersCollection(collection); int res = IterateMarkersCollection(collection);
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
if (document->_failedTransactions != nullptr) { if (document->_failedTransactions != nullptr) {
@ -2880,28 +2851,25 @@ pid_name_t;
static TRI_json_t* ExtractFields (TRI_json_t const* json, static TRI_json_t* ExtractFields (TRI_json_t const* json,
size_t* fieldCount, size_t* fieldCount,
TRI_idx_iid_t iid) { TRI_idx_iid_t iid) {
TRI_json_t* fld; TRI_json_t* fld = TRI_LookupArrayJson(json, "fields");
size_t j;
fld = TRI_LookupArrayJson(json, "fields"); if (! TRI_IsListJson(fld)) {
if (fld == NULL || fld->_type != TRI_JSON_LIST) {
LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid); LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid);
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); TRI_set_errno(TRI_ERROR_BAD_PARAMETER);
return NULL; return nullptr;
} }
*fieldCount = fld->_value._objects._length; *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_json_t*>(TRI_AtVector(&fld->_value._objects, j)); TRI_json_t* sub = static_cast<TRI_json_t*>(TRI_AtVector(&fld->_value._objects, j));
if (! TRI_IsStringJson(sub)) { if (! TRI_IsStringJson(sub)) {
LOG_ERROR("ignoring index %llu, 'fields' must be a list of attribute paths", (unsigned long long) iid); LOG_ERROR("ignoring index %llu, 'fields' must be a list of attribute paths", (unsigned long long) iid);
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); 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, static TRI_json_t* ExtractFieldValues (TRI_json_t const* jsonIndex,
size_t* fieldCount, size_t* fieldCount,
TRI_idx_iid_t iid) { TRI_idx_iid_t iid) {
TRI_json_t* keyValues; TRI_json_t* keyValues = TRI_LookupArrayJson(jsonIndex, "fields");
size_t j;
keyValues = TRI_LookupArrayJson(jsonIndex, "fields"); if (! TRI_IsListJson(keyValues)) {
if (keyValues == NULL || keyValues->_type != TRI_JSON_LIST) {
LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid); LOG_ERROR("ignoring index %llu, 'fields' must be a list", (unsigned long long) iid);
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); 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 // Some simple checks
// ........................................................................... // ...........................................................................
for (j = 0; j < *fieldCount; ++j) { for (size_t j = 0; j < *fieldCount; ++j) {
// ......................................................................... // .........................................................................
// Extract the jth key value pair // 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 // 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); 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); 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)) { if (! TRI_IsStringJson(key)) {
LOG_ERROR("ignoring index %llu, key in 'fields' pair must be an attribute (string)", (unsigned long long) iid); 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); 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_json_t*>(TRI_AtVector(&keyValue->_value._objects, 1)); TRI_json_t* value = static_cast<TRI_json_t*>(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); LOG_ERROR("ignoring index %llu, value in 'fields' pair must be a list ([...])", (unsigned long long) iid);
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); 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; 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<TRI_index_t*>(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_index_t*>(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 /// @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, TRI_idx_type_e type,
bool unique, bool unique,
bool allowAnyAttributeOrder) { bool allowAnyAttributeOrder) {
TRI_vector_t* indexPaths = NULL; TRI_vector_t* indexPaths = nullptr;
size_t j;
// ........................................................................... // ...........................................................................
// go through every index and see if we have a match // 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<TRI_index_t*>(collection->_allIndexes._buffer[j]); TRI_index_t* idx = static_cast<TRI_index_t*>(collection->_allIndexes._buffer[j]);
bool found;
size_t k;
// ......................................................................... // .........................................................................
// check if the type of the index matches // check if the type of the index matches
// ......................................................................... // .........................................................................
if (idx->_type != type) { if (idx->_type != type || idx->_unique != unique) {
continue;
}
// .........................................................................
// check if uniqueness matches
// .........................................................................
if (idx->_unique != unique) {
continue; 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 // 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 // go through all the attributes and see if they match
// ......................................................................... // .........................................................................
found = true; bool found = true;
if (allowAnyAttributeOrder) { if (allowAnyAttributeOrder) {
// any permutation of attributes is allowed // 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)); TRI_shape_pid_t indexShape = *((TRI_shape_pid_t*) TRI_AtVector(indexPaths, k));
size_t l;
found = false; 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)); TRI_shape_pid_t givenShape = *((TRI_shape_pid_t*) TRI_AtVector(paths, l));
if (indexShape == givenShape) { if (indexShape == givenShape) {
@ -3226,7 +3101,7 @@ static TRI_index_t* LookupPathIndexDocumentCollection (TRI_document_collection_t
} }
else { else {
// attributes need to present in a given order // 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 indexShape = *((TRI_shape_pid_t*) TRI_AtVector(indexPaths, k));
TRI_shape_pid_t givenShape = *((TRI_shape_pid_t*) TRI_AtVector(paths, 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,
bool*), bool*),
TRI_index_t** dst) { TRI_index_t** dst) {
TRI_index_t* idx;
TRI_json_t* bv; TRI_json_t* bv;
TRI_json_t* fld;
TRI_vector_pointer_t attributes; TRI_vector_pointer_t attributes;
bool unique; bool unique;
size_t fieldCount; size_t fieldCount;
size_t j;
if (dst != NULL) { if (dst != nullptr) {
*dst = NULL; *dst = nullptr;
} }
// extract fields // extract fields
fld = ExtractFields(definition, &fieldCount, iid); TRI_json_t* fld = ExtractFields(definition, &fieldCount, iid);
if (fld == NULL) { if (fld == nullptr) {
return TRI_errno(); 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 // determine if the hash index is unique or non-unique
bv = TRI_LookupArrayJson(definition, "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); 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); 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); TRI_InitVectorPointer(&attributes, TRI_CORE_MEM_ZONE);
// find fields // find fields
for (j = 0; j < fieldCount; ++j) { for (size_t j = 0; j < fieldCount; ++j) {
TRI_json_t* fieldStr = static_cast<TRI_json_t*>(TRI_AtVector(&fld->_value._objects, j)); TRI_json_t* fieldStr = static_cast<TRI_json_t*>(TRI_AtVector(&fld->_value._objects, j));
TRI_PushBackVectorPointer(&attributes, fieldStr->_value._string.data); TRI_PushBackVectorPointer(&attributes, fieldStr->_value._string.data);
} }
// create the index // 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; *dst = idx;
} }
// cleanup // cleanup
TRI_DestroyVectorPointer(&attributes); TRI_DestroyVectorPointer(&attributes);
if (idx == NULL) { if (idx == nullptr) {
LOG_ERROR("cannot create hash index %llu", (unsigned long long) iid); LOG_ERROR("cannot create index %llu", (unsigned long long) iid);
return TRI_errno(); 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, bool TRI_DropIndexDocumentCollection (TRI_document_collection_t* document,
TRI_idx_iid_t iid, TRI_idx_iid_t iid,
TRI_server_id_t generatingServer) { TRI_server_id_t generatingServer) {
return DropIndex(document, iid, generatingServer, true); if (iid == 0) {
} // invalid index id or primary index
return true;
}
//////////////////////////////////////////////////////////////////////////////// TRI_index_t* found = nullptr;
/// @brief drops an index, without index file removal and replication TRI_vocbase_t* vocbase = document->_vocbase;
////////////////////////////////////////////////////////////////////////////////
bool TRI_DropIndex2DocumentCollection (TRI_document_collection_t* document, TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
TRI_idx_iid_t iid,
TRI_server_id_t generatingServer) { // .............................................................................
return DropIndex(document, iid, generatingServer, false); // 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<TRI_index_t*>(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_index_t*>(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 sorted,
bool create) { bool create) {
pid_name_t* pidnames; pid_name_t* pidnames;
size_t j;
// ............................................................................. // .............................................................................
// sorted case // sorted case
@ -3586,7 +3527,7 @@ static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes,
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); 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<char*>(attributes->_buffer[j]); pidnames[j]._name = static_cast<char*>(attributes->_buffer[j]);
if (create) { 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_InitVector(pids, TRI_CORE_MEM_ZONE, sizeof(TRI_shape_pid_t));
TRI_InitVectorPointer(names, TRI_CORE_MEM_ZONE); 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_PushBackVector(pids, &pidnames[j]._pid);
TRI_PushBackVectorPointer(names, pidnames[j]._name); 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_InitVector(pids, TRI_CORE_MEM_ZONE, sizeof(TRI_shape_pid_t));
TRI_InitVectorPointer(names, TRI_CORE_MEM_ZONE); 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<char*>(attributes->_buffer[j]); char* name = static_cast<char*>(attributes->_buffer[j]);
TRI_shape_pid_t pid; TRI_shape_pid_t pid;
@ -3732,34 +3673,29 @@ static int CapConstraintFromJson (TRI_document_collection_t* document,
TRI_json_t const* definition, TRI_json_t const* definition,
TRI_idx_iid_t iid, TRI_idx_iid_t iid,
TRI_index_t** dst) { TRI_index_t** dst) {
TRI_json_t* val1;
TRI_json_t* val2;
TRI_index_t* idx; TRI_index_t* idx;
size_t count;
int64_t size;
if (dst != NULL) { if (dst != nullptr) {
*dst = NULL; *dst = nullptr;
} }
val1 = TRI_LookupArrayJson(definition, "size"); TRI_json_t* val1 = TRI_LookupArrayJson(definition, "size");
val2 = TRI_LookupArrayJson(definition, "byteSize"); TRI_json_t* val2 = TRI_LookupArrayJson(definition, "byteSize");
if ((val1 == NULL || val1->_type != TRI_JSON_NUMBER) && if (! TRI_IsNumberJson(val1) && ! TRI_IsNumberJson(val2)) {
(val2 == NULL || val2->_type != TRI_JSON_NUMBER)) {
LOG_ERROR("ignoring cap constraint %llu, 'size' and 'byteSize' missing", LOG_ERROR("ignoring cap constraint %llu, 'size' and 'byteSize' missing",
(unsigned long long) iid); (unsigned long long) iid);
return TRI_set_errno(TRI_ERROR_BAD_PARAMETER); return TRI_set_errno(TRI_ERROR_BAD_PARAMETER);
} }
count = 0; size_t count = 0;
if (val1 != NULL && val1->_value._number > 0.0) { if (TRI_IsNumberJson(val1) && val1->_value._number > 0.0) {
count = (size_t) val1->_value._number; count = (size_t) val1->_value._number;
} }
size = 0; int64_t size = 0;
if (val2 != NULL && val2->_value._number > (double) TRI_CAP_CONSTRAINT_MIN_SIZE) { if (TRI_IsNumberJson(val2) && val2->_value._number > (double) TRI_CAP_CONSTRAINT_MIN_SIZE) {
size = (int64_t) val2->_value._number; 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); return TRI_set_errno(TRI_ERROR_BAD_PARAMETER);
} }
idx = CreateCapConstraintDocumentCollection(document, count, size, iid, NULL); idx = CreateCapConstraintDocumentCollection(document, count, size, iid, nullptr);
if (dst != NULL) { if (dst != nullptr) {
*dst = idx; *dst = idx;
} }
return idx == NULL ? TRI_errno() : TRI_ERROR_NO_ERROR; return idx == nullptr ? TRI_errno() : TRI_ERROR_NO_ERROR;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -771,14 +771,6 @@ bool TRI_DropIndexDocumentCollection (TRI_document_collection_t*,
TRI_idx_iid_t, TRI_idx_iid_t,
TRI_server_id_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 // --SECTION-- CAP CONSTRAINT
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -37,7 +37,7 @@
#include "BasicsC/tri-strings.h" #include "BasicsC/tri-strings.h"
#include "BasicsC/utf8-helper.h" #include "BasicsC/utf8-helper.h"
#include "BasicsC/fasthash.h" #include "BasicsC/fasthash.h"
#include "BasicsC/xxhash.h" #include "Basics/JsonHelper.h"
#include "CapConstraint/cap-constraint.h" #include "CapConstraint/cap-constraint.h"
#include "GeoIndex/geo-index.h" #include "GeoIndex/geo-index.h"
#include "FulltextIndex/fulltext-index.h" #include "FulltextIndex/fulltext-index.h"
@ -46,11 +46,14 @@
#include "HashIndex/hash-index.h" #include "HashIndex/hash-index.h"
#include "ShapedJson/shape-accessor.h" #include "ShapedJson/shape-accessor.h"
#include "ShapedJson/shaped-json.h" #include "ShapedJson/shaped-json.h"
#include "Utils/Exception.h"
#include "VocBase/document-collection.h" #include "VocBase/document-collection.h"
#include "VocBase/edge-collection.h" #include "VocBase/edge-collection.h"
#include "VocBase/replication-logger.h" #include "VocBase/replication-logger.h"
#include "VocBase/server.h" #include "VocBase/server.h"
#include "VocBase/voc-shaper.h" #include "VocBase/voc-shaper.h"
#include "Wal/LogfileManager.h"
#include "Wal/Marker.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- INDEX // --SECTION-- INDEX
@ -117,8 +120,7 @@ bool TRI_NeedsFullCoverageIndex (TRI_idx_type_e type) {
case TRI_IDX_TYPE_CAP_CONSTRAINT: case TRI_IDX_TYPE_CAP_CONSTRAINT:
return true; return true;
case TRI_IDX_TYPE_BITARRAY_INDEX: case TRI_IDX_TYPE_BITARRAY_INDEX:
return false; case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX: // removed
case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX:
case TRI_IDX_TYPE_UNKNOWN: case TRI_IDX_TYPE_UNKNOWN:
return false; 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) { bool TRI_RemoveIndexFile (TRI_document_collection_t* collection, TRI_index_t* idx) {
char* filename;
char* name;
char* number;
int res;
// construct filename // 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); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
LOG_ERROR("out of memory when creating index number"); LOG_ERROR("out of memory when creating index number");
return false; 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_set_errno(TRI_ERROR_OUT_OF_MEMORY);
TRI_FreeString(TRI_CORE_MEM_ZONE, number); 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; 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_set_errno(TRI_ERROR_OUT_OF_MEMORY);
TRI_FreeString(TRI_CORE_MEM_ZONE, number); 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, name);
TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, number);
res = TRI_UnlinkFile(filename); int res = TRI_UnlinkFile(filename);
TRI_FreeString(TRI_CORE_MEM_ZONE, filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
if (res != TRI_ERROR_NO_ERROR) { 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, int TRI_SaveIndex (TRI_document_collection_t* document,
TRI_index_t* idx, TRI_index_t* idx,
TRI_server_id_t generatingServer) { TRI_server_id_t generatingServer) {
TRI_json_t* json;
TRI_vocbase_t* vocbase;
char* filename;
char* name;
char* number;
bool ok;
// convert into JSON // 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"); LOG_TRACE("cannot save index definition: index cannot be jsonified");
return TRI_set_errno(TRI_ERROR_INTERNAL); return TRI_set_errno(TRI_ERROR_INTERNAL);
} }
// construct filename // construct filename
number = TRI_StringUInt64(idx->_iid); char* number = TRI_StringUInt64(idx->_iid);
name = TRI_Concatenate3String("index-", number, ".json"); char* name = TRI_Concatenate3String("index-", number, ".json");
filename = TRI_Concatenate2File(document->_directory, name); char* filename = TRI_Concatenate2File(document->_directory, name);
TRI_FreeString(TRI_CORE_MEM_ZONE, name); TRI_FreeString(TRI_CORE_MEM_ZONE, name);
TRI_FreeString(TRI_CORE_MEM_ZONE, number); TRI_FreeString(TRI_CORE_MEM_ZONE, number);
vocbase = document->_vocbase; TRI_vocbase_t* vocbase = document->_vocbase;
// and save // 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); TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
@ -410,16 +400,29 @@ int TRI_SaveIndex (TRI_document_collection_t* document,
return TRI_errno(); return TRI_errno();
} }
// it is safe to use _name as we hold a read-lock on the collection status int res = TRI_ERROR_NO_ERROR;
TRI_LogCreateIndexReplication(vocbase,
document->_info._cid, try {
document->_info._name, triagens::wal::CreateIndexMarker marker(vocbase->_id, document->_info._cid, idx->_iid, triagens::basics::JsonHelper::toString(json));
idx->_iid, triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker, false);
json,
generatingServer); 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); TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
// TODO: what to do here?
return TRI_ERROR_NO_ERROR; 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_index_t* TRI_LookupIndex (TRI_document_collection_t* document,
TRI_idx_iid_t iid) { 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<TRI_index_t*>(document->_allIndexes._buffer[i]); TRI_index_t* idx = static_cast<TRI_index_t*>(document->_allIndexes._buffer[i]);
if (idx->_iid == iid) { 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); 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); json = TRI_CreateArrayJson(zone);
if (json != NULL) { if (json != nullptr) {
char* number; char* number;
number = TRI_StringUInt64(idx->_iid); 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) { void TRI_DestroyIndexResult (TRI_index_result_t* result) {
if (result->_documents != NULL) { if (result->_documents != nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, result->_documents); 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) { 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)); 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_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(src,j)));
TRI_PushBackVector(dst, &shape); 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_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(paths, j)));
TRI_shape_path_t const* path = shaper->lookupAttributePathByPid(const_cast<TRI_shaper_t*>(shaper), shape); TRI_shape_path_t const* path = shaper->lookupAttributePathByPid(const_cast<TRI_shaper_t*>(shaper), shape);
if (path == NULL) { if (path == nullptr) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
TRI_Free(TRI_CORE_MEM_ZONE, (void*) fieldList); 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); 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) { void TRI_DestroyEdgeIndex (TRI_index_t* idx) {
TRI_edge_index_t* edgesIndex; TRI_edge_index_t* edgesIndex = (TRI_edge_index_t*) idx;
edgesIndex = (TRI_edge_index_t*) idx;
LOG_TRACE("destroying edge index"); 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->_numFields = relationOperator->_parameters->_value._objects._length;
relationOperator->_fields = static_cast<TRI_shaped_json_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_shaped_json_t) * relationOperator->_numFields, false)); relationOperator->_fields = static_cast<TRI_shaped_json_t*>(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) { for (size_t j = 0; j < relationOperator->_numFields; ++j) {
TRI_json_t* jsonObject = (TRI_json_t*) TRI_AtVector(&(relationOperator->_parameters->_value._objects), 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 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 relationOperator->_fields[j] = *shapedObject; // shallow copy here is ok
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shapedObject); // don't require storage anymore 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_shaped_json_t shapedJson;
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->getDataPtr()); // ONLY IN INDEX, PROTECTED by RUNTIME 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"); LOG_WARNING("encountered invalid marker with shape id 0");
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
@ -1382,7 +1383,7 @@ static TRI_json_t* JsonSkiplistIndex (TRI_index_t const* idx) {
if (path == nullptr) { if (path == nullptr) {
TRI_Free(TRI_CORE_MEM_ZONE, (void*) fieldList); 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); 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); errorResult = FillLookupBitarrayOperator(indexOperator, baIndex->base._collection);
if (errorResult != TRI_ERROR_NO_ERROR) { if (errorResult != TRI_ERROR_NO_ERROR) {
return NULL; return nullptr;
} }
iteratorResult = BitarrayIndex_find(baIndex->_bitarrayIndex, iteratorResult = BitarrayIndex_find(baIndex->_bitarrayIndex,
indexOperator, indexOperator,
&baIndex->_paths, &baIndex->_paths,
baIndex, baIndex,
NULL); nullptr);
TRI_FreeIndexOperator(indexOperator); TRI_FreeIndexOperator(indexOperator);

View File

@ -213,9 +213,10 @@ static void FreeCap (TRI_replication_logger_t* logger) {
TRI_document_collection_t* document = logger->_trxCollection->_collection->_collection; TRI_document_collection_t* document = logger->_trxCollection->_collection->_collection;
TRI_ASSERT(document != NULL); TRI_ASSERT(document != NULL);
TRI_DropIndex2DocumentCollection(document, // TODO: this wont work anymore - remove function altogether
logger->_cap->_iid, TRI_DropIndexDocumentCollection(document,
TRI_GetIdServer()); logger->_cap->_iid,
TRI_GetIdServer());
logger->_cap = NULL; logger->_cap = NULL;
} }
@ -468,26 +469,6 @@ static int LogEvent (TRI_replication_logger_t* logger,
return TRI_ERROR_NO_ERROR; 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 /// @brief stringify a "replication" operation with a tick
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -505,128 +486,6 @@ static bool StringifyTickReplication (TRI_string_buffer_t* buffer,
return true; 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 /// @brief get current state from the replication logger
/// note: must hold the lock when calling this /// 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; 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 /// @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; 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: // Local Variables:
// mode: outline-minor // mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"

View File

@ -199,70 +199,6 @@ struct TRI_json_s* TRI_JsonStateReplicationLogger (TRI_replication_logger_state_
struct TRI_json_s* TRI_JsonReplicationLogger (TRI_replication_logger_t*); 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 #endif
// Local Variables: // Local Variables:

View File

@ -36,6 +36,7 @@
#include "BasicsC/logging.h" #include "BasicsC/logging.h"
#include "BasicsC/tri-strings.h" #include "BasicsC/tri-strings.h"
#include "BasicsC/utf8-helper.h" #include "BasicsC/utf8-helper.h"
#include "Utils/Exception.h"
#include "VocBase/document-collection.h" #include "VocBase/document-collection.h"
#include "Wal/LogfileManager.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; 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 // lock the index and check that the element is still missing
{ {
MUTEX_LOCKER(s->_attributeLock); 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 the element appeared, return the aid
if (p != nullptr) { if (p != nullptr) {
return GetAttributeId(p); 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<void*>(slotInfo.mem), false);
TRI_ASSERT(f == nullptr);
// enter into the dictionaries
f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, const_cast<void*>(slotInfo.mem), false);
TRI_ASSERT(f == nullptr);
} }
// write marker into wal return aid;
triagens::wal::SlotInfoCopy slotInfo = triagens::wal::LogfileManager::instance()->allocateAndWrite(marker.mem(), marker.size(), false); }
catch (triagens::arango::Exception const& ex) {
if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { res = ex.code();
LOG_WARNING("could not save attribute marker in log: %s", TRI_errno_string(slotInfo.errorCode)); }
return 0; catch (...) {
} res = TRI_ERROR_INTERNAL;
void* f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast<void*>(slotInfo.mem), false);
TRI_ASSERT(f == nullptr);
// enter into the dictionaries
f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, const_cast<void*>(slotInfo.mem), false);
TRI_ASSERT(f == nullptr);
} }
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 // get next shape id
TRI_shape_sid_t const sid = s->_nextSid++; TRI_shape_sid_t const sid = s->_nextSid++;
shape->_sid = sid; 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); MUTEX_LOCKER(s->_shapeLock);
found = static_cast<TRI_shape_t const*>(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape)); found = static_cast<TRI_shape_t const*>(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape));
@ -341,26 +356,35 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
} }
// write marker into wal // 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) { if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) {
LOG_WARNING("could not save shape marker in log: %s", TRI_errno_string(slotInfo.errorCode)); THROW_ARANGO_EXCEPTION(slotInfo.errorCode);
return nullptr;
} }
char const* m = static_cast<char const*>(slotInfo.mem) + sizeof(triagens::wal::shape_marker_t); char const* m = static_cast<char const*>(slotInfo.mem) + sizeof(triagens::wal::shape_marker_t);
result = reinterpret_cast<TRI_shape_t const*>(m); TRI_shape_t const* result = reinterpret_cast<TRI_shape_t const*>(m);
void* f = TRI_InsertKeyAssociativeSynced(&s->_shapeIds, &sid, (void*) m, false); void* f = TRI_InsertKeyAssociativeSynced(&s->_shapeIds, &sid, (void*) m, false);
TRI_ASSERT(f == nullptr); TRI_ASSERT(f == nullptr);
f = TRI_InsertElementAssociativeSynced(&s->_shapeDictionary, (void*) m, false); f = TRI_InsertElementAssociativeSynced(&s->_shapeDictionary, (void*) m, false);
TRI_ASSERT(f == nullptr); 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); 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;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -43,6 +43,7 @@
#include "BasicsC/tri-strings.h" #include "BasicsC/tri-strings.h"
#include "BasicsC/threads.h" #include "BasicsC/threads.h"
#include "Utils/Exception.h"
#include "Utils/transactions.h" #include "Utils/transactions.h"
#include "VocBase/auth.h" #include "VocBase/auth.h"
#include "VocBase/barrier.h" #include "VocBase/barrier.h"
@ -55,6 +56,7 @@
#include "VocBase/server.h" #include "VocBase/server.h"
#include "VocBase/transaction.h" #include "VocBase/transaction.h"
#include "VocBase/vocbase-defaults.h" #include "VocBase/vocbase-defaults.h"
#include "Wal/LogfileManager.h"
#include "Ahuacatl/ahuacatl-functions.h" #include "Ahuacatl/ahuacatl-functions.h"
@ -187,15 +189,32 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase,
} }
// post-condition // 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_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
TRI_LogDropCollectionReplication(vocbase, int res = TRI_ERROR_NO_ERROR;
collection->_cid,
collection->_name,
generatingServer);
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; return true;
} }
@ -443,9 +462,6 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
char const* name, char const* name,
TRI_voc_cid_t cid, TRI_voc_cid_t cid,
char const* path) { char const* path) {
void const* found;
int res;
// create the init object // create the init object
TRI_vocbase_col_t init; TRI_vocbase_col_t init;
@ -455,7 +471,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
init._type = static_cast<TRI_col_type_t>(type); init._type = static_cast<TRI_col_type_t>(type);
init._status = TRI_VOC_COL_STATUS_CORRUPTED; init._status = TRI_VOC_COL_STATUS_CORRUPTED;
init._collection = NULL; init._collection = nullptr;
// default flags: everything is allowed // default flags: everything is allowed
init._canDrop = true; 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._dbName, vocbase->_name, strlen(vocbase->_name));
TRI_CopyString(init._name, name, sizeof(init._name) - 1); TRI_CopyString(init._name, name, sizeof(init._name) - 1);
if (path == NULL) { if (path == nullptr) {
init._path[0] = '\0'; init._path[0] = '\0';
} }
else { else {
@ -491,18 +507,19 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
// create a new proxy // create a new proxy
TRI_vocbase_col_t* collection = static_cast<TRI_vocbase_col_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vocbase_col_t), false)); TRI_vocbase_col_t* collection = static_cast<TRI_vocbase_col_t*>(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); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL; return nullptr;
} }
memcpy(collection, &init, sizeof(TRI_vocbase_col_t)); memcpy(collection, &init, sizeof(TRI_vocbase_col_t));
collection->_isLocal = true; collection->_isLocal = true;
// check name // 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("duplicate entry for collection name '%s'", name);
LOG_ERROR("collection id %llu has same name as already added collection %llu", LOG_ERROR("collection id %llu has same name as already added collection %llu",
(unsigned long long) cid, (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_Free(TRI_UNKNOWN_MEM_ZONE, collection);
TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_NAME); TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_NAME);
return NULL; return nullptr;
} }
if (res != TRI_ERROR_NO_ERROR) { 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_Free(TRI_UNKNOWN_MEM_ZONE, collection);
TRI_set_errno(res); TRI_set_errno(res);
return NULL; return nullptr;
} }
// check collection identifier // check collection identifier
TRI_ASSERT(collection->_cid == cid); TRI_ASSERT(collection->_cid == cid);
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found); res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found);
if (found != NULL) { if (found != nullptr) {
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name); TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
LOG_ERROR("duplicate collection identifier %llu for name '%s'", 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_Free(TRI_UNKNOWN_MEM_ZONE, collection);
TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_IDENTIFIER); TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_IDENTIFIER);
return NULL; return nullptr;
} }
if (res != TRI_ERROR_NO_ERROR) { 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_Free(TRI_UNKNOWN_MEM_ZONE, collection);
TRI_set_errno(res); 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); TRI_InitReadWriteLock(&collection->_lock);
@ -566,13 +583,7 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase,
TRI_col_info_t* parameter, TRI_col_info_t* parameter,
TRI_voc_cid_t cid, TRI_voc_cid_t cid,
TRI_server_id_t generatingServer) { TRI_server_id_t generatingServer) {
TRI_vocbase_col_t* collection; char const* name = parameter->_name;
TRI_collection_t* col;
TRI_json_t* json;
char const* name;
void const* found;
name = parameter->_name;
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase); 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 // 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); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
LOG_DEBUG("collection named '%s' already exists", name); LOG_DEBUG("collection named '%s' already exists", name);
TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_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); TRI_document_collection_t* document = TRI_CreateDocumentCollection(vocbase, vocbase->_path, parameter, cid);
if (document == NULL) { if (document == nullptr) {
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
return NULL; return nullptr;
} }
col = document; TRI_collection_t* col = document;
// add collection container // add collection container
collection = AddCollection(vocbase, TRI_vocbase_col_t* collection = AddCollection(vocbase,
col->_info._type, col->_info._type,
col->_info._name, col->_info._name,
col->_info._cid, col->_info._cid,
col->_directory); col->_directory);
if (collection == nullptr) { if (collection == nullptr) {
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
@ -635,19 +646,35 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase,
document->_directory, document->_directory,
sizeof(collection->_path) - 1); 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 // release the lock on the list of collections
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
// replicate and finally unlock the collection int res = TRI_ERROR_NO_ERROR;
TRI_LogCreateCollectionReplication(vocbase,
cid,
name,
json,
generatingServer);
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
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; return collection;
} }
@ -688,7 +715,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
// check if the new name is unused // check if the new name is unused
found = (void*) TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, newName); found = (void*) TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, newName);
if (found != NULL) { if (found != nullptr) {
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); 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 // 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); 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); 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); 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_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_voc_cid_t cid,
TRI_server_id_t generatingServer) { TRI_server_id_t generatingServer) {
TRI_vocbase_col_t* collection; TRI_ASSERT(parameters != nullptr);
char* name;
TRI_ASSERT(parameter != NULL);
name = parameter->_name;
// check that the name does not contain any strange characters // 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); TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_NAME);
return NULL; return nullptr;
} }
TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock); TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
collection = CreateCollection(vocbase, parameter, cid, generatingServer); TRI_vocbase_col_t* collection = CreateCollection(vocbase, parameters, cid, generatingServer);
TRI_ReadUnlockReadWriteLock(&vocbase->_inventoryLock); TRI_ReadUnlockReadWriteLock(&vocbase->_inventoryLock);

View File

@ -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 /// @brief set all open logfiles to status sealed
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -295,6 +295,14 @@ struct RecoverState {
uint32_t, uint32_t,
bool); 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 /// @brief set all open logfiles to status sealed
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -583,6 +583,120 @@ void ChangeCollectionMarker::dump () const {
} }
#endif #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<index_create_marker_t*>(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<index_create_marker_t*>(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<index_drop_marker_t*>(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<index_drop_marker_t*>(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 // --SECTION-- BeginTransactionMarker
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -807,7 +921,7 @@ void DocumentMarker::dump () const {
std::cout << "WAL DOCUMENT MARKER FOR DB " << m->_databaseId std::cout << "WAL DOCUMENT MARKER FOR DB " << m->_databaseId
<< ", COLLECTION " << m->_collectionId << ", COLLECTION " << m->_collectionId
<< ", REV: " << m->_rid << ", REV: " << m->_revisionId
<< ", TRX: " << m->_transactionId << ", TRX: " << m->_transactionId
<< ", KEY: " << key() << ", KEY: " << key()
<< ", OFFSETKEY: " << m->_offsetKey << ", OFFSETKEY: " << m->_offsetKey
@ -946,8 +1060,8 @@ void EdgeMarker::dump () const {
std::cout << "WAL EDGE MARKER FOR DB " << m->_databaseId std::cout << "WAL EDGE MARKER FOR DB " << m->_databaseId
<< ", COLLECTION " << m->_collectionId << ", COLLECTION " << m->_collectionId
<< ", REV: " << rid() << ", REV: " << m->_revisionId
<< ", TRX: " << tid() << ", TRX: " << m->_transactionId
<< ", KEY: " << key() << ", KEY: " << key()
<< ", FROMCID " << m->_fromCid << ", FROMCID " << m->_fromCid
<< ", TOCID " << m->_toCid << ", TOCID " << m->_toCid
@ -1076,7 +1190,7 @@ void RemoveMarker::dump () const {
std::cout << "WAL REMOVE MARKER FOR DB " << m->_databaseId std::cout << "WAL REMOVE MARKER FOR DB " << m->_databaseId
<< ", COLLECTION " << m->_collectionId << ", COLLECTION " << m->_collectionId
<< ", REV: " << m->_rid << ", REV: " << m->_revisionId
<< ", TRX: " << m->_transactionId << ", TRX: " << m->_transactionId
<< ", KEY: " << key() << ", KEY: " << key()
<< "\n"; << "\n";

View File

@ -123,6 +123,27 @@ namespace triagens {
// char* properties // 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 /// @brief wal transaction begin marker
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -502,6 +523,50 @@ namespace triagens {
void dump () const; 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 // --SECTION-- BeginTransactionMarker
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -34,6 +34,7 @@ var ArangoCollection = arangodb.ArangoCollection;
var db = arangodb.db; var db = arangodb.db;
var ERRORS = arangodb.errors; var ERRORS = arangodb.errors;
var wait = require("internal").wait; var wait = require("internal").wait;
var testHelper = require("org/arangodb/test-helper").Helper;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- collection methods // --SECTION-- collection methods
@ -253,20 +254,17 @@ function CollectionEdgeSuite () {
assertEqual("vx2", k2._key); assertEqual("vx2", k2._key);
assertEqual(vn + "/vx2", k2._id); assertEqual(vn + "/vx2", k2._id);
vertex.unload(); testHelper.waitUnload(vertex);
edge.unload(); testHelper.waitUnload(edge);
console.log("waiting for collections to unload");
wait(4);
var e1 = edge.save(vn + "/vx1", vn + "/vx2", { _key: "ex1", connect: "vx1->vx2" }); 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" }); var e2 = edge.save(vn + "/vx2", vn + "/vx1", { _key: "ex2", connect: "vx2->vx1" });
testHelper.waitUnload(vertex);
testHelper.waitUnload(edge);
vertex.unload(); vertex.unload();
edge.unload(); edge.unload();
console.log("waiting for collections to unload");
wait(4);
var e3 = edge.save(k1, k2, { _key: "ex3", connect: "vx1->vx2" }); var e3 = edge.save(k1, k2, { _key: "ex3", connect: "vx1->vx2" });
d1 = edge.document("ex1"); d1 = edge.document("ex1");

View File

@ -62,6 +62,9 @@
error: function (msg) { error: function (msg) {
console.error("In database '%s': %s", db._name(), 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) { log: function (msg) {
this.info(msg); this.info(msg);
} }