mirror of https://gitee.com/bigwinds/arangodb
added tests for task management
This commit is contained in:
parent
1168f089da
commit
cfc2d407d7
15
CHANGELOG
15
CHANGELOG
|
@ -1,13 +1,19 @@
|
|||
v2.1.0 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* added server-side periodic task management functions:
|
||||
|
||||
- internal.executeTask(): executes a periodic task
|
||||
- internal.deleteTask(): removes a periodic task
|
||||
- internal.getTasks(): lists all periodic tasks
|
||||
|
||||
the previous undocumented function `internal.definePeriodic` is now
|
||||
deprecated and will be removed in a future release.
|
||||
|
||||
* decrease the size of some seldomly used system collections on creation.
|
||||
|
||||
This will make these collections use less disk space and mapped memory.
|
||||
|
||||
* fixed issue #848: db.someEdgeCollection.inEdge does not return correct
|
||||
value when called the 2nd time after a .save to the edge collection
|
||||
|
||||
* added AQL date functions
|
||||
|
||||
* added AQL FLATTEN() and FLATTEN_RECURSIVE() list functions
|
||||
|
@ -127,6 +133,9 @@ v2.0.8 (XXXX-XX-XX)
|
|||
watch API crashed it. This was because atomic operations worked on data
|
||||
structures that were not properly aligned on 32 bit systems.
|
||||
|
||||
* fixed issue #848: db.someEdgeCollection.inEdge does not return correct
|
||||
value when called the 2nd time after a .save to the edge collection
|
||||
|
||||
|
||||
v2.0.7 (2014-05-05)
|
||||
-------------------
|
||||
|
|
|
@ -370,6 +370,7 @@ SHELL_COMMON = \
|
|||
SHELL_SERVER_ONLY = \
|
||||
@top_srcdir@/js/server/tests/shell-sharding-helpers.js \
|
||||
@top_srcdir@/js/server/tests/shell-compaction-noncluster.js \
|
||||
@top_srcdir@/js/server/tests/shell-tasks.js \
|
||||
@top_srcdir@/js/server/tests/shell-transactions-noncluster.js \
|
||||
@top_srcdir@/js/server/tests/shell-routing.js \
|
||||
@top_srcdir@/js/server/tests/shell-any-noncluster.js \
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#include "V8PeriodicJob.h"
|
||||
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "BasicsC/json.h"
|
||||
#include "BasicsC/logging.h"
|
||||
#include "V8/v8-conv.h"
|
||||
#include "V8/v8-utils.h"
|
||||
#include "V8Server/ApplicationV8.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
@ -48,15 +50,13 @@ using namespace triagens::arango;
|
|||
|
||||
V8PeriodicJob::V8PeriodicJob (TRI_vocbase_t* vocbase,
|
||||
ApplicationV8* v8Dealer,
|
||||
string const& module,
|
||||
string const& func,
|
||||
string const& parameter)
|
||||
string const& command,
|
||||
TRI_json_t const* parameters)
|
||||
: Job("V8 Periodic Job"),
|
||||
_vocbase(vocbase),
|
||||
_v8Dealer(v8Dealer),
|
||||
_module(module),
|
||||
_func(func),
|
||||
_parameter(parameter),
|
||||
_command(command),
|
||||
_parameters(parameters),
|
||||
_canceled(0) {
|
||||
}
|
||||
|
||||
|
@ -101,17 +101,43 @@ Job::status_t V8PeriodicJob::work () {
|
|||
// now execute the function within this context
|
||||
{
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get built-in Function constructor (see ECMA-262 5th edition 15.3.2)
|
||||
v8::Handle<v8::Object> current = v8::Context::GetCurrent()->Global();
|
||||
v8::Local<v8::Function> ctor = v8::Local<v8::Function>::Cast(current->Get(v8::String::New("Function")));
|
||||
|
||||
// Invoke Function constructor to create function with the given body and no arguments
|
||||
v8::Handle<v8::Value> args[2] = { v8::String::New("params"), v8::String::New(_command.c_str(), _command.size()) };
|
||||
v8::Local<v8::Object> function = ctor->NewInstance(2, args);
|
||||
|
||||
string module = StringUtils::escape(_module, "\"");
|
||||
string func = StringUtils::escape(_func, "\"");
|
||||
string parameter = StringUtils::escape(_parameter, "\"");
|
||||
|
||||
string command = "(require(\"" + module + "\")[\"" + func + "\"])(\"" + parameter + "\")";
|
||||
|
||||
TRI_ExecuteJavaScriptString(context->_context,
|
||||
v8::String::New(command.c_str(), (int) command.size()),
|
||||
v8::String::New("periodic function"),
|
||||
true);
|
||||
v8::Handle<v8::Function> action = v8::Local<v8::Function>::Cast(function);
|
||||
|
||||
if (action.IsEmpty()) {
|
||||
_v8Dealer->exitContext(context);
|
||||
// TODO: adjust exit code??
|
||||
return status_t(JOB_DONE);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> fArgs;
|
||||
if (_parameters != 0) {
|
||||
fArgs = TRI_ObjectJson(_parameters);
|
||||
}
|
||||
else {
|
||||
fArgs = v8::Undefined();
|
||||
}
|
||||
|
||||
// call the function
|
||||
v8::TryCatch tryCatch;
|
||||
action->Call(current, 1, &fArgs);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
if (tryCatch.CanContinue()) {
|
||||
TRI_LogV8Exception(&tryCatch);
|
||||
}
|
||||
else {
|
||||
LOG_WARNING("caught non-printable exception in periodic task");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_v8Dealer->exitContext(context);
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include "Dispatcher/Job.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
extern "C" {
|
||||
struct TRI_json_s;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class V8PeriodicJob
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -56,9 +60,8 @@ namespace triagens {
|
|||
|
||||
V8PeriodicJob (TRI_vocbase_t*,
|
||||
ApplicationV8*,
|
||||
string const& module,
|
||||
string const& func,
|
||||
string const& parameter);
|
||||
std::string const&,
|
||||
struct TRI_json_s const*);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Job methods
|
||||
|
@ -76,7 +79,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const string& queue ();
|
||||
const std::string& queue ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
@ -127,22 +130,16 @@ namespace triagens {
|
|||
ApplicationV8* _v8Dealer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief module name
|
||||
/// @brief the command to execute
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string _module;
|
||||
std::string const _command;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function name
|
||||
/// @brief paramaters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string _func;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief paramater string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string _parameter;
|
||||
struct TRI_json_s const* _parameters;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief cancel flag
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
#include "V8PeriodicTask.h"
|
||||
|
||||
#include "BasicsC/json.h"
|
||||
#include "Dispatcher/Dispatcher.h"
|
||||
#include "Scheduler/Scheduler.h"
|
||||
#include "V8/v8-conv.h"
|
||||
#include "V8Server/V8PeriodicJob.h"
|
||||
#include "VocBase/server.h"
|
||||
|
||||
|
@ -52,17 +54,15 @@ V8PeriodicTask::V8PeriodicTask (string const& id,
|
|||
Dispatcher* dispatcher,
|
||||
double offset,
|
||||
double period,
|
||||
string const& module,
|
||||
string const& func,
|
||||
string const& parameter)
|
||||
string const& command,
|
||||
TRI_json_t* parameters)
|
||||
: Task(id, name),
|
||||
PeriodicTask(offset, period),
|
||||
_vocbase(vocbase),
|
||||
_v8Dealer(v8Dealer),
|
||||
_dispatcher(dispatcher),
|
||||
_module(module),
|
||||
_func(func),
|
||||
_parameter(parameter) {
|
||||
_command(command),
|
||||
_parameters(parameters) {
|
||||
|
||||
assert(vocbase != 0);
|
||||
|
||||
|
@ -77,12 +77,30 @@ V8PeriodicTask::V8PeriodicTask (string const& id,
|
|||
V8PeriodicTask::~V8PeriodicTask () {
|
||||
// decrease reference counter for the database used
|
||||
TRI_ReleaseVocBase(_vocbase);
|
||||
|
||||
if (_parameters != 0) {
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _parameters);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PeriodicTask methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void V8PeriodicTask::getDescription (TRI_json_t* json) {
|
||||
PeriodicTask::getDescription(json);
|
||||
|
||||
TRI_json_t* cmd = TRI_CreateString2CopyJson(TRI_UNKNOWN_MEM_ZONE, _command.c_str(), _command.size());
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "command", cmd);
|
||||
|
||||
TRI_json_t* db = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, _vocbase->_name);
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "database", db);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief handles the next tick
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -91,10 +109,9 @@ bool V8PeriodicTask::handlePeriod () {
|
|||
V8PeriodicJob* job = new V8PeriodicJob(
|
||||
_vocbase,
|
||||
_v8Dealer,
|
||||
_module,
|
||||
_func,
|
||||
_parameter);
|
||||
|
||||
"(function (params) { " + _command + " } )(params);",
|
||||
_parameters);
|
||||
|
||||
_dispatcher->addJob(job);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
extern "C" {
|
||||
struct TRI_json_s;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class V8PeriodicTask
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -65,9 +69,8 @@ namespace triagens {
|
|||
rest::Dispatcher*,
|
||||
double,
|
||||
double,
|
||||
string const&,
|
||||
string const&,
|
||||
string const&);
|
||||
std::string const&,
|
||||
struct TRI_json_s*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
|
@ -81,6 +84,12 @@ namespace triagens {
|
|||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void getDescription (struct TRI_json_s*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the task is user-defined
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -126,22 +135,16 @@ namespace triagens {
|
|||
rest::Dispatcher* _dispatcher;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief module name
|
||||
/// @brief command to execute
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const _module;
|
||||
std::string const _command;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function name
|
||||
/// @brief paramaters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const _func;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief paramater string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const _parameter;
|
||||
struct TRI_json_s* _parameters;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "V8Server/V8PeriodicTask.h"
|
||||
#include "V8Server/v8-vocbase.h"
|
||||
#include "VocBase/server.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
|
||||
|
@ -75,12 +76,6 @@ static TRI_action_result_t ExecuteActionVocbase (TRI_vocbase_t* vocbase,
|
|||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief global VocBase
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_t* GlobalVocbase = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief global V8 dealer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1153,7 +1148,7 @@ static v8::Handle<v8::Value> JS_ClusterTest (v8::Arguments const& argv) {
|
|||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief defines and executes a periodic task
|
||||
/// @brief defines and executes a task
|
||||
///
|
||||
/// @FUN{internal.executeTask(@FA{task})}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1203,70 +1198,52 @@ static v8::Handle<v8::Value> JS_ExecuteTask (v8::Arguments const& argv) {
|
|||
|
||||
// period in seconds & count
|
||||
double period = 0.0;
|
||||
int64_t count;
|
||||
|
||||
if (obj->HasOwnProperty(TRI_V8_SYMBOL("period"))) {
|
||||
period = TRI_ObjectToDouble(obj->Get(TRI_V8_SYMBOL("period")));
|
||||
}
|
||||
|
||||
|
||||
if (period <= 0.0) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "task period must be specified and positive");
|
||||
}
|
||||
if (period <= 0.0) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "task period must be specified and positive");
|
||||
}
|
||||
|
||||
if (obj->HasOwnProperty(TRI_V8_SYMBOL("count"))) {
|
||||
// check for count attribute
|
||||
count = TRI_ObjectToInt64(obj->Get(TRI_V8_SYMBOL("count")));
|
||||
|
||||
// extract the command
|
||||
if (! obj->HasOwnProperty(TRI_V8_SYMBOL("command"))) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "command must be specified");
|
||||
}
|
||||
|
||||
if (count <= 0) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "task execution count must be specified and positive");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no count specified. this means the job will go on forever
|
||||
count = -1;
|
||||
}
|
||||
string command;
|
||||
if (obj->Get(TRI_V8_SYMBOL("command"))->IsFunction()) {
|
||||
// need to add ( and ) around function because call would otherwise break
|
||||
command = "(" + TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("command"))) + ")(params)";
|
||||
}
|
||||
else {
|
||||
count = 1; // single execution
|
||||
command = TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("command")));
|
||||
}
|
||||
|
||||
assert(count == -1 || count > 0);
|
||||
// extract the parameters
|
||||
TRI_json_t* parameters = 0;
|
||||
|
||||
// TODO: count is currently not used
|
||||
|
||||
// extract the module name
|
||||
if (! obj->HasOwnProperty(TRI_V8_SYMBOL("module"))) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "module must be specified");
|
||||
}
|
||||
|
||||
string const module = TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("module")));
|
||||
|
||||
// extract the function name
|
||||
if (! obj->HasOwnProperty(TRI_V8_SYMBOL("funcname"))) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "funcname must be specified");
|
||||
}
|
||||
|
||||
string const func = TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("funcname")));
|
||||
|
||||
// extract the parameter
|
||||
string parameter;
|
||||
if (obj->HasOwnProperty(TRI_V8_SYMBOL("parameter"))) {
|
||||
parameter = TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("parameter")));
|
||||
if (obj->HasOwnProperty(TRI_V8_SYMBOL("params"))) {
|
||||
parameters = TRI_ObjectToJson(obj->Get(TRI_V8_SYMBOL("params")));
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
// create a new periodic task
|
||||
V8PeriodicTask* task = new V8PeriodicTask(
|
||||
id,
|
||||
name,
|
||||
GlobalVocbase,
|
||||
static_cast<TRI_vocbase_t*>(v8g->_vocbase),
|
||||
GlobalV8Dealer,
|
||||
GlobalScheduler,
|
||||
GlobalDispatcher,
|
||||
offset,
|
||||
period,
|
||||
module,
|
||||
func,
|
||||
parameter);
|
||||
command,
|
||||
parameters);
|
||||
|
||||
int res = GlobalScheduler->registerTask(task);
|
||||
|
||||
|
@ -1276,17 +1253,21 @@ static v8::Handle<v8::Value> JS_ExecuteTask (v8::Arguments const& argv) {
|
|||
TRI_V8_EXCEPTION(scope, res);
|
||||
}
|
||||
|
||||
// return the result
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
// get the JSON representation of the task
|
||||
TRI_json_t* json = task->toJson();
|
||||
|
||||
result->Set(TRI_V8_SYMBOL("id"), v8::String::New(id.c_str(), (int) id.size()));
|
||||
result->Set(TRI_V8_SYMBOL("name"), v8::String::New(name.c_str(), (int) name.size()));
|
||||
if (json != 0) {
|
||||
v8::Handle<v8::Value> result = TRI_ObjectJson(json);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
return scope.Close(result);
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes a periodic task
|
||||
/// @brief deletes a task
|
||||
///
|
||||
/// @FUN{internal.deleteTask(@FA{id})}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1298,7 +1279,17 @@ static v8::Handle<v8::Value> JS_DeleteTask (v8::Arguments const& argv) {
|
|||
TRI_V8_EXCEPTION_USAGE(scope, "deleteTask(<id>)");
|
||||
}
|
||||
|
||||
string const id = TRI_ObjectToString(argv[0]);
|
||||
string id;
|
||||
if (argv[0]->IsObject()) {
|
||||
// extract "id" from object
|
||||
v8::Handle<v8::Object> obj = argv[0].As<v8::Object>();
|
||||
if (obj->Has(TRI_V8_SYMBOL("id"))) {
|
||||
id = TRI_ObjectToString(obj->Get(TRI_V8_SYMBOL("id")));
|
||||
}
|
||||
}
|
||||
else {
|
||||
id = TRI_ObjectToString(argv[0]);
|
||||
}
|
||||
|
||||
if (GlobalScheduler == 0 || GlobalDispatcher == 0) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_ERROR_INTERNAL, "no scheduler found");
|
||||
|
@ -1314,7 +1305,7 @@ static v8::Handle<v8::Value> JS_DeleteTask (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets all registered periodic tasks
|
||||
/// @brief gets all registered tasks
|
||||
///
|
||||
/// @FUN{internal.getTasks()}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1357,7 +1348,6 @@ void TRI_InitV8Actions (v8::Handle<v8::Context> context,
|
|||
ApplicationV8* applicationV8) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
GlobalVocbase = vocbase;
|
||||
GlobalV8Dealer = applicationV8;
|
||||
|
||||
// check the isolate
|
||||
|
|
|
@ -758,6 +758,13 @@
|
|||
if (typeof SYS_EXECUTE_TASK !== "undefined") {
|
||||
exports.executeTask = SYS_EXECUTE_TASK;
|
||||
delete SYS_EXECUTE_TASK;
|
||||
|
||||
// TODO: remove this in next release
|
||||
exports.definePeriodic = function (offset, period, module, funcname) {
|
||||
require("console").warn("definePeriodic() is deprecated. please use executeTask() instead");
|
||||
var command = "require('" + module + "')." + funcname + "();"
|
||||
exports.executeTask({ offset: offset, period: period, command: command });
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -758,6 +758,13 @@
|
|||
if (typeof SYS_EXECUTE_TASK !== "undefined") {
|
||||
exports.executeTask = SYS_EXECUTE_TASK;
|
||||
delete SYS_EXECUTE_TASK;
|
||||
|
||||
// TODO: remove this in next release
|
||||
exports.definePeriodic = function (offset, period, module, funcname) {
|
||||
require("console").warn("definePeriodic() is deprecated. please use executeTask() instead");
|
||||
var command = "require('" + module + "')." + funcname + "();";
|
||||
exports.executeTask({ offset: offset, period: period, command: command });
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -54,10 +54,10 @@ if (cluster.isCluster()) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reloads the user authentication data
|
||||
/// @brief creates a statistics entry
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
exports.historian = function (param) {
|
||||
exports.historian = function () {
|
||||
"use strict";
|
||||
|
||||
try {
|
||||
|
|
|
@ -58,9 +58,7 @@ var Buffer = require("buffer").Buffer;
|
|||
name: "statistics-collector",
|
||||
offset: 1,
|
||||
period: 10,
|
||||
module: "org/arangodb/statistics",
|
||||
funcname: "historian",
|
||||
parameter: "_statistics"
|
||||
command: "require('org/arangodb/statistics').historian();"
|
||||
});
|
||||
}
|
||||
}());
|
||||
|
|
|
@ -0,0 +1,433 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the task manager
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 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 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var jsunity = require("jsunity");
|
||||
|
||||
var arangodb = require("org/arangodb");
|
||||
var internal = require("internal");
|
||||
var db = arangodb.db;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function TaskSuite () {
|
||||
var cn = "UnitTestsTasks";
|
||||
|
||||
var cleanTasks = function () {
|
||||
internal.getTasks().forEach(function(task) {
|
||||
if (task.id.match(/^UnitTest/) || task.name.match(/^UnitTest/)) {
|
||||
internal.deleteTask(task);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var getTasks = function () {
|
||||
var sorter = function (l, r) {
|
||||
if (l.id !== r.id) {
|
||||
return (l.id < r.id ? -1 : 1);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
return internal.getTasks().filter(function (task) {
|
||||
return task.name.match(/^UnitTest/);
|
||||
}).sort(sorter);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
cleanTasks();
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
cleanTasks();
|
||||
|
||||
db._drop(cn);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task without an id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskNoId : function () {
|
||||
try {
|
||||
internal.executeTask({ });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task without a period
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskNoPeriod : function () {
|
||||
try {
|
||||
internal.executeTask({ id: "UnitTestsNoPeriod", command: "1+1;" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task with an invalid period
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskInvalidPeriod1 : function () {
|
||||
try {
|
||||
internal.executeTask({ id: "UnitTestsNoPeriod", period: -1, command: "1+1;" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task with an invalid period
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskInvalidPeriod2 : function () {
|
||||
try {
|
||||
internal.executeTask({ id: "UnitTestsNoPeriod", period: 0, command: "1+1;" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task without a command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskNoCommand : function () {
|
||||
try {
|
||||
internal.executeTask({ id: "UnitTestsNoPeriod", period: 1 });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task with an automatic id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskAutomaticId : function () {
|
||||
var task = internal.executeTask({ name: "UnitTests1", command: "1+1;", period: 1 });
|
||||
|
||||
assertMatch(/^\d+$/, task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
assertEqual(1, task.period);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task with a duplicate id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskDuplicateId : function () {
|
||||
var task = internal.executeTask({ id: "UnitTests1", name: "UnitTests1", command: "1+1;", period: 1 });
|
||||
|
||||
assertEqual("UnitTests1", task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
|
||||
assertEqual(1, task.period);
|
||||
|
||||
try {
|
||||
internal.executeTask({ id: "UnitTests1", name: "UnitTests1", command: "1+1;", period: 1 });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_TASK_DUPLICATE_ID.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove without an id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskRemoveWithoutId : function () {
|
||||
try {
|
||||
internal.deleteTask();
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_BAD_PARAMETER.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task and remove it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskRemoveByTask : function () {
|
||||
var task = internal.executeTask({ id: "UnitTests1", name: "UnitTests1", command: "1+1;", period: 1 });
|
||||
|
||||
assertEqual("UnitTests1", task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
assertEqual(1, task.period);
|
||||
|
||||
internal.deleteTask(task);
|
||||
|
||||
try {
|
||||
// deleting again should fail
|
||||
internal.deleteTask(task);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_TASK_NOT_FOUND.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task and remove it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateTaskRemoveById : function () {
|
||||
var task = internal.executeTask({ id: "UnitTests1", name: "UnitTests1", command: "1+1;", period: 1 });
|
||||
|
||||
assertEqual("UnitTests1", task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
assertEqual(1, task.period);
|
||||
|
||||
internal.deleteTask(task.id);
|
||||
|
||||
try {
|
||||
// deleting again should fail
|
||||
internal.deleteTask(task.id);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_TASK_NOT_FOUND.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get list of tasks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetTasks : function () {
|
||||
var task1 = internal.executeTask({
|
||||
id: "UnitTests1",
|
||||
name: "UnitTests1",
|
||||
command: "1+1;",
|
||||
period: 1
|
||||
});
|
||||
|
||||
var task2 = internal.executeTask({
|
||||
id: "UnitTests2",
|
||||
name: "UnitTests2",
|
||||
command: "2+2;",
|
||||
period: 2
|
||||
});
|
||||
|
||||
var tasks = getTasks();
|
||||
|
||||
assertEqual(2, tasks.length);
|
||||
assertEqual(task1.id, tasks[0].id);
|
||||
assertEqual(task1.name, tasks[0].name);
|
||||
assertEqual(task1.type, tasks[0].type);
|
||||
assertEqual(task1.period, tasks[0].period);
|
||||
assertEqual(task1.database, tasks[0].database);
|
||||
|
||||
assertEqual(task2.id, tasks[1].id);
|
||||
assertEqual(task2.name, tasks[1].name);
|
||||
assertEqual(task2.type, tasks[1].type);
|
||||
assertEqual(task2.period, tasks[1].period);
|
||||
assertEqual(task2.database, tasks[1].database);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get list of tasks pre and post task deletion
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetTasks : function () {
|
||||
var task1 = internal.executeTask({
|
||||
id: "UnitTests1",
|
||||
name: "UnitTests1",
|
||||
command: "1+1;",
|
||||
period: 1
|
||||
});
|
||||
|
||||
var tasks = getTasks();
|
||||
|
||||
assertEqual(1, tasks.length);
|
||||
assertEqual(task1.id, tasks[0].id);
|
||||
assertEqual(task1.name, tasks[0].name);
|
||||
assertEqual(task1.type, tasks[0].type);
|
||||
assertEqual(task1.period, tasks[0].period);
|
||||
assertEqual(task1.database, tasks[0].database);
|
||||
|
||||
var task2 = internal.executeTask({
|
||||
id: "UnitTests2",
|
||||
name: "UnitTests2",
|
||||
command: "2+2;",
|
||||
period: 2
|
||||
});
|
||||
|
||||
tasks = getTasks();
|
||||
|
||||
assertEqual(2, tasks.length);
|
||||
assertEqual(task1.id, tasks[0].id);
|
||||
assertEqual(task1.name, tasks[0].name);
|
||||
assertEqual(task1.type, tasks[0].type);
|
||||
assertEqual(task1.period, tasks[0].period);
|
||||
assertEqual(task1.database, tasks[0].database);
|
||||
assertEqual(task2.id, tasks[1].id);
|
||||
assertEqual(task2.name, tasks[1].name);
|
||||
assertEqual(task2.type, tasks[1].type);
|
||||
assertEqual(task2.period, tasks[1].period);
|
||||
assertEqual(task2.database, tasks[1].database);
|
||||
|
||||
internal.deleteTask(task1);
|
||||
|
||||
tasks = getTasks();
|
||||
|
||||
assertEqual(1, tasks.length);
|
||||
assertEqual(task2.id, tasks[0].id);
|
||||
assertEqual(task2.name, tasks[0].name);
|
||||
assertEqual(task2.type, tasks[0].type);
|
||||
assertEqual(task2.period, tasks[0].period);
|
||||
assertEqual(task2.database, tasks[0].database);
|
||||
|
||||
internal.deleteTask(task2);
|
||||
|
||||
tasks = getTasks();
|
||||
|
||||
assertEqual(0, tasks.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task and run it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateStringCommand : function () {
|
||||
db._drop(cn);
|
||||
db._create(cn);
|
||||
|
||||
assertEqual(0, db[cn].count());
|
||||
|
||||
var command = "require('internal').db." + cn + ".save({ value: params });";
|
||||
|
||||
var task = internal.executeTask({
|
||||
id: "UnitTests1",
|
||||
name: "UnitTests1",
|
||||
command: command,
|
||||
period: 1,
|
||||
params: 23
|
||||
});
|
||||
|
||||
assertEqual("UnitTests1", task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
assertEqual(1, task.period);
|
||||
assertEqual("_system", task.database);
|
||||
|
||||
internal.wait(5);
|
||||
|
||||
internal.deleteTask(task);
|
||||
|
||||
assertTrue(db[cn].count() > 0);
|
||||
assertTrue(db[cn].byExample({ value: 23 }).count() > 0);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a task and run it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCreateFunctionCommand : function () {
|
||||
db._drop(cn);
|
||||
db._create(cn);
|
||||
|
||||
assertEqual(0, db[cn].count());
|
||||
|
||||
var command = function (params) {
|
||||
require('internal').db[params.cn].save({ value: params.val });
|
||||
};
|
||||
|
||||
var task = internal.executeTask({
|
||||
id: "UnitTests1",
|
||||
name: "UnitTests1",
|
||||
command: command,
|
||||
period: 1,
|
||||
params: { cn: cn, val: 42 }
|
||||
});
|
||||
|
||||
assertEqual("UnitTests1", task.id);
|
||||
assertEqual("UnitTests1", task.name);
|
||||
assertEqual("periodic", task.type);
|
||||
assertEqual(1, task.period);
|
||||
assertEqual("_system", task.database);
|
||||
|
||||
internal.wait(5);
|
||||
|
||||
internal.deleteTask(task);
|
||||
|
||||
assertTrue(db[cn].count() > 0);
|
||||
assertTrue(db[cn].byExample({ value: 23 }).count() === 0);
|
||||
assertTrue(db[cn].byExample({ value: 42 }).count() > 0);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- main
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(TaskSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -238,16 +238,11 @@ TRI_json_t* Scheduler::getUserTasks () {
|
|||
Task* task = (*i).first;
|
||||
|
||||
if (task->isUserDefined()) {
|
||||
TRI_json_t* obj = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
TRI_json_t* obj = task->toJson();
|
||||
|
||||
if (obj != 0) {
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, obj, "id", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, task->id().c_str()));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, obj, "name", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, task->name().c_str()));
|
||||
|
||||
task->getDescription(obj);
|
||||
TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, obj);
|
||||
}
|
||||
|
||||
TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, obj);
|
||||
}
|
||||
|
||||
++i;
|
||||
|
|
|
@ -59,9 +59,26 @@ Task::~Task () {
|
|||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// protected methods
|
||||
// public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a JSON representation of the task
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* Task::toJson () {
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
if (json != 0) {
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "id", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, this->id().c_str()));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "name", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, this->name().c_str()));
|
||||
|
||||
this->getDescription(json);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the task is user-defined
|
||||
/// note: this function may be overridden
|
||||
|
@ -71,14 +88,6 @@ bool Task::isUserDefined () const {
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
/// this does nothing for basic tasks, but derived classes may override it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Task::getDescription (TRI_json_t* json) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief allow thread to run on slave event loop
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -87,3 +96,15 @@ bool Task::needsMainEventLoop () const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
/// this does nothing for basic tasks, but derived classes may override it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Task::getDescription (TRI_json_t* json) {
|
||||
}
|
||||
|
||||
|
|
|
@ -99,10 +99,10 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
/// @brief get a JSON representation of the task
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void getDescription (struct TRI_json_s*);
|
||||
struct TRI_json_s* toJson ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the task is a user task
|
||||
|
@ -138,6 +138,12 @@ namespace triagens {
|
|||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a task specific description in JSON format
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void getDescription (struct TRI_json_s*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief called to set up the callback information
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue