Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
  }
}
Пример #11
0
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(&parameters->_value._objects, i);
    TRI_json_t* value = TRI_AtVector(&parameters->_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;
}
Пример #12
0
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);
}
Пример #13
0
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;
}
Пример #14
0
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;
}