mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/ArangoDB into devel
This commit is contained in:
commit
5a0857d910
16
CHANGELOG
16
CHANGELOG
|
@ -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)
|
||||
--------------------
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 = [¬Supported](AstNode const* n, void*) -> bool {
|
||||
auto supportedGuard = [¬Supported, pathVar](AstNode const* n, void*) -> bool {
|
||||
if (notSupported) {
|
||||
return false;
|
||||
}
|
||||
if (!IsSupportedNode(n)) {
|
||||
if (!IsSupportedNode(pathVar, n)) {
|
||||
notSupported = true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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]());
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue