1
0
Fork 0

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

This commit is contained in:
Wilfried Goesgens 2017-02-23 13:30:02 +01:00
commit 5a0857d910
10 changed files with 149 additions and 57 deletions

View File

@ -10,7 +10,7 @@ v3.2.alpha2 (2017-02-20)
* Removed undocumented internal HTTP API:
* PUT _api/edges
The documented GET _api/edges and the undocumented POST _api/edges remains unmodified.
* moved V8 code into a git submodule
@ -35,6 +35,12 @@ v3.2.alpha2 (2017-02-20)
arangoexport can be used to export collections to json, jsonl or xml
and export a graph or collections to xgmml.
* fixed a race condition when closing a connection
* raised default hard limit on threads for very small to 64
* fixed negative counting of http connection in UI
v3.2.alpha1 (2017-02-05)
------------------------
@ -61,8 +67,16 @@ v3.2.alpha1 (2017-02-05)
v3.1.12 (XXXX-XX-XX)
--------------------
* fixed issue #2320
* fixed issue #2315
* fixed a race condition when closing a connection
* raised default hard limit on threads for very small to 64
* fixed negative counting of http connection in UI
v3.1.11 (2017-02-17)
--------------------

View File

@ -853,7 +853,9 @@ void AqlValue::toVelocyPack(transaction::Methods* trx,
case VPACK_INLINE:
case VPACK_MANAGED: {
if (resolveExternals) {
arangodb::basics::VelocyPackHelper::SanitizeExternals(slice(), builder);
bool const sanitizeExternals = true;
bool const sanitizeCustom = true;
arangodb::basics::VelocyPackHelper::sanitizeNonClientTypes(slice(), VPackSlice::noneSlice(), builder, trx->transactionContextPtr()->getVPackOptions(), sanitizeExternals, sanitizeCustom);
} else {
builder.add(slice());
}

View File

@ -103,7 +103,57 @@ static AstNode* BuildExpansionReplacement(Ast* ast, AstNode const* condition, As
return ast->createNodeBinaryOperator(type, lhs, rhs);
}
static inline bool IsSupportedNode(AstNode const* node) {
static bool IsSupportedNode(Variable const* pathVar, AstNode const* node) {
// do a quick first check for all comparisons
switch (node->type) {
case NODE_TYPE_OPERATOR_BINARY_ARRAY_EQ:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_NE:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_LT:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_LE:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_GT:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_GE:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_IN:
case NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN:
case NODE_TYPE_OPERATOR_BINARY_EQ:
case NODE_TYPE_OPERATOR_BINARY_NE:
case NODE_TYPE_OPERATOR_BINARY_LT:
case NODE_TYPE_OPERATOR_BINARY_LE:
case NODE_TYPE_OPERATOR_BINARY_GT:
case NODE_TYPE_OPERATOR_BINARY_GE:
case NODE_TYPE_OPERATOR_BINARY_IN:
case NODE_TYPE_OPERATOR_BINARY_NIN: {
// the following types of expressions are not supported
// p.edges[0]._from op whatever attribute access
// whatever attribute access op p.edges[0]._from
AstNode const* lhs = node->getMember(0);
AstNode const* rhs = node->getMember(1);
if (lhs->isAttributeAccessForVariable(pathVar, true)) {
// p.xxx op whatever
if (rhs->type != NODE_TYPE_VALUE &&
rhs->type != NODE_TYPE_ARRAY &&
rhs->type != NODE_TYPE_OBJECT &&
rhs->type != NODE_TYPE_REFERENCE) {
return false;
}
} else if (rhs->isAttributeAccessForVariable(pathVar, true)) {
// whatever op p.xxx
if (lhs->type != NODE_TYPE_VALUE &&
lhs->type != NODE_TYPE_ARRAY &&
lhs->type != NODE_TYPE_OBJECT &&
lhs->type != NODE_TYPE_REFERENCE) {
return false;
}
}
break;
}
default: {
// intentionally no other cases defined...
// we'll simply fall through to the next switch..case statement
break;
}
}
switch (node->type) {
case NODE_TYPE_VARIABLE:
case NODE_TYPE_OPERATOR_UNARY_PLUS:
@ -169,7 +219,7 @@ static bool checkPathVariableAccessFeasible(Ast* ast, AstNode* parent,
Variable const* pathVar,
bool& conditionIsImpossible) {
AstNode* node = parent->getMemberUnchecked(testIndex);
if (!IsSupportedNode(node)) {
if (!IsSupportedNode(pathVar, node)) {
return false;
}
// We need to walk through each branch and validate:
@ -193,11 +243,11 @@ static bool checkPathVariableAccessFeasible(Ast* ast, AstNode* parent,
// We define that patternStep >= 6 is complete Match.
unsigned char patternStep = 0;
auto supportedGuard = [&notSupported](AstNode const* n, void*) -> bool {
auto supportedGuard = [&notSupported, pathVar](AstNode const* n, void*) -> bool {
if (notSupported) {
return false;
}
if (!IsSupportedNode(n)) {
if (!IsSupportedNode(pathVar, n)) {
notSupported = true;
return false;
}

View File

@ -212,6 +212,10 @@ bool Scheduler::start(ConditionVariable* cv) {
_nrRealMaximum = 4 * _nrMaximal;
}
if (_nrRealMaximum <= 64) {
_nrRealMaximum = 64;
}
for (size_t i = 0; i < 2; ++i) {
startNewThread();
}

View File

@ -46,6 +46,14 @@ boost::lockfree::queue<
// --SECTION-- static public methods
// -----------------------------------------------------------------------------
void ConnectionStatistics::SET_HTTP(ConnectionStatistics* stat) {
if (stat != nullptr) {
stat->_http = true;
TRI_HttpConnectionsStatistics.incCounter();
}
}
void ConnectionStatistics::initialize() {
_statisticsBuffer.reset(new ConnectionStatistics[QUEUE_SIZE]());

View File

@ -47,11 +47,7 @@ class ConnectionStatistics {
}
}
static void SET_HTTP(ConnectionStatistics* stat) {
if (stat != nullptr) {
stat->_http = true;
}
}
static void SET_HTTP(ConnectionStatistics* stat);
static void fill(basics::StatisticsCounter& httpConnections,
basics::StatisticsCounter& totalRequests,

View File

@ -2048,7 +2048,8 @@ static void JS_IsSystemDatabase(
////////////////////////////////////////////////////////////////////////////////
/// @brief fake this method so the interface is similar to the client.
////////////////////////////////////////////////////////////////////////////////
static void JS_fakeFlushCache(v8::FunctionCallbackInfo<v8::Value> const& args) {
static void JS_FakeFlushCache(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_TRY_CATCH_BEGIN(isolate);
TRI_V8_RETURN_UNDEFINED();
TRI_V8_TRY_CATCH_END;
@ -2057,6 +2058,7 @@ static void JS_fakeFlushCache(v8::FunctionCallbackInfo<v8::Value> const& args) {
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock databaseUseDatabase
////////////////////////////////////////////////////////////////////////////////
static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate);
@ -2125,7 +2127,7 @@ static void ListDatabasesCoordinator(
std::vector<DatabaseID> list = ci->databases(true);
v8::Handle<v8::Array> result = v8::Array::New(isolate);
for (size_t i = 0; i < list.size(); ++i) {
result->Set((uint32_t)i, TRI_V8_STD_STRING(list[i]));
result->Set(static_cast<uint32_t>(i), TRI_V8_STD_STRING(list[i]));
}
TRI_V8_RETURN(result);
} else {
@ -2883,9 +2885,8 @@ void TRI_InitV8VocBridge(v8::Isolate* isolate, v8::Handle<v8::Context> context,
JS_Databases);
TRI_AddMethodVocbase(isolate, ArangoNS, TRI_V8_ASCII_STRING("_useDatabase"),
JS_UseDatabase);
TRI_AddMethodVocbase(isolate, ArangoNS, TRI_V8_ASCII_STRING("_flushCache"),
JS_fakeFlushCache, true);
JS_FakeFlushCache, true);
TRI_InitV8Statistics(isolate, context);

View File

@ -998,41 +998,20 @@ uint64_t VelocyPackHelper::hashByAttributes(
}
#endif
void VelocyPackHelper::SanitizeExternals(VPackSlice const input,
VPackBuilder& output) {
bool VelocyPackHelper::hasNonClientTypes(VPackSlice input, bool checkExternals, bool checkCustom) {
if (input.isExternal()) {
// recursively resolve externals
SanitizeExternals(input.resolveExternal(), output);
return checkExternals;
} else if (input.isCustom()) {
return checkCustom;
} 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);
}
}
bool VelocyPackHelper::hasExternals(VPackSlice input) {
if (input.isExternal()) {
return true;
} else if (input.isObject()) {
for (auto const& it : VPackObjectIterator(input)) {
if (hasExternals(it.value)) {
for (auto const& it : VPackObjectIterator(input, true)) {
if (hasNonClientTypes(it.value, checkExternals, checkCustom)) {
return true;
}
}
} else if (input.isArray()) {
for (auto const& it : VPackArrayIterator(input)) {
if (hasExternals(it)) {
if (hasNonClientTypes(it, checkExternals, checkCustom)) {
return true;
}
}
@ -1040,16 +1019,50 @@ bool VelocyPackHelper::hasExternals(VPackSlice input) {
return false;
}
VPackBuffer<uint8_t> VelocyPackHelper::sanitizeExternalsChecked(
VPackSlice input, VPackOptions const* options, bool checkExternals) {
void VelocyPackHelper::sanitizeNonClientTypes(VPackSlice input,
VPackSlice base,
VPackBuilder& output,
VPackOptions const* options,
bool sanitizeExternals,
bool sanitizeCustom) {
if (sanitizeExternals && input.isExternal()) {
// recursively resolve externals
sanitizeNonClientTypes(input.resolveExternal(), base, output, options, sanitizeExternals, sanitizeCustom);
} else if (sanitizeCustom && input.isCustom()) {
if (options == nullptr || options->customTypeHandler == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "cannot sanitize vpack without custom type handler");
}
std::string custom = options->customTypeHandler->toString(input, options, base);
output.add(VPackValue(custom));
} else if (input.isObject()) {
output.openObject();
for (auto const& it : VPackObjectIterator(input)) {
output.add(VPackValue(it.key.copyString()));
sanitizeNonClientTypes(it.value, input, output, options, sanitizeExternals, sanitizeCustom);
}
output.close();
} else if (input.isArray()) {
output.openArray();
for (auto const& it : VPackArrayIterator(input)) {
sanitizeNonClientTypes(it, input, output, options, sanitizeExternals, sanitizeCustom);
}
output.close();
} else {
output.add(input);
}
}
VPackBuffer<uint8_t> VelocyPackHelper::sanitizeNonClientTypesChecked(
VPackSlice input, VPackOptions const* options, bool sanitizeExternals, bool sanitizeCustom) {
VPackBuffer<uint8_t> buffer;
VPackBuilder builder(buffer, options);
bool resolveExt = true;
if (checkExternals) {
resolveExt = hasExternals(input);
if (sanitizeExternals) {
resolveExt = hasNonClientTypes(input, sanitizeExternals, sanitizeCustom);
}
if (resolveExt) { // resolve
SanitizeExternals(input, builder);
buffer.reserve(input.byteSize()); // reserve space space already
sanitizeNonClientTypes(input, VPackSlice::noneSlice(), builder, options, sanitizeExternals, sanitizeCustom);
} else {
builder.add(input);
}

View File

@ -402,16 +402,20 @@ class VelocyPackHelper {
static constexpr arangodb::velocypack::Slice IllegalValue() {
return arangodb::velocypack::Slice::illegalSlice();
}
static bool hasNonClientTypes(arangodb::velocypack::Slice, bool checkExternals, bool checkCustom);
static void SanitizeExternals(arangodb::velocypack::Slice const,
arangodb::velocypack::Builder&);
static void sanitizeNonClientTypes(arangodb::velocypack::Slice input,
arangodb::velocypack::Slice base,
arangodb::velocypack::Builder& output,
arangodb::velocypack::Options const*,
bool sanitizeExternals, bool sanitizeCustom);
static bool hasExternals(arangodb::velocypack::Slice const);
static VPackBuffer<uint8_t> sanitizeExternalsChecked(
arangodb::velocypack::Slice const,
static VPackBuffer<uint8_t> sanitizeNonClientTypesChecked(
arangodb::velocypack::Slice,
VPackOptions const* options = &VPackOptions::Options::Defaults,
bool checkExternals = true);
bool sanitizeExternals = true,
bool sanitizeCustom = true);
static uint64_t extractIdValue(VPackSlice const& slice);

View File

@ -52,7 +52,7 @@ void GeneralResponse::addPayload(VPackSlice const& slice,
if (!skipBody) {
if (resolveExternals) {
auto tmpBuffer =
basics::VelocyPackHelper::sanitizeExternalsChecked(slice, options);
basics::VelocyPackHelper::sanitizeNonClientTypesChecked(slice, options);
_vpackPayloads.push_back(std::move(tmpBuffer));
} else {
// just copy
@ -76,7 +76,7 @@ void GeneralResponse::addPayload(VPackBuffer<uint8_t>&& buffer,
addPayloadPreHook(true, resolveExternals, skipBody);
if (!skipBody) {
if (resolveExternals) {
auto tmpBuffer = basics::VelocyPackHelper::sanitizeExternalsChecked(
auto tmpBuffer = basics::VelocyPackHelper::sanitizeNonClientTypesChecked(
VPackSlice(buffer.data()), options);
_vpackPayloads.push_back(std::move(tmpBuffer));
} else {