uint64_t TRI_HashJsonByAttributes (TRI_json_t const* json, char const *attributes[], int nrAttributes, bool docComplete, int* error) { uint64_t hash; if (NULL != error) { *error = TRI_ERROR_NO_ERROR; } hash = TRI_FnvHashBlockInitial(); if (TRI_IsArrayJson(json)) { int i; for (i = 0; i < nrAttributes; i++) { TRI_json_t const* subjson = TRI_LookupArrayJson(json, attributes[i]); if (NULL == subjson && !docComplete && NULL != error) { *error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN; } hash = HashJsonRecursive(hash, subjson); } } return hash; }
bool DocumentAccessor::isArray () const { if (_current != nullptr) { return TRI_IsArrayJson(_current); } // ok, must be a document/edge return false; }
void TRI_FromJsonVocBaseDefaults (TRI_vocbase_defaults_t* defaults, TRI_json_t const* json) { TRI_json_t* optionJson; if (! TRI_IsArrayJson(json)) { return; } optionJson = TRI_LookupArrayJson(json, "removeOnDrop"); if (TRI_IsBooleanJson(optionJson)) { defaults->removeOnDrop = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "removeOnCompacted"); if (TRI_IsBooleanJson(optionJson)) { defaults->removeOnCompacted = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "waitForSync"); if (TRI_IsBooleanJson(optionJson)) { defaults->defaultWaitForSync = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "forceSyncShapes"); if (TRI_IsBooleanJson(optionJson)) { defaults->forceSyncShapes = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "forceSyncProperties"); if (TRI_IsBooleanJson(optionJson)) { defaults->forceSyncProperties = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "requireAuthentication"); if (TRI_IsBooleanJson(optionJson)) { defaults->requireAuthentication = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "authenticateSystemOnly"); if (TRI_IsBooleanJson(optionJson)) { defaults->authenticateSystemOnly = optionJson->_value._boolean; } optionJson = TRI_LookupArrayJson(json, "defaultMaximalSize"); if (TRI_IsNumberJson(optionJson)) { defaults->defaultMaximalSize = (TRI_voc_size_t) optionJson->_value._number; } }
bool TRI_DeleteArrayJson (TRI_memory_zone_t* zone, TRI_json_t* array, size_t index) { TRI_ASSERT(TRI_IsArrayJson(array)); size_t const n = TRI_LengthArrayJson(array); if (index >= n) { return false; } TRI_json_t* element = static_cast<TRI_json_t*>(TRI_AtVector(&array->_value._objects, index)); TRI_ASSERT(element != nullptr); TRI_DestroyJson(zone, element); TRI_RemoveVector(&array->_value._objects, index); return true; }
KeyGenerator::GeneratorType KeyGenerator::generatorType (TRI_json_t const* parameters) { if (! TRI_IsArrayJson(parameters)) { return KeyGenerator::TYPE_TRADITIONAL; } TRI_json_t const* type = TRI_LookupArrayJson(parameters, "type"); if (! TRI_IsStringJson(type)) { return KeyGenerator::TYPE_TRADITIONAL; } char const* typeName = type->_value._string.data; if (TRI_CaseEqualString(typeName, TraditionalKeyGenerator::name().c_str())) { return KeyGenerator::TYPE_TRADITIONAL; } if (TRI_CaseEqualString(typeName, AutoIncrementKeyGenerator::name().c_str())) { return KeyGenerator::TYPE_AUTOINCREMENT; } // error return KeyGenerator::TYPE_UNKNOWN; }
static int LoadConfiguration (TRI_vocbase_t* vocbase, TRI_replication_applier_configuration_t* config) { TRI_json_t* json; TRI_json_t* value; char* filename; int res; TRI_DestroyConfigurationReplicationApplier(config); TRI_InitConfigurationReplicationApplier(config); filename = GetConfigurationFilename(vocbase); if (! TRI_ExistsFile(filename)) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_FILE_NOT_FOUND; } json = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, NULL); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (! TRI_IsArrayJson(json)) { if (json != NULL) { TRI_FreeJson(TRI_CORE_MEM_ZONE, json); } return TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION; } res = TRI_ERROR_NO_ERROR; if (config->_endpoint != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_endpoint); config->_endpoint = NULL; } if (config->_database != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_database); config->_database = NULL; } if (config->_username != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_username); config->_username = NULL; } if (config->_password != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_password); config->_password = NULL; } // read the endpoint value = TRI_LookupArrayJson(json, "endpoint"); if (! TRI_IsStringJson(value)) { res = TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION; } else { config->_endpoint = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } // read the database name value = TRI_LookupArrayJson(json, "database"); if (! TRI_IsStringJson(value)) { config->_database = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, vocbase->_name); } else { config->_database = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } // read username / password value = TRI_LookupArrayJson(json, "username"); if (TRI_IsStringJson(value)) { config->_username = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } value = TRI_LookupArrayJson(json, "password"); if (TRI_IsStringJson(value)) { config->_password = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } value = TRI_LookupArrayJson(json, "requestTimeout"); if (TRI_IsNumberJson(value)) { config->_requestTimeout = value->_value._number; } value = TRI_LookupArrayJson(json, "connectTimeout"); if (TRI_IsNumberJson(value)) { config->_connectTimeout = value->_value._number; } value = TRI_LookupArrayJson(json, "maxConnectRetries"); if (TRI_IsNumberJson(value)) { config->_maxConnectRetries = (uint64_t) value->_value._number; } value = TRI_LookupArrayJson(json, "chunkSize"); if (TRI_IsNumberJson(value)) { config->_chunkSize = (uint64_t) value->_value._number; } value = TRI_LookupArrayJson(json, "autoStart"); if (TRI_IsBooleanJson(value)) { config->_autoStart = value->_value._boolean; } value = TRI_LookupArrayJson(json, "adaptivePolling"); if (TRI_IsBooleanJson(value)) { config->_adaptivePolling = value->_value._boolean; } TRI_FreeJson(TRI_CORE_MEM_ZONE, json); return res; }
int TRI_LoadStateReplicationApplier (TRI_vocbase_t* vocbase, TRI_replication_applier_state_t* state) { TRI_json_t* json; TRI_json_t* serverId; char* filename; int res; TRI_InitStateReplicationApplier(state); filename = GetStateFilename(vocbase); if (filename == NULL) { return TRI_ERROR_OUT_OF_MEMORY; } LOG_TRACE("looking for replication state file '%s'", filename); if (! TRI_ExistsFile(filename)) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_FILE_NOT_FOUND; } LOG_TRACE("replication state file '%s' found", filename); json = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, NULL); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (! TRI_IsArrayJson(json)) { if (json != NULL) { TRI_FreeJson(TRI_CORE_MEM_ZONE, json); } return TRI_ERROR_REPLICATION_INVALID_APPLIER_STATE; } res = TRI_ERROR_NO_ERROR; // read the server id serverId = TRI_LookupArrayJson(json, "serverId"); if (! TRI_IsStringJson(serverId)) { res = TRI_ERROR_REPLICATION_INVALID_APPLIER_STATE; } else { state->_serverId = TRI_UInt64String2(serverId->_value._string.data, serverId->_value._string.length - 1); } if (res == TRI_ERROR_NO_ERROR) { // read the ticks res |= ReadTick(json, "lastAppliedContinuousTick", &state->_lastAppliedContinuousTick); // set processed = applied state->_lastProcessedContinuousTick = state->_lastAppliedContinuousTick; } TRI_FreeJson(TRI_CORE_MEM_ZONE, json); LOG_TRACE("replication state file read successfully"); return res; }
TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context, const TRI_vector_pointer_t* const availableIndexes, const char* const collectionName, const TRI_vector_pointer_t* candidates) { TRI_aql_index_t* picked = NULL; TRI_vector_pointer_t matches; size_t i, n; TRI_InitVectorPointer(&matches, TRI_UNKNOWN_MEM_ZONE); assert(context); assert(collectionName); assert(candidates); n = availableIndexes->_length; for (i = 0; i < n; ++i) { TRI_index_t* idx = (TRI_index_t*) availableIndexes->_buffer[i]; size_t numIndexFields; bool lastTypeWasExact; size_t j; if (! CanUseIndex(idx)) { continue; } LogIndexString("checking", idx, collectionName); TRI_ClearVectorPointer(&matches); lastTypeWasExact = true; numIndexFields = idx->_fields._length; // now loop over all index fields, from left to right // index field order is important because skiplists can be used with leftmost prefixes as well, // but not with rightmost prefixes for (j = 0; j < numIndexFields; ++j) { char* indexedFieldName; char* fieldName; size_t k; indexedFieldName = idx->_fields._buffer[j]; if (indexedFieldName == NULL) { continue; } // now loop over all candidates for (k = 0; k < candidates->_length; ++k) { TRI_aql_field_access_t* candidate = (TRI_aql_field_access_t*) TRI_AtVectorPointer(candidates, k); if (candidate->_type == TRI_AQL_ACCESS_IMPOSSIBLE || candidate->_type == TRI_AQL_ACCESS_ALL) { // wrong index type, doesn't help us at all continue; } fieldName = candidate->_fullName + candidate->_variableNameLength + 1; if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) { // primary index key names must be treated differently. _id and _key are the same if (! TRI_EqualString("_id", fieldName) && ! TRI_EqualString(TRI_VOC_ATTRIBUTE_KEY, fieldName)) { continue; } } else if (idx->_type == TRI_IDX_TYPE_EDGE_INDEX) { // edge index key names must be treated differently. _from and _to can be used independently if (! TRI_EqualString(TRI_VOC_ATTRIBUTE_FROM, fieldName) && ! TRI_EqualString(TRI_VOC_ATTRIBUTE_TO, fieldName)) { continue; } } else if (! TRI_EqualString(indexedFieldName, fieldName)) { // different attribute, doesn't help continue; } // attribute is used in index if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX || idx->_type == TRI_IDX_TYPE_EDGE_INDEX) { if (! IsExactCandidate(candidate)) { // wrong access type for primary index continue; } TRI_PushBackVectorPointer(&matches, candidate); } else if (idx->_type == TRI_IDX_TYPE_HASH_INDEX) { if (! IsExactCandidate(candidate)) { // wrong access type for hash index continue; } if (candidate->_type == TRI_AQL_ACCESS_LIST && numIndexFields != 1) { // we found a list, but the index covers multiple attributes. that means we cannot use list access continue; } TRI_PushBackVectorPointer(&matches, candidate); } else if (idx->_type == TRI_IDX_TYPE_BITARRAY_INDEX) { if (! IsExactCandidate(candidate)) { // wrong access type for hash index continue; } if (candidate->_type == TRI_AQL_ACCESS_LIST) { // we found a list, but the index covers multiple attributes. that means we cannot use list access continue; } TRI_PushBackVectorPointer(&matches, candidate); } else if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) { bool candidateIsExact; if (candidate->_type != TRI_AQL_ACCESS_EXACT && candidate->_type != TRI_AQL_ACCESS_LIST && candidate->_type != TRI_AQL_ACCESS_RANGE_SINGLE && candidate->_type != TRI_AQL_ACCESS_RANGE_DOUBLE && candidate->_type != TRI_AQL_ACCESS_REFERENCE) { // wrong access type for skiplists continue; } if (candidate->_type == TRI_AQL_ACCESS_LIST && numIndexFields != 1) { // we found a list, but the index covers multiple attributes. that means we cannot use list access continue; } candidateIsExact = IsExactCandidate(candidate); if ((candidateIsExact && ! lastTypeWasExact) || (! candidateIsExact && ! lastTypeWasExact)) { // if we already had a range query, we cannot check for equality after that // if we already had a range query, we cannot check another range after that continue; } if (candidate->_type == TRI_AQL_ACCESS_RANGE_SINGLE) { // range type. check if the compare value is a list or an object TRI_json_t* value = candidate->_value._singleRange._value; if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) { // list or object, we cannot use this for comparison in a skiplist continue; } } else if (candidate->_type == TRI_AQL_ACCESS_RANGE_DOUBLE) { // range type. check if the compare value is a list or an object TRI_json_t* value = candidate->_value._between._lower._value; if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) { // list or object, we cannot use this for comparison in a skiplist continue; } value = candidate->_value._between._upper._value; if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) { // list or object, we cannot use this for comparison in a skiplist continue; } } lastTypeWasExact = candidateIsExact; TRI_PushBackVectorPointer(&matches, candidate); } } // finished iterating over all candidates if (matches._length != j + 1) { // we already have picked less candidate fields than we should break; } } if (matches._length < 1) { // nothing found continue; } // we now do or don't have an index candidate in the matches vector if (matches._length < numIndexFields && TRI_NeedsFullCoverageIndex(idx->_type)) { // the matches vector does not fully cover the indexed fields, but the index requires it continue; } // if we can use the primary index, we'll use it picked = PickIndex(context, picked, idx, &matches); } TRI_DestroyVectorPointer(&matches); if (picked) { LogIndexString("using", picked->_idx, collectionName); } return picked; }
KeyGenerator* KeyGenerator::factory (TRI_json_t const* options) { KeyGenerator::GeneratorType type; bool const readOptions = TRI_IsArrayJson(options); if (readOptions) { type = generatorType(options); } else { type = TYPE_TRADITIONAL; } if (type == TYPE_UNKNOWN) { return nullptr; } bool allowUserKeys = true; if (readOptions) { TRI_json_t* option = TRI_LookupArrayJson(options, "allowUserKeys"); if (TRI_IsBooleanJson(option)) { allowUserKeys = option->_value._boolean; } } if (type == TYPE_TRADITIONAL) { return new TraditionalKeyGenerator(allowUserKeys); } else if (type == TYPE_AUTOINCREMENT) { uint64_t offset = 0; uint64_t increment = 1; if (readOptions) { TRI_json_t* option; option = TRI_LookupArrayJson(options, "increment"); if (TRI_IsNumberJson(option)) { increment = (uint64_t) option->_value._number; if (increment == 0 || increment >= (1ULL << 16)) { return nullptr; } } option = TRI_LookupArrayJson(options, "offset"); if (TRI_IsNumberJson(option)) { offset = (uint64_t) option->_value._number; if (offset >= UINT64_MAX) { return nullptr; } } } return new AutoIncrementKeyGenerator(allowUserKeys, offset, increment); } return nullptr; }