void arangodb::traverser::TraverserOptions::toVelocyPackIndexes(VPackBuilder& builder) const { VPackObjectBuilder guard(&builder); // base indexes builder.add("base", VPackValue(VPackValueType::Array)); for (auto const& it : _baseLookupInfos) { for (auto const& it2 : it.idxHandles) { builder.openObject(); it2.getIndex()->toVelocyPack(builder, false); builder.close(); } } builder.close(); // depth lookup indexes builder.add("levels", VPackValue(VPackValueType::Object)); for (auto const& it : _depthLookupInfo) { builder.add(VPackValue(std::to_string(it.first))); builder.add(VPackValue(VPackValueType::Array)); for (auto const& it2 : it.second) { for (auto const& it3 : it2.idxHandles) { builder.openObject(); it3.getIndex()->toVelocyPack(builder, false); builder.close(); } } builder.close(); } builder.close(); }
/// @brief initializeCursor, could be called multiple times int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) { DEBUG_BEGIN_BLOCK(); // For every call we simply forward via HTTP if (!_isResponsibleForInitializeCursor) { // do nothing... return TRI_ERROR_NO_ERROR; } VPackBuilder builder; builder.openObject(); if (items == nullptr) { // first call, items is still a nullptr builder.add("exhausted", VPackValue(true)); builder.add("error", VPackValue(false)); } else { builder.add("exhausted", VPackValue(false)); builder.add("error", VPackValue(false)); builder.add("pos", VPackValue(pos)); builder.add(VPackValue("items")); builder.openObject(); items->toVelocyPack(_engine->getQuery()->trx(), builder); builder.close(); } builder.close(); std::string bodyString(builder.slice().toJson()); std::unique_ptr<ClusterCommResult> res = sendRequest( rest::RequestType::PUT, "/_api/aql/initializeCursor/", bodyString); throwExceptionAfterBadSyncRequest(res.get(), false); // If we get here, then res->result is the response which will be // a serialized AqlItemBlock: StringBuffer const& responseBodyBuf(res->result->getBody()); { std::shared_ptr<VPackBuilder> builder = VPackParser::fromJson( responseBodyBuf.c_str(), responseBodyBuf.length()); VPackSlice slice = builder->slice(); if (slice.hasKey("code")) { return slice.get("code").getNumericValue<int>(); } return TRI_ERROR_INTERNAL; } // cppcheck-suppress style DEBUG_END_BLOCK(); }
int Syncer::createCollection(VPackSlice const& slice, arangodb::LogicalCollection** dst) { if (dst != nullptr) { *dst = nullptr; } if (!slice.isObject()) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } std::string const name = VelocyPackHelper::getStringValue(slice, "name", ""); if (name.empty()) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } TRI_voc_cid_t const cid = getCid(slice); if (cid == 0) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } TRI_col_type_e const type = static_cast<TRI_col_type_e>(VelocyPackHelper::getNumericValue<int>( slice, "type", TRI_COL_TYPE_DOCUMENT)); arangodb::LogicalCollection* col = getCollectionByIdOrName(cid, name); if (col != nullptr && col->type() == type) { // collection already exists. TODO: compare attributes return TRI_ERROR_NO_ERROR; } // merge in "isSystem" attribute VPackBuilder s; s.openObject(); s.add("isSystem", VPackValue(true)); s.close(); VPackBuilder merged = VPackCollection::merge(s.slice(), slice, true); int res = TRI_ERROR_NO_ERROR; try { col = _vocbase->createCollection(merged.slice(), cid, true); } catch (basics::Exception const& ex) { res = ex.code(); } catch (...) { res = TRI_ERROR_INTERNAL; } if (res != TRI_ERROR_NO_ERROR) { return res; } TRI_ASSERT(col != nullptr); if (dst != nullptr) { *dst = col; } return TRI_ERROR_NO_ERROR; }
void RestWalHandler::transactions() { auto const& info = arangodb::wal::LogfileManager::instance()->runningTransactions(); VPackBuilder builder; builder.openObject(); builder.add("runningTransactions", VPackValue(static_cast<double>(std::get<0>(info)))); // lastCollectedId { auto value = std::get<1>(info); if (value == UINT64_MAX) { builder.add("minLastCollected", VPackValue(VPackValueType::Null)); } else { builder.add("minLastCollected", VPackValue(value)); } } // lastSealedId { auto value = std::get<2>(info); if (value == UINT64_MAX) { builder.add("minLastSealed", VPackValue(VPackValueType::Null)); } else { builder.add("minLastSealed", VPackValue(value)); } } builder.close(); generateResult(rest::ResponseCode::OK, builder.slice()); }
/// @brief create an AqlValue from a vector of AqlItemBlock*s AqlValue AqlValue::CreateFromBlocks( arangodb::AqlTransaction* trx, std::vector<AqlItemBlock*> const& src, std::vector<std::string> const& variableNames) { VPackBuilder builder; builder.openArray(); for (auto const& current : src) { RegisterId const n = current->getNrRegs(); std::vector<RegisterId> registers; for (RegisterId j = 0; j < n; ++j) { // temporaries don't have a name and won't be included if (!variableNames[j].empty()) { registers.emplace_back(j); } } for (size_t i = 0; i < current->size(); ++i) { builder.openObject(); // only enumerate the registers that are left for (auto const& reg : registers) { builder.add(VPackValue(variableNames[reg])); current->getValueReference(i, reg).toVelocyPack(trx, builder, false); } builder.close(); } } builder.close(); return AqlValue(builder); }
int RestoreFeature::tryCreateDatabase(ClientFeature* client, std::string const& name) { VPackBuilder builder; builder.openObject(); builder.add("name", VPackValue(name)); builder.add("users", VPackValue(VPackValueType::Array)); builder.openObject(); builder.add("username", VPackValue(client->username())); builder.add("passwd", VPackValue(client->password())); builder.close(); builder.close(); builder.close(); std::string const body = builder.slice().toJson(); std::unique_ptr<SimpleHttpResult> response( _httpClient->request(GeneralRequest::RequestType::POST, "/_api/database", body.c_str(), body.size())); if (response == nullptr || !response->isComplete()) { return TRI_ERROR_INTERNAL; } auto returnCode = response->getHttpReturnCode(); if (returnCode == static_cast<int>(GeneralResponse::ResponseCode::OK) || returnCode == static_cast<int>(GeneralResponse::ResponseCode::CREATED)) { // all ok return TRI_ERROR_NO_ERROR; } if (returnCode == static_cast<int>(GeneralResponse::ResponseCode::UNAUTHORIZED) || returnCode == static_cast<int>(GeneralResponse::ResponseCode::FORBIDDEN)) { // invalid authorization _httpClient->setErrorMessage(getHttpErrorMessage(response.get(), nullptr), false); return TRI_ERROR_FORBIDDEN; } // any other error _httpClient->setErrorMessage(getHttpErrorMessage(response.get(), nullptr), false); return TRI_ERROR_INTERNAL; }
void arangodb::traverser::TraverserOptions::LookupInfo::buildEngineInfo( VPackBuilder& result) const { result.openObject(); result.add(VPackValue("handle")); // We only run toVelocyPack on Coordinator. TRI_ASSERT(idxHandles.size() == 1); result.openObject(); idxHandles[0].toVelocyPack(result, false); result.close(); result.add(VPackValue("expression")); result.openObject(); // We need to encapsulate the expression into an expression object result.add(VPackValue("expression")); expression->toVelocyPack(result, true); result.close(); result.add(VPackValue("condition")); indexCondition->toVelocyPack(result, true); result.add("condNeedUpdate", VPackValue(conditionNeedUpdate)); result.add("condMemberToUpdate", VPackValue(conditionMemberToUpdate)); result.close(); }
int Syncer::createCollection(VPackSlice const& slice, TRI_vocbase_col_t** dst) { if (dst != nullptr) { *dst = nullptr; } if (!slice.isObject()) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } std::string const name = VelocyPackHelper::getStringValue(slice, "name", ""); if (name.empty()) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } TRI_voc_cid_t const cid = getCid(slice); if (cid == 0) { return TRI_ERROR_REPLICATION_INVALID_RESPONSE; } TRI_col_type_e const type = static_cast<TRI_col_type_e>(VelocyPackHelper::getNumericValue<int>( slice, "type", static_cast<int>(TRI_COL_TYPE_DOCUMENT))); TRI_vocbase_col_t* col = getCollectionByIdOrName(cid, name); if (col != nullptr && static_cast<TRI_col_type_t>(col->_type) == static_cast<TRI_col_type_t>(type)) { // collection already exists. TODO: compare attributes return TRI_ERROR_NO_ERROR; } // merge in "isSystem" attribute VPackBuilder s; s.openObject(); s.add("isSystem", VPackValue(true)); s.close(); VPackBuilder merged = VPackCollection::merge(s.slice(), slice, true); VocbaseCollectionInfo params(_vocbase, name.c_str(), merged.slice()); col = TRI_CreateCollectionVocBase(_vocbase, params, cid, true); if (col == nullptr) { return TRI_errno(); } if (dst != nullptr) { *dst = col; } return TRI_ERROR_NO_ERROR; }
void RestVocbaseBaseHandler::generatePreconditionFailed( std::string const& collectionName, std::string const& key, TRI_voc_rid_t rev) { VPackBuilder builder; builder.openObject(); builder.add(StaticStrings::IdString, VPackValue(assembleDocumentId(collectionName, key, false))); builder.add(StaticStrings::KeyString, VPackValue(key)); builder.add(StaticStrings::RevString, VPackValue(std::to_string(rev))); builder.close(); generatePreconditionFailed(builder.slice()); }
void TraverserExpression::toVelocyPack(VPackBuilder& builder) const { builder.openObject(); builder.add("isEdgeAccess", VPackValue(isEdgeAccess)); builder.add("comparisonType", VPackValue(static_cast<int32_t>(comparisonType))); builder.add(VPackValue("varAccess")); varAccess->toVelocyPack(builder, true); if (compareTo != nullptr) { builder.add("compareTo", compareTo->slice()); } builder.close(); }
void SingleServerTraversalPath::pathToVelocyPack(arangodb::Transaction* trx, VPackBuilder& result) { result.openObject(); result.add(VPackValue("edges")); result.openArray(); for (auto const& it : _path.edges) { auto cached = _traverser->_edges.find(it); // All edges are cached!! TRI_ASSERT(cached != _traverser->_edges.end()); result.addExternal((*cached).second); } result.close(); result.add(VPackValue("vertices")); result.openArray(); for (auto const& it : _path.vertices) { result.add(_traverser->fetchVertexData(it).slice()); } result.close(); result.close(); }
void VelocyPackHelper::SanitizeExternals(VPackSlice const input, VPackBuilder& output) { if (input.isExternal()) { output.add(input.resolveExternal()); } else if (input.isObject()) { output.openObject(); for (auto const& it : VPackObjectIterator(input)) { output.add(VPackValue(it.key.copyString())); SanitizeExternals(it.value, output); } output.close(); } else if (input.isArray()) { output.openArray(); for (auto const& it : VPackArrayIterator(input)) { SanitizeExternals(it, output); } output.close(); } else { output.add(input); } }
RestStatus RestAqlFunctionsHandler::execute() { // extract the sub-request type auto const type = _request->requestType(); if (type == rest::RequestType::GET) { VPackBuilder builder; builder.openObject(); builder.add(VPackValue("functions")); aql::FunctionDefinitions::toVelocyPack(builder); builder.close(); generateResult(rest::ResponseCode::OK, builder.slice()); return RestStatus::DONE; } generateError(rest::ResponseCode::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); return RestStatus::DONE; }
/// @brief getSome AqlItemBlock* RemoteBlock::getSome(size_t atLeast, size_t atMost) { DEBUG_BEGIN_BLOCK(); // For every call we simply forward via HTTP traceGetSomeBegin(); VPackBuilder builder; builder.openObject(); builder.add("atLeast", VPackValue(atLeast)); builder.add("atMost", VPackValue(atMost)); builder.close(); std::string bodyString(builder.slice().toJson()); std::unique_ptr<ClusterCommResult> res = sendRequest(rest::RequestType::PUT, "/_api/aql/getSome/", bodyString); throwExceptionAfterBadSyncRequest(res.get(), false); // If we get here, then res->result is the response which will be // a serialized AqlItemBlock: std::shared_ptr<VPackBuilder> responseBodyBuilder = res->result->getBodyVelocyPack(); VPackSlice responseBody = responseBodyBuilder->slice(); ExecutionStats newStats(responseBody.get("stats")); _engine->_stats.addDelta(_deltaStats, newStats); _deltaStats = newStats; if (VelocyPackHelper::getBooleanValue(responseBody, "exhausted", true)) { traceGetSomeEnd(nullptr); return nullptr; } auto r = new arangodb::aql::AqlItemBlock(responseBody); traceGetSomeEnd(r); return r; // cppcheck-suppress style DEBUG_END_BLOCK(); }
void RestVocbaseBaseHandler::generateSaved( arangodb::OperationResult const& result, std::string const& collectionName, TRI_col_type_e type, VPackOptions const* options, bool isMultiple) { if (result.wasSynchronous) { createResponse(GeneralResponse::ResponseCode::CREATED); } else { createResponse(GeneralResponse::ResponseCode::ACCEPTED); } if (isMultiple && !result.countErrorCodes.empty()) { VPackBuilder errorBuilder; errorBuilder.openObject(); for (auto const& it : result.countErrorCodes) { errorBuilder.add(basics::StringUtils::itoa(it.first), VPackValue(it.second)); } errorBuilder.close(); _response->setHeaderNC(StaticStrings::ErrorCodes, errorBuilder.toJson()); } generate20x(result, collectionName, type, options); }
static void JS_VersionClient(v8::FunctionCallbackInfo<v8::Value> const& args) { TRI_V8_TRY_CATCH_BEGIN(isolate); v8::HandleScope scope(isolate); bool details = false; if (args.Length() > 0) { details = TRI_ObjectToBoolean(args[0]); } if (!details) { // return version string TRI_V8_RETURN(TRI_V8_ASCII_STRING(ARANGODB_VERSION)); } // return version details VPackBuilder builder; builder.openObject(); rest::Version::getVPack(builder); builder.close(); TRI_V8_RETURN(TRI_VPackToV8(isolate, builder.slice())); TRI_V8_TRY_CATCH_END }
/// @brief skipSome size_t RemoteBlock::skipSome(size_t atLeast, size_t atMost) { DEBUG_BEGIN_BLOCK(); // For every call we simply forward via HTTP VPackBuilder builder; builder.openObject(); builder.add("atLeast", VPackValue(atLeast)); builder.add("atMost", VPackValue(atMost)); builder.close(); std::string bodyString(builder.slice().toJson()); std::unique_ptr<ClusterCommResult> res = sendRequest(rest::RequestType::PUT, "/_api/aql/skipSome/", bodyString); throwExceptionAfterBadSyncRequest(res.get(), false); // If we get here, then res->result is the response which will be // a serialized AqlItemBlock: StringBuffer const& responseBodyBuf(res->result->getBody()); { std::shared_ptr<VPackBuilder> builder = VPackParser::fromJson( responseBodyBuf.c_str(), responseBodyBuf.length()); VPackSlice slice = builder->slice(); if (!slice.hasKey("error") || slice.get("error").getBoolean()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_AQL_COMMUNICATION); } size_t skipped = 0; if (slice.hasKey("skipped")) { skipped = slice.get("skipped").getNumericValue<size_t>(); } return skipped; } // cppcheck-suppress style DEBUG_END_BLOCK(); }
// read in- or outbound edges bool RestEdgesHandler::readEdges( std::vector<traverser::TraverserExpression*> const& expressions) { std::vector<std::string> const& suffix = _request->suffix(); if (suffix.size() != 1) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "expected GET " + EDGES_PATH + "/<collection-identifier>?vertex=<vertex-handle>&" "direction=<direction>"); return false; } std::string collectionName = suffix[0]; CollectionNameResolver resolver(_vocbase); TRI_col_type_e colType = resolver.getCollectionTypeCluster(collectionName); if (colType == TRI_COL_TYPE_UNKNOWN) { generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND); return false; } if (colType != TRI_COL_TYPE_EDGE) { generateError(rest::ResponseCode::BAD, TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID); return false; } bool found; std::string dir = _request->value("direction", found); if (!found || dir.empty()) { dir = "any"; } std::string dirString(dir); TRI_edge_direction_e direction; if (dirString == "any") { direction = TRI_EDGE_ANY; } else if (dirString == "out" || dirString == "outbound") { direction = TRI_EDGE_OUT; } else if (dirString == "in" || dirString == "inbound") { direction = TRI_EDGE_IN; } else { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "<direction> must by any, in, or out, not: " + dirString); return false; } std::string const& startVertex = _request->value("vertex", found); if (!found || startVertex.empty()) { generateError(rest::ResponseCode::BAD, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD, "illegal document handle"); return false; } if (ServerState::instance()->isCoordinator()) { std::string vertexString(startVertex); rest::ResponseCode responseCode; VPackBuilder resultDocument; resultDocument.openObject(); int res = getFilteredEdgesOnCoordinator( _vocbase->name(), collectionName, vertexString, direction, expressions, responseCode, resultDocument); if (res != TRI_ERROR_NO_ERROR) { generateError(responseCode, res); return false; } resultDocument.add("error", VPackValue(false)); resultDocument.add("code", VPackValue(200)); resultDocument.close(); generateResult(rest::ResponseCode::OK, resultDocument.slice()); return true; } // find and load collection given by name or identifier SingleCollectionTransaction trx( StandaloneTransactionContext::Create(_vocbase), collectionName, TRI_TRANSACTION_READ); // ............................................................................. // inside read transaction // ............................................................................. int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { generateTransactionError(collectionName, res, ""); return false; } size_t filtered = 0; size_t scannedIndex = 0; VPackBuilder resultBuilder; resultBuilder.openObject(); // build edges resultBuilder.add(VPackValue("edges")); // only key resultBuilder.openArray(); // NOTE: collecitonName is the shard-name in DBServer case bool ok = getEdgesForVertex(startVertex, collectionName, expressions, direction, trx, resultBuilder, scannedIndex, filtered); resultBuilder.close(); res = trx.finish(res); if (!ok) { // Error has been built internally return false; } if (res != TRI_ERROR_NO_ERROR) { if (ServerState::instance()->isDBServer()) { // If we are a DBserver, we want to use the cluster-wide collection // name for error reporting: collectionName = trx.resolver()->getCollectionName(trx.cid()); } generateTransactionError(collectionName, res, ""); return false; } resultBuilder.add("error", VPackValue(false)); resultBuilder.add("code", VPackValue(200)); resultBuilder.add("stats", VPackValue(VPackValueType::Object)); resultBuilder.add("scannedIndex", VPackValue(scannedIndex)); resultBuilder.add("filtered", VPackValue(filtered)); resultBuilder.close(); // inner object resultBuilder.close(); // and generate a response generateResult(rest::ResponseCode::OK, resultBuilder.slice(), trx.transactionContext()); return true; }
void RestWalHandler::properties() { auto l = arangodb::wal::LogfileManager::instance(); if (_request->requestType() == rest::RequestType::PUT) { std::shared_ptr<VPackBuilder> parsedRequest; VPackSlice slice; try { slice = _request->payload(); } catch (...) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid body value. expecting object"); return; } if (!slice.isObject()) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid body value. expecting object"); } if (slice.hasKey("allowOversizeEntries")) { bool value = slice.get("allowOversizeEntries").getBoolean(); l->allowOversizeEntries(value); } if (slice.hasKey("logfileSize")) { uint32_t value = slice.get("logfileSize").getNumericValue<uint32_t>(); l->filesize(value); } if (slice.hasKey("historicLogfiles")) { uint32_t value = slice.get("historicLogfiles").getNumericValue<uint32_t>(); l->historicLogfiles(value); } if (slice.hasKey("reserveLogfiles")) { uint32_t value = slice.get("reserveLogfiles").getNumericValue<uint32_t>(); l->reserveLogfiles(value); } if (slice.hasKey("throttleWait")) { uint64_t value = slice.get("throttleWait").getNumericValue<uint64_t>(); l->maxThrottleWait(value); } if (slice.hasKey("throttleWhenPending")) { uint64_t value = slice.get("throttleWhenPending").getNumericValue<uint64_t>(); l->throttleWhenPending(value); } } VPackBuilder builder; builder.openObject(); builder.add("allowOversizeEntries", VPackValue(l->allowOversizeEntries())); builder.add("logfileSize", VPackValue(l->filesize())); builder.add("historicLogfiles", VPackValue(l->historicLogfiles())); builder.add("reserveLogfiles", VPackValue(l->reserveLogfiles())); builder.add("syncInterval", VPackValue(l->syncInterval())); builder.add("throttleWait", VPackValue(l->maxThrottleWait())); builder.add("throttleWhenPending", VPackValue(l->throttleWhenPending())); builder.close(); generateResult(rest::ResponseCode::OK, builder.slice()); }
// Internal function to receive all edges for a list of vertices // Not publicly documented on purpose. // NOTE: It ONLY except _id strings. Nothing else bool RestEdgesHandler::readEdgesForMultipleVertices() { std::vector<std::string> const& suffix = _request->suffix(); if (suffix.size() != 1) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "expected POST " + EDGES_PATH + "/<collection-identifier>?direction=<direction>"); return false; } bool parseSuccess = true; std::shared_ptr<VPackBuilder> parsedBody = parseVelocyPackBody(&VPackOptions::Defaults, parseSuccess); if (!parseSuccess) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "expected POST " + EDGES_PATH + "/<collection-identifier>?direction=<direction>"); // A body is required return false; } VPackSlice body = parsedBody->slice(); if (!body.isArray()) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "Expected an array of vertex _id's in body parameter"); return false; } std::string collectionName = suffix[0]; CollectionNameResolver resolver(_vocbase); TRI_col_type_e colType = resolver.getCollectionTypeCluster(collectionName); if (colType == TRI_COL_TYPE_UNKNOWN) { generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND); return false; } else if (colType != TRI_COL_TYPE_EDGE) { generateError(rest::ResponseCode::BAD, TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID); return false; } bool found; std::string dirString = _request->value("direction", found); if (!found || dirString.empty()) { dirString = "any"; } TRI_edge_direction_e direction; if (dirString == "any") { direction = TRI_EDGE_ANY; } else if (dirString == "out" || dirString == "outbound") { direction = TRI_EDGE_OUT; } else if (dirString == "in" || dirString == "inbound") { direction = TRI_EDGE_IN; } else { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "<direction> must by any, in, or out, not: " + dirString); return false; } std::vector<traverser::TraverserExpression*> const expressions; if (ServerState::instance()->isCoordinator()) { rest::ResponseCode responseCode; VPackBuilder resultDocument; resultDocument.openObject(); for (auto const& it : VPackArrayIterator(body)) { if (it.isString()) { std::string vertexString(it.copyString()); int res = getFilteredEdgesOnCoordinator( _vocbase->name(), collectionName, vertexString, direction, expressions, responseCode, resultDocument); if (res != TRI_ERROR_NO_ERROR) { generateError(responseCode, res); return false; } } } resultDocument.add("error", VPackValue(false)); resultDocument.add("code", VPackValue(200)); resultDocument.close(); generateResult(rest::ResponseCode::OK, resultDocument.slice()); return true; } // find and load collection given by name or identifier SingleCollectionTransaction trx( StandaloneTransactionContext::Create(_vocbase), collectionName, TRI_TRANSACTION_READ); // ............................................................................. // inside read transaction // ............................................................................. int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { generateTransactionError(collectionName, res, ""); return false; } // If we are a DBserver, we want to use the cluster-wide collection // name for error reporting: if (ServerState::instance()->isDBServer()) { collectionName = trx.resolver()->getCollectionName(trx.cid()); } size_t filtered = 0; size_t scannedIndex = 0; VPackBuilder resultBuilder; resultBuilder.openObject(); // build edges resultBuilder.add(VPackValue("edges")); // only key resultBuilder.openArray(); bool ok = getEdgesForVertexList(body, expressions, direction, trx, resultBuilder, scannedIndex, filtered); if (!ok) { // Ignore the error } resultBuilder.close(); res = trx.finish(res); if (res != TRI_ERROR_NO_ERROR) { generateTransactionError(collectionName, res, ""); return false; } resultBuilder.add("error", VPackValue(false)); resultBuilder.add("code", VPackValue(200)); resultBuilder.add("stats", VPackValue(VPackValueType::Object)); resultBuilder.add("scannedIndex", VPackValue(scannedIndex)); resultBuilder.add("filtered", VPackValue(filtered)); resultBuilder.close(); // inner object resultBuilder.close(); // and generate a response generateResult(rest::ResponseCode::OK, resultBuilder.slice(), trx.transactionContext()); return true; }
void arangodb::traverser::TraverserOptions::buildEngineInfo(VPackBuilder& result) const { result.openObject(); result.add("minDepth", VPackValue(minDepth)); result.add("maxDepth", VPackValue(maxDepth)); result.add("bfs", VPackValue(useBreadthFirst)); result.add(VPackValue("uniqueVertices")); switch (uniqueVertices) { case UniquenessLevel::NONE: result.add(VPackValue(0)); break; case UniquenessLevel::PATH: result.add(VPackValue(1)); break; case UniquenessLevel::GLOBAL: result.add(VPackValue(2)); break; } result.add(VPackValue("uniqueEdges")); switch (uniqueEdges) { case UniquenessLevel::NONE: result.add(VPackValue(0)); break; case UniquenessLevel::PATH: result.add(VPackValue(1)); break; case UniquenessLevel::GLOBAL: result.add(VPackValue(2)); break; } result.add(VPackValue("baseLookupInfos")); result.openArray(); for (auto const& it: _baseLookupInfos) { it.buildEngineInfo(result); } result.close(); if (!_depthLookupInfo.empty()) { result.add(VPackValue("depthLookupInfo")); result.openObject(); for (auto const& pair : _depthLookupInfo) { result.add(VPackValue(basics::StringUtils::itoa(pair.first))); result.openArray(); for (auto const& it : pair.second) { it.buildEngineInfo(result); } result.close(); } result.close(); } if (!_vertexExpressions.empty()) { result.add(VPackValue("vertexExpressions")); result.openObject(); for (auto const& pair : _vertexExpressions) { result.add(VPackValue(basics::StringUtils::itoa(pair.first))); result.openObject(); result.add(VPackValue("expression")); pair.second->toVelocyPack(result, true); result.close(); } result.close(); } if (_baseVertexExpression != nullptr) { result.add(VPackValue("baseVertexExpression")); result.openObject(); result.add(VPackValue("expression")); _baseVertexExpression->toVelocyPack(result, true); result.close(); } result.add(VPackValue("tmpVar")); _tmpVar->toVelocyPack(result); result.close(); }
/// @brief sendToClient: for each row of the incoming AqlItemBlock use the /// attributes <shardKeys> of the Aql value <val> to determine to which shard /// the row should be sent and return its clientId size_t DistributeBlock::sendToClient(AqlItemBlock* cur) { DEBUG_BEGIN_BLOCK(); // inspect cur in row _pos and check to which shard it should be sent . . AqlValue val = cur->getValueReference(_pos, _regId); VPackSlice input = val.slice(); // will throw when wrong type bool usedAlternativeRegId = false; if (input.isNull() && _alternativeRegId != ExecutionNode::MaxRegisterId) { // value is set, but null // check if there is a second input register available (UPSERT makes use of // two input registers, // one for the search document, the other for the insert document) val = cur->getValueReference(_pos, _alternativeRegId); input = val.slice(); // will throw when wrong type usedAlternativeRegId = true; } VPackSlice value = input; VPackBuilder builder; VPackBuilder builder2; bool hasCreatedKeyAttribute = false; if (input.isString() && static_cast<DistributeNode const*>(_exeNode) ->_allowKeyConversionToObject) { builder.openObject(); builder.add(StaticStrings::KeyString, input); builder.close(); // clear the previous value cur->destroyValue(_pos, _regId); // overwrite with new value cur->setValue(_pos, _regId, AqlValue(builder)); value = builder.slice(); hasCreatedKeyAttribute = true; } else if (!input.isObject()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID); } TRI_ASSERT(value.isObject()); if (static_cast<DistributeNode const*>(_exeNode)->_createKeys) { // we are responsible for creating keys if none present if (_usesDefaultSharding) { // the collection is sharded by _key... if (!hasCreatedKeyAttribute && !value.hasKey(StaticStrings::KeyString)) { // there is no _key attribute present, so we are responsible for // creating one VPackBuilder temp; temp.openObject(); temp.add(StaticStrings::KeyString, VPackValue(createKey(value))); temp.close(); builder2 = VPackCollection::merge(input, temp.slice(), true); // clear the previous value and overwrite with new value: if (usedAlternativeRegId) { cur->destroyValue(_pos, _alternativeRegId); cur->setValue(_pos, _alternativeRegId, AqlValue(builder2)); } else { cur->destroyValue(_pos, _regId); cur->setValue(_pos, _regId, AqlValue(builder2)); } value = builder2.slice(); } } else { // the collection is not sharded by _key if (hasCreatedKeyAttribute || value.hasKey(StaticStrings::KeyString)) { // a _key was given, but user is not allowed to specify _key if (usedAlternativeRegId || !_allowSpecifiedKeys) { THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_MUST_NOT_SPECIFY_KEY); } } else { VPackBuilder temp; temp.openObject(); temp.add(StaticStrings::KeyString, VPackValue(createKey(value))); temp.close(); builder2 = VPackCollection::merge(input, temp.slice(), true); // clear the previous value and overwrite with new value: if (usedAlternativeRegId) { cur->destroyValue(_pos, _alternativeRegId); cur->setValue(_pos, _alternativeRegId, AqlValue(builder2.slice())); } else { cur->destroyValue(_pos, _regId); cur->setValue(_pos, _regId, AqlValue(builder2.slice())); } value = builder2.slice(); } } } std::string shardId; bool usesDefaultShardingAttributes; auto clusterInfo = arangodb::ClusterInfo::instance(); auto collInfo = _collection->getCollection(); int res = clusterInfo->getResponsibleShard(collInfo.get(), value, true, shardId, usesDefaultShardingAttributes); // std::cout << "SHARDID: " << shardId << "\n"; if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } TRI_ASSERT(!shardId.empty()); return getClientId(shardId); // cppcheck-suppress style DEBUG_END_BLOCK(); }