1
0
Fork 0

Merge branch 'devel' into vpack

This commit is contained in:
Max Neunhoeffer 2015-12-21 15:22:46 +01:00
commit 61fe51072c
11 changed files with 192 additions and 127 deletions

View File

@ -7,6 +7,21 @@ v3.0.0 (XXXX-XX-XX)
v2.8.0 (XXXX-XX-XX)
-------------------
* fixes for AQL optimizer and traversal
* added `--create-collection-type` option to arangoimp
This allows specifying the type of the collection to be created when
`--create-collection` is set to `true`.
* randomly shuffle available V8 contexts when picking one for an HTTP or scheduler
task. This distributes requests more evenly across contexts so they can eventually
be garbage-collected.
v2.8.0-beta2 (2015-12-16)
-------------------------
* added AQL query optimizer rule "sort-in-values"
This rule pre-sorts the right-hand side operand of the `IN` and `NOT IN`
@ -293,9 +308,42 @@ v2.8.0-alpha1 (2015-12-03)
re-enabled by explicitly setting the option `returnBodyOnError` to `false` (#1437)
v2.7.4 (XXXX-XX-XX)
-------------------
* randomly shuffle available V8 contexts when picking one for an HTTP or scheduler
task. This distributes requests more evenly across contexts so they can eventually
be garbage-collected.
* added the following attributes to the result of `collection.figures()` and the
corresponding HTTP API at `PUT /_api/collection/<name>/figures`:
- `documentReferences`: The number of references to documents in datafiles
that JavaScript code currently holds. This information can be used for
debugging compaction and unload issues.
- `waitingFor`: An optional string value that contains information about
which object type is at the head of the collection's cleanup queue. This
information can be used for debugging compaction and unload issues.
- `compactionStatus.time`: The point in time the compaction for the collection
was last executed. This information can be used for debugging compaction
issues.
- `compactionStatus.message`: The action that was performed when the compaction
was last run for the collection. This information can be used for debugging
compaction issues.
Note: `waitingFor` and `compactionStatus` may be empty when called on a coordinator
in a cluster.
* the compaction will now provide queryable status info that can be used to track
its progress. The compaction status is displayed in the web interface, too.
v2.7.3 (2015-12-17)
-------------------
* fixed some replication value conversion issues when replication applier properties
were set via ArangoShell
* fixed disappearing of documents for collections transferred via `sync` or
`syncCollection` if the collection was dropped right before synchronization
and drop and (re-)create collection markers were located in the same WAL file

View File

@ -88,7 +88,7 @@ You have two options here, you can either use a managed graph (see [the graphs c
- `edges`: an array of all edges on this path.
- `IN` `MIN`..`MAX` `OUTBOUND` startVertex `GRAPH` graphName
- `OUTBOUND|INBOUND|ANY` traversal will be done for outbound / inbound / inbound+outbound pointing edges
- **startVertex**: one vertex where the traversal will originate from
- **startVertex**: one vertex where the traversal will originate from, this can be specified in the form of an id string or in the form of a document with the attribute `_id`. All other values will lead to a warning and an empty result. If the specified id does not exist, the result is empty as well and there is no warning.
- **graphName**: the name of a managed graph. It's vertex and edge collections will be looked up.
- `MIN`: edges and vertices returned by this query will start at the traversal depth of `MIN` (thus edges and vertices below will not be returned). If not specified, defaults to `1`.
- `MAX`: up to `MAX` length paths are traversed. If omitted in the query, `MAX` equals `MIN`. Thus only the vertices and edges in the range of `MIN` are returned.

View File

@ -335,12 +335,17 @@ void TraversalBlock::initializePaths (AqlItemBlock const* items) {
if (! _usedConstant) {
_usedConstant = true;
auto pos = _vertexId.find("/");
auto v(triagens::arango::traverser::VertexId(
_resolver->getCollectionIdCluster(_vertexId.substr(0, pos).c_str()),
_vertexId.c_str() + pos + 1
));
if (pos == std::string::npos) {
_engine->getQuery()->registerWarning(TRI_ERROR_BAD_PARAMETER, "Invalid input for traversal: Only id strings or objects with _id are allowed");
}
else {
auto v(triagens::arango::traverser::VertexId(
_resolver->getCollectionIdCluster(_vertexId.substr(0, pos).c_str()),
_vertexId.c_str() + pos + 1
));
_traverser->setStartVertex(v);
_traverser->setStartVertex(v);
}
}
}
else {
@ -373,7 +378,7 @@ void TraversalBlock::initializePaths (AqlItemBlock const* items) {
_traverser->setStartVertex(v);
}
else {
_engine->getQuery()->registerWarning(TRI_ERROR_BAD_PARAMETER, "Invalid input for traversal: Only strings or objects with _id are allowed");
_engine->getQuery()->registerWarning(TRI_ERROR_BAD_PARAMETER, "Invalid input for traversal: Only id strings or objects with _id are allowed");
}
}
}

View File

@ -148,7 +148,7 @@ TraversalNode::TraversalNode (ExecutionPlan* plan,
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, "invalid start vertex. Must either be an _id string or an object with _id.");
}
_inVariable = nullptr;
_vertexId = start->getStringValue();
_vertexId = std::string(start->getStringValue(), start->getStringLength());;
break;
default:
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, "invalid start vertex. Must either be an _id string or an object with _id.");

View File

@ -438,6 +438,9 @@ ApplicationV8::V8Context* ApplicationV8::enterContext (TRI_vocbase_t* vocbase,
LOG_TRACE("found unused V8 context");
TRI_ASSERT(! _freeContexts.empty());
// randomly shuffle free contexts so that different get contexts get used (and garbage collected)
std::random_shuffle(_freeContexts.begin(), _freeContexts.end());
context = _freeContexts.back();
TRI_ASSERT(context != nullptr);
@ -692,8 +695,8 @@ void ApplicationV8::collectGarbage () {
TRI_ASSERT(v8::Locker::IsLocked(isolate));
TRI_GET_GLOBALS();
hasActiveExternals = v8g->hasActiveExternals();
TRI_RunGarbageCollectionV8(isolate, 1.0);
hasActiveExternals = v8g->hasActiveExternals();
localContext->Exit();
}

View File

@ -50,16 +50,16 @@
// --SECTION-- private constants
// -----------------------------------------------------------------------------
static char const* ReasonNoDatafiles = "collection has no datafiles";
static char const* ReasonCompactionBlocked = "existing compactor file is in the way and waiting to be processed";
static char const* ReasonDatafileSmall = "datafile is small and will be merged with next";
static char const* ReasonEmpty = "datafile contains data but collection is empty";
static char const* ReasonOnlyDeletions = "datafile contains only deletion markers";
static char const* ReasonDeadSize = "datafile contains much dead object space";
static char const* ReasonDeadSizeShare = "datafile contains high share of dead objects";
static char const* ReasonDeadCount = "datafile contains many dead objects";
static char const* ReasonDeletionCount = "datafile contains many deletions";
static char const* ReasonNothingToCompact = "no compaction opportunity found during inspection";
static char const* ReasonNoDatafiles = "skipped compaction because collection has no datafiles";
static char const* ReasonCompactionBlocked = "skipped compaction because existing compactor file is in the way and waits to be processed";
static char const* ReasonDatafileSmall = "compacting datafile because it's small and will be merged with next";
static char const* ReasonEmpty = "compacting datafile because it collection is empty";
static char const* ReasonOnlyDeletions = "compacting datafile because it contains only deletion markers";
static char const* ReasonDeadSize = "compacting datafile because it contains much dead object space";
static char const* ReasonDeadSizeShare = "compacting datafile because it contains high share of dead objects";
static char const* ReasonDeadCount = "compacting datafile because it contains many dead objects";
static char const* ReasonDeletionCount = "compacting datafile because it contains many deletions";
static char const* ReasonNothingToCompact = "checked datafiles, but no compaction opportunity found";
////////////////////////////////////////////////////////////////////////////////
/// @brief minimum size of dead data (in bytes) in a datafile that will make

View File

@ -40,7 +40,7 @@
<div class="contentDiv" id="arangoCollectionsContainer">
<div id="userManagementThumbnailsIn" class="tileList">
<div class="tileList">
<div class="tile">
<div class="fullBorderBox">
<a href="#" id="createDatabase" class="add">

View File

@ -526,8 +526,11 @@
}
}
var origin = window.location.href.split("/"),
preUrl = origin[0] + '//' + origin[2] + '/' + origin[3] + '/_system/' + origin[5] + '/' + origin[6] + '/';
$.ajax(
url + urlParams,
preUrl + url + urlParams,
{async: true}
).done(
function (d) {

View File

@ -13,21 +13,22 @@
template: templateEngine.createTemplate("userManagementView.ejs"),
events: {
"click #createUser" : "createUser",
"click #submitCreateUser" : "submitCreateUser",
"click #createUser" : "createUser",
"click #submitCreateUser" : "submitCreateUser",
// "click #deleteUser" : "removeUser",
// "click #submitDeleteUser" : "submitDeleteUser",
"click .editUser" : "editUser",
"click .icon" : "editUser",
"click #submitEditUser" : "submitEditUser",
"click #userManagementToggle" : "toggleView",
"keyup #userManagementSearchInput" : "search",
"click #userManagementSearchSubmit" : "search",
"click #callEditUserPassword" : "editUserPassword",
"click #submitEditUserPassword" : "submitEditUserPassword",
"click #submitEditCurrentUserProfile" : "submitEditCurrentUserProfile",
"click .css-label" : "checkBoxes",
"change #userSortDesc" : "sorting"
// "click .editUser" : "editUser",
// "click .icon" : "editUser",
"click #userManagementThumbnailsIn .tile" : "editUser",
"click #submitEditUser" : "submitEditUser",
"click #userManagementToggle" : "toggleView",
"keyup #userManagementSearchInput" : "search",
"click #userManagementSearchSubmit" : "search",
"click #callEditUserPassword" : "editUserPassword",
"click #submitEditUserPassword" : "submitEditUserPassword",
"click #submitEditCurrentUserProfile" : "submitEditCurrentUserProfile",
"click .css-label" : "checkBoxes",
"change #userSortDesc" : "sorting"
},
@ -202,6 +203,11 @@
},
editUser : function(e) {
if ($(e.currentTarget).hasClass('tile')) {
e.currentTarget = $(e.currentTarget).find('img');
}
this.collection.fetch();
var username = this.evaluateUserName($(e.currentTarget).attr("id"), '_edit-user');
if (username === '') {

View File

@ -328,7 +328,7 @@
bottom: 12.1% !important;
left: 50%;
margin-left: -($int-width) / 2;
width: $int-width + 20px;
width: $int-width + 20px !important;
.modal-body {
// min-height: $dashboard-height;

View File

@ -766,6 +766,61 @@ function multiCollectionGraphSuite () {
});
},
testOtherCollectionAttributeAccessInput: function () {
var query = "FOR y IN @@vCol "
+ "FOR x IN OUTBOUND y._id @@eCol SORT x._id ASC RETURN x._id";
var bindVars = {
"@eCol": en,
"@vCol": vn
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 6);
assertEqual(result[0], vertex.B);
assertEqual(result[1], vertex.B);
assertEqual(result[2], vertex.C);
assertEqual(result[3], vertex.D);
assertEqual(result[4], vertex.E);
assertEqual(result[5], vertex.F);
},
testTraversalAttributeAccessInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "FOR y IN OUTBOUND x._id @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
},
testTraversalLetIdInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "LET next = x._id "
+ "FOR y IN OUTBOUND next @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
},
testTraversalLetDocInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "LET next = x "
+ "FOR y IN OUTBOUND next @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
}
};
}
@ -847,62 +902,8 @@ function multiEdgeCollectionGraphSuite () {
var jsonResult = AQL_EXECUTEJSON(plan, { optimizer: { rules: [ "-all" ] } }).json;
assertEqual(jsonResult, result, query);
});
},
testOtherCollectionAttributeAccessInput: function () {
var query = "FOR y IN @@vCol "
+ "FOR x IN OUTBOUND y._id @@eCol SORT x._id ASC RETURN x._id";
var bindVars = {
"@eCol": en,
"@vCol": vn
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 6);
assertEqual(result[0], vertex.B);
assertEqual(result[1], vertex.B);
assertEqual(result[2], vertex.C);
assertEqual(result[3], vertex.D);
assertEqual(result[4], vertex.E);
assertEqual(result[5], vertex.F);
},
testTraversalAttributeAccessInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "FOR y IN OUTBOUND x._id @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
},
testTraversalLetIdInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "LET next = x._id "
+ "FOR y IN OUTBOUND next @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
},
testTraversalLetDocInput: function () {
var query = "FOR x IN OUTBOUND @startId @@eCol "
+ "LET next = x "
+ "FOR y IN OUTBOUND next @@eCol SORT y._id ASC RETURN y._id";
var bindVars = {
"@eCol": en,
"startId": vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
}
};
}
@ -1027,11 +1028,11 @@ function potentialErrorsSuite () {
"@eCol": en,
"@vCol": vn
};
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 1);
},
testStepsSubquery: function() {
@ -1042,6 +1043,7 @@ function potentialErrorsSuite () {
};
try {
db._query(query, bindVars).toArray();
fail();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
@ -1054,6 +1056,7 @@ function potentialErrorsSuite () {
};
try {
db._query(query, bindVars).toArray();
fail();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
@ -1066,6 +1069,7 @@ function potentialErrorsSuite () {
};
try {
db._query(query, bindVars).toArray();
fail();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
@ -1076,11 +1080,11 @@ function potentialErrorsSuite () {
var bindVars = {
"@eCol": en,
};
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 1);
},
testCrazyStart4: function () {
@ -1088,11 +1092,11 @@ function potentialErrorsSuite () {
var bindVars = {
"@eCol": en,
};
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 1);
},
testCrazyStart5: function () {
@ -1100,11 +1104,11 @@ function potentialErrorsSuite () {
var bindVars = {
"@eCol": en,
};
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 0);
},
testCrazyStart6: function () {
@ -1125,14 +1129,14 @@ function potentialErrorsSuite () {
"@eCol": en,
"@vCol": vn
};
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 1);
// Fix the query, just use the first value
query = "FOR x IN OUTBOUND (FOR y IN @@vCol FILTER y._id == @startId RETURN y)[0] @@eCol RETURN x._id";
var result = db._query(query, bindVars).toArray();
result = db._query(query, bindVars).toArray();
assertEqual(result.length, 1);
assertEqual(result[0], vertex.C);
},
@ -1143,19 +1147,15 @@ function potentialErrorsSuite () {
"startId": vertex.A,
"@eCol": en
};
// Fail because it is an array
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
var x = db._query(query, bindVars);
var result = x.toArray();
var extra = x.getExtra();
assertEqual(result, []);
assertEqual(extra.warnings.length, 1);
// Actually use the string!
query = "FOR x IN OUTBOUND (FOR y IN @@eCol FILTER y._id == @startId RETURN 'peter')[0] @@eCol RETURN x._id";
try {
db._query(query, bindVars).toArray();
} catch (e) {
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
}
result = db._query(query, bindVars).toArray();
assertEqual(result.length, 0);
}
};