TRI_shadow_t* TRI_StoreShadowData (TRI_shadow_store_t* const store, const void* const data) { TRI_shadow_t* shadow; assert(store); shadow = CreateShadow(data); if (shadow) { LOG_TRACE("storing shadow %p with data ptr %p and id %llu", shadow, shadow->_data, (unsigned long long) shadow->_id); TRI_LockMutex(&store->_lock); if (TRI_InsertKeyAssociativePointer(&store->_ids, &shadow->_id, shadow, false)) { // duplicate entry LOG_WARNING("storing shadow failed"); TRI_UnlockMutex(&store->_lock); TRI_Free(TRI_UNKNOWN_MEM_ZONE, shadow); return NULL; } TRI_InsertKeyAssociativePointer(&store->_pointers, data, shadow, false); TRI_UnlockMutex(&store->_lock); } // might be NULL in case of OOM return shadow; }
bool TRI_AddVariableScopeAql (TRI_aql_context_t* const context, const char* name, TRI_aql_node_t* const definingNode) { TRI_aql_variable_t* variable; TRI_aql_scope_t* scope; void* result; assert(context); assert(name); if (TRI_VariableExistsScopeAql(context, name)) { return false; } variable = TRI_CreateVariableAql(name, definingNode); if (variable == NULL) { return false; } scope = CurrentScope(context); result = TRI_InsertKeyAssociativePointer(&scope->_variables, variable->_name, (void*) variable, false); assert(result == NULL); return true; }
TRI_doc_datafile_info_t* TRI_FindDatafileInfoPrimaryCollection (TRI_primary_collection_t* primary, TRI_voc_fid_t fid) { TRI_doc_datafile_info_t const* found; TRI_doc_datafile_info_t* dfi; found = TRI_LookupByKeyAssociativePointer(&primary->_datafileInfo, &fid); if (found != NULL) { union { TRI_doc_datafile_info_t const* c; TRI_doc_datafile_info_t* v; } cnv; cnv.c = found; return cnv.v; } dfi = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_doc_datafile_info_t), true); if (dfi == NULL) { return NULL; } dfi->_fid = fid; TRI_InsertKeyAssociativePointer(&primary->_datafileInfo, &fid, dfi, true); return dfi; }
TRI_doc_datafile_info_t* TRI_FindDatafileInfoPrimaryCollection (TRI_primary_collection_t* primary, TRI_voc_fid_t fid, bool create) { TRI_doc_datafile_info_t const* found; TRI_doc_datafile_info_t* dfi; found = TRI_LookupByKeyAssociativePointer(&primary->_datafileInfo, &fid); if (found != NULL) { return CONST_CAST(found); } if (! create) { return NULL; } // allocate and set to 0 dfi = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_doc_datafile_info_t), true); if (dfi == NULL) { return NULL; } dfi->_fid = fid; TRI_InsertKeyAssociativePointer(&primary->_datafileInfo, &fid, dfi, true); return dfi; }
bool TRI_RegisterFunctionAql (TRI_associative_pointer_t* functions, const char* const externalName, const char* const internalName, const bool isDeterministic, const bool isGroup, const char* const argPattern, void (*optimise)(const TRI_aql_node_t* const, TRI_aql_context_t* const, TRI_aql_field_access_t*)) { TRI_aql_function_t* function; function = (TRI_aql_function_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_function_t), false); if (function == NULL) { return false; } function->_externalName = TRI_UpperAsciiStringZ(TRI_UNKNOWN_MEM_ZONE, externalName); if (function->_externalName == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, function); return false; } // normalize name by upper-casing it function->_internalName = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, internalName); if (function->_internalName == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, function->_externalName); TRI_Free(TRI_UNKNOWN_MEM_ZONE, function); return false; } function->_argPattern = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, argPattern); if (function->_argPattern == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, function->_internalName); TRI_Free(TRI_UNKNOWN_MEM_ZONE, function->_externalName); TRI_Free(TRI_UNKNOWN_MEM_ZONE, function); return false; } if (TRI_InsertKeyAssociativePointer(functions, function->_externalName, function, false)) { // function already registered TRI_Free(TRI_UNKNOWN_MEM_ZONE, function->_externalName); TRI_Free(TRI_UNKNOWN_MEM_ZONE, function->_internalName); TRI_Free(TRI_UNKNOWN_MEM_ZONE, function); return false; } function->_isDeterministic = isDeterministic; function->_isGroup = isGroup; function->optimise = optimise; // set minArgs and maxArgs SetArgumentCount(function); return true; }
bool TRI_HasDuplicateKeyJson (const TRI_json_t* const object) { if (object && object->_type == TRI_JSON_ARRAY) { size_t n; // if we don't have attributes, we do not need to check for duplicates // if we only have one attribute, we don't need to check for duplicates in // the array, but we need to recursively validate the array values (if // array value itself is an array) n = object->_value._objects._length; if (n > 0) { TRI_associative_pointer_t hash; size_t i; TRI_InitAssociativePointer(&hash, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); for (i = 0; i < n; i += 2) { TRI_json_t* key; TRI_json_t* value; void* previous; key = TRI_AtVector(&object->_value._objects, i); if (key->_type != TRI_JSON_STRING) { continue; } value = TRI_AtVector(&object->_value._objects, i + 1); // recursively check sub-array elements if (value->_type == TRI_JSON_ARRAY && TRI_HasDuplicateKeyJson(value)) { // duplicate found in sub-array TRI_DestroyAssociativePointer(&hash); return true; } previous = TRI_InsertKeyAssociativePointer(&hash, key->_value._string.data, key->_value._string.data, false); if (previous != NULL) { // duplicate found TRI_DestroyAssociativePointer(&hash); return true; } } TRI_DestroyAssociativePointer(&hash); } } // no duplicate found return false; }
static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase, TRI_col_type_t type, char const* name, TRI_voc_cid_t cid, char const* path) { void const* found; TRI_vocbase_col_t* col; // create a new proxy col = TRI_Allocate(sizeof(TRI_vocbase_col_t)); col->_vocbase = vocbase; col->_type = type; TRI_CopyString(col->_name, name, sizeof(col->_name)); col->_path = (path == NULL ? NULL : TRI_DuplicateString(path)); col->_collection = NULL; col->_newBorn = 0; col->_loaded = 0; col->_corrupted = 0; col->_cid = cid; // check name found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, name, col, false); if (found != NULL) { TRI_Free(col); LOG_ERROR("duplicate entry for name '%s'", name); return NULL; } // check collection identifier if (cid != 0) { found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsById, &cid, col, false); if (found != NULL) { TRI_Free(col); LOG_ERROR("duplicate entry for identifier '%s'", cid); return NULL; } } TRI_PushBackVectorPointer(&vocbase->_collections, col); return col; }
TRI_general_cursor_t* TRI_CreateGeneralCursor (TRI_vocbase_t* vocbase, TRI_general_cursor_result_t* result, const bool doCount, const TRI_general_cursor_length_t batchSize, TRI_json_t* extra) { TRI_general_cursor_t* cursor; TRI_ASSERT(vocbase != NULL); cursor = (TRI_general_cursor_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_t), false); if (cursor == NULL) { return NULL; } cursor->_vocbase = vocbase; cursor->_store = vocbase->_cursors; cursor->_result = result; cursor->_extra = extra; // might be NULL cursor->_expires = TRI_microtime() + 3600; // default lifetime: 1h cursor->_id = TRI_NewTickServer(); // state cursor->_currentRow = 0; cursor->_length = result->getLength(result); cursor->_hasCount = doCount; cursor->_batchSize = batchSize; cursor->_usage._refCount = 0; cursor->_usage._isDeleted = false; // assign functions cursor->next = NextGeneralCursor; cursor->hasNext = HasNextGeneralCursor; cursor->hasCount = HasCountGeneralCursor; cursor->getBatchSize = GetBatchSizeGeneralCursor; cursor->getExtra = GetExtraGeneralCursor; cursor->free = TRI_FreeGeneralCursor; TRI_InitSpin(&cursor->_lock); TRI_LockSpin(&vocbase->_cursors->_lock); // TODO: check for errors here TRI_InsertKeyAssociativePointer(&vocbase->_cursors->_ids, &cursor->_id, cursor, true); TRI_UnlockSpin(&vocbase->_cursors->_lock); LOG_TRACE("created general cursor"); return cursor; }
bool TRI_AddCollectionAql (TRI_aql_context_t* const context, const char* const name) { assert(context); assert(name); // duplicates are not a problem here, we simply ignore them TRI_InsertKeyAssociativePointer(&context->_collectionNames, name, (void*) name, false); if (context->_collectionNames._nrUsed > AQL_MAX_COLLECTIONS) { TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_TOO_MANY_COLLECTIONS, NULL); return false; } return true; }
static TRI_shape_aid_t FindAttributeNameArrayShaper (TRI_shaper_t* shaper, char const* name) { array_shaper_t* s; void const* p; s = (array_shaper_t*) shaper; p = TRI_LookupByKeyAssociativePointer(&s->_attributeNames, name); if (p == NULL) { size_t n; attribute_2_id_t* a2i; void* f; int res; n = strlen(name) + 1; a2i = TRI_Allocate(shaper->_memoryZone, sizeof(attribute_2_id_t) + n, false); if (a2i == NULL) { return 0; } a2i->_aid = 1 + s->_attributes._length; a2i->_size = n; memcpy(((char*) a2i) + sizeof(attribute_2_id_t), name, n); f = TRI_InsertKeyAssociativePointer(&s->_attributeNames, name, a2i, false); if (f == NULL) { TRI_Free(shaper->_memoryZone, a2i); return 0; } res = TRI_PushBackVectorPointer(&s->_attributes, a2i); if (res != TRI_ERROR_NO_ERROR) { TRI_RemoveKeyAssociativePointer(&s->_attributeNames, name); TRI_Free(shaper->_memoryZone, a2i); return 0; } return a2i->_aid; } else { attribute_2_id_t const* a2i = (attribute_2_id_t const*) p; return a2i->_aid; } }
bool TRI_AddParameterValuesAql (TRI_aql_context_t* const context, const TRI_json_t* const parameters) { size_t i; size_t n; assert(context); if (parameters == NULL) { // no bind parameters, direclty return return true; } if (parameters->_type != TRI_JSON_ARRAY) { // parameters must be a list TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_BIND_PARAMETERS_INVALID, NULL); return false; } n = parameters->_value._objects._length; if (n == 0) { // empty list, this is ok return true; } for (i = 0; i < n; i += 2) { TRI_json_t* name = TRI_AtVector(¶meters->_value._objects, i); TRI_json_t* value = TRI_AtVector(¶meters->_value._objects, i + 1); TRI_aql_bind_parameter_t* parameter; assert(TRI_IsStringJson(name)); assert(value); parameter = CreateParameter(name->_value._string.data, name->_value._string.length - 1, value); if (parameter == NULL) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return false; } TRI_InsertKeyAssociativePointer(&context->_parameters._values, parameter->_name, parameter, false); } return true; }
bool TRI_RegisterMimetype (const char* extension, const char* mimetype, bool appendCharset) { mimetype_t* entry = static_cast<mimetype_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(mimetype_t), false)); entry->_extension = TRI_DuplicateString(extension); entry->_appendCharset = appendCharset; if (appendCharset) { entry->_mimetype = TRI_Concatenate2String(mimetype, "; charset=utf-8"); } else { entry->_mimetype = TRI_DuplicateString(mimetype); } void* found = TRI_InsertKeyAssociativePointer(&Mimetypes, extension, entry, false); return (found != nullptr); }
bool TRI_LoadAuthInfo (TRI_vocbase_t* vocbase) { TRI_vocbase_col_t* collection; TRI_primary_collection_t* primary; void** beg; void** end; void** ptr; LOG_DEBUG("starting to load authentication and authorisation information"); collection = TRI_LookupCollectionByNameVocBase(vocbase, "_users"); if (collection == NULL) { LOG_INFO("collection '_users' does not exist, no authentication available"); return false; } TRI_UseCollectionVocBase(vocbase, collection); primary = collection->_collection; if (primary == NULL) { LOG_FATAL_AND_EXIT("collection '_users' cannot be loaded"); } if (! TRI_IS_DOCUMENT_COLLECTION(primary->base._info._type)) { TRI_ReleaseCollectionVocBase(vocbase, collection); LOG_FATAL_AND_EXIT("collection '_users' has an unknown collection type"); } TRI_WriteLockReadWriteLock(&vocbase->_authInfoLock); // ............................................................................. // inside a write transaction // ............................................................................. collection->_collection->beginWrite(collection->_collection); beg = primary->_primaryIndex._table; end = beg + primary->_primaryIndex._nrAlloc; ptr = beg; for (; ptr < end; ++ptr) { if (*ptr) { TRI_doc_mptr_t const* d; TRI_shaped_json_t shapedJson; d = (TRI_doc_mptr_t const*) *ptr; if (d->_validTo == 0) { TRI_vocbase_auth_t* auth; TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, d->_data); auth = ConvertAuthInfo(vocbase, primary, &shapedJson); if (auth != NULL) { TRI_vocbase_auth_t* old; old = TRI_InsertKeyAssociativePointer(&vocbase->_authInfo, auth->_username, auth, true); if (old != NULL) { FreeAuthInfo(old); } } } } } collection->_collection->endWrite(collection->_collection); // ............................................................................. // outside a write transaction // ............................................................................. vocbase->_authInfoFlush = true; TRI_WriteUnlockReadWriteLock(&vocbase->_authInfoLock); TRI_ReleaseCollectionVocBase(vocbase, collection); return true; }
bool TRI_HasDuplicateKeyJson (TRI_json_t const* object) { if (object && object->_type == TRI_JSON_OBJECT) { size_t const n = TRI_LengthVector(&object->_value._objects); const bool hasMultipleElements = (n > 2); // if we don't have attributes, we do not need to check for duplicates // if we only have one attribute, we don't need to check for duplicates in // the array, but we need to recursively validate the array values (if // array value itself is an array) if (n > 0) { TRI_associative_pointer_t hash; size_t i; if (hasMultipleElements) { TRI_InitAssociativePointer(&hash, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); } for (i = 0; i < n; i += 2) { auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&object->_value._objects, i)); if (! TRI_IsStringJson(key)) { continue; } auto value = static_cast<TRI_json_t const*>(TRI_AtVector(&object->_value._objects, i + 1)); // recursively check sub-array elements if (value->_type == TRI_JSON_OBJECT && TRI_HasDuplicateKeyJson(value)) { // duplicate found in sub-array if (hasMultipleElements) { TRI_DestroyAssociativePointer(&hash); } return true; } if (hasMultipleElements) { void* previous = TRI_InsertKeyAssociativePointer(&hash, key->_value._string.data, key->_value._string.data, false); if (previous != nullptr) { // duplicate found TRI_DestroyAssociativePointer(&hash); return true; } } } if (hasMultipleElements) { TRI_DestroyAssociativePointer(&hash); } } } // no duplicate found return false; }