1
0
Fork 0

Merge branch 'devel' of ssh://github.com/triAGENS/ArangoDB into sharding

This commit is contained in:
Max Neunhoeffer 2014-01-31 18:56:47 +01:00
commit 73f3dbc328
22 changed files with 767 additions and 334 deletions

View File

@ -1192,7 +1192,7 @@ bool RestDocumentHandler::replaceDocument () {
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{keepNull,string,optional}
/// @RESTQUERYPARAM{keepNull,boolean,optional}
/// If the intention is to delete existing attributes with the patch command,
/// the URL query parameter `keepNull` can be used with a value of `false`.
/// This will modify the behavior of the patch command to remove any attributes

View File

@ -628,7 +628,7 @@ bool RestEdgeHandler::createDocumentCoordinator (string const& collname,
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{keepNull,string,optional}
/// @RESTQUERYPARAM{keepNull,boolean,optional}
/// If the intention is to delete existing attributes with the patch command,
/// the URL query parameter `keepNull` can be used with a value of `false`.
/// This will modify the behavior of the patch command to remove any attributes

View File

@ -1475,7 +1475,7 @@ function delete_api_structure (req, res) {
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{keepNull,string,optional}
/// @RESTQUERYPARAM{keepNull,boolean,optional}
/// If the intention is to delete existing attributes with the patch command,
/// the URL query parameter `keepNull` can be used with a value of `false`.
/// This will modify the behavior of the patch command to remove any attributes

View File

@ -118,6 +118,7 @@ function AbstractAdapter(nodes, edges, descendant, viewer, config) {
}
node.x = x || initialX.getStart();
node.y = y || initialY.getStart();
node.weight = 1;
nodes.push(node);
node._outboundCounter = 0;
node._inboundCounter = 0;

View File

@ -181,7 +181,7 @@ function EventDispatcher(nodeShaper, edgeShaper, config) {
}
if (config.drag !== undefined) {
if (eventlib.checkDragConfig(config.drag)) {
self.events.DRAG = new eventlib.Drag(config.drag);
self.events.DRAG = eventlib.Drag(config.drag);
}
}
if (config.nodeEditor !== undefined) {

View File

@ -135,7 +135,7 @@ function ArangoAdapterControls(list, adapter) {
idprefix, [{
type: "extendable",
id: "attribute",
objects: prioList
objects: adapter.getPrioList()
}], function () {
var list = $("input[id^=" + idprefix + "attribute_]"),
prios = [];

View File

@ -29,10 +29,8 @@
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
/* Archive
function EventDispatcherControls(list, cursorIconBox, nodeShaper, edgeShaper, dispatcherConfig) {
*/
function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig) {
function EventDispatcherControls(list, nodeShaper, edgeShaper, start, dispatcherConfig) {
"use strict";
if (list === undefined) {
@ -44,6 +42,9 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
if (edgeShaper === undefined) {
throw "The EdgeShaper has to be given.";
}
if (start === undefined) {
throw "The Start callback has to be given.";
}
var self = this,
icons = {
@ -60,14 +61,6 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
appendToList = function(button) {
list.appendChild(button);
},
createButton = function(title, callback) {
uiComponentsHelper.createButton(
list,
title,
"control_event_" + title,
callback
);
},
createIcon = function(icon, title, callback) {
var btn = uiComponentsHelper.createIconButton(
icon,
@ -132,6 +125,7 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
dispatcher.events.CREATENODE(data, function(node) {
$("#" + idprefix + "modal").modal('hide');
nodeShaper.reshapeNodes();
start();
}, pos.x, pos.y)();
}
);
@ -197,19 +191,20 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
nodesUp = dispatcher.events.FINISHCREATEEDGE(function(edge){
edgeShaper.removeCursorFollowingEdge();
dispatcher.bind("svg", "mousemove", function(){});
start();
}),
svgUp = function() {
dispatcher.events.CANCELCREATEEDGE();
edgeShaper.removeCursorFollowingEdge();
dispatcher.bind("svg", "mousemove", function(){});
};
callbacks.nodes.startEdge = nodesDown;
callbacks.nodes.endEdge = nodesUp;
callbacks.svg.cancelEdge = svgUp;
},
createEditsCBs = function() {
var prefix = "control_event_edit",
idprefix = prefix + "_",
nodeCallback = function(n) {
var nodeCallback = function(n) {
modalDialogHelper.createModalEditDialog(
"Edit Node " + n._id,
"control_event_node_edit_",
@ -236,14 +231,42 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
callbacks.nodes.edit = nodeCallback;
callbacks.edges.edit = edgeCallback;
},
createDeleteCBs = function() {
callbacks.nodes.del = dispatcher.events.DELETENODE(
function() {}
);
callbacks.edges.del = dispatcher.events.DELETEEDGE(
function() {}
);
var nodeCallback = function(n) {
modalDialogHelper.createModalDeleteDialog(
"Delete Node " + n._id,
"control_event_node_delete_",
n,
function(n) {
dispatcher.events.DELETENODE(function() {
$("#control_event_node_delete_modal").modal('hide');
nodeShaper.reshapeNodes();
edgeShaper.reshapeEdges();
start();
})(n);
}
);
},
edgeCallback = function(e) {
modalDialogHelper.createModalDeleteDialog(
"Delete Edge " + e._id,
"control_event_edge_delete_",
e,
function(e) {
dispatcher.events.DELETEEDGE(function() {
$("#control_event_edge_delete_modal").modal('hide');
nodeShaper.reshapeNodes();
edgeShaper.reshapeEdges();
start();
})(e);
}
);
};
callbacks.nodes.del = nodeCallback;
callbacks.edges.del = edgeCallback;
},
createSpotCB = function() {
callbacks.nodes.spot = dispatcher.events.EXPAND;
};
@ -400,13 +423,7 @@ function EventDispatcherControls(list, nodeShaper, edgeShaper, dispatcherConfig)
this.addControlDelete = function() {
var icon = icons.trash,
callback = function() {
rebindNodes({click: dispatcher.events.DELETENODE(function() {
})});
rebindEdges({click: dispatcher.events.DELETEEDGE(function() {
})});
rebindSVG();
self.rebindAll(self.deleteRebinds());
};
createIcon(icon, "delete", callback);
};

View File

@ -111,9 +111,9 @@ function GraphViewerPreview(container, viewerConfig) {
var toolbox = document.createElement("div");
dispatcherUI = new EventDispatcherControls(
toolbox,
// mousePointerBox,
viewer.nodeShaper,
viewer.edgeShaper,
viewer.start,
viewer.dispatcherConfig
);
toolbox.id = "toolbox";
@ -153,6 +153,7 @@ function GraphViewerPreview(container, viewerConfig) {
// mousePointerBox,
viewer.nodeShaper,
viewer.edgeShaper,
viewer.start,
viewer.dispatcherConfig
);
},
@ -212,4 +213,4 @@ function GraphViewerPreview(container, viewerConfig) {
viewer.loadGraph("1");
parseActions(viewerConfig.actions);
}
}

View File

@ -326,6 +326,7 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
toolbox,
graphViewer.nodeShaper,
graphViewer.edgeShaper,
graphViewer.start,
graphViewer.dispatcherConfig
);
toolbox.id = "toolbox";

View File

@ -112,9 +112,9 @@ function GraphViewerWidget(viewerConfig, startNode) {
var toolbox = document.createElement("div");
dispatcherUI = new EventDispatcherControls(
toolbox,
//mousePointerBox,
viewer.nodeShaper,
viewer.edgeShaper,
viewer.start,
viewer.dispatcherConfig
);
toolbox.id = "toolbox";
@ -154,6 +154,7 @@ function GraphViewerWidget(viewerConfig, startNode) {
// mousePointerBox,
viewer.nodeShaper,
viewer.edgeShaper,
viewer.start,
viewer.dispatcherConfig
);
},

View File

@ -84,7 +84,6 @@ var modalDialogHelper = modalDialogHelper || {};
thirdCell.className = "actionCell";
thirdCell.appendChild(addRow);
addRow.id = idprefix + "new";
addRow.className = "graphViewer-icon-button gv-icon-small add";
@ -296,6 +295,65 @@ var modalDialogHelper = modalDialogHelper || {};
for (i = 1; i < list.length; i++) {
addNewLine(list[i]);
}
},
modalContent = function(title, idprefix) {
// Create needed Elements
var div = document.createElement("div"),
headerDiv = document.createElement("div"),
buttonDismiss = document.createElement("button"),
header = document.createElement("a"),
bodyDiv = document.createElement("div"),
bodyTable = document.createElement("table");
// Set Classnames and attributes.
div.id = idprefix + "modal";
div.className = "modal hide fade";
div.setAttribute("tabindex", "-1");
div.setAttribute("role", "dialog");
div.setAttribute("aria-labelledby", "myModalLabel");
div.setAttribute("aria-hidden", true);
div.style.display = "none";
div.onhidden = function() {
unbindSubmit();
document.body.removeChild(div);
};
headerDiv.className = "modal-header";
header.className = "arangoHeader";
buttonDismiss.id = idprefix + "modal_dismiss";
buttonDismiss.className = "close";
buttonDismiss.dataDismiss = "modal";
buttonDismiss.ariaHidden = "true";
buttonDismiss.appendChild(document.createTextNode("×"));
header.appendChild(document.createTextNode(title));
bodyDiv.className = "modal-body";
bodyTable.id = idprefix + "table";
// Append in correct ordering
div.appendChild(headerDiv);
div.appendChild(bodyDiv);
headerDiv.appendChild(buttonDismiss);
headerDiv.appendChild(header);
bodyDiv.appendChild(bodyTable);
document.body.appendChild(div);
buttonDismiss.onclick = function() {
unbindSubmit();
$("#" + idprefix + "modal").modal('hide');
};
return {
div: div,
bodyTable: bodyTable
};
};
insertModalRow = function(table, idprefix, o) {
@ -342,49 +400,17 @@ var modalDialogHelper = modalDialogHelper || {};
}
return tr;
};
modalDialogHelper.modalDivTemplate = function (title, buttonTitle, idprefix, callback) {
// Create needed Elements
buttonTitle = buttonTitle || "Switch";
var div = document.createElement("div"),
headerDiv = document.createElement("div"),
buttonDismiss = document.createElement("button"),
header = document.createElement("a"),
footerDiv = document.createElement("div"),
buttonCancel = document.createElement("button"),
buttonSubmit = document.createElement("button"),
bodyDiv = document.createElement("div"),
bodyTable = document.createElement("table");
// Set Classnames and attributes.
div.id = idprefix + "modal";
div.className = "modal hide fade";
div.setAttribute("tabindex", "-1");
div.setAttribute("role", "dialog");
div.setAttribute("aria-labelledby", "myModalLabel");
div.setAttribute("aria-hidden", true);
div.style.display = "none";
div.onhidden = function() {
unbindSubmit();
document.body.removeChild(div);
};
headerDiv.className = "modal-header";
header.className = "arangoHeader";
buttonDismiss.id = idprefix + "modal_dismiss";
buttonDismiss.className = "close";
buttonDismiss.dataDismiss = "modal";
buttonDismiss.ariaHidden = "true";
buttonDismiss.appendChild(document.createTextNode("×"));
header.appendChild(document.createTextNode(title));
bodyDiv.className = "modal-body";
bodyTable.id = idprefix + "table";
var footerDiv = document.createElement("div"),
buttonCancel = document.createElement("button"),
buttonSubmit = document.createElement("button"),
content = modalContent(title, idprefix);
footerDiv.className = "modal-footer";
buttonCancel.id = idprefix + "cancel";
@ -396,26 +422,11 @@ var modalDialogHelper = modalDialogHelper || {};
buttonSubmit.style.marginRight = "8px";
buttonSubmit.appendChild(document.createTextNode(buttonTitle));
// Append in correct ordering
div.appendChild(headerDiv);
div.appendChild(bodyDiv);
div.appendChild(footerDiv);
headerDiv.appendChild(buttonDismiss);
headerDiv.appendChild(header);
bodyDiv.appendChild(bodyTable);
content.div.appendChild(footerDiv);
footerDiv.appendChild(buttonSubmit);
footerDiv.appendChild(buttonCancel);
document.body.appendChild(div);
// Add click events
buttonDismiss.onclick = function() {
unbindSubmit();
$("#" + idprefix + "modal").modal('hide');
};
buttonCancel.onclick = function() {
unbindSubmit();
$("#" + idprefix + "modal").modal('hide');
@ -427,7 +438,7 @@ var modalDialogHelper = modalDialogHelper || {};
};
bindSubmit(buttonSubmit);
// Return the table which has to be filled somewhere else
return bodyTable;
return content.bodyTable;
};
modalDialogHelper.createModalDialog = function(title, idprefix, objects, callback) {
@ -440,6 +451,7 @@ var modalDialogHelper = modalDialogHelper || {};
modalDialogHelper.createModalChangeDialog = function(title, idprefix, objects, callback) {
var table = modalDialogHelper.modalDivTemplate(title, "Change", idprefix, callback);
console.log(objects);
_.each(objects, function(o) {
insertModalRow(table, idprefix, o);
});
@ -454,9 +466,43 @@ var modalDialogHelper = modalDialogHelper || {};
createDialogWithObject(title, "Create", idprefix, object, callback);
};
modalDialogHelper.createModalViewDialog = function(title, idprefix, object, callback) {
createViewWithObject(title, "Edit", idprefix, object, callback);
};
modalDialogHelper.createModalDeleteDialog = function(title, idprefix, object, callback) {
var footerDiv = document.createElement("div"),
buttonCancel = document.createElement("button"),
buttonSubmit = document.createElement("button"),
content = modalContent(title, idprefix);
footerDiv.className = "modal-footer";
buttonCancel.id = idprefix + "cancel";
buttonCancel.className = "btn btn-close btn-margin";
buttonCancel.appendChild(document.createTextNode("Close"));
buttonSubmit.id = idprefix + "submit";
buttonSubmit.className = "btn btn-danger";
buttonSubmit.style.marginRight = "8px";
buttonSubmit.appendChild(document.createTextNode("Delete"));
content.div.appendChild(footerDiv);
footerDiv.appendChild(buttonSubmit);
footerDiv.appendChild(buttonCancel);
// Add click events
buttonCancel.onclick = function() {
unbindSubmit();
$("#" + idprefix + "modal").modal('hide');
};
buttonSubmit.onclick = function() {
unbindSubmit();
callback(object);
$("#" + idprefix + "modal").modal('hide');
};
bindSubmit(buttonSubmit);
$("#" + idprefix + "modal").modal('show');
};
}());

View File

@ -40,8 +40,9 @@
describe('Event Dispatcher UI', function () {
var svg, dispatcherUI, list, $list,
nodeShaper, edgeShaper, layouter,
nodes, edges, adapter,
nodeShaper, edgeShaper, layouter,
nodes, edges, adapter,
start,
//mousePointerbox,
addSpies = function() {
@ -55,11 +56,15 @@
spyOn(adapter, "loadNode");
spyOn(adapter, "expandCommunity");
spyOn(adapter, "explore");
spyOn(start, "cb");
};
beforeEach(function () {
start = {
cb: function() {}
};
nodes = [{
_id: 1,
x: 3,
@ -163,7 +168,7 @@
*/
dispatcherUI = new EventDispatcherControls(
list, nodeShaper, edgeShaper, completeConfig
list, nodeShaper, edgeShaper, start.cb, completeConfig
);
spyOn(nodeShaper, "changeTo").andCallThrough();
@ -216,6 +221,10 @@
var e = new EventDispatcherControls(list, nodeShaper);
}).toThrow("The EdgeShaper has to be given.");
expect(function() {
var e = new EventDispatcherControls(list, nodeShaper, edgeShaper);
}).toThrow("The Start callback has to be given.");
});
it('should be able to add a new node control to the list', function() {
@ -600,14 +609,15 @@
});
});
it('should be able to add a delete control to the list', function() {
runs(function() {
describe("delete control", function() {
beforeEach(function() {
dispatcherUI.addControlDelete();
expect($("#control_event_list #control_event_delete").length).toEqual(1);
helper.simulateMouseEvent("click", "control_event_delete");
});
it("should be added to the list", function() {
expect($("#control_event_list #control_event_delete").length).toEqual(1);
expect(edgeShaper.changeTo).toHaveBeenCalledWith({
actions: {
reset: true,
@ -621,24 +631,27 @@
click: jasmine.any(Function)
}
});
//expect(mousePointerbox.className).toEqual("mousepointer icon-trash");
helper.simulateMouseEvent("click", "1");
});
it("should ask for permission and delete nodes", function() {
var id = "1";
helper.simulateMouseEvent("click", id);
helper.simulateMouseEvent("click", "control_event_node_delete_submit");
expect(adapter.deleteNode).toHaveBeenCalledWith(
nodes[0],
jasmine.any(Function)
);
helper.simulateMouseEvent("click", "1-2");
});
it("should ask for permission and delete nodes", function() {
var id = "1-2";
helper.simulateMouseEvent("click", id);
helper.simulateMouseEvent("click", "control_event_edge_delete_submit");
expect(adapter.deleteEdge).toHaveBeenCalledWith(
edges[0],
jasmine.any(Function)
);
});
});
});
describe('the connect control', function() {

View File

@ -72,7 +72,7 @@
cont.offsetWidth,
cont.offsetHeight,
{
type: "preview",
type: "preview",
width: width,
height: height
},
@ -138,7 +138,7 @@
ui;
spy.shapes = oldShapes;
ui = new GraphViewerPreview(cont, config);
ui = new GraphViewerPreview(cont, config);
expect(window.NodeShaper).wasCalledWith(
jasmine.any(Object),
{
@ -494,4 +494,4 @@
});
}());
}());

View File

@ -19,7 +19,7 @@
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, UPGRADE,
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
SYS_PLATFORM */
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL */
////////////////////////////////////////////////////////////////////////////////
/// @brief module "internal"
@ -662,6 +662,33 @@
delete SYS_HTTP_STATISTICS;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an external process
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_EXECUTE_EXTERNAL !== "undefined") {
exports.executeExternal = SYS_EXECUTE_EXTERNAL;
delete SYS_EXECUTE_EXTERNAL;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief kills an external process
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_KILL_EXTERNAL !== "undefined") {
exports.killExternal = SYS_KILL_EXTERNAL;
delete SYS_KILL_EXTERNAL;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a status of an external process
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_STATUS_EXTERNAL !== "undefined") {
exports.statusExternal = SYS_STATUS_EXTERNAL;
delete SYS_STATUS_EXTERNAL;
}
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------

View File

@ -42,17 +42,13 @@
#endif
#include "BasicsC/tri-strings.h"
#include "BasicsC/locks.h"
#include "BasicsC/logging.h"
// -----------------------------------------------------------------------------
// --SECTION-- private types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief contains all data documented by "proc"
///
@ -124,19 +120,10 @@ process_state_t;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief original process name
////////////////////////////////////////////////////////////////////////////////
@ -178,18 +165,142 @@ static bool MustFreeEnvironment = false;
static size_t MaximalProcessTitleSize = 0;
////////////////////////////////////////////////////////////////////////////////
/// @}
/// @brief all external processes
////////////////////////////////////////////////////////////////////////////////
static TRI_vector_pointer_t ExternalProcesses;
////////////////////////////////////////////////////////////////////////////////
/// @brief lock for protected access to vector ExternalProcesses
////////////////////////////////////////////////////////////////////////////////
static TRI_mutex_t ExternalProcessesLock;
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief creates pipe pair
////////////////////////////////////////////////////////////////////////////////
static bool CreatePipes (int* pipe_server_to_child,
int* pipe_child_to_server) {
if (pipe(pipe_server_to_child) == -1) {
LOG_ERROR("cannot create pipe");
return false;
}
if (pipe(pipe_child_to_server) == -1) {
LOG_ERROR("cannot create pipe");
close(pipe_server_to_child[0]);
close(pipe_server_to_child[1]);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief starts external process
////////////////////////////////////////////////////////////////////////////////
static void StartExternalProcess (TRI_external_t* external, bool usePipes) {
int pipe_server_to_child[2];
int pipe_child_to_server[2];
int processPid;
bool ok;
if (usePipes) {
ok = CreatePipes(pipe_server_to_child, pipe_child_to_server);
if (! ok) {
external->_status = TRI_EXT_PIPE_FAILED;
return;
}
}
processPid = fork();
// child process
if (processPid == 0) {
// set stdin and stdout of child process
if (usePipes) {
dup2(pipe_server_to_child[0], 0);
dup2(pipe_child_to_server[1], 1);
fcntl(0, F_SETFD, 0);
fcntl(1, F_SETFD, 0);
fcntl(2, F_SETFD, 0);
// close pipes
close(pipe_server_to_child[0]);
close(pipe_server_to_child[1]);
close(pipe_child_to_server[0]);
close(pipe_child_to_server[1]);
}
else {
close(0);
fcntl(1, F_SETFD, 0);
fcntl(2, F_SETFD, 0);
}
// ignore signals in worker process
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGUSR1, SIG_IGN);
// execute worker
execv(external->_executable, external->_arguments);
// should not happen
LOG_ERROR("execution of '%s' failed with %d", external->_executable, errno);
exit(1);
}
// parent
if (processPid == -1) {
LOG_ERROR("fork failed");
if (usePipes) {
close(pipe_server_to_child[0]);
close(pipe_server_to_child[1]);
close(pipe_child_to_server[0]);
close(pipe_child_to_server[1]);
}
external->_status = TRI_EXT_FORK_FAILED;
return;
}
LOG_DEBUG("fork succeeded %d", processPid);
if (usePipes) {
close(pipe_server_to_child[0]);
close(pipe_child_to_server[1]);
external->_writePipe = pipe_server_to_child[1];
external->_readPipe = pipe_child_to_server[0];
}
else {
external->_writePipe = -1;
external->_readPipe = -1;
}
external->_pid = processPid;
external->_status = TRI_EXT_RUNNING;
}
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief converts usec and sec into seconds
////////////////////////////////////////////////////////////////////////////////
@ -472,22 +583,148 @@ void TRI_SetProcessTitle (char const* title) {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
/// @brief starts an external process
////////////////////////////////////////////////////////////////////////////////
TRI_external_id_t TRI_CreateExternalProcess (const char* executable,
const char** arguments,
size_t n) {
TRI_external_t* external;
TRI_external_id_t pid;
size_t i;
// create the external structure
external = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(TRI_external_t), true);
external->_executable = TRI_DuplicateString(executable);
external->_numberArguments = n;
external->_arguments = TRI_Allocate(TRI_CORE_MEM_ZONE, (n + 2) * sizeof(char*), true);
external->_arguments[0] = TRI_DuplicateString(executable);
for (i = 0; i < n; ++i) {
external->_arguments[i + 1] = TRI_DuplicateString(arguments[i]);
}
external->_arguments[n + 1] = NULL;
external->_status = TRI_EXT_NOT_STARTED;
StartExternalProcess(external, false);
TRI_LockMutex(&ExternalProcessesLock);
TRI_PushBackVectorPointer(&ExternalProcesses, external);
pid = external->_pid;
TRI_UnlockMutex(&ExternalProcessesLock);
return pid;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the status of an external process
////////////////////////////////////////////////////////////////////////////////
TRI_external_status_t TRI_CheckExternalProcess (pid_t pid) {
TRI_external_status_t status;
TRI_external_t* external;
int loc;
int opts;
pid_t res;
size_t i;
TRI_LockMutex(&ExternalProcessesLock);
status._status = TRI_EXT_NOT_FOUND;
status._exitStatus = 0;
for (i = 0; i < ExternalProcesses._length; ++i) {
external = TRI_AtVectorPointer(&ExternalProcesses, i);
if (external->_pid == pid) {
break;
}
}
if (i == ExternalProcesses._length) {
TRI_UnlockMutex(&ExternalProcessesLock);
return status;
}
if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) {
opts = WNOHANG | WUNTRACED;
res = waitpid(external->_pid, &loc, opts);
if (res == 0) {
external->_exitStatus = 0;
}
else if (WIFEXITED(loc)) {
external->_status = TRI_EXT_TERMINATED;
external->_exitStatus = WEXITSTATUS(loc);
}
else if (WIFSIGNALED(loc)) {
external->_status = TRI_EXT_ABORTED;
external->_exitStatus = 0;
}
else if (WIFSTOPPED(loc)) {
external->_status = TRI_EXT_STOPPED;
external->_exitStatus = 0;
}
}
status._status = external->_status;
status._exitStatus = external->_exitStatus;
TRI_UnlockMutex(&ExternalProcessesLock);
return status;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief kills an external process
////////////////////////////////////////////////////////////////////////////////
void TRI_KillExternalProcess (pid_t pid) {
TRI_external_t* external;
size_t i;
TRI_LockMutex(&ExternalProcessesLock);
for (i = 0; i < ExternalProcesses._length; ++i) {
external = TRI_AtVectorPointer(&ExternalProcesses, i);
if (external->_pid == pid) {
break;
}
}
if (i == ExternalProcesses._length) {
TRI_UnlockMutex(&ExternalProcessesLock);
return;
}
if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) {
int val = kill(external->_pid , SIGKILL);
if (val) {
external->_status = TRI_EXT_KILL_FAILED;
}
else {
TRI_RemoveVectorPointer(&ExternalProcesses, i);
}
}
else {
TRI_RemoveVectorPointer(&ExternalProcesses, i);
}
TRI_UnlockMutex(&ExternalProcessesLock);
}
// -----------------------------------------------------------------------------
// --SECTION-- MODULE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// --SECTION-- modules initialisation
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the process components
////////////////////////////////////////////////////////////////////////////////
@ -500,10 +737,13 @@ void TRI_InitialiseProcess (int argc, char* argv[]) {
ProcessName = TRI_DuplicateString(argv[0]);
ARGC = argc;
ARGV = argv;
TRI_InitVectorPointer(&ExternalProcesses, TRI_CORE_MEM_ZONE);
TRI_InitMutex(&ExternalProcessesLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief shut downs the process components
/// @brief shuts down the process components
////////////////////////////////////////////////////////////////////////////////
void TRI_ShutdownProcess () {
@ -523,11 +763,14 @@ void TRI_ShutdownProcess () {
TRI_Free(TRI_CORE_MEM_ZONE, environ);
}
#endif
TRI_DestroyVectorPointer(&ExternalProcesses);
TRI_DestroyMutex(&ExternalProcessesLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor

View File

@ -40,30 +40,16 @@ extern "C" {
// --SECTION-- public constants
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief invalid process
////////////////////////////////////////////////////////////////////////////////
#define INVALID_PROCESS (0)
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief returns information about the process
////////////////////////////////////////////////////////////////////////////////
@ -81,18 +67,61 @@ typedef struct TRI_process_info_s {
TRI_process_info_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
/// @brief status of an external process
////////////////////////////////////////////////////////////////////////////////
typedef enum {
TRI_EXT_NOT_STARTED = 0, // not yet started
TRI_EXT_PIPE_FAILED = 1, // pipe before start failed
TRI_EXT_FORK_FAILED = 2, // fork failed
TRI_EXT_RUNNING = 3, // running
TRI_EXT_NOT_FOUND = 4, // unknown pid
TRI_EXT_TERMINATED = 5, // process has terminated normally
TRI_EXT_ABORTED = 6, // process has terminated abnormally
TRI_EXT_STOPPED = 7, // process has been stopped
TRI_EXT_KILL_FAILED = 8, // kill failed
}
TRI_external_status_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief identifier of an external process
////////////////////////////////////////////////////////////////////////////////
typedef pid_t TRI_external_id_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief external process description
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_external_s {
char* _executable;
size_t _numberArguments;
char** _arguments;
TRI_external_id_t _pid;
int _readPipe;
int _writePipe;
TRI_external_status_e _status;
int _exitStatus;
}
TRI_external_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief external process status
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_external_status_s {
TRI_external_status_e _status;
int _exitStatus;
}
TRI_external_status_t;
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief converts usec and sec into seconds
////////////////////////////////////////////////////////////////////////////////
@ -132,22 +161,33 @@ uint64_t TRI_ProcessSize (TRI_pid_t pid);
void TRI_SetProcessTitle (char const* title);
////////////////////////////////////////////////////////////////////////////////
/// @}
/// @brief starts an external process
////////////////////////////////////////////////////////////////////////////////
TRI_external_id_t TRI_CreateExternalProcess (const char* executable,
const char** arguments,
size_t n);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the status of an external process
////////////////////////////////////////////////////////////////////////////////
TRI_external_status_t TRI_CheckExternalProcess (pid_t pid);
////////////////////////////////////////////////////////////////////////////////
/// @brief kills an external process
////////////////////////////////////////////////////////////////////////////////
void TRI_KillExternalProcess (pid_t pid);
// -----------------------------------------------------------------------------
// --SECTION-- MODULE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// --SECTION-- modules initialisation
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SystemProcess
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the process components
////////////////////////////////////////////////////////////////////////////////
@ -160,16 +200,16 @@ void TRI_InitialiseProcess (int argc, char* argv[]);
void TRI_ShutdownProcess (void);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"

View File

@ -41,26 +41,12 @@
#include "BasicsC/logging.h"
#include "BasicsC/locks.h"
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Sockets
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Sockets
/// @{
/// @brief closes a socket
////////////////////////////////////////////////////////////////////////////////
int TRI_closesocket(TRI_socket_t s) {
@ -173,24 +159,14 @@ bool TRI_SetNonBlockingSocket (TRI_socket_t s) {
#endif
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- MODULE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// --SECTION-- modules initialisation
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Sockets
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the sockets components
////////////////////////////////////////////////////////////////////////////////
@ -205,9 +181,9 @@ void TRI_InitialiseSockets (void) {
void TRI_ShutdownSockets (void) {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor

View File

@ -45,11 +45,6 @@ using namespace triagens::rest;
// --SECTION-- static initialisers
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief set port if none specified
////////////////////////////////////////////////////////////////////////////////
@ -62,19 +57,10 @@ const uint16_t EndpointIp::_defaultPort = 8529;
const std::string EndpointIp::_defaultHost = "127.0.0.1";
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IP socket endpoint
////////////////////////////////////////////////////////////////////////////////
@ -92,7 +78,7 @@ EndpointIp::EndpointIp (const Endpoint::EndpointType type,
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys an IPv4 socket endpoint
/// @brief destroys an IP socket endpoint
////////////////////////////////////////////////////////////////////////////////
EndpointIp::~EndpointIp () {
@ -101,17 +87,12 @@ EndpointIp::~EndpointIp () {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
/// @brief connects a socket
////////////////////////////////////////////////////////////////////////////////
TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
@ -122,8 +103,8 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
char serv[NI_MAXSERV];
if (::getnameinfo(aip->ai_addr, (socklen_t) aip->ai_addrlen,
host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
LOG_TRACE("bind to address '%s', port %d", host, (int) _port);
}
@ -214,19 +195,10 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
return _socket;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief connect the endpoint
////////////////////////////////////////////////////////////////////////////////
@ -351,6 +323,7 @@ TRI_socket_t EndpointIp::connect (double connectTimeout, double requestTimeout)
return listenSocket;
}
#endif
////////////////////////////////////////////////////////////////////////////////
@ -388,9 +361,9 @@ bool EndpointIp::initIncoming (TRI_socket_t incoming) {
return setSocketFlags(incoming);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor

View File

@ -31,7 +31,6 @@
#include "Rest/Endpoint.h"
namespace triagens {
namespace rest {
@ -45,17 +44,11 @@ namespace triagens {
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
protected:
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an endpoint
////////////////////////////////////////////////////////////////////////////////
protected:
EndpointIp (const EndpointType,
const DomainType,
const EncryptionType,
@ -64,27 +57,17 @@ namespace triagens {
const std::string&,
const uint16_t);
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys an endpoint
////////////////////////////////////////////////////////////////////////////////
public:
~EndpointIp ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
@ -99,20 +82,10 @@ namespace triagens {
static const string _defaultHost;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
@ -121,19 +94,10 @@ namespace triagens {
TRI_socket_t connectSocket (const struct addrinfo*, double, double);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
@ -170,19 +134,10 @@ namespace triagens {
return _host;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
@ -196,11 +151,6 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
uint16_t _port;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
};
}
@ -208,6 +158,10 @@ namespace triagens {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"

View File

@ -40,11 +40,6 @@ using namespace triagens::rest;
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief creates an IPv4 socket endpoint
////////////////////////////////////////////////////////////////////////////////
@ -65,9 +60,9 @@ EndpointIpV4::EndpointIpV4 (const Endpoint::EndpointType type,
EndpointIpV4::~EndpointIpV4 () {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor

View File

@ -44,11 +44,6 @@ namespace triagens {
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
@ -68,19 +63,10 @@ namespace triagens {
~EndpointIpV4 ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
@ -98,19 +84,16 @@ namespace triagens {
string getHostString () const {
return getHost() + ':' + triagens::basics::StringUtils::itoa(getPort());
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
};
}
}
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"

View File

@ -458,6 +458,7 @@ static v8::Handle<v8::Value> JS_Download (v8::Arguments const& argv) {
}
v8::Handle<v8::Array> options = v8::Handle<v8::Array>::Cast(argv[2]);
if (options.IsEmpty()) {
TRI_V8_EXCEPTION_USAGE(scope, signature);
}
@ -647,11 +648,12 @@ static v8::Handle<v8::Value> JS_Download (v8::Arguments const& argv) {
map<string, string>::const_iterator it;
v8::Handle<v8::Object> headers = v8::Object::New();
for (it = responseHeaders.begin(); it != responseHeaders.end(); ++it) {
headers->Set(v8::String::New((*it).first.c_str()), v8::String::New((*it).second.c_str()));
}
result->Set(v8::String::New("headers"), headers);
result->Set(v8::String::New("headers"), headers);
if (returnBodyOnError || (returnCode >= 200 && returnCode <= 299)) {
try {
@ -2374,6 +2376,162 @@ static v8::Handle<v8::Value> JS_HttpStatistics (v8::Arguments const& argv) {
return scope.Close(result);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes a external program
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ExecuteExternal (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract the arguments
if (2 < argv.Length() || argv.Length() < 1) {
TRI_V8_EXCEPTION_USAGE(scope, "executeExternal(<filename>, [<arguments>])");
}
TRI_Utf8ValueNFC name(TRI_UNKNOWN_MEM_ZONE, argv[0]);
if (*name == 0) {
TRI_V8_TYPE_ERROR(scope, "<filename> must be a string");
}
char** arguments = 0;
size_t n = 0;
if (2 <= argv.Length()) {
v8::Handle<v8::Value> a = argv[1];
if (a->IsArray()) {
v8::Handle<v8::Array> arr = v8::Handle<v8::Array>::Cast(a);
n = arr->Length();
arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false);
for (size_t i = 0; i < n; ++i) {
TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, arr->Get(i));
if (*arg == 0) {
arguments[i] = TRI_DuplicateString("");
}
else {
arguments[i] = TRI_DuplicateString(*arg);
}
}
}
else {
n = 1;
arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false);
TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, a);
if (*arg == 0) {
arguments[0] = TRI_DuplicateString("");
}
else {
arguments[0] = TRI_DuplicateString(*arg);
}
}
}
TRI_external_id_t external = TRI_CreateExternalProcess(*name, (const char**) arguments, n);
if (arguments != 0) {
for (size_t i = 0; i < n; ++i) {
TRI_FreeString(TRI_CORE_MEM_ZONE, arguments[i]);
}
TRI_Free(TRI_CORE_MEM_ZONE, arguments);
}
// return the result
return scope.Close(v8::Number::New(external));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the status of an external process
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_StatusExternal (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract the arguments
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "statusExternal(<external-identifier>)");
}
TRI_external_id_t pid = TRI_ObjectToUInt64(argv[0], true);
TRI_external_status_t external = TRI_CheckExternalProcess(pid);
v8::Handle<v8::Object> result = v8::Object::New();
const char* status = "UNKNOWN";
switch (external._status) {
case TRI_EXT_NOT_STARTED: status = "NOT-STARTED"; break;
case TRI_EXT_PIPE_FAILED: status = "FAILED"; break;
case TRI_EXT_FORK_FAILED: status = "FAILED"; break;
case TRI_EXT_RUNNING: status = "RUNNING"; break;
case TRI_EXT_NOT_FOUND: status = "NOT-FOUND"; break;
case TRI_EXT_TERMINATED: status = "TERMINATED"; break;
case TRI_EXT_ABORTED: status = "ABORTED"; break;
case TRI_EXT_STOPPED: status = "STOPPED"; break;
case TRI_EXT_KILL_FAILED: status = "ZOMBIE"; break;
}
result->Set(v8::String::New("status"), v8::String::New(status));
if (external._status == TRI_EXT_TERMINATED) {
result->Set(v8::String::New("exit"), v8::Number::New(external._exitStatus));
}
// return the result
return scope.Close(result);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief kills an external process
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_KillExternal (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract the arguments
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "killExternal(<external-identifier>)");
}
TRI_external_id_t pid = TRI_ObjectToUInt64(argv[0], true);
TRI_KillExternalProcess(pid);
// return the result
return scope.Close(v8::Undefined());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a port is available
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_TestPort (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract the arguments
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "testPort(<address>)");
}
string address = TRI_ObjectToString(argv[0]);
Endpoint* endpoint = Endpoint::serverFactory(address);
TRI_socket_t s = endpoint->connect(1, 1);
if (s.fileDescriptor == 0) {
endpoint->disconnect();
}
delete endpoint;
// return the result
return scope.Close(v8::Boolean::New(s.fileDescriptor != 0));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoError
////////////////////////////////////////////////////////////////////////////////
@ -2720,7 +2878,7 @@ v8::Handle<v8::Object> TRI_CreateErrorObject (int errorNumber, string const& mes
}
////////////////////////////////////////////////////////////////////////////////
/// @brief normalize a v8 object
/// @brief normalizes a v8 object
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> TRI_normalize_V8_Obj (v8::Handle<v8::Value> obj) {
@ -2856,20 +3014,22 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64DECODE", JS_Base64Decode);
TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64ENCODE", JS_Base64Encode);
TRI_AddGlobalFunctionVocbase(context, "SYS_CHECK_AND_MARK_NONCE", JS_MarkNonce);
TRI_AddGlobalFunctionVocbase(context, "SYS_CLIENT_STATISTICS", JS_ClientStatistics);
TRI_AddGlobalFunctionVocbase(context, "SYS_CREATE_NONCE", JS_CreateNonce);
TRI_AddGlobalFunctionVocbase(context, "SYS_DOWNLOAD", JS_Download);
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute);
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_EXTERNAL", JS_ExecuteExternal);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_ALPHA_NUMBERS", JS_RandomAlphaNum);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt);
TRI_AddGlobalFunctionVocbase(context, "SYS_GETLINE", JS_Getline);
TRI_AddGlobalFunctionVocbase(context, "SYS_HTTP_STATISTICS", JS_HttpStatistics);
TRI_AddGlobalFunctionVocbase(context, "SYS_KILL_EXTERNAL", JS_KillExternal);
TRI_AddGlobalFunctionVocbase(context, "SYS_LOAD", JS_Load);
TRI_AddGlobalFunctionVocbase(context, "SYS_LOG", JS_Log);
TRI_AddGlobalFunctionVocbase(context, "SYS_LOG_LEVEL", JS_LogLevel);
TRI_AddGlobalFunctionVocbase(context, "SYS_MD5", JS_Md5);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_ALPHA_NUMBERS", JS_RandomAlphaNum);
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt);
TRI_AddGlobalFunctionVocbase(context, "SYS_HTTP_STATISTICS", JS_HttpStatistics);
TRI_AddGlobalFunctionVocbase(context, "SYS_CREATE_NONCE", JS_CreateNonce);
TRI_AddGlobalFunctionVocbase(context, "SYS_CHECK_AND_MARK_NONCE", JS_MarkNonce);
TRI_AddGlobalFunctionVocbase(context, "SYS_OUTPUT", JS_Output);
TRI_AddGlobalFunctionVocbase(context, "SYS_PARSE", JS_Parse);
TRI_AddGlobalFunctionVocbase(context, "SYS_PROCESS_STATISTICS", JS_ProcessStatistics);
@ -2880,6 +3040,8 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "SYS_SERVER_STATISTICS", JS_ServerStatistics);
TRI_AddGlobalFunctionVocbase(context, "SYS_SHA256", JS_Sha256);
TRI_AddGlobalFunctionVocbase(context, "SYS_SPRINTF", JS_SPrintF);
TRI_AddGlobalFunctionVocbase(context, "SYS_STATUS_EXTERNAL", JS_StatusExternal);
TRI_AddGlobalFunctionVocbase(context, "SYS_TEST_PORT", JS_TestPort);
TRI_AddGlobalFunctionVocbase(context, "SYS_TIME", JS_Time);
TRI_AddGlobalFunctionVocbase(context, "SYS_WAIT", JS_Wait);