1
0
Fork 0

Merge branch 'devel' of ssh://github.com/ArangoDB/ArangoDB into devel

This commit is contained in:
Max Neunhoeffer 2016-10-12 14:39:24 +02:00
commit 300066f376
33 changed files with 287 additions and 313 deletions

View File

@ -32,12 +32,13 @@
#include <iomanip>
#include "Basics/directories.h"
#include "Basics/StringUtils.h"
#include "Basics/Utf8Helper.h"
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(BIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif
@ -74,7 +75,7 @@ static string hexedump (const string &s) {
struct StringUtilsSetup {
StringUtilsSetup () {
FIX_ICU_ENV;
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("")) {
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("", SBIN_DIRECTORY)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -31,11 +31,12 @@
#include <boost/test/unit_test.hpp>
#include "Basics/hashes.h"
#include "Basics/directories.h"
#include "Basics/Utf8Helper.h"
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif
@ -51,7 +52,7 @@
struct CHashesSetup {
CHashesSetup () {
FIX_ICU_ENV;
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("")) {
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("", SBIN_DIRECTORY)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -31,12 +31,13 @@
#include <boost/test/unit_test.hpp>
#include "Basics/json.h"
#include "Basics/directories.h"
#include "Basics/StringBuffer.h"
#include "Basics/Utf8Helper.h"
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif
@ -58,7 +59,7 @@
struct CJsonSetup {
CJsonSetup () {
FIX_ICU_ENV;
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("")) {
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("", SBIN_DIRECTORY)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -32,10 +32,11 @@
#include "Basics/tri-strings.h"
#include "Basics/Utf8Helper.h"
#include "Basics/directories.h"
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif
@ -55,7 +56,7 @@
struct CNormalizeStringTestSetup {
CNormalizeStringTestSetup () {
FIX_ICU_ENV;
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("")) {
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("", SBIN_DIRECTORY)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -33,10 +33,11 @@
#include "Basics/tri-strings.h"
#include "Basics/Utf8Helper.h"
#include "Basics/directories.h"
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif
@ -62,7 +63,7 @@
struct CStringUtf8Setup {
CStringUtf8Setup () {
FIX_ICU_ENV;
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("")) {
if (!arangodb::basics::Utf8Helper::DefaultUtf8Helper.setCollatorLanguage("", SBIN_DIRECTORY)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -64,6 +64,82 @@ describe ArangoDB do
end
################################################################################
## create and using cursors, continuation
################################################################################
context "handling a cursor with continuation:" do
before do
@cn = "users"
ArangoDB.drop_collection(@cn)
@cid = ArangoDB.create_collection(@cn, false)
(0...2001).each{|i|
ArangoDB.post("/_api/document?collection=#{@cid}", :body => "{ \"_key\" : \"test#{i}\" }")
}
end
after do
ArangoDB.drop_collection(@cn)
end
it "creates a cursor" do
cmd = api
body = "{ \"query\" : \"FOR u IN #{@cn} RETURN u\", \"count\" : true }"
doc = ArangoDB.log_post("#{prefix}-create-batchsize", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(2001)
doc.parsed_response['result'].length.should eq(1000)
doc.parsed_response['cached'].should eq(false)
id = doc.parsed_response['id']
cmd = api + "/#{id}"
doc = ArangoDB.log_put("#{prefix}-create-batchsize", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(2001)
doc.parsed_response['result'].length.should eq(1000)
doc.parsed_response['cached'].should eq(false)
cmd = api + "/#{id}"
doc = ArangoDB.log_put("#{prefix}-create-batchsize", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should be_nil
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['count'].should eq(2001)
doc.parsed_response['result'].length.should eq(1)
doc.parsed_response['cached'].should eq(false)
cmd = api + "/#{id}"
doc = ArangoDB.log_put("#{prefix}-create-batchsize", cmd)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['errorNum'].should eq(1600)
doc.parsed_response['code'].should eq(404)
end
end
################################################################################
## create and using cursors
################################################################################

View File

@ -461,7 +461,8 @@ void RestCursorHandler::modifyCursor() {
builder.close();
_response->setContentType(rest::ContentType::JSON);
generateResult(rest::ResponseCode::OK, builder.slice());
generateResult(rest::ResponseCode::OK, builder.slice(),
static_cast<VelocyPackCursor*>(cursor)->result()->context);
cursors->release(cursor);
} catch (...) {

View File

@ -38,7 +38,7 @@ class RestUploadHandler : public RestVocbaseBaseHandler {
public:
char const* name() const override final { return "RestUploadHandler"; }
RestHandler::status execute();
RestHandler::status execute() override;
//////////////////////////////////////////////////////////////////////////////
/// @brief parses a multi-part request body and determines the boundaries of

View File

@ -103,7 +103,7 @@ static int runServer(int argc, char** argv) {
std::string name = context.binaryName();
auto options = std::make_shared<options::ProgramOptions>(
argv[0], "Usage: " + name + " [<options>]", "For more information use:");
argv[0], "Usage: " + name + " [<options>]", "For more information use:", SBIN_DIRECTORY);
application_features::ApplicationServer server(options, SBIN_DIRECTORY);

View File

@ -120,7 +120,7 @@ void VelocyPackCursor::dump(VPackBuilder& builder) {
VPackOptions const* oldOptions = builder.options;
builder.options = _result.context->getVPackOptions();
builder.options = _result.context->getVPackOptionsForDump();
builder.add("result", VPackValue(VPackValueType::Array));
for (size_t i = 0; i < n; ++i) {

View File

@ -1332,6 +1332,18 @@ static void JS_SendChunk(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_TRY_CATCH_END
}
static void JS_IsEnterprise(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate);
#ifndef USE_ENTERPRISE
TRI_V8_RETURN(v8::False(isolate));
#else
TRI_V8_RETURN(v8::True(isolate));
#endif
TRI_V8_TRY_CATCH_END
}
////////////////////////////////////////////////////////////////////////////////
/// @brief stores the V8 actions function inside the global variable
////////////////////////////////////////////////////////////////////////////////
@ -1364,6 +1376,11 @@ void TRI_InitV8Actions(v8::Isolate* isolate, v8::Handle<v8::Context> context) {
JS_RequestParts, true);
TRI_AddGlobalFunctionVocbase(
isolate, context, TRI_V8_ASCII_STRING("SYS_SEND_CHUNK"), JS_SendChunk);
TRI_AddGlobalFunctionVocbase(
isolate, context,
TRI_V8_ASCII_STRING("SYS_IS_ENTERPRISE"),
JS_IsEnterprise);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -47,7 +47,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangobench [<options>]", "For more information use:"));
argv[0], "Usage: arangobench [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangodump [<options>]", "For more information use:"));
argv[0], "Usage: arangodump [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -45,7 +45,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangoimp [<options>]", "For more information use:"));
argv[0], "Usage: arangoimp [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -45,7 +45,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangorestore [<options>]", "For more information use:"));
argv[0], "Usage: arangorestore [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -51,7 +51,7 @@ int main(int argc, char* argv[]) {
std::string name = context.binaryName();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: " + name + " [<options>]", "For more information use:"));
argv[0], "Usage: " + name + " [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -42,7 +42,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangovpack [<options>]", "For more information use:"));
argv[0], "Usage: arangovpack [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -12,7 +12,7 @@ endif()
# Global macros ----------------------------------------------------------------
macro (generate_root_config name)
FILE(READ ${PROJECT_SOURCE_DIR}/etc/arangodb3/${name}.conf.in FileContent)
STRING(REPLACE "@PKGDATADIR@" "@ROOTDIR@/share/arangodb3"
STRING(REPLACE "@PKGDATADIR@" "@ROOTDIR@$/{CMAKE_INSTALL_DATAROOTDIR_ARANGO}"
FileContent "${FileContent}")
STRING(REPLACE "@LOCALSTATEDIR@" "@ROOTDIR@/var"
FileContent "${FileContent}")

View File

@ -34,6 +34,12 @@ const cluster = require('@arangodb/cluster');
const Graph = require('@arangodb/general-graph');
const createRouter = require('@arangodb/foxx/router');
const actions = require('@arangodb/actions');
const isEnterprise = require('internal').isEnterprise();
let SmartGraph = {};
if (isEnterprise) {
SmartGraph = require('@arangodb/smart-graph');
}
const NOT_MODIFIED = statuses('not modified');
const ACCEPTED = statuses('accepted');
@ -43,6 +49,24 @@ const OK = statuses('ok');
const router = createRouter();
module.context.use(router);
const loadGraph = (name) => {
try {
if (isEnterprise) {
return SmartGraph._graph(name);
} else {
return Graph._graph(name);
}
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
};
router.use((req, res, next) => {
try {
next();
@ -113,7 +137,8 @@ function setResponse (res, name, body, code) {
res.json({
error: false,
[name]: body,
code});
code
});
}
function matchVertexRevision (req, rev) {
@ -197,29 +222,43 @@ router.post('/', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
let g;
try {
g = Graph._create(
req.body.name,
req.body.edgeDefinitions,
req.body.orphanCollections,
{waitForSync}
);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_DUPLICATE.code) {
throw Object.assign(
new httperr.Conflict(e.errorMessage),
{errorNum: e.errorNum, cause: e}
if (isEnterprise && req.body.isSmart === true) {
const smartGraphAttribute = req.body.options.smartGraphAttribute;
const numberOfShards = req.body.options.numberOfShards;
g = SmartGraph._create(
req.body.name,
req.body.edgeDefinitions,
req.body.orphanCollections,
{waitForSync, numberOfShards, smartGraphAttribute}
);
} else {
g = Graph._create(
req.body.name,
req.body.edgeDefinitions,
req.body.orphanCollections,
{waitForSync}
);
}
if (e.isArangoError && [
errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code,
errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.code,
errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code,
errors.ERROR_GRAPH_COLLECTION_USED_IN_ORPHANS.code
].indexOf(e.errorNum) !== -1) {
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
} catch (e) {
if (e.isArangoError) {
switch (e.errorNum) {
case errors.ERROR_BAD_PARAMETER.code:
case errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code:
case errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.code:
case errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code:
case errors.ERROR_GRAPH_COLLECTION_USED_IN_ORPHANS.code:
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
case errors.ERROR_GRAPH_DUPLICATE.code:
throw Object.assign(
new httperr.Conflict(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
default:
}
}
throw e;
}
@ -228,8 +267,13 @@ router.post('/', function (req, res) {
.queryParam('waitForSync', waitForSyncFlag)
.body(joi.object({
name: joi.string().required(),
edgeDefinitions: joi.any().optional(),
orphanCollections: joi.any().optional()
edgeDefinitions: joi.array().optional(),
orphanCollections: joi.array().optional(),
isSmart: joi.boolean().optional(),
options: joi.object({
smartGraphAttribute: joi.string().required(),
numberOfShards: joi.number().integer().greater(0).required()
}).optional()
}).required(), 'The required information for a graph')
.error('bad request', 'Graph creation error.')
.error('conflict', 'Graph creation error.')
@ -238,18 +282,7 @@ router.post('/', function (req, res) {
router.get('/:graph', function (req, res) {
const name = req.pathParams.graph;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
setResponse(res, 'graph', graphForClient(g), OK);
})
.pathParam('graph', graphName)
@ -292,18 +325,7 @@ router.delete('/:graph', function (req, res) {
router.get('/:graph/vertex', function (req, res) {
const name = req.pathParams.graph;
const excludeOrphans = req.queryParams.excludeOrphans;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
const mapFunc = (
req.pathParams.collectionObjects
? (c) => collectionRepresentation(c, false, false, false)
@ -318,36 +340,25 @@ router.get('/:graph/vertex', function (req, res) {
router.post('/:graph/vertex', function (req, res) {
const name = req.pathParams.graph;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
try {
g._addVertexCollection(req.body.collection);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
if (e.isArangoError && [
errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.code,
errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code,
errors.ERROR_GRAPH_COLLECTION_USED_IN_ORPHANS.code
].indexOf(e.errorNum) !== -1) {
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
if (e.isArangoError) {
switch (e.errorNum) {
case errors.ERROR_BAD_PARAMETER.code:
case errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.code:
case errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code:
case errors.ERROR_GRAPH_COLLECTION_USED_IN_ORPHANS.code:
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e});
case errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code:
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e});
}
}
throw e;
}
@ -366,18 +377,7 @@ router.delete('/:graph/vertex/:collection', function (req, res) {
const dropCollection = Boolean(req.queryParams.dropCollection);
const name = req.pathParams.graph;
const defName = req.pathParams.collection;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
try {
g._removeVertexCollection(defName, dropCollection);
} catch (e) {
@ -407,18 +407,7 @@ router.delete('/:graph/vertex/:collection', function (req, res) {
router.get('/:graph/edge', function (req, res) {
const name = req.pathParams.graph;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
setResponse(res, 'collections', _.map(g._edgeCollections(), (c) => c.name()).sort(), OK);
})
.pathParam('graph', graphName)
@ -428,30 +417,20 @@ router.get('/:graph/edge', function (req, res) {
router.post('/:graph/edge', function (req, res) {
const name = req.pathParams.graph;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
try {
g._extendEdgeDefinitions(req.body);
} catch (e) {
if (e.isArangoError && [
errors.ERROR_GRAPH_COLLECTION_MULTI_USE.code,
errors.ERROR_GRAPH_COLLECTION_USE_IN_MULTI_GRAPHS.code,
errors.ERROR_GRAPH_CREATE_MALFORMED_EDGE_DEFINITION.code
].indexOf(e.errorNum) !== -1) {
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
if (e.isArangoError) {
switch (e.errorNum) {
case errors.ERROR_GRAPH_COLLECTION_MULTI_USE.code:
case errors.ERROR_GRAPH_COLLECTION_USE_IN_MULTI_GRAPHS.code:
case errors.ERROR_GRAPH_CREATE_MALFORMED_EDGE_DEFINITION.code:
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
}
throw e;
}
@ -471,18 +450,7 @@ router.post('/:graph/edge', function (req, res) {
router.put('/:graph/edge/:definition', function (req, res) {
const name = req.pathParams.graph;
const defName = req.pathParams.definition;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
if (defName !== req.body.collection) {
throw Object.assign(
new httperr.NotFound(errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.message),
@ -492,14 +460,15 @@ router.put('/:graph/edge/:definition', function (req, res) {
try {
g._editEdgeDefinitions(req.body);
} catch (e) {
if (e.isArangoError && [
errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code,
errors.ERROR_GRAPH_CREATE_MALFORMED_EDGE_DEFINITION.code
].indexOf(e.errorNum) !== -1) {
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
if (e.isArangoError) {
switch (e.errorNum) {
case errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code:
case errors.ERROR_GRAPH_CREATE_MALFORMED_EDGE_DEFINITION.code:
throw Object.assign(
new httperr.BadRequest(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
}
throw e;
}
@ -522,15 +491,12 @@ router.delete('/:graph/edge/:definition', function (req, res) {
const dropCollection = Boolean(req.queryParams.dropCollection);
const name = req.pathParams.graph;
const defName = req.pathParams.definition;
let g;
const g = loadGraph(name);
try {
g = Graph._graph(name);
g._deleteEdgeDefinition(defName, dropCollection);
} catch (e) {
if (e.isArangoError && [
errors.ERROR_GRAPH_NOT_FOUND.code,
errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code
].indexOf(e.errorNum) !== -1) {
if (e.isArangoError &&
errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code === e.errorNum) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
@ -557,18 +523,7 @@ router.post('/:graph/vertex/:collection', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let meta;
try {
@ -598,18 +553,7 @@ router.get('/:graph/vertex/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -639,18 +583,7 @@ router.put('/:graph/vertex/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -688,18 +621,7 @@ router.patch('/:graph/vertex/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -737,18 +659,7 @@ router.delete('/:graph/vertex/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -799,23 +710,12 @@ router.post('/:graph/edge/:collection', function (req, res) {
{errorNum: errors.ERROR_GRAPH_INVALID_EDGE.code}
);
}
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let meta;
try {
meta = g[collection].save(req.body);
} catch(e) {
} catch (e) {
if (e.errorNum !== errors.ERROR_GRAPH_INVALID_EDGE.code) {
throw Object.assign(
new httperr.Gone(e.errorMessage),
@ -839,18 +739,7 @@ router.get('/:graph/edge/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -880,18 +769,7 @@ router.put('/:graph/edge/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -929,18 +807,7 @@ router.patch('/:graph/edge/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {
@ -978,18 +845,7 @@ router.delete('/:graph/edge/:collection/:key', function (req, res) {
const collection = req.pathParams.collection;
const key = req.pathParams.key;
const id = `${collection}/${key}`;
let g;
try {
g = Graph._graph(name);
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_NOT_FOUND.code) {
throw Object.assign(
new httperr.NotFound(e.errorMessage),
{errorNum: e.errorNum, cause: e}
);
}
throw e;
}
const g = loadGraph(name);
checkCollection(g, collection);
let doc;
try {

View File

@ -2124,11 +2124,11 @@ exports._renameCollection = function (oldName, newName) {
// //////////////////////////////////////////////////////////////////////////////
exports._list = function () {
return db._query(`FOR x IN _graphs FILTER !x.isSmart RETURN x._key`).toArray();
return db._query(`FOR x IN _graphs RETURN x._key`).toArray();
};
exports._listObjects = function () {
return db._query(`FOR x IN _graphs FILTER !x.isSmart RETURN x`).toArray();
return db._query(`FOR x IN _graphs RETURN x`).toArray();
};
// //////////////////////////////////////////////////////////////////////////////

View File

@ -355,4 +355,14 @@
exports.DEFAULT_REPLICATION_FACTOR_SYSTEM = global.SYS_DEFAULT_REPLICATION_FACTOR_SYSTEM;
delete global.SYS_DEFAULT_REPLICATION_FACTOR_SYSTEM;
}
// //////////////////////////////////////////////////////////////////////////////
// / @brief returns if we are in enterprise version or not
// //////////////////////////////////////////////////////////////////////////////
if (global.SYS_IS_ENTERPRISE) {
exports.isEnterprise = global.SYS_IS_ENTERPRISE;
delete global.SYS_IS_ENTERPRISE;
}
}());

View File

@ -216,6 +216,7 @@ class ApplicationServer {
_progressReports.emplace_back(reporter);
}
const char* getBinaryPath() { return _binaryPath;}
private:
// look up a feature and return a pointer to it. may be nullptr
static ApplicationFeature* lookupFeature(std::string const&);

View File

@ -33,7 +33,8 @@ using namespace arangodb::options;
LanguageFeature::LanguageFeature(
application_features::ApplicationServer* server)
: ApplicationFeature(server, "Language") {
: ApplicationFeature(server, "Language"),
_binaryPath(server->getBinaryPath()){
setOptional(false);
requiresElevatedPrivileges(false);
startsAfter("Logger");
@ -46,7 +47,7 @@ void LanguageFeature::collectOptions(
}
void LanguageFeature::prepare() {
if (!Utf8Helper::DefaultUtf8Helper.setCollatorLanguage(_language)) {
if (!Utf8Helper::DefaultUtf8Helper.setCollatorLanguage(_language, _binaryPath)) {
std::string msg =
"cannot initialize ICU; please make sure ICU*dat is available; "
"the variable ICU_DATA='";

View File

@ -37,6 +37,7 @@ class LanguageFeature final : public application_features::ApplicationFeature {
private:
std::string _language;
const char* _binaryPath;
};
}

View File

@ -25,6 +25,7 @@
#include "Utf8Helper.h"
#include "Logger/Logger.h"
#include "Basics/tri-strings.h"
#include "Basics/directories.h"
#include "unicode/normalizer2.h"
#include "unicode/brkiter.h"
#include "unicode/ucasemap.h"
@ -38,13 +39,14 @@
using namespace arangodb::basics;
Utf8Helper Utf8Helper::DefaultUtf8Helper;
Utf8Helper Utf8Helper::DefaultUtf8Helper(SBIN_DIRECTORY);
Utf8Helper::Utf8Helper(std::string const& lang) : _coll(nullptr) {
setCollatorLanguage(lang);
Utf8Helper::Utf8Helper(std::string const& lang, char const* binaryPath)
: _coll(nullptr) {
setCollatorLanguage(lang, binaryPath);
}
Utf8Helper::Utf8Helper() : Utf8Helper("") {}
Utf8Helper::Utf8Helper(char const* binaryPath) : Utf8Helper("", binaryPath) {}
Utf8Helper::~Utf8Helper() {
if (_coll) {
@ -127,9 +129,9 @@ int Utf8Helper::compareUtf16(uint16_t const* left, size_t leftLength,
(const UChar*)right, (int32_t)rightLength);
}
bool Utf8Helper::setCollatorLanguage(std::string const& lang) {
bool Utf8Helper::setCollatorLanguage(std::string const& lang, char const* binaryPath) {
#ifdef _WIN32
TRI_FixIcuDataEnv();
TRI_FixIcuDataEnv(binaryPath);
#endif
UErrorCode status = U_ZERO_ERROR;

View File

@ -52,9 +52,9 @@ class Utf8Helper {
/// This parameter can instead be an ICU style C locale (e.g. "en_US")
//////////////////////////////////////////////////////////////////////////////
explicit Utf8Helper(std::string const& lang);
Utf8Helper(std::string const& lang, char const* binaryPath);
Utf8Helper();
explicit Utf8Helper(char const* binaryPath);
~Utf8Helper();
@ -91,7 +91,7 @@ class Utf8Helper {
/// This parameter can instead be an ICU style C locale (e.g. "en_US")
//////////////////////////////////////////////////////////////////////////////
bool setCollatorLanguage(std::string const& lang);
bool setCollatorLanguage(std::string const& lang, char const* binaryPath);
//////////////////////////////////////////////////////////////////////////////
/// @brief get collator language

View File

@ -2326,7 +2326,7 @@ void TRI_SetUserTempPath(std::string const& path) { TempPath = path; }
#if _WIN32
std::string TRI_LocateInstallDirectory(const char *binaryPath) {
std::string thisPath = TRI_LocateBinaryPath(null);
std::string thisPath = TRI_LocateBinaryPath(nullptr);
return TRI_GetInstallRoot(thisPath, binaryPath) +
std::string(1, TRI_DIR_SEPARATOR_CHAR);
}

View File

@ -336,7 +336,7 @@ bool TRI_CopySymlink(std::string const& srcItem, std::string const& dstItem,
////////////////////////////////////////////////////////////////////////////////
#if _WIN32
std::string TRI_LocateInstallDirectory();
std::string TRI_LocateInstallDirectory(const char* binaryPath);
#endif
////////////////////////////////////////////////////////////////////////////////

View File

@ -312,12 +312,12 @@ int TRI_OPEN_WIN32(char const* filename, int openFlags) {
/// @brief fixes the ICU_DATA environment path
////////////////////////////////////////////////////////////////////////////////
void TRI_FixIcuDataEnv() {
void TRI_FixIcuDataEnv(const char* binaryPath) {
if (getenv("ICU_DATA") != nullptr) {
return;
}
std::string p = TRI_LocateInstallDirectory();
std::string p = TRI_LocateInstallDirectory(binaryPath);
if (!p.empty()) {
std::string e = "ICU_DATA=" + p + ICU_DESTINATION_DIRECTORY;

View File

@ -93,7 +93,7 @@ void TRI_usleep(unsigned long);
/// @brief fixes the ICU_DATA environment path
////////////////////////////////////////////////////////////////////////////////
void TRI_FixIcuDataEnv();
void TRI_FixIcuDataEnv(const char* binaryPath);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a Windows error to a *nix system error

View File

@ -102,6 +102,7 @@ class ProgramOptions {
ProgramOptions(char const* progname, std::string const& usage,
std::string const& more,
const char *binaryPath,
TerminalWidthFuncType const& terminalWidth = TRI_ColumnsWidth,
SimilarityFuncType const& similarity = TRI_Levenshtein)
: _progname(progname),
@ -111,7 +112,8 @@ class ProgramOptions {
_similarity(similarity),
_processingResult(),
_sealed(false),
_overrideOptions(false) {
_overrideOptions(false),
_binaryPath(binaryPath){
// find progname wildcard in string
size_t const pos = _usage.find(ARANGODB_PROGRAM_OPTIONS_PROGNAME);
@ -126,7 +128,7 @@ class ProgramOptions {
// sets a value translator
void setTranslator(
std::function<std::string(std::string const&)> translator) {
std::function<std::string(std::string const&, char const*)> translator) {
_translator = translator;
}
@ -357,7 +359,7 @@ class ProgramOptions {
return true;
}
std::string result = option.parameter->set(_translator(value));
std::string result = option.parameter->set(_translator(value, _binaryPath));
if (!result.empty()) {
// parameter validation failed
@ -621,7 +623,9 @@ class ProgramOptions {
// allow or disallow overriding already set options
bool _overrideOptions;
// translate input values
std::function<std::string(std::string const&)> _translator;
std::function<std::string(std::string const&, char const*)> _translator;
// directory of this binary
char const* _binaryPath;
};
}
}

View File

@ -23,7 +23,7 @@
#include "Translator.h"
#include "Basics/tri-strings.h"
#include "Basics/files.h"
std::string arangodb::options::EnvironmentTranslator(std::string const& value) {
std::string arangodb::options::EnvironmentTranslator(std::string const& value, const char *binaryPath) {
if (value.empty()) {
return value;
}
@ -57,7 +57,7 @@ std::string arangodb::options::EnvironmentTranslator(std::string const& value) {
if (v == nullptr) {
#if _WIN32
if (TRI_EqualString(k.c_str(), "ROOTDIR")) {
vv = TRI_LocateInstallDirectory();
vv = TRI_LocateInstallDirectory(binaryPath);
if (! vv.empty()) {
char c = *(vv.rbegin());

View File

@ -27,7 +27,7 @@
namespace arangodb {
namespace options {
std::string EnvironmentTranslator(std::string const& value);
std::string EnvironmentTranslator(std::string const& value, const char* binaryPath);
}
}