1
0
Fork 0

Merge branch 'devel' into jwt

This commit is contained in:
Andreas Streichardt 2016-06-01 17:59:10 +02:00
commit 74719c76a6
30 changed files with 4977 additions and 214 deletions

View File

@ -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`

View File

@ -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

View File

@ -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

View File

@ -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";
}
}
}
}

View File

@ -316,31 +316,33 @@ 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;
index_t maxind = 0;
{
MUTEX_LOCKER(mutexLocker, _ioLock);
applied = _spearhead.apply(query); // Apply to spearhead
indices = _state.log(query, applied, term(), id()); // Log w/ indicies
}
if (!indices.empty()) {
maxind = *std::max_element(indices.begin(), indices.end());
}
// _appendCV.signal(); // Wake up run
reportIn(id(), maxind);
return write_ret_t(true, id(), applied,
indices); // Indices to wait for to rest
} 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);

View File

@ -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();
}
@ -108,52 +112,67 @@ bool CleanOutServer::start() const {
// 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());
// 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++;
}
LOG_TOPIC(INFO, Logger::AGENCY) << "Pending: Clean out server " + _server;
}
}
}
// Check if we can get things done in the first place
if (!checkFeasibility()) {
finish("DBServers/" + _server);
return false;
}
return true;
}
// Schedule shard relocations
scheduleMoveShards();
return true;
}
LOG_TOPIC(INFO, Logger::AGENCY) <<
"Precondition failed for starting job " + _jobId;
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;
}

View File

@ -32,17 +32,21 @@ namespace consensus {
struct CleanOutServer : public Job {
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 unsigned status () const override;
virtual bool create () const override;
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 unsigned status() const override;
virtual bool create() const override;
virtual bool start() const override;
// Check if all shards' replication factors can be satisfied after clean out.
bool checkFeasibility() const;
bool scheduleMoveShards() const;
std::string const& _server;
std::string _server;
};

View File

@ -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;

View File

@ -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;
};

View File

@ -32,8 +32,8 @@ 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()) {
if (status() == TODO) {
@ -44,9 +44,13 @@ 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);
}
}
FailedServer::~FailedServer () {}
@ -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;
}
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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);

View File

@ -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);
@ -113,7 +119,7 @@ std::vector<arangodb::consensus::index_t> State::log(
buf->append((char const*)i[0].begin(), i[0].byteSize());
idx[j] = _log.back().index + 1;
_log.push_back(log_t(idx[j], term, lid, buf)); // log to RAM
persist(idx[j], term, lid, i[0]); // log to disk
persist(idx[j], term, lid, i[0]); // log to disk
++j;
}
}

View File

@ -53,7 +53,9 @@ Supervision::~Supervision() { shutdown(); };
void Supervision::wakeUp() {
TRI_ASSERT(_agent != nullptr);
_snapshot = _agent->readDB().get(_agencyPrefix);
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();
_agent->write(report);
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;
}

View File

@ -149,9 +149,9 @@ struct FunctionDefiner {
void addStringFunctions() {
// string functions
add({"CONCAT", "AQL_CONCAT", "szl|+", true, true, false,
true, true, &Functions::Concat});
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});

View File

@ -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,26 +1265,88 @@ 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);
for (size_t i = 0; i < n; ++i) {
AqlValue member = ExtractFunctionParameterValue(trx, parameters, i);
if (member.isNull(true)) {
continue;
}
// convert member to a string and append
AppendAsString(trx, adapter, member);
if (member.isNull(true)) {
continue;
}
// convert member to a string and append
AppendAsString(trx, adapter, member);
}
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);
}
}
/// @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;
}
try {
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

View File

@ -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*,

View File

@ -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

View File

@ -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() {

View File

@ -79,6 +79,8 @@ class AllIndexIterator final : public IndexIterator {
~AllIndexIterator() {}
TRI_doc_mptr_t* next() override;
void nextBabies(std::vector<TRI_doc_mptr_t*>&, size_t) override;
void reset() override;

View File

@ -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;

View File

@ -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;

View File

@ -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);
if (RegexCache[modifiers][regex] === undefined) {
RegexCache[modifiers][regex] = COMPILE_REGEX(regex, modifiers);
}
try {
if (RegexCache[modifiers][regex] === undefined) {
RegexCache[modifiers][regex] = COMPILE_REGEX(regex, modifiers);
}
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);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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) {