mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' into jwt
This commit is contained in:
commit
74719c76a6
|
@ -154,6 +154,210 @@ POW( 5, -1 ) // 0.2
|
|||
POW( 5, 0 ) // 1
|
||||
```
|
||||
|
||||
!SUBSECTION LOG()
|
||||
|
||||
`LOG(value) → num`
|
||||
|
||||
Returns the natural logarithm of *value*. The base is Euler's
|
||||
constant (2.71828...).
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the natural logarithm of *value*
|
||||
|
||||
```js
|
||||
LOG(2.718281828459045) // 1
|
||||
LOG(10) // 2.302585092994046
|
||||
LOG(0) // null
|
||||
```
|
||||
|
||||
!SUBSECTION LOG2()
|
||||
|
||||
`LOG2(value) → num`
|
||||
|
||||
Returns the base 2 logarithm of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the base 2 logarithm of *value*
|
||||
|
||||
```js
|
||||
LOG2(1024) // 10
|
||||
LOG2(8) // 3
|
||||
LOG2(0) // null
|
||||
```
|
||||
|
||||
!SUBSECTION LOG10()
|
||||
|
||||
`LOG10(value) → num`
|
||||
|
||||
Returns the base 10 logarithm of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the base 10 logarithm of *value*
|
||||
|
||||
```js
|
||||
LOG10(10000) // 10
|
||||
LOG10(10) // 1
|
||||
LOG10(0) // null
|
||||
```
|
||||
|
||||
!SUBSECTION EXP()
|
||||
|
||||
`EXP(value) → num`
|
||||
|
||||
Returns Euler's constant (2.71828...) raised to the power of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): Euler's constant raised to the power of *value*
|
||||
|
||||
```js
|
||||
EXP(1) // 2.718281828459045
|
||||
EXP(10) // 22026.46579480671
|
||||
EXP(0) // 1
|
||||
```
|
||||
|
||||
!SUBSECTION EXP2()
|
||||
|
||||
`EXP2(value) → num`
|
||||
|
||||
Returns 2 raised to the power of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): 2 raised to the power of *value*
|
||||
|
||||
```js
|
||||
EXP2(16) // 65536
|
||||
EXP2(1) // 2
|
||||
EXP2(0) // 1
|
||||
```
|
||||
|
||||
!SUBSECTION SIN()
|
||||
|
||||
`SIN(value) → num`
|
||||
|
||||
Returns the sine of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the sine of *value*
|
||||
|
||||
```js
|
||||
SIN(3.141592653589783 / 2) // 1
|
||||
SIN(0) // 0
|
||||
SIN(-3.141592653589783 / 2) // -1
|
||||
```
|
||||
|
||||
!SUBSECTION COS()
|
||||
|
||||
`COS(value) → num`
|
||||
|
||||
Returns the cosine of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the cosine of *value*
|
||||
|
||||
```js
|
||||
COS(1) // 0.5403023058681398
|
||||
COS(0) // 1
|
||||
COS(-3.141592653589783) // -1
|
||||
```
|
||||
|
||||
!SUBSECTION TAN()
|
||||
|
||||
`TAN(value) → num`
|
||||
|
||||
Returns the tangent of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the tangent of *value*
|
||||
|
||||
```js
|
||||
TAN(10) // 0.6483608274590866
|
||||
TAN(5) // -3.380515006246586
|
||||
TAN(0) // 0
|
||||
```
|
||||
|
||||
!SUBSECTION ASIN()
|
||||
|
||||
`ASIN(value) → num`
|
||||
|
||||
Returns the arcsine of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the arcsine of *value*
|
||||
|
||||
```js
|
||||
ASIN(-1) // -1.5707963267948966
|
||||
ASIN(0) // 0
|
||||
ASIN(2) // null
|
||||
2) // null
|
||||
```
|
||||
|
||||
!SUBSECTION ACOS()
|
||||
|
||||
`ACOS(value) → num`
|
||||
|
||||
Returns the arccosine of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the arccosine of *value*
|
||||
|
||||
```js
|
||||
ACOS(-1) // 3.141592653589793
|
||||
ACOS(0) // 1.5707963267948966
|
||||
ACOS(1) // 0
|
||||
```
|
||||
|
||||
!SUBSECTION ATAN()
|
||||
|
||||
`ATAN(value) → num`
|
||||
|
||||
Returns the arctangent of *value*.
|
||||
|
||||
- **value** (number): the input value
|
||||
- returns **num** (number): the arctangent of *value*
|
||||
|
||||
```js
|
||||
ATAN(-1) // -0.7853981633974483
|
||||
ATAN(0) // 0
|
||||
ATAN(10) // 1.4711276743037347
|
||||
```
|
||||
|
||||
!SUBSECTION ATAN2()
|
||||
|
||||
`ATAN2(y, x) → num`
|
||||
|
||||
Returns the arctangent of quotient of *y* and *x*.
|
||||
```
|
||||
|
||||
!SUBSECTION DEGREES()
|
||||
|
||||
`DEGREES(rad) → num`
|
||||
|
||||
Returns the angle converted from radians to degrees.
|
||||
|
||||
- **rad** (number): the input value
|
||||
- returns **num** (number): the angle in degrees
|
||||
|
||||
```js
|
||||
DEGREES(0.7853981633974483) // 45
|
||||
DEGREES(0) // 0
|
||||
DEGREES(3.141592653589793) // 180
|
||||
```
|
||||
|
||||
!SUBSECTION RADIANS()
|
||||
|
||||
`RADIANS(deg) → num`
|
||||
|
||||
Returns the angle converted from degrees to radians.
|
||||
|
||||
- **deg** (number): the input value
|
||||
- returns **num** (number): the angle in radians
|
||||
|
||||
```js
|
||||
RADIANS(180) // 3.141592653589793
|
||||
RADIANS(90) // 1.5707963267948966
|
||||
RADIANS(0) // 0
|
||||
```
|
||||
|
||||
!SUBSECTION RAND()
|
||||
|
||||
`RAND() → randomNumber`
|
||||
|
|
|
@ -105,6 +105,35 @@ The following AQL functions have been added in 3.0:
|
|||
- *TYPENAME(value)*: Returns the data type name of *value*. The data type name can
|
||||
be either *null*, *bool*, *number*, *string*, *array* or *object*.
|
||||
|
||||
- *LOG(value)*: Returns the natural logarithm of *value*. The base is Euler's constant
|
||||
(2.71828...).
|
||||
|
||||
- *LOG2(value)*: Returns the base 2 logarithm of *value*.
|
||||
|
||||
- *LOG10(value)*: Returns the base 10 logarithm of *value*.
|
||||
|
||||
- *EXP(value)*: Returns Euler's constant (2.71828...) raised to the power of *value*.
|
||||
|
||||
- *EXP2(value)*: Returns 2 raised to the power of *value*.
|
||||
|
||||
- *SIN(value)*: Returns the sine of *value*.
|
||||
|
||||
- *COS(value)*: Returns the cosine of *value*.
|
||||
|
||||
- *TAN(value)*: Returns the tangent of *value*.
|
||||
|
||||
- *ASIN(value)*: Returns the arcsine of *value*.
|
||||
|
||||
- *ACOS(value)*: Returns the arccosine of *value*.
|
||||
|
||||
- *ATAN(value)*: Returns the arctangent of *value*.
|
||||
|
||||
- *ATAN2(y, x)*: Returns the arctangent of the quotient of *y* and *x*.
|
||||
|
||||
- *RADIANS(value)*: Returns the angle converted from degrees to radians.
|
||||
|
||||
- *DEGREES(value)*: Returns the angle converted from radians to degrees.
|
||||
|
||||
!SUBSECTION Optimizer improvements
|
||||
|
||||
!SUBSUBSECTION "inline-subqueries" rule
|
||||
|
|
|
@ -249,9 +249,9 @@ win64-relative-debug:
|
|||
pack-winXX:
|
||||
rm -rf ../b && mkdir ../b
|
||||
|
||||
${MAKE} winXX-cmake BITS="$(BITS)" TARGET="$(TARGET)"
|
||||
${MAKE} winXX-cmake BITS="$(BITS)" TARGET="$(TARGET)" BUILD_TARGET=RelWithDebInfo
|
||||
${MAKE} winXX-build BITS="$(BITS)" TARGET="$(TARGET)" BUILD_TARGET=RelWithDebInfo
|
||||
${MAKE} packXX BITS="$(BITS)"
|
||||
${MAKE} packXX BITS="$(BITS)" BUILD_TARGET=RelWithDebInfo
|
||||
|
||||
pack-winXX-MOREOPTS:
|
||||
rm -rf ../b && mkdir ../b
|
||||
|
|
|
@ -44,7 +44,7 @@ AgencyFeature::AgencyFeature(application_features::ApplicationServer* server)
|
|||
_notify(false),
|
||||
_supervision(false),
|
||||
_waitForSync(true),
|
||||
_supervisionFrequency(5.0),
|
||||
_supervisionFrequency(1.0),
|
||||
_compactionStepSize(1000) {
|
||||
setOptional(true);
|
||||
requiresElevatedPrivileges(false);
|
||||
|
@ -190,9 +190,22 @@ void AgencyFeature::start() {
|
|||
}
|
||||
|
||||
void AgencyFeature::stop() {
|
||||
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_agent->beginShutdown();
|
||||
|
||||
if (_agent != nullptr) {
|
||||
int counter = 0;
|
||||
while (_agent->isRunning()) {
|
||||
usleep(100000);
|
||||
// emit warning after 5 seconds
|
||||
if (++counter == 10 * 5) {
|
||||
LOG(WARN) << "waiting for agent thread to finish";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -316,7 +316,8 @@ bool Agent::load() {
|
|||
|
||||
// Write new entries to replicated state and store
|
||||
write_ret_t Agent::write(query_t const& query) {
|
||||
if (_constituent.leading()) { // Only working as leader
|
||||
|
||||
if (_constituent.leading()) { // Only leader
|
||||
|
||||
std::vector<bool> applied;
|
||||
std::vector<index_t> indices;
|
||||
|
@ -341,6 +342,7 @@ write_ret_t Agent::write(query_t const& query) {
|
|||
} else { // Else we redirect
|
||||
return write_ret_t(false, _constituent.leaderID());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Read from store
|
||||
|
@ -379,13 +381,15 @@ void Agent::beginShutdown() {
|
|||
// Personal hygiene
|
||||
Thread::beginShutdown();
|
||||
|
||||
// Stop supervision
|
||||
if (_config.supervision) {
|
||||
_supervision.beginShutdown();
|
||||
}
|
||||
|
||||
// Stop constituent and key value stores
|
||||
_constituent.beginShutdown();
|
||||
_spearhead.beginShutdown();
|
||||
_readDB.beginShutdown();
|
||||
if (_config.supervision) {
|
||||
_supervision.beginShutdown();
|
||||
}
|
||||
|
||||
// Wake up all waiting REST handler (waitFor)
|
||||
CONDITION_LOCKER(guard, _appendCV);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "Agent.h"
|
||||
#include "Job.h"
|
||||
#include "MoveShard.h"
|
||||
|
||||
using namespace arangodb::consensus;
|
||||
|
||||
|
@ -35,6 +36,9 @@ CleanOutServer::CleanOutServer (
|
|||
Job(snapshot, agent, jobId, creator, prefix), _server(server) {
|
||||
|
||||
if (exists()) {
|
||||
if (_server == "") {
|
||||
_server = _snapshot(pendingPrefix + _jobId + "/server").getString();
|
||||
}
|
||||
if (status() == TODO) {
|
||||
start();
|
||||
}
|
||||
|
@ -113,40 +117,17 @@ bool CleanOutServer::start() const {
|
|||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) << "Pending: Clean out server " + _server;
|
||||
|
||||
Node::Children const& databases =
|
||||
_snapshot("/Plan/Collections").children();
|
||||
|
||||
size_t sub = 0;
|
||||
|
||||
for (auto const& database : databases) {
|
||||
for (auto const& collptr : database.second->children()) {
|
||||
Node const& collection = *(collptr.second);
|
||||
Node const& replicationFactor = collection("replicationFactor");
|
||||
if (replicationFactor.slice().getUInt() > 1) {
|
||||
for (auto const& shard : collection("shards").children()) {
|
||||
VPackArrayIterator dbsit(shard.second->slice());
|
||||
|
||||
// Only proceed if leader and create job
|
||||
if ((*dbsit.begin()).copyString() != _server) {
|
||||
/* MoveShardFromLeader (
|
||||
_snapshot, _agent, _jobId + "-" + std::to_string(sub++),
|
||||
_jobId, _agencyPrefix, database.first, collptr.first,
|
||||
shard.first, _server, shard.second->slice()[1].copyString());*/
|
||||
sub++;
|
||||
} else {
|
||||
/* MoveShardFromFollower (
|
||||
_snapshot, _agent, _jobId + "-" + std::to_string(sub++),
|
||||
_jobId, _agencyPrefix, database.first, collptr.first,
|
||||
shard.first, _server, shard.second->slice()[1].copyString());*/
|
||||
sub++;
|
||||
// Check if we can get things done in the first place
|
||||
if (!checkFeasibility()) {
|
||||
finish("DBServers/" + _server);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Schedule shard relocations
|
||||
scheduleMoveShards();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) <<
|
||||
|
@ -154,6 +135,44 @@ bool CleanOutServer::start() const {
|
|||
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool CleanOutServer::scheduleMoveShards() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CleanOutServer::checkFeasibility () const {
|
||||
|
||||
// Check if server is already in cleaned servers: fail!
|
||||
Node::Children const& cleanedServers =
|
||||
_snapshot("/Target/CleanedServers").children();
|
||||
for (auto const cleaned : cleanedServers) {
|
||||
if (cleaned.first == _server) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY) << _server <<
|
||||
" has been cleaned out already!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine number of available servers
|
||||
Node::Children const& dbservers = _snapshot("/Plan/DBServers").children();
|
||||
uint64_t nservers = dbservers.size() - cleanedServers.size() - 1;
|
||||
|
||||
// See if available servers after cleanout satisfy all replication factors
|
||||
Node::Children const& databases = _snapshot("/Plan/Collections").children();
|
||||
for (auto const& database : databases) {
|
||||
for (auto const& collptr : database.second->children()) {
|
||||
try {
|
||||
uint64_t replFactor = (*collptr.second)("replicationFactor").getUInt();
|
||||
if (replFactor > nservers) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY) <<
|
||||
"Cannot house all shard replics after cleaning out " << _server;
|
||||
return false;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
|
@ -32,17 +32,21 @@ namespace consensus {
|
|||
|
||||
struct CleanOutServer : public Job {
|
||||
|
||||
CleanOutServer (Node const& snapshot, Agent* agent, std::string const& jobId,
|
||||
CleanOutServer(Node const& snapshot, Agent* agent, std::string const& jobId,
|
||||
std::string const& creator, std::string const& prefix,
|
||||
std::string const& server);
|
||||
|
||||
virtual ~CleanOutServer ();
|
||||
virtual ~CleanOutServer();
|
||||
|
||||
virtual unsigned status () const override;
|
||||
virtual bool create () const override;
|
||||
virtual unsigned status() const override;
|
||||
virtual bool create() const override;
|
||||
virtual bool start() const override;
|
||||
|
||||
std::string const& _server;
|
||||
// Check if all shards' replication factors can be satisfied after clean out.
|
||||
bool checkFeasibility() const;
|
||||
bool scheduleMoveShards() const;
|
||||
|
||||
std::string _server;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ FailedLeader::FailedLeader(
|
|||
Job(snapshot, agent, jobId, creator, agencyPrefix), _database(database),
|
||||
_collection(collection), _shard(shard), _from(from), _to(to) {
|
||||
|
||||
try{
|
||||
try {
|
||||
if (exists()) {
|
||||
if (!status()) {
|
||||
start();
|
||||
|
@ -46,12 +46,10 @@ FailedLeader::FailedLeader(
|
|||
start();
|
||||
}
|
||||
} catch (...) {
|
||||
std::string tmp = shard;
|
||||
if (tmp == "") {
|
||||
Node const& job = _snapshot(pendingPrefix + _jobId);
|
||||
tmp = job("shard").toJson();
|
||||
if (_shard == "") {
|
||||
_shard = _snapshot(pendingPrefix + _jobId + "/shard").getString();
|
||||
}
|
||||
finish("Shards/" + tmp);
|
||||
finish("Shards/" + _shard, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -116,7 +114,7 @@ bool FailedLeader::start() const {
|
|||
todo.openArray();
|
||||
try {
|
||||
_snapshot(toDoPrefix + _jobId).toBuilder(todo);
|
||||
} catch (std::exception const& e) {
|
||||
} catch (std::exception const&) {
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) <<
|
||||
"Failed to get key " + toDoPrefix + _jobId + " from agency snapshot";
|
||||
return false;
|
||||
|
|
|
@ -32,8 +32,11 @@ namespace consensus {
|
|||
|
||||
struct FailedLeader : public Job {
|
||||
|
||||
FailedLeader(Node const& snapshot, Agent* agent, std::string const& jobId,
|
||||
std::string const& creator, std::string const& agencyPrefix,
|
||||
FailedLeader(Node const& snapshot,
|
||||
Agent* agent,
|
||||
std::string const& jobId,
|
||||
std::string const& creator,
|
||||
std::string const& agencyPrefix,
|
||||
std::string const& database = std::string(),
|
||||
std::string const& collection = std::string(),
|
||||
std::string const& shard = std::string(),
|
||||
|
@ -46,11 +49,11 @@ struct FailedLeader : public Job {
|
|||
virtual bool start() const override;
|
||||
virtual unsigned status () const override;
|
||||
|
||||
std::string const& _database;
|
||||
std::string const& _collection;
|
||||
std::string const& _shard;
|
||||
std::string const& _from;
|
||||
std::string const& _to;
|
||||
std::string _database;
|
||||
std::string _collection;
|
||||
std::string _shard;
|
||||
std::string _from;
|
||||
std::string _to;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ using namespace arangodb::consensus;
|
|||
FailedServer::FailedServer(Node const& snapshot, Agent* agent, std::string const& jobId,
|
||||
std::string const& creator, std::string const& agencyPrefix,
|
||||
std::string const& failed) :
|
||||
Job(snapshot, agent, jobId, creator, agencyPrefix), _failed(failed) {
|
||||
Job(snapshot, agent, jobId, creator, agencyPrefix), _server(failed) {
|
||||
|
||||
try {
|
||||
if (exists()) {
|
||||
|
@ -44,7 +44,11 @@ FailedServer::FailedServer(Node const& snapshot, Agent* agent, std::string const
|
|||
start();
|
||||
}
|
||||
} catch (...) {
|
||||
finish("DBServers/" + _failed);
|
||||
if (_server == "") {
|
||||
_server = _snapshot(pendingPrefix + _jobId + "/server").getString();
|
||||
}
|
||||
|
||||
finish("DBServers/" + _server, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,7 +64,7 @@ bool FailedServer::start() const {
|
|||
todo.openArray();
|
||||
try {
|
||||
_snapshot(toDoPrefix + _jobId).toBuilder(todo);
|
||||
} catch (std::exception const& e) {
|
||||
} catch (std::exception const&) {
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) <<
|
||||
"Failed to get key " + toDoPrefix + _jobId + " from agency snapshot";
|
||||
return false;
|
||||
|
@ -88,7 +92,7 @@ bool FailedServer::start() const {
|
|||
pending.close();
|
||||
|
||||
// --- Block toServer
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _failed,
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _server,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("jobId", VPackValue(_jobId));
|
||||
pending.close();
|
||||
|
@ -98,7 +102,7 @@ bool FailedServer::start() const {
|
|||
// Preconditions
|
||||
// --- Check that toServer not blocked
|
||||
pending.openObject();
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _failed,
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _server,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("oldEmpty", VPackValue(true));
|
||||
pending.close();
|
||||
|
@ -111,7 +115,7 @@ bool FailedServer::start() const {
|
|||
if (res.accepted && res.indices.size()==1 && res.indices[0]) {
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) <<
|
||||
"Pending: DB Server " + _failed + " failed.";
|
||||
"Pending: DB Server " + _server + " failed.";
|
||||
|
||||
Node::Children const& databases =
|
||||
_snapshot("/Plan/Collections").children();
|
||||
|
@ -127,14 +131,14 @@ bool FailedServer::start() const {
|
|||
VPackArrayIterator dbsit(shard.second->slice());
|
||||
|
||||
// Only proceed if leader and create job
|
||||
if ((*dbsit.begin()).copyString() != _failed) {
|
||||
if ((*dbsit.begin()).copyString() != _server) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FailedLeader(
|
||||
_snapshot, _agent, _jobId + "-" + std::to_string(sub++), _jobId,
|
||||
_agencyPrefix, database.first, collptr.first, shard.first,
|
||||
_failed, shard.second->slice()[1].copyString());
|
||||
_server, shard.second->slice()[1].copyString());
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +158,7 @@ bool FailedServer::start() const {
|
|||
bool FailedServer::create () const {
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||
<< "Todo: DB Server " + _failed + " failed.";
|
||||
<< "Todo: DB Server " + _server + " failed.";
|
||||
|
||||
std::string path = _agencyPrefix + toDoPrefix + _jobId;
|
||||
|
||||
|
@ -163,7 +167,7 @@ bool FailedServer::create () const {
|
|||
todo.openObject();
|
||||
todo.add(path, VPackValue(VPackValueType::Object));
|
||||
todo.add("type", VPackValue("failedServer"));
|
||||
todo.add("server", VPackValue(_failed));
|
||||
todo.add("server", VPackValue(_server));
|
||||
todo.add("jobId", VPackValue(_jobId));
|
||||
todo.add("creator", VPackValue(_creator));
|
||||
todo.add("timeCreated",
|
||||
|
@ -206,7 +210,7 @@ unsigned FailedServer::status () const {
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
if (finish("DBServers/" + _failed)) {
|
||||
if (finish("DBServers/" + _server)) {
|
||||
return FINISHED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ struct FailedServer : public Job {
|
|||
virtual bool create () const override;
|
||||
virtual unsigned status () const override;
|
||||
|
||||
std::string const& _failed;
|
||||
std::string _server;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Kaveh Vahedipour
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MoveShard.h"
|
||||
|
||||
#include "Agent.h"
|
||||
#include "Job.h"
|
||||
|
||||
using namespace arangodb::consensus;
|
||||
|
||||
MoveShard::MoveShard (Node const& snapshot, Agent* agent,
|
||||
std::string const& jobId, std::string const& creator,
|
||||
std::string const& prefix, std::string const& database,
|
||||
std::string const& collection, std::string const& shard,
|
||||
std::string const& from, std::string const& to) :
|
||||
Job(snapshot, agent, jobId, creator, prefix), _database(database),
|
||||
_collection(collection), _shard(shard), _from(from), _to(to) {
|
||||
|
||||
try {
|
||||
|
||||
if (exists()) {
|
||||
|
||||
if (_shard == "") {
|
||||
_shard = _snapshot(pendingPrefix + _jobId + "/shard").getString();
|
||||
}
|
||||
if (_database == "") {
|
||||
_database = _snapshot(pendingPrefix + _jobId + "/database").getString();
|
||||
}
|
||||
if (_collection == "") {
|
||||
_collection =
|
||||
_snapshot(pendingPrefix + _jobId + "/collection").getString();
|
||||
}
|
||||
if (_from == "") {
|
||||
_from = _snapshot(pendingPrefix + _jobId + "/fromServer").getString();
|
||||
}
|
||||
if (_to == "") {
|
||||
_to = _snapshot(pendingPrefix + _jobId + "/toServer").getString();
|
||||
}
|
||||
|
||||
if (!status()) {
|
||||
start();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
create();
|
||||
start();
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
finish("Shards/" + _shard, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
MoveShard::~MoveShard () {}
|
||||
|
||||
bool MoveShard::create () const {
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||
<< "Todo: Move shard " + _shard + " from " + _from + " to " << _to;
|
||||
|
||||
std::string path = _agencyPrefix + toDoPrefix + _jobId;
|
||||
|
||||
Builder todo;
|
||||
todo.openArray();
|
||||
todo.openObject();
|
||||
todo.add(path, VPackValue(VPackValueType::Object));
|
||||
todo.add("creator", VPackValue(_creator));
|
||||
todo.add("type", VPackValue("failedLeader"));
|
||||
todo.add("database", VPackValue(_database));
|
||||
todo.add("collection", VPackValue(_collection));
|
||||
todo.add("shard", VPackValue(_shard));
|
||||
todo.add("fromServer", VPackValue(_from));
|
||||
todo.add("toServer", VPackValue(_to));
|
||||
|
||||
todo.add("isLeader", VPackValue(true));
|
||||
todo.add("jobId", VPackValue(_jobId));
|
||||
todo.add("timeCreated",
|
||||
VPackValue(timepointToString(std::chrono::system_clock::now())));
|
||||
todo.close(); todo.close(); todo.close();
|
||||
|
||||
write_ret_t res = transact(_agent, todo);
|
||||
|
||||
if (res.accepted && res.indices.size()==1 && res.indices[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) << "Failed to insert job " + _jobId;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool MoveShard::start() const {
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||
<< "Pending: Move shard " + _shard + " from " + _from + " to " << _to;
|
||||
|
||||
// Copy todo to pending
|
||||
/* Builder todo, pending;
|
||||
|
||||
// Get todo entry
|
||||
todo.openArray();
|
||||
_snapshot(toDoPrefix + _jobId).toBuilder(todo);
|
||||
todo.close();
|
||||
|
||||
// Enter peding, remove todo, block toserver
|
||||
pending.openArray();
|
||||
|
||||
// --- Add pending
|
||||
pending.openObject();
|
||||
pending.add(_agencyPrefix + pendingPrefix + _jobId,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("timeStarted",
|
||||
VPackValue(timepointToString(std::chrono::system_clock::now())));
|
||||
for (auto const& obj : VPackObjectIterator(todo.slice()[0])) {
|
||||
pending.add(obj.key.copyString(), obj.value);
|
||||
}
|
||||
pending.close();
|
||||
|
||||
// --- Delete todo
|
||||
pending.add(_agencyPrefix + toDoPrefix + _jobId,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("op", VPackValue("delete"));
|
||||
pending.close();
|
||||
|
||||
// --- Block toServer
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _server,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("jobId", VPackValue(_jobId));
|
||||
pending.close();
|
||||
|
||||
// --- Announce in Sync that server is cleaning out
|
||||
pending.add(_agencyPrefix + serverStatePrefix + _server,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("cleaning", VPackValue(true));
|
||||
pending.close();
|
||||
|
||||
pending.close();
|
||||
|
||||
// Preconditions
|
||||
// --- Check that toServer not blocked
|
||||
pending.openObject();
|
||||
pending.add(_agencyPrefix + blockedServersPrefix + _server,
|
||||
VPackValue(VPackValueType::Object));
|
||||
pending.add("oldEmpty", VPackValue(true));
|
||||
pending.close();
|
||||
|
||||
pending.close(); pending.close();
|
||||
|
||||
// Transact to agency
|
||||
write_ret_t res = transact(_agent, pending);
|
||||
|
||||
if (res.accepted && res.indices.size()==1 && res.indices[0]) {
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) << "Pending: Clean out server " + _server;
|
||||
|
||||
Node::Children const& databases =
|
||||
_snapshot("/Plan/Collections").children();
|
||||
|
||||
size_t sub = 0;
|
||||
|
||||
for (auto const& database : databases) {
|
||||
for (auto const& collptr : database.second->children()) {
|
||||
Node const& collection = *(collptr.second);
|
||||
Node const& replicationFactor = collection("replicationFactor");
|
||||
if (replicationFactor.slice().getUInt() > 1) {
|
||||
for (auto const& shard : collection("shards").children()) {
|
||||
VPackArrayIterator dbsit(shard.second->slice());
|
||||
|
||||
MoveShard (
|
||||
_snapshot, _agent, _jobId + "-" + std::to_string(sub++),
|
||||
_jobId, _agencyPrefix, database.first, collptr.first,
|
||||
shard.first, _server, _server);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_TOPIC(INFO, Logger::AGENCY) <<
|
||||
"Precondition failed for starting job " + _jobId;
|
||||
*/
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
unsigned MoveShard::status () const {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Kaveh Vahedipour
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_CONSENSUS_MOVE_SHARD_FROM_FOLLOWER_H
|
||||
#define ARANGOD_CONSENSUS_MOVE_SHARD_FROM_FOLLOWER_H 1
|
||||
|
||||
#include "Job.h"
|
||||
#include "Supervision.h"
|
||||
|
||||
namespace arangodb {
|
||||
namespace consensus {
|
||||
|
||||
struct MoveShard : public Job {
|
||||
|
||||
MoveShard (Node const& snapshot,
|
||||
Agent* agent,
|
||||
std::string const& jobId,
|
||||
std::string const& creator,
|
||||
std::string const& prefix,
|
||||
std::string const& database = std::string(),
|
||||
std::string const& collection = std::string(),
|
||||
std::string const& shard = std::string(),
|
||||
std::string const& from = std::string(),
|
||||
std::string const& to = std::string());
|
||||
|
||||
virtual ~MoveShard ();
|
||||
|
||||
virtual unsigned status () const override;
|
||||
virtual bool create () const override;
|
||||
virtual bool start() const override;
|
||||
|
||||
std::string _database;
|
||||
std::string _collection;
|
||||
std::string _shard;
|
||||
std::string _from;
|
||||
std::string _to;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
|
@ -611,3 +611,39 @@ std::vector<std::string> Node::exists(std::vector<std::string> const& rel) const
|
|||
std::vector<std::string> Node::exists(std::string const& rel) const {
|
||||
return exists(split(rel, '/'));
|
||||
}
|
||||
|
||||
int Node::getInt() const {
|
||||
|
||||
if (type() == NODE) {
|
||||
throw StoreException("Must not convert NODE type to int");
|
||||
}
|
||||
return static_cast<int>(slice().getInt());
|
||||
|
||||
}
|
||||
|
||||
uint64_t Node::getUInt() const {
|
||||
|
||||
if (type() == NODE) {
|
||||
throw StoreException("Must not convert NODE type to unsigned int");
|
||||
}
|
||||
return slice().getUInt();
|
||||
|
||||
}
|
||||
|
||||
double Node::getDouble() const {
|
||||
|
||||
if (type() == NODE) {
|
||||
throw StoreException("Must not convert NODE type to int");
|
||||
}
|
||||
return slice().getDouble();
|
||||
|
||||
}
|
||||
|
||||
std::string Node::getString() const {
|
||||
|
||||
if (type() == NODE) {
|
||||
throw StoreException("Must not convert NODE type to string");
|
||||
}
|
||||
return slice().copyString();
|
||||
|
||||
}
|
||||
|
|
|
@ -202,6 +202,18 @@ class Node {
|
|||
/// @brief Part of relative path which exists
|
||||
std::vector<std::string> exists(std::string const&) const;
|
||||
|
||||
/// @brief Get integer value (throws if type NODE or if conversion fails)
|
||||
int getInt() const;
|
||||
|
||||
/// @brief Get insigned value (throws if type NODE or if conversion fails)
|
||||
uint64_t getUInt() const;
|
||||
|
||||
/// @brief Get double value (throws if type NODE or if conversion fails)
|
||||
double getDouble() const;
|
||||
|
||||
/// @brief Get string value (throws if type NODE or if conversion fails)
|
||||
std::string getString() const;
|
||||
|
||||
protected:
|
||||
/// @brief Add time to live entry
|
||||
virtual bool addTimeToLive(long millis);
|
||||
|
|
|
@ -91,7 +91,13 @@ bool State::persist(arangodb::consensus::index_t index, term_t term,
|
|||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
OperationResult result = trx.insert("log", body.slice(), _options);
|
||||
OperationResult result;
|
||||
try {
|
||||
result = trx.insert("log", body.slice(), _options);
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY) <<
|
||||
"Failed to persist log entry:" << e.what();
|
||||
}
|
||||
res = trx.finish(result.code);
|
||||
|
||||
return (res == TRI_ERROR_NO_ERROR);
|
||||
|
|
|
@ -53,7 +53,9 @@ Supervision::~Supervision() { shutdown(); };
|
|||
|
||||
void Supervision::wakeUp() {
|
||||
TRI_ASSERT(_agent != nullptr);
|
||||
if (!this->isStopping()) {
|
||||
_snapshot = _agent->readDB().get(_agencyPrefix);
|
||||
}
|
||||
_cv.signal();
|
||||
}
|
||||
|
||||
|
@ -124,7 +126,9 @@ std::vector<check_t> Supervision::checkDBServers() {
|
|||
report->close();
|
||||
report->close();
|
||||
report->close();
|
||||
if (!this->isStopping()) {
|
||||
_agent->write(report);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -132,7 +136,8 @@ std::vector<check_t> Supervision::checkDBServers() {
|
|||
}
|
||||
|
||||
bool Supervision::doChecks(bool timedout) {
|
||||
if (_agent == nullptr) {
|
||||
|
||||
if (_agent == nullptr || this->isStopping()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -235,7 +240,7 @@ bool Supervision::start(Agent* agent) {
|
|||
bool Supervision::updateAgencyPrefix (size_t nTries, int intervalSec) {
|
||||
|
||||
// Try nTries to get agency's prefix in intervals
|
||||
for (size_t i = 0; i < nTries; i++) {
|
||||
while (!this->isStopping()) {
|
||||
_snapshot = _agent->readDB().get("/");
|
||||
if (_snapshot.children().size() > 0) {
|
||||
_agencyPrefix = std::string("/") + _snapshot.children().begin()->first;
|
||||
|
@ -256,11 +261,11 @@ void Supervision::getUniqueIds() {
|
|||
uint64_t latestId;
|
||||
// Run forever, supervision does not make sense before the agency data
|
||||
// is initialized by some other server...
|
||||
while (true) {
|
||||
while (!this->isStopping()) {
|
||||
try {
|
||||
latestId = std::stoul(
|
||||
_agent->readDB().get(_agencyPrefix + "/Sync/LatestID").slice().toJson());
|
||||
} catch (std::exception const& e) {
|
||||
} catch (std::exception const&) {
|
||||
std::this_thread::sleep_for (std::chrono::seconds(1));
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ struct FunctionDefiner {
|
|||
add({"CONCAT", "AQL_CONCAT", "szl|+", true, true, false,
|
||||
true, true, &Functions::Concat});
|
||||
add({"CONCAT_SEPARATOR", "AQL_CONCAT_SEPARATOR",
|
||||
"s,szl|+", true, true, false, true, true});
|
||||
"s,szl|+", true, true, false, true, true, &Functions::ConcatSeparator});
|
||||
add({"CHAR_LENGTH", "AQL_CHAR_LENGTH", "s", true, true,
|
||||
false, true, true});
|
||||
add({"LOWER", "AQL_LOWER", "s", true, true, false, true, true});
|
||||
|
|
|
@ -72,8 +72,13 @@ static AqlValue NumberValue(arangodb::AqlTransaction* trx, int value) {
|
|||
}
|
||||
|
||||
/// @brief convert a number value into an AqlValue
|
||||
static AqlValue NumberValue(arangodb::AqlTransaction* trx, double value) {
|
||||
static AqlValue NumberValue(arangodb::AqlTransaction* trx, double value, bool nullify) {
|
||||
if (std::isnan(value) || !std::isfinite(value) || value == HUGE_VAL || value == -HUGE_VAL) {
|
||||
if (nullify) {
|
||||
// convert to null
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
// convert to 0
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::ZeroValue());
|
||||
}
|
||||
|
||||
|
@ -1245,7 +1250,6 @@ AqlValue Functions::Concat(arangodb::aql::Query* query,
|
|||
StringBufferLeaser buffer(trx);
|
||||
arangodb::basics::VPackStringBufferAdapter adapter(buffer->stringBuffer());
|
||||
|
||||
bool handled = false;
|
||||
size_t const n = parameters.size();
|
||||
|
||||
if (n == 1) {
|
||||
|
@ -1261,11 +1265,10 @@ AqlValue Functions::Concat(arangodb::aql::Query* query,
|
|||
// convert member to a string and append
|
||||
AppendAsString(trx, adapter, AqlValue(it.begin()));
|
||||
}
|
||||
handled = true;
|
||||
return AqlValue(buffer->c_str(), buffer->length());
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue member = ExtractFunctionParameterValue(trx, parameters, i);
|
||||
|
||||
|
@ -1276,11 +1279,74 @@ AqlValue Functions::Concat(arangodb::aql::Query* query,
|
|||
// convert member to a string and append
|
||||
AppendAsString(trx, adapter, member);
|
||||
}
|
||||
|
||||
try {
|
||||
return AqlValue(buffer->c_str(), buffer->length());
|
||||
} catch (...) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief function CONCAT_SEPARATOR
|
||||
AqlValue Functions::ConcatSeparator(arangodb::aql::Query* query,
|
||||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
StringBufferLeaser buffer(trx);
|
||||
arangodb::basics::VPackStringBufferAdapter adapter(buffer->stringBuffer());
|
||||
|
||||
bool found = false;
|
||||
size_t const n = parameters.size();
|
||||
|
||||
AqlValue separator = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
AppendAsString(trx, adapter, separator);
|
||||
std::string const s(buffer->c_str(), buffer->length());
|
||||
|
||||
buffer->clear();
|
||||
|
||||
if (n == 2) {
|
||||
AqlValue member = ExtractFunctionParameterValue(trx, parameters, 1);
|
||||
|
||||
if (member.isArray()) {
|
||||
// reserve *some* space
|
||||
buffer->reserve((s.size() + 10) * member.length());
|
||||
|
||||
AqlValueMaterializer materializer(trx);
|
||||
VPackSlice slice = materializer.slice(member, false);
|
||||
|
||||
for (auto const& it : VPackArrayIterator(slice, true)) {
|
||||
if (it.isNull()) {
|
||||
continue;
|
||||
}
|
||||
if (found) {
|
||||
buffer->appendText(s);
|
||||
}
|
||||
// convert member to a string and append
|
||||
AppendAsString(trx, adapter, AqlValue(it.begin()));
|
||||
found = true;
|
||||
}
|
||||
return AqlValue(buffer->c_str(), buffer->length());
|
||||
}
|
||||
}
|
||||
|
||||
// reserve *some* space
|
||||
buffer->reserve((s.size() + 10) * n);
|
||||
for (size_t i = 1; i < n; ++i) {
|
||||
AqlValue member = ExtractFunctionParameterValue(trx, parameters, i);
|
||||
|
||||
if (member.isNull(true)) {
|
||||
continue;
|
||||
}
|
||||
if (found) {
|
||||
buffer->appendText(s);
|
||||
}
|
||||
|
||||
// convert member to a string and append
|
||||
AppendAsString(trx, adapter, member);
|
||||
found = true;
|
||||
}
|
||||
|
||||
size_t length = buffer->length();
|
||||
try {
|
||||
return AqlValue(buffer->c_str(), length);
|
||||
return AqlValue(buffer->c_str(), buffer->length());
|
||||
} catch (...) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
@ -1755,7 +1821,7 @@ AqlValue Functions::Sum(arangodb::aql::Query* query,
|
|||
}
|
||||
}
|
||||
|
||||
return NumberValue(trx, sum);
|
||||
return NumberValue(trx, sum, false);
|
||||
}
|
||||
|
||||
/// @brief function AVERAGE
|
||||
|
@ -1794,7 +1860,7 @@ AqlValue Functions::Average(arangodb::aql::Query* query,
|
|||
}
|
||||
|
||||
if (count > 0 && !std::isnan(sum) && sum != HUGE_VAL && sum != -HUGE_VAL) {
|
||||
return NumberValue(trx, sum / static_cast<size_t>(count));
|
||||
return NumberValue(trx, sum / static_cast<size_t>(count), false);
|
||||
}
|
||||
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
|
@ -2901,7 +2967,7 @@ AqlValue Functions::Round(arangodb::aql::Query* query,
|
|||
double input = value.toDouble(failed);
|
||||
|
||||
// Rounds down for < x.4999 and up for > x.50000
|
||||
return NumberValue(trx, std::floor(input + 0.5));
|
||||
return NumberValue(trx, std::floor(input + 0.5), true);
|
||||
}
|
||||
|
||||
/// @brief function ABS
|
||||
|
@ -2915,7 +2981,7 @@ AqlValue Functions::Abs(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::abs(input));
|
||||
return NumberValue(trx, std::abs(input), true);
|
||||
}
|
||||
|
||||
/// @brief function CEIL
|
||||
|
@ -2929,7 +2995,7 @@ AqlValue Functions::Ceil(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::ceil(input));
|
||||
return NumberValue(trx, std::ceil(input), true);
|
||||
}
|
||||
|
||||
/// @brief function FLOOR
|
||||
|
@ -2943,7 +3009,7 @@ AqlValue Functions::Floor(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::floor(input));
|
||||
return NumberValue(trx, std::floor(input), true);
|
||||
}
|
||||
|
||||
/// @brief function SQRT
|
||||
|
@ -2957,7 +3023,7 @@ AqlValue Functions::Sqrt(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::sqrt(input));
|
||||
return NumberValue(trx, std::sqrt(input), true);
|
||||
}
|
||||
|
||||
/// @brief function POW
|
||||
|
@ -2973,7 +3039,7 @@ AqlValue Functions::Pow(arangodb::aql::Query* query,
|
|||
double base = baseValue.toDouble(failed);
|
||||
double exp = expValue.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::pow(base, exp));
|
||||
return NumberValue(trx, std::pow(base, exp), true);
|
||||
}
|
||||
|
||||
/// @brief function LOG
|
||||
|
@ -2987,7 +3053,7 @@ AqlValue Functions::Log(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::log(input));
|
||||
return NumberValue(trx, std::log(input), true);
|
||||
}
|
||||
|
||||
/// @brief function LOG2
|
||||
|
@ -3001,7 +3067,7 @@ AqlValue Functions::Log2(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::log2(input));
|
||||
return NumberValue(trx, std::log2(input), true);
|
||||
}
|
||||
|
||||
/// @brief function LOG10
|
||||
|
@ -3015,7 +3081,7 @@ AqlValue Functions::Log10(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::log10(input));
|
||||
return NumberValue(trx, std::log10(input), true);
|
||||
}
|
||||
|
||||
/// @brief function EXP
|
||||
|
@ -3029,7 +3095,7 @@ AqlValue Functions::Exp(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::exp(input));
|
||||
return NumberValue(trx, std::exp(input), true);
|
||||
}
|
||||
|
||||
/// @brief function EXP2
|
||||
|
@ -3043,7 +3109,7 @@ AqlValue Functions::Exp2(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::exp2(input));
|
||||
return NumberValue(trx, std::exp2(input), true);
|
||||
}
|
||||
|
||||
/// @brief function SIN
|
||||
|
@ -3057,7 +3123,7 @@ AqlValue Functions::Sin(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::sin(input));
|
||||
return NumberValue(trx, std::sin(input), true);
|
||||
}
|
||||
|
||||
/// @brief function COS
|
||||
|
@ -3071,7 +3137,7 @@ AqlValue Functions::Cos(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::cos(input));
|
||||
return NumberValue(trx, std::cos(input), true);
|
||||
}
|
||||
|
||||
/// @brief function TAN
|
||||
|
@ -3085,7 +3151,7 @@ AqlValue Functions::Tan(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::tan(input));
|
||||
return NumberValue(trx, std::tan(input), true);
|
||||
}
|
||||
|
||||
/// @brief function ASIN
|
||||
|
@ -3099,7 +3165,7 @@ AqlValue Functions::Asin(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::asin(input));
|
||||
return NumberValue(trx, std::asin(input), true);
|
||||
}
|
||||
|
||||
/// @brief function ACOS
|
||||
|
@ -3113,7 +3179,7 @@ AqlValue Functions::Acos(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::acos(input));
|
||||
return NumberValue(trx, std::acos(input), true);
|
||||
}
|
||||
|
||||
/// @brief function ATAN
|
||||
|
@ -3127,7 +3193,7 @@ AqlValue Functions::Atan(arangodb::aql::Query* query,
|
|||
bool failed = false; // we're intentionally ignoring this variable here
|
||||
double input = value.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::atan(input));
|
||||
return NumberValue(trx, std::atan(input), true);
|
||||
}
|
||||
|
||||
/// @brief function ATAN2
|
||||
|
@ -3143,7 +3209,7 @@ AqlValue Functions::Atan2(arangodb::aql::Query* query,
|
|||
double input1 = value1.toDouble(failed);
|
||||
double input2 = value2.toDouble(failed);
|
||||
|
||||
return NumberValue(trx, std::atan2(input1, input2));
|
||||
return NumberValue(trx, std::atan2(input1, input2), true);
|
||||
}
|
||||
|
||||
/// @brief function RADIANS
|
||||
|
@ -3158,7 +3224,7 @@ AqlValue Functions::Radians(arangodb::aql::Query* query,
|
|||
double degrees = value.toDouble(failed);
|
||||
|
||||
// acos(-1) == PI
|
||||
return NumberValue(trx, degrees * (std::acos(-1) / 180.0));
|
||||
return NumberValue(trx, degrees * (std::acos(-1.0) / 180.0), true);
|
||||
}
|
||||
|
||||
/// @brief function DEGREES
|
||||
|
@ -3173,7 +3239,7 @@ AqlValue Functions::Degrees(arangodb::aql::Query* query,
|
|||
double radians = value.toDouble(failed);
|
||||
|
||||
// acos(-1) == PI
|
||||
return NumberValue(trx, radians * (180.0 / std::acos(-1)));
|
||||
return NumberValue(trx, radians * (180.0 / std::acos(-1.0)), true);
|
||||
}
|
||||
|
||||
/// @brief function RAND
|
||||
|
@ -3183,7 +3249,7 @@ AqlValue Functions::Rand(arangodb::aql::Query* query,
|
|||
ValidateParameters(parameters, "RAND", 0, 0);
|
||||
|
||||
// This random functionality is not too good yet...
|
||||
return NumberValue(trx, static_cast<double>(std::rand()) / RAND_MAX);
|
||||
return NumberValue(trx, static_cast<double>(std::rand()) / RAND_MAX, true);
|
||||
}
|
||||
|
||||
/// @brief function FIRST_DOCUMENT
|
||||
|
@ -3682,7 +3748,7 @@ AqlValue Functions::VarianceSample(
|
|||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
return NumberValue(trx, value / (count - 1));
|
||||
return NumberValue(trx, value / (count - 1), true);
|
||||
}
|
||||
|
||||
/// @brief function VARIANCE_POPULATION
|
||||
|
@ -3712,7 +3778,7 @@ AqlValue Functions::VariancePopulation(
|
|||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
return NumberValue(trx, value / count);
|
||||
return NumberValue(trx, value / count, true);
|
||||
}
|
||||
|
||||
/// @brief function STDDEV_SAMPLE
|
||||
|
@ -3741,7 +3807,7 @@ AqlValue Functions::StdDevSample(
|
|||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
return NumberValue(trx, sqrt(value / (count - 1)));
|
||||
return NumberValue(trx, std::sqrt(value / (count - 1)), true);
|
||||
}
|
||||
|
||||
/// @brief function STDDEV_POPULATION
|
||||
|
@ -3770,7 +3836,7 @@ AqlValue Functions::StdDevPopulation(
|
|||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
return NumberValue(trx, sqrt(value / count));
|
||||
return NumberValue(trx, std::sqrt(value / count), true);
|
||||
}
|
||||
|
||||
/// @brief function MEDIAN
|
||||
|
@ -3799,9 +3865,9 @@ AqlValue Functions::Median(arangodb::aql::Query* query,
|
|||
size_t midpoint = l / 2;
|
||||
|
||||
if (l % 2 == 0) {
|
||||
return NumberValue(trx, (values[midpoint - 1] + values[midpoint]) / 2);
|
||||
return NumberValue(trx, (values[midpoint - 1] + values[midpoint]) / 2, true);
|
||||
}
|
||||
return NumberValue(trx, values[midpoint]);
|
||||
return NumberValue(trx, values[midpoint], true);
|
||||
}
|
||||
|
||||
/// @brief function PERCENTILE
|
||||
|
@ -3867,7 +3933,7 @@ AqlValue Functions::Percentile(arangodb::aql::Query* query,
|
|||
|
||||
size_t l = values.size();
|
||||
if (l == 1) {
|
||||
return NumberValue(trx, values[0]);
|
||||
return NumberValue(trx, values[0], true);
|
||||
}
|
||||
|
||||
TRI_ASSERT(l > 1);
|
||||
|
@ -3877,7 +3943,7 @@ AqlValue Functions::Percentile(arangodb::aql::Query* query,
|
|||
double const pos = floor(idx);
|
||||
|
||||
if (pos >= l) {
|
||||
return NumberValue(trx, values[l - 1]);
|
||||
return NumberValue(trx, values[l - 1], true);
|
||||
}
|
||||
if (pos <= 0) {
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
|
@ -3886,19 +3952,19 @@ AqlValue Functions::Percentile(arangodb::aql::Query* query,
|
|||
double const delta = idx - pos;
|
||||
return NumberValue(trx, delta * (values[static_cast<size_t>(pos)] -
|
||||
values[static_cast<size_t>(pos) - 1]) +
|
||||
values[static_cast<size_t>(pos) - 1]);
|
||||
values[static_cast<size_t>(pos) - 1], true);
|
||||
}
|
||||
|
||||
double const idx = p * l / 100.0;
|
||||
double const pos = ceil(idx);
|
||||
if (pos >= l) {
|
||||
return NumberValue(trx, values[l - 1]);
|
||||
return NumberValue(trx, values[l - 1], true);
|
||||
}
|
||||
if (pos <= 0) {
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
}
|
||||
|
||||
return NumberValue(trx, values[static_cast<size_t>(pos) - 1]);
|
||||
return NumberValue(trx, values[static_cast<size_t>(pos) - 1], true);
|
||||
}
|
||||
|
||||
/// @brief function RANGE
|
||||
|
|
|
@ -93,6 +93,8 @@ struct Functions {
|
|||
VPackFunctionParameters const&);
|
||||
static AqlValue Concat(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ConcatSeparator(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Like(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Regex(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
|
|
|
@ -87,6 +87,7 @@ add_executable(${BIN_ARANGOD}
|
|||
Agency/CleanOutServer.cpp
|
||||
Agency/FailedLeader.cpp
|
||||
Agency/FailedServer.cpp
|
||||
Agency/MoveShard.cpp
|
||||
Agency/NotifierThread.cpp
|
||||
Agency/NotifyCallback.cpp
|
||||
Agency/Node.cpp
|
||||
|
|
|
@ -102,6 +102,23 @@ TRI_doc_mptr_t* AllIndexIterator::next() {
|
|||
return _index->findSequential(_trx, _position, _total);
|
||||
};
|
||||
|
||||
void AllIndexIterator::nextBabies(std::vector<TRI_doc_mptr_t*>& buffer, size_t limit) {
|
||||
size_t atMost = limit;
|
||||
|
||||
buffer.clear();
|
||||
|
||||
while (atMost > 0) {
|
||||
auto result = next();
|
||||
|
||||
if (result == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.emplace_back(result);
|
||||
--atMost;
|
||||
}
|
||||
}
|
||||
|
||||
void AllIndexIterator::reset() { _position.reset(); }
|
||||
|
||||
TRI_doc_mptr_t* AnyIndexIterator::next() {
|
||||
|
|
|
@ -80,6 +80,8 @@ class AllIndexIterator final : public IndexIterator {
|
|||
|
||||
TRI_doc_mptr_t* next() override;
|
||||
|
||||
void nextBabies(std::vector<TRI_doc_mptr_t*>&, size_t) override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -4016,6 +4016,19 @@ function unitTest(cases, options) {
|
|||
LOGS_DIR = fs.join(TOP_DIR, "logs");
|
||||
PEM_FILE = fs.join(TOP_DIR, "UnitTests", "server.pem");
|
||||
|
||||
let checkFiles = [
|
||||
ARANGOBENCH_BIN,
|
||||
ARANGODUMP_BIN,
|
||||
ARANGOD_BIN,
|
||||
ARANGOIMP_BIN,
|
||||
ARANGORESTORE_BIN,
|
||||
ARANGOSH_BIN];
|
||||
for (let b = 0; b < checkFiles.length; ++b) {
|
||||
if (! fs.isFile(checkFiles[b]) && ! fs.isFile(checkFiles[b]+ ".exe" )) {
|
||||
throw "unable to locate " + checkFiles[b];
|
||||
}
|
||||
}
|
||||
|
||||
const jsonReply = options.jsonReply;
|
||||
delete options.jsonReply;
|
||||
|
||||
|
|
|
@ -255,6 +255,21 @@ function assertQueryWarningAndNull (errorCode, query, bindVars) {
|
|||
assertEqual([ null ], result.json);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief assert a specific warning running a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function assertQueryWarningAndFalse (errorCode, query, bindVars) {
|
||||
var result = AQL_EXECUTE(query, bindVars), i, found = { };
|
||||
|
||||
for (i = 0; i < result.warnings.length; ++i) {
|
||||
found[result.warnings[i].code] = true;
|
||||
}
|
||||
|
||||
assertTrue(found[errorCode]);
|
||||
assertEqual([ false ], result.json);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a linearized version of an execution plan
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -477,6 +492,7 @@ exports.getRawQueryResults = getRawQueryResults;
|
|||
exports.getQueryResults = getQueryResults;
|
||||
exports.assertQueryError = assertQueryError;
|
||||
exports.assertQueryWarningAndNull = assertQueryWarningAndNull;
|
||||
exports.assertQueryWarningAndFalse = assertQueryWarningAndFalse;
|
||||
exports.getLinearizedPlan = getLinearizedPlan;
|
||||
exports.getCompactPlan = getCompactPlan;
|
||||
exports.findExecutionNodes = findExecutionNodes;
|
||||
|
|
|
@ -876,6 +876,16 @@ function CREATE_REGEX_PATTERN (chars) {
|
|||
function COMPILE_REGEX (regex, modifiers) {
|
||||
'use strict';
|
||||
|
||||
return new RegExp(AQL_TO_STRING(regex), modifiers);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compile a regex from a string pattern
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function COMPILE_LIKE (regex, modifiers) {
|
||||
'use strict';
|
||||
|
||||
regex = AQL_TO_STRING(regex);
|
||||
var i, n = regex.length;
|
||||
var escaped = false;
|
||||
|
@ -1044,10 +1054,13 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
|
|||
/// @brief return the numeric value or undefined if it is out of range
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function NUMERIC_VALUE (value) {
|
||||
function NUMERIC_VALUE (value, nullify) {
|
||||
'use strict';
|
||||
|
||||
if (isNaN(value) || ! isFinite(value)) {
|
||||
if (value === null || isNaN(value) || ! isFinite(value)) {
|
||||
if (nullify) {
|
||||
return null;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2272,7 +2285,7 @@ function AQL_LIKE (value, regex, caseInsensitive) {
|
|||
regex = AQL_TO_STRING(regex);
|
||||
|
||||
if (LikeCache[modifiers][regex] === undefined) {
|
||||
LikeCache[modifiers][regex] = COMPILE_REGEX(regex, modifiers);
|
||||
LikeCache[modifiers][regex] = COMPILE_LIKE(regex, modifiers);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -2298,11 +2311,11 @@ function AQL_REGEX (value, regex, caseInsensitive) {
|
|||
|
||||
regex = AQL_TO_STRING(regex);
|
||||
|
||||
try {
|
||||
if (RegexCache[modifiers][regex] === undefined) {
|
||||
RegexCache[modifiers][regex] = COMPILE_REGEX(regex, modifiers);
|
||||
}
|
||||
|
||||
try {
|
||||
return RegexCache[modifiers][regex].test(AQL_TO_STRING(value));
|
||||
}
|
||||
catch (err) {
|
||||
|
@ -2712,7 +2725,7 @@ function AQL_TO_NUMBER (value) {
|
|||
case TYPEWEIGHT_NUMBER:
|
||||
return value;
|
||||
case TYPEWEIGHT_STRING:
|
||||
var result = NUMERIC_VALUE(Number(value));
|
||||
var result = NUMERIC_VALUE(Number(value), false);
|
||||
return ((TYPEWEIGHT(result) === TYPEWEIGHT_NUMBER) ? result : null);
|
||||
case TYPEWEIGHT_ARRAY:
|
||||
if (value.length === 0) {
|
||||
|
@ -2889,7 +2902,7 @@ function AQL_IS_DATESTRING (value) {
|
|||
function AQL_FLOOR (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.floor(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.floor(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2899,7 +2912,7 @@ function AQL_FLOOR (value) {
|
|||
function AQL_CEIL (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.ceil(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.ceil(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2909,7 +2922,7 @@ function AQL_CEIL (value) {
|
|||
function AQL_ROUND (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.round(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.round(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2919,7 +2932,7 @@ function AQL_ROUND (value) {
|
|||
function AQL_ABS (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.abs(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.abs(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2939,7 +2952,7 @@ function AQL_RAND () {
|
|||
function AQL_SQRT (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.sqrt(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.sqrt(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2949,7 +2962,7 @@ function AQL_SQRT (value) {
|
|||
function AQL_POW (base, exp) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.pow(AQL_TO_NUMBER(base), AQL_TO_NUMBER(exp)));
|
||||
return NUMERIC_VALUE(Math.pow(AQL_TO_NUMBER(base), AQL_TO_NUMBER(exp)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2959,7 +2972,7 @@ function AQL_POW (base, exp) {
|
|||
function AQL_LOG (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.log(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.log(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2969,7 +2982,7 @@ function AQL_LOG (value) {
|
|||
function AQL_LOG2 (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.log2(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.log2(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2979,7 +2992,7 @@ function AQL_LOG2 (value) {
|
|||
function AQL_LOG10 (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.log10(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.log10(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2989,7 +3002,7 @@ function AQL_LOG10 (value) {
|
|||
function AQL_EXP (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.exp(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.exp(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2999,7 +3012,7 @@ function AQL_EXP (value) {
|
|||
function AQL_EXP2 (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.pow(2, AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.pow(2, AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3009,7 +3022,7 @@ function AQL_EXP2 (value) {
|
|||
function AQL_SIN (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.sin(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.sin(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3019,7 +3032,7 @@ function AQL_SIN (value) {
|
|||
function AQL_COS (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.cos(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.cos(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3029,7 +3042,7 @@ function AQL_COS (value) {
|
|||
function AQL_TAN (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.tan(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.tan(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3039,7 +3052,7 @@ function AQL_TAN (value) {
|
|||
function AQL_ASIN (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.asin(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.asin(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3049,7 +3062,7 @@ function AQL_ASIN (value) {
|
|||
function AQL_ACOS (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.acos(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.acos(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3059,7 +3072,7 @@ function AQL_ACOS (value) {
|
|||
function AQL_ATAN (value) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.atan(AQL_TO_NUMBER(value)));
|
||||
return NUMERIC_VALUE(Math.atan(AQL_TO_NUMBER(value)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3069,7 +3082,7 @@ function AQL_ATAN (value) {
|
|||
function AQL_ATAN2 (value1, value2) {
|
||||
'use strict';
|
||||
|
||||
return NUMERIC_VALUE(Math.atan2(AQL_TO_NUMBER(value1), AQL_TO_NUMBER(value2)));
|
||||
return NUMERIC_VALUE(Math.atan2(AQL_TO_NUMBER(value1), AQL_TO_NUMBER(value2)), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,11 +29,8 @@
|
|||
|
||||
var internal = require("internal");
|
||||
var cluster = require("@arangodb/cluster");
|
||||
|
||||
var db = internal.db;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialized
|
||||
///
|
||||
|
@ -415,7 +412,6 @@ function compute15Minute (start, clusterId) {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief statistics interval
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -590,7 +586,7 @@ exports.installPeriodicTasks = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
console.info("Statistics: Installing regular tasks...");
|
||||
console.debug("Statistics: Installing regular tasks...");
|
||||
|
||||
var interval = exports.STATISTICS_INTERVAL;
|
||||
var interval15 = exports.STATISTICS_HISTORY_INTERVAL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,7 @@ var jsunity = require("jsunity");
|
|||
var helper = require("@arangodb/aql-helper");
|
||||
var getQueryResults = helper.getQueryResults;
|
||||
var assertQueryError = helper.assertQueryError;
|
||||
var assertQueryWarningAndFalse = helper.assertQueryWarningAndFalse;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
|
@ -56,6 +57,135 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
tearDown : function () {
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test regex function, invalid arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRegexInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REGEX()");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REGEX(\"test\")");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REGEX(\"test\", \"meow\", \"foo\", \"bar\")");
|
||||
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"[\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"[^\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"a.(\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"(a\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"(a]\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"**\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"?\")");
|
||||
assertQueryWarningAndFalse(errors.ERROR_QUERY_INVALID_REGEX.code, "RETURN REGEX(\"test\", \"*\")");
|
||||
},
|
||||
|
||||
testRegex : function () {
|
||||
var values = [
|
||||
// whole words
|
||||
["the quick brown fox", "the", true],
|
||||
["the quick brown fox", "quick", true],
|
||||
["the quick brown fox", "quicK", false],
|
||||
["the quick brown fox", "quIcK", false],
|
||||
["the quick brown fox", "brown", true],
|
||||
["the quick brown fox", "fox", true],
|
||||
["the quick brown fox", "The", false],
|
||||
["the quick brown fox", "THE", false],
|
||||
["the quick brown fox", "foxx", false],
|
||||
["the quick brown fox", "hasi", false],
|
||||
|
||||
// anchored
|
||||
["the quick brown fox", "^the", true],
|
||||
["the quick brown fox", "^the$", false],
|
||||
["the quick brown fox", "^the quick", true],
|
||||
["the quick brown fox", "^the quick brown", true],
|
||||
["the quick brown fox", "^the quick brown fo", true],
|
||||
["the quick brown fox", "^th", true],
|
||||
["the quick brown fox", "^t", true],
|
||||
["the quick brown fox", "^the quick$", false],
|
||||
["the quick brown fox", "^quick", false],
|
||||
["the quick brown fox", "quick$", false],
|
||||
["the quick brown fox", "^quick$", false],
|
||||
["the quick brown fox", "^brown", false],
|
||||
["the quick brown fox", "brown$", false],
|
||||
["the quick brown fox", "^brown$", false],
|
||||
["the quick brown fox", "fox", true],
|
||||
["the quick brown fox", "fox$", true],
|
||||
["the quick brown fox", "^fox$", false],
|
||||
["the quick brown fox", "The", false],
|
||||
["the quick brown fox", "^The", false],
|
||||
["the quick brown fox", "THE", false],
|
||||
["the quick brown fox", "^THE", false],
|
||||
["the quick brown fox", "foxx", false],
|
||||
["the quick brown fox", "foxx$", false],
|
||||
["the quick brown fox", "the quick brown fox$", true],
|
||||
["the quick brown fox", "brown fox$", true],
|
||||
["the quick brown fox", "quick brown fox$", true],
|
||||
["the quick brown fox", "he quick brown fox$", true],
|
||||
["the quick brown fox", "e quick brown fox$", true],
|
||||
["the quick brown fox", "quick brown fox$", true],
|
||||
["the quick brown fox", "x$", true],
|
||||
["the quick brown fox", "^", true],
|
||||
["the quick brown fox", "$", true],
|
||||
["the quick brown fox", "^.*$", true],
|
||||
["the quick brown fox", ".*", true],
|
||||
["the quick brown fox", "^.*", true],
|
||||
["the quick brown fox", "^.*$", true],
|
||||
|
||||
// partials
|
||||
["the quick brown fox", " quick", true],
|
||||
["the quick brown fox", " Quick", false],
|
||||
["the quick brown fox", "the quick", true],
|
||||
["the quick brown fox", "the slow", false],
|
||||
["the quick brown fox", "the quick brown", true],
|
||||
["the quick brown fox", "the quick browne", false],
|
||||
["the quick brown fox", "the quick brownfox", false],
|
||||
["the quick brown fox", "the quick brown fox", true],
|
||||
["the quick brown fox", "the quick brown foxx", false],
|
||||
["the quick brown fox", "quick brown fox", true],
|
||||
["the quick brown fox", "a quick brown fox", false],
|
||||
["the quick brown fox", "brown fox", true],
|
||||
["the quick brown fox", "rown fox", true],
|
||||
["the quick brown fox", "rown f", true],
|
||||
["the quick brown fox", "e q", true],
|
||||
["the quick brown fox", "f z", false],
|
||||
["the quick brown fox", "red fo", false],
|
||||
["the quick brown fox", "köter", false],
|
||||
["the quick brown fox", "ö", false],
|
||||
["the quick brown fox", "z", false],
|
||||
["the quick brown fox", "z", false],
|
||||
["the quick brown fox", " ", true],
|
||||
["the quick brown fox", " ", false],
|
||||
["the quick brown fox", "", true],
|
||||
|
||||
// wildcards
|
||||
["the quick brown fox", "the.*fox", true],
|
||||
["the quick brown fox", "^the.*fox$", true],
|
||||
["the quick brown fox", "^the.*dog$", false],
|
||||
["the quick brown fox", "the (quick|slow) (red|green|brown) (dog|cat|fox)", true],
|
||||
["the quick brown fox", "the .*(red|green|brown) (dog|cat|fox)", true],
|
||||
["the quick brown fox", "^the .*(red|green|brown) (dog|cat|fox)", true],
|
||||
["the quick brown fox", "the (quick|slow) (red|green|brown) (dog|cat)", false],
|
||||
["the quick brown fox", "^the (quick|slow) (red|green|brown) (dog|cat)", false],
|
||||
["the quick brown fox", "^the .*(red|green|brown) (dog|cat)", false],
|
||||
["the quick brown fox", "the .*(red|green|brown) (dog|cat)", false],
|
||||
["the quick brown fox", "the (slow|lazy) brown (fox|wolf)", false],
|
||||
["the quick brown fox", "the.*brown (fox|wolf)", true],
|
||||
["the quick brown fox", "^t.*(fox|wolf)", true],
|
||||
["the quick brown fox", "^t.*(fox|wolf)$", true],
|
||||
["the quick brown fox", "^t.*(fo|wolf)x$", true],
|
||||
["the quick brown fox", "^t.*(fo|wolf)xx", false],
|
||||
];
|
||||
|
||||
values.forEach(function(v) {
|
||||
var query = "RETURN REGEX(@what, @re)";
|
||||
assertEqual(v[2], getQueryResults(query, { what: v[0], re: v[1] })[0], v);
|
||||
|
||||
query = "RETURN NOOPT(REGEX(@what, @re))";
|
||||
assertEqual(v[2], getQueryResults(query, { what: v[0], re: v[1] })[0], v);
|
||||
|
||||
query = "RETURN NOOPT(V8(REGEX(@what, @re)))";
|
||||
assertEqual(v[2], getQueryResults(query, { what: v[0], re: v[1] })[0], v);
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test like function, invalid arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1184,6 +1314,102 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
assertEqual([ "[\"yes\",{}]yestrue" ], getQueryResults("RETURN CONCAT_SEPARATOR(\"yes\", [ \"yes\", { } ], null, true)"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorCxx1 : function () {
|
||||
var expected = [ "the,Quick,Brown,Fox,Jumps" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR(',', 'the', 'Quick', null, 'Brown', null, 'Fox', 'Jumps'))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorCxx2 : function () {
|
||||
var expected = [ "the*/*/Quick*/*/Brown*/*/*/*/Fox*/*/Jumps" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR('*/*/', 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps'))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorListCxx1 : function () {
|
||||
var expected = [ "[\"the\",\"Quick\",null,\"Brown\",null,\"Fox\",\"Jumps\"],higher,[\"than\",\"you\"]" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR(',', [ 'the', 'Quick', null, 'Brown', null, 'Fox', 'Jumps' ], 'higher', [ 'than', 'you' ]))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorListCxx2 : function () {
|
||||
var expected = [ "[\"the\",\"Quick\",null,\"Brown\",\"\",\"Fox\",\"Jumps\"]*/*/[]*/*/higher*/*/[\"than\",\"you\"]" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR('*/*/', [ 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps' ], [ ], 'higher', [ 'than', 'you' ]))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorListCxx3 : function () {
|
||||
var expected = [ "the*/*/Quick*/*/Brown*/*/*/*/Fox*/*/Jumps*/*/[]*/*/higher*/*/[\"than\",\"you\"]" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR('*/*/', 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps', [ ], 'higher', [ 'than', 'you' ]))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorListCxx4 : function () {
|
||||
var expected = [ "the*/*/Quick*/*/Brown*/*/*/*/Fox*/*/Jumps" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR('*/*/', [ 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps' ]))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorListCxx5 : function () {
|
||||
var expected = [ "the*/*/Quick*/*/Brown*/*/*/*/Fox*/*/Jumps*/*/[]*/*/higher*/*/[\"than\",\"you\"]" ];
|
||||
var actual = getQueryResults("FOR r IN [ 1 ] RETURN NOOPT(CONCAT_SEPARATOR('*/*/', [ 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps', [ ], 'higher', [ 'than', 'you' ] ]))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test concat_separator function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testConcatSeparatorCxxInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(CONCAT_SEPARATOR())");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(CONCAT_SEPARATOR(\"yes\"))");
|
||||
assertEqual([ "yesyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(null, \"yes\", \"yes\"))"));
|
||||
assertEqual([ "yestrueyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(true, \"yes\", \"yes\"))"));
|
||||
assertEqual([ "yes4yes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(4, \"yes\", \"yes\"))"));
|
||||
assertEqual([ "yes[]yes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR([ ], \"yes\", \"yes\"))"));
|
||||
assertEqual([ "yes{}yes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR({ }, \"yes\", \"yes\"))"));
|
||||
assertEqual([ "trueyesyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", true, \"yes\"))"));
|
||||
assertEqual([ "4yesyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", 4, \"yes\"))"));
|
||||
assertEqual([ "[]yesyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", [ ], \"yes\"))"));
|
||||
assertEqual([ "{}yesyes" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", { }, \"yes\"))"));
|
||||
assertEqual([ "yesyestrue" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", \"yes\", true))"));
|
||||
assertEqual([ "yesyes4" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", \"yes\", 4))"));
|
||||
assertEqual([ "yesyes[]" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", \"yes\", [ ]))"));
|
||||
assertEqual([ "yesyes[1,2,3]" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", \"yes\", [ 1,2,3 ]))"));
|
||||
assertEqual([ "yesyes{}" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", \"yes\", { }))"));
|
||||
assertEqual([ "yesyes{}" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", [ \"yes\", { } ]))"));
|
||||
assertEqual([ "[\"yes\",{}]yestrue" ], getQueryResults("RETURN NOOPT(CONCAT_SEPARATOR(\"yes\", [ \"yes\", { } ], null, true))"));
|
||||
},
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test charlength function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -34,8 +34,25 @@ const scriptArguments = {
|
|||
let ARANGOD;
|
||||
let ARANGOSH;
|
||||
|
||||
ARANGOD = fs.join(fs.join(fs.makeAbsolute('')), "build/bin/arangod");
|
||||
ARANGOSH = fs.join(fs.join(fs.makeAbsolute('')), "build/bin/arangosh");
|
||||
function locateArangod() {
|
||||
ARANGOD = fs.join(fs.join(fs.makeAbsolute('')), "build/bin/arangod");
|
||||
if(!fs.isFile(ARANGOD) && !fs.isFile(ARANGOD + ".exe")) {
|
||||
ARANGOD = fs.join(fs.join(fs.makeAbsolute('')), "bin/arangod");
|
||||
}
|
||||
if(!fs.isFile(ARANGOD) && !fs.isFile(ARANGOD + ".exe")) {
|
||||
throw "Cannot find Aarangod to execute tests against";
|
||||
}
|
||||
}
|
||||
|
||||
function locateArangosh() {
|
||||
ARANGOSH = fs.join(fs.join(fs.makeAbsolute('')), "build/bin/arangosh");
|
||||
if(!fs.isFile(ARANGOSH) && !fs.isFile(ARANGOSH + ".exe")) {
|
||||
ARANGOSH = fs.join(fs.join(fs.makeAbsolute('')), "bin/arangosh");
|
||||
}
|
||||
if(!fs.isFile(ARANGOSH) && !fs.isFile(ARANGOSH + ".exe")) {
|
||||
throw "Cannot find arangosh to run tests with";
|
||||
}
|
||||
}
|
||||
|
||||
function endpointToURL(endpoint) {
|
||||
if (endpoint.substr(0, 6) === "ssl://") {
|
||||
|
@ -131,7 +148,9 @@ function main(argv) {
|
|||
serverArgs["server.threads"] = "3";
|
||||
|
||||
print("================================================================================");
|
||||
print(ARANGOD);
|
||||
print(toArgv(serverArgs));
|
||||
locateArangod();
|
||||
instanceInfo.pid = executeExternal(ARANGOD, toArgv(serverArgs)).pid;
|
||||
|
||||
// Wait until the server is up:
|
||||
|
@ -166,6 +185,10 @@ function main(argv) {
|
|||
'javascript.execute': scriptArguments.outputFile
|
||||
};
|
||||
|
||||
locateArangosh();
|
||||
print("--------------------------------------------------------------------------------");
|
||||
print(ARANGOSH);
|
||||
print(internal.toArgv(arangoshArgs));
|
||||
res = executeExternalAndWait(ARANGOSH, internal.toArgv(arangoshArgs));
|
||||
|
||||
if (startServer) {
|
||||
|
|
Loading…
Reference in New Issue