triagens::basics::Json DocumentAccessor::toJson () {
  if (_current == nullptr) {
    // we're still pointing to the original document
    auto shaper = _document->getShaper();

    // fetch document from mptr
    TRI_shaped_json_t shaped;
    TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, _mptr->getDataPtr());
    triagens::basics::Json json(shaper->memoryZone(), TRI_JsonShapedJson(shaper, &shaped));

    // add internal attributes

    // _id, _key, _rev
    char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
    std::string id(_resolver->getCollectionName(_document->_info._cid));
    id.push_back('/');
    id.append(key);
    json(TRI_VOC_ATTRIBUTE_ID, triagens::basics::Json(id));
    json(TRI_VOC_ATTRIBUTE_REV, triagens::basics::Json(std::to_string(TRI_EXTRACT_MARKER_RID(_mptr))));
    json(TRI_VOC_ATTRIBUTE_KEY, triagens::basics::Json(key));
      
    if (TRI_IS_EDGE_MARKER(_mptr)) {
      // _from
      std::string from(_resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_FROM_CID(_mptr)));
      from.push_back('/');
      from.append(TRI_EXTRACT_MARKER_FROM_KEY(_mptr));
      json(TRI_VOC_ATTRIBUTE_FROM, triagens::basics::Json(from));
        
      // _to
      std::string to(_resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(_mptr)));
      to.push_back('/');
      to.append(TRI_EXTRACT_MARKER_TO_KEY(_mptr));
      json(TRI_VOC_ATTRIBUTE_TO, triagens::basics::Json(to));
    }

    return json;
  }

  if (_current == _json.get()) {
    // _current points at the JSON that we own

    // steal the JSON
    TRI_json_t* value = _json.release();
    setToNull();
    return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, value);
  }

  TRI_json_t* copy = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, _current);

  if (copy != nullptr) {
    _json.release();
    return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, copy);
  }
  // fall-through intentional

  return triagens::basics::Json(triagens::basics::Json::Null);
}
Exemple #2
0
static int RemoveGeoIndex (TRI_index_t* idx,
                           TRI_doc_mptr_t const* doc,
                           bool isRollback) {
  GeoCoordinate gc;
  TRI_shaped_json_t shapedJson;
  TRI_geo_index_t* geo;
  TRI_shaper_t* shaper;
  bool missing;
  bool ok;
  double latitude;
  double longitude;

  geo = (TRI_geo_index_t*) idx;
  shaper = geo->base._collection->getShaper();  // ONLY IN INDEX, PROTECTED by RUNTIME
  TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, doc->getDataPtr());  // ONLY IN INDEX, PROTECTED by RUNTIME

  // lookup OLD latitude and longitude
  if (geo->_location != 0) {
    ok = ExtractDoubleList(shaper, &shapedJson, geo->_location, &latitude, &longitude, &missing);
  }
  else {
    ok = ExtractDoubleArray(shaper, &shapedJson, geo->_latitude, &latitude, &missing);
    ok = ok && ExtractDoubleArray(shaper, &shapedJson, geo->_longitude, &longitude, &missing);
  }

  // and remove old entry
  if (ok) {
    gc.latitude = latitude;
    gc.longitude = longitude;

    gc.data = CONST_CAST(doc);

    // ignore non-existing elements in geo-index
    GeoIndex_remove(geo->_geoIndex, &gc);
  }

  return TRI_ERROR_NO_ERROR;
}
void DocumentAccessor::lookupDocumentAttribute (char const* name, size_t nameLength) {
  if (*name == '_' && name[1] != '\0') {
    if (name[1] == 'k' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_KEY, nameLength) == 0) {
      // _key value is copied into JSON
      char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
      if (key == nullptr) {
        setToNull();
        return;
      }
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, key, strlen(key)));

      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }

      _current = _json.get();
      return;
    }

    if (name[1] == 'i' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_ID, nameLength) == 0) {
      // _id
      char buffer[512]; // big enough for max key length + max collection name length
      size_t pos = _resolver->getCollectionName(&buffer[0], _document->_info._cid);
      buffer[pos++] = '/';
      char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
      if (key == nullptr) {
        setToNull();
        return;
      }
      size_t len = strlen(key);
      memcpy(&buffer[pos], key, len);
      buffer[pos + len] = '\0';
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }
      _current = _json.get();
      return;
    }

    if (name[1] == 'r' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_REV, nameLength) == 0) {
      // _rev
      char buffer[21];
      TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_mptr);
      size_t len = TRI_StringUInt64InPlace(rid, &buffer[0]);
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], len));
      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }
      _current = _json.get();
      return;
    }

    if (TRI_IS_EDGE_MARKER(_mptr)) {
      if (name[1] == 'f' && nameLength == 5 && memcmp(name, TRI_VOC_ATTRIBUTE_FROM, nameLength) == 0) {
        // _from
        char buffer[512]; // big enough for max key length + max collection name length
        size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_FROM_CID(_mptr));
        buffer[pos++] = '/';
        char const* key = TRI_EXTRACT_MARKER_FROM_KEY(_mptr);
        if (key == nullptr) {
          setToNull();
          return;
        }
        size_t len = strlen(key);
        memcpy(&buffer[pos], key, len);
        buffer[pos + len] = '\0';
        _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
        if (_json.get() == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
        }
        _current = _json.get();
        return;
      }

      if (name[1] == 't' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_TO, nameLength) == 0) {
        // to
        char buffer[512]; // big enough for max key length + max collection name length
        size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_TO_CID(_mptr));
        buffer[pos++] = '/';
        char const* key = TRI_EXTRACT_MARKER_TO_KEY(_mptr);
        if (key == nullptr) {
          setToNull();
          return;
        }
        size_t len = strlen(key);
        memcpy(&buffer[pos], key, len);
        buffer[pos + len] = '\0';
        _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
        if (_json.get() == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
        }
        _current = _json.get();
        return;
      }
    }

    // fall-through intentional
  }

  auto shaper = _document->getShaper();

  TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name);

  if (pid == 0) {
    // attribute does not exist
    setToNull();
    return;
  }

  // attribute exists
  TRI_shaped_json_t document;
  TRI_EXTRACT_SHAPED_JSON_MARKER(document, _mptr->getDataPtr());

  TRI_shaped_json_t json;
  TRI_shape_t const* shape;

  bool ok = shaper->extractShapedJson(&document, 0, pid, &json, &shape);

  if (ok && shape != nullptr) {
    _json.reset(TRI_JsonShapedJson(shaper, &json));
    if (_json.get() == nullptr) {
      THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
    }
    _current = _json.get();
    return;
  }

  // not found
  setToNull();
}
Exemple #4
0
static int HashIndexHelper (TRI_hash_index_t const* hashIndex,
                            TRI_hash_index_element_t* hashElement,
                            TRI_doc_mptr_t const* document) {
  int res;
  size_t j;

  TRI_shaper_t* shaper;                 // underlying shaper
  TRI_shape_access_t const* acc;        // shape accessor
  TRI_shaped_json_t shapedObject;	// the sub-object
  TRI_shaped_json_t shapedJson;         // the object behind document
  TRI_shaped_sub_t shapedSub;           // the relative sub-object

  shaper = hashIndex->base._collection->_shaper;

  // .............................................................................
  // Assign the document to the TRI_hash_index_element_t structure - so that it
  // can later be retreived.
  // .............................................................................

  TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->_data);

  hashElement->_document = CONST_CAST(document);

  // .............................................................................
  // Extract the attribute values
  // .............................................................................

  res = TRI_ERROR_NO_ERROR;

  for (j = 0;  j < hashIndex->_paths._length;  ++j) {
    TRI_shape_pid_t path = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_paths, j)));

    // determine if document has that particular shape
    acc = TRI_FindAccessorVocShaper(shaper, shapedJson._sid, path);

    // field not part of the object
    if (acc == NULL || acc->_shape == NULL) {
      shapedSub._sid = shaper->_sidNull;
      shapedSub._length = 0;
      shapedSub._offset = 0;

      res = TRI_WARNING_ARANGO_INDEX_HASH_DOCUMENT_ATTRIBUTE_MISSING;
    }

    // extract the field
    else {
      if (! TRI_ExecuteShapeAccessor(acc, &shapedJson, &shapedObject)) {
        // hashElement->fields: memory deallocated in the calling procedure
        return TRI_ERROR_INTERNAL;
      }

      if (shapedObject._sid == shaper->_sidNull) {
        res = TRI_WARNING_ARANGO_INDEX_HASH_DOCUMENT_ATTRIBUTE_MISSING;
      }

      shapedSub._sid = shapedObject._sid;
      shapedSub._length = shapedObject._data.length;
      shapedSub._offset = ((char const*) shapedObject._data.data) - ((char const*) document->_data);
    }

    // store the json shaped sub-object -- this is what will be hashed
    hashElement->_subObjects[j] = shapedSub;
  }

  return res;
}
Exemple #5
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;
}
Exemple #6
0
static int HashIndexHelper (TRI_hash_index_t const* hashIndex,
                            T* hashElement,
                            TRI_doc_mptr_t const* document) {
  TRI_shaper_t* shaper;                 // underlying shaper
  TRI_shaped_json_t shapedObject;       // the sub-object
  TRI_shaped_json_t shapedJson;         // the object behind document
  TRI_shaped_sub_t shapedSub;           // the relative sub-object

  shaper = hashIndex->base._collection->getShaper();  // ONLY IN INDEX, PROTECTED by RUNTIME

  // .............................................................................
  // Assign the document to the TRI_hash_index_element_t structure - so that it
  // can later be retreived.
  // .............................................................................

  TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->getDataPtr());  // ONLY IN INDEX, PROTECTED by RUNTIME

  hashElement->_document = const_cast<TRI_doc_mptr_t*>(document);
  char const* ptr = document->getShapedJsonPtr();  // ONLY IN INDEX

  // .............................................................................
  // Extract the attribute values
  // .............................................................................

  int res = TRI_ERROR_NO_ERROR;

  size_t const n = NumPaths(hashIndex);
  for (size_t j = 0;  j < n;  ++j) {
    TRI_shape_pid_t path = *((TRI_shape_pid_t*)(TRI_AtVector(&hashIndex->_paths, j)));

    // determine if document has that particular shape
    TRI_shape_access_t const* acc = TRI_FindAccessorVocShaper(shaper, shapedJson._sid, path);

    // field not part of the object
    if (acc == nullptr || acc->_resultSid == TRI_SHAPE_ILLEGAL) {
      shapedSub._sid    = TRI_LookupBasicSidShaper(TRI_SHAPE_NULL);
      shapedSub._length = 0;
      shapedSub._offset = 0;

      res = TRI_ERROR_ARANGO_INDEX_DOCUMENT_ATTRIBUTE_MISSING;
    }

    // extract the field
    else {
      if (! TRI_ExecuteShapeAccessor(acc, &shapedJson, &shapedObject)) {
        // hashElement->fields: memory deallocated in the calling procedure
        return TRI_ERROR_INTERNAL;
      }

      if (shapedObject._sid == TRI_LookupBasicSidShaper(TRI_SHAPE_NULL)) {
        res = TRI_ERROR_ARANGO_INDEX_DOCUMENT_ATTRIBUTE_MISSING;
      }

      shapedSub._sid    = shapedObject._sid;
      shapedSub._length = shapedObject._data.length;
      shapedSub._offset = static_cast<uint32_t>(((char const*) shapedObject._data.data) - ptr);
    }

    // store the json shaped sub-object -- this is what will be hashed
    hashElement->_subObjects[j] = shapedSub;
  }

  return res;
}
Exemple #7
0
static int InsertGeoIndex (TRI_index_t* idx,
                           TRI_doc_mptr_t const* doc,
                           bool isRollback) {
  GeoCoordinate gc;
  TRI_shaped_json_t shapedJson;
  TRI_geo_index_t* geo;
  TRI_shaper_t* shaper;
  bool missing;
  bool ok;
  double latitude;
  double longitude;
  int res;

  geo = (TRI_geo_index_t*) idx;
  shaper = geo->base._collection->getShaper();  // ONLY IN INDEX, PROTECTED by RUNTIME

  // lookup latitude and longitude
  TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, doc->getDataPtr());  // ONLY IN INDEX, PROTECTED by RUNTIME

  if (geo->_location != 0) {
    if (geo->_geoJson) {
      ok = ExtractDoubleList(shaper, &shapedJson, geo->_location, &longitude, &latitude, &missing);
    }
    else {
      ok = ExtractDoubleList(shaper, &shapedJson, geo->_location, &latitude, &longitude, &missing);
    }
  }
  else {
    ok = ExtractDoubleArray(shaper, &shapedJson, geo->_latitude, &latitude, &missing);
    ok = ok && ExtractDoubleArray(shaper, &shapedJson, geo->_longitude, &longitude, &missing);
  }

  if (! ok) {
    if (idx->_unique) {
      if (idx->_ignoreNull && missing) {
        return TRI_ERROR_NO_ERROR;
      }
      else {
        return TRI_set_errno(TRI_ERROR_ARANGO_GEO_INDEX_VIOLATED);
      }
    }
    else {
      return TRI_ERROR_NO_ERROR;
    }
  }

  // and insert into index
  gc.latitude = latitude;
  gc.longitude = longitude;

  gc.data = CONST_CAST(doc);

  res = GeoIndex_insert(geo->_geoIndex, &gc);

  if (res == -1) {
    LOG_WARNING("found duplicate entry in geo-index, should not happen");
    return TRI_set_errno(TRI_ERROR_INTERNAL);
  }
  else if (res == -2) {
    return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
  }
  else if (res == -3) {
    if (idx->_unique) {
      LOG_DEBUG("illegal geo-coordinates, ignoring entry");
      return TRI_set_errno(TRI_ERROR_ARANGO_GEO_INDEX_VIOLATED);
    }
    else {
      return TRI_ERROR_NO_ERROR;
    }
  }
  else if (res < 0) {
    return TRI_set_errno(TRI_ERROR_INTERNAL);
  }

  return TRI_ERROR_NO_ERROR;
}