1
0
Fork 0

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

This commit is contained in:
Michael Hackstein 2014-07-01 16:52:21 +02:00
commit aac1d3ecde
77 changed files with 1748 additions and 2369 deletions

View File

@ -53,9 +53,12 @@ int utf8_charlen(int c)
size_t utf8_strlen(const char *str, size_t bytelen)
{
size_t charlen = 0;
#if 0
// can never by true
if (bytelen < 0) {
bytelen = strlen(str);
}
#endif
while (bytelen) {
int c;
int l = utf8_tounicode(str, &c);

View File

@ -1,7 +1,7 @@
!CHAPTER Graphs
**Warning Deprecated**
**Warning: Deprecated**
This module is deprecated and will be removed soon.
Please use [General Graphs](../General-Graphs/README.md) instead.

View File

@ -1,6 +1,6 @@
!CHAPTER General HTTP Request Handling in ArangoDB
!SUBSECTION Protocol
!SECTION Protocol
ArangoDB exposes its API via HTTP, making the server accessible easily with
a variety of clients and tools (e.g. browsers, curl, telnet). The communication
@ -21,8 +21,7 @@ an HTTP 505 (HTTP version not supported) error.
ArangoDB will always respond to client requests with HTTP 1.1. Clients
should therefore support HTTP version 1.1.
!SUBSECTION Blocking vs. Non-blocking Requests
!SECTION Blocking vs. Non-blocking Requests
ArangoDB supports both blocking and non-blocking requests.
@ -69,7 +68,7 @@ case of a crash. Clients should therefore not use the asynchronous feature
when they have strict durability requirements or if they rely on the immediate
result of the request they send.
!SUBSECTION HTTP Keep-Alive
!SECTION HTTP Keep-Alive
ArangoDB supports HTTP keep-alive. If the client does not send a *Connection*
header in its request, and the client uses HTTP version 1.1, ArangoDB will assume
@ -84,7 +83,7 @@ using HTTP 1.0, except if they send an *Connection: Keep-Alive* header.
The default Keep-Alive timeout can be specified at server start using the
*--server.keep-alive-timeout* parameter.
!SUBSECTION Authentication
!SECTION Authentication
Client authentication can be achieved by using the *Authorization* HTTP header in
client requests. ArangoDB supports HTTP Basic authentication.
@ -126,7 +125,7 @@ to ArangoDB, ArangoDB will only send status code 401, but no *WWW-Authenticate*
This allows clients to implement credentials handling and bypassing the browser's
built-in dialog.
!SUBSECTION Error Handling
!SECTION Error Handling
The following should be noted about how ArangoDB handles client errors in its
HTTP layer:
@ -173,7 +172,7 @@ HTTP layer:
Requests using any other HTTP method (such as for example CONNECT, TRACE etc.)
will be rejected by ArangoDB.
!SUBSECTION Cross Origin Resource Sharing (CORS) requests
!SECTION Cross Origin Resource Sharing (CORS) requests
ArangoDB will automatically handle CORS requests as follows:
@ -212,7 +211,7 @@ The response to the HTTP OPTIONS request will however be a generic response that
will not expose any private data and thus can be considered "safe" even without
credentials.
!SUBSECTION HTTP method overriding
!SECTION HTTP method overriding
Since version 1.4, ArangoDB provides a startup option *--server.allow-method-override*.
This option can be set to allow overriding the HTTP request method (e.g. GET, POST,
@ -229,5 +228,4 @@ just let certain types of requests (e.g. GET and POST) pass through.
Enabling this option may impose a security risk, so it should only be used in very
controlled environments. Thus the default value for this option is *false* (no method
overriding allowed). You need to enable it explicitly if you want to use this
feature.
feature.

View File

@ -1,595 +1,29 @@
!CHAPTER HTTP Interface for Administration and Monitoring
`GET /_admin/log`*(reads the global log from the server)*
!SUBSECTION Query parameters
`upto (string,optional)`
Returns all log entries up to log level upto. Note that upto must be:
* fatal or 0
* error or 1
* warning or 2
* info or 3
* debug or 4 The default value is info.
* level (string,optional)
* Returns all log entries of log level level. Note that the URL parameters upto and level are mutually exclusive.
* start (number,optional)
* Returns all log entries such that their log entry identifier (lid value) is greater or equal to start.
* size (number,optional)
* Restricts the result to at most size log entries.
* offset (number,optional)
* Starts to return log entries skipping the first offset log entries. offset and size can be used for pagination.
* search (string,optional)
* Only return the log entries containing the text specified in search.
* sort (string,optional)
* Sort the log entries either ascending (if sort is asc) or descending (if sort is desc) according to their lid values. Note that the lid imposes a chronological order. The default value is asc.
!SUBSECTION Description
Returns fatal, error, warning or info log messages from the server's global log. The result is a JSON object with the following attributes:
* lid: a list of log entry identifiers. Each log message is uniquely identified by its lid and the identifiers are in ascending order.
* level: a list of the log-levels for all log entries.
* timestamp: a list of the timestamps as seconds since 1970-01-01 for all log entries.
* text a list of the texts of all log entries
* totalAmount: the total amount of log entries before pagination.
!SUBSECTION Return codes
`HTTP 400`
is returned if invalid values are specified for upto or level.
`HTTP 403`
is returned if the log is requested for any database other than _system.
`HTTP 500`
is returned if the server cannot generate the result due to an out-of-memory error.
`POST /_admin/modules/flush`*(flushs the module cache)*
!SUBSECTION Description
The call flushes the modules cache on the server. See JSModulesCache for details about this cache.
!SUBSECTION Return codes
`HTTP 200`
Module cache was flushed successfully.
`POST /_admin/routing/reload`*(reloads the routing collection)*
!SUBSECTION Description
Reloads the routing information from the collection routing.
!SUBSECTION Return codes
`HTTP 200`
Routing information was reloaded successfully.
`GET /_admin/statistics`*(reads the statistics)*
!SUBSECTION Description
Returns the statistics information. The returned object contains the statistics figures grouped together according to the description returned by _admin/statistics-description. For instance, to access a figure userTime from the group system, you first select the sub-object describing the group stored in system and in that sub-object the value for userTime is stored in the attribute of the same name.
In case of a distribution, the returned object contains the total count in count and the distribution list in counts. The sum (or total) of the individual values is returned in sum.
!SUBSECTION Return codes
`HTTP 200`
Statistics were returned successfully.
*Examples*
```
unix> curl --dump - http://localhost:8529/_admin/statistics
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"time" : 1401375816.797818,
"system" : {
"minorPageFaults" : 58001,
"majorPageFaults" : 220,
"userTime" : 3.25,
"systemTime" : 0.39,
"numberOfThreads" : 17,
"residentSize" : 118894592,
"residentSizePercent" : 0.0015610849021088387,
"virtualSize" : 2694352896
},
"client" : {
"httpConnections" : 1,
"connectionTime" : {
"sum" : 0.0004601478576660156,
"count" : 1,
"counts" : [
1,
0,
0,
0
]
},
"totalTime" : {
"sum" : 11.666441202163696,
"count" : 848,
"counts" : [
688,
90,
59,
7,
1,
3,
0
]
},
"requestTime" : {
"sum" : 11.539090871810913,
"count" : 848,
"counts" : [
688,
90,
59,
7,
1,
3,
0
]
},
"queueTime" : {
"sum" : 0.027733325958251953,
"count" : 848,
"counts" : [
848,
0,
0,
0,
0,
0,
0
]
},
"ioTime" : {
"sum" : 0.09961700439453125,
"count" : 848,
"counts" : [
848,
0,
0,
0,
0,
0,
0
]
},
"bytesSent" : {
"sum" : 495532,
"count" : 848,
"counts" : [
232,
501,
1,
114,
0,
0
]
},
"bytesReceived" : {
"sum" : 196766,
"count" : 848,
"counts" : [
623,
225,
0,
0,
0,
0
]
}
},
"http" : {
"requestsTotal" : 848,
"requestsAsync" : 0,
"requestsGet" : 223,
"requestsHead" : 0,
"requestsPost" : 446,
"requestsPut" : 34,
"requestsPatch" : 3,
"requestsDelete" : 142,
"requestsOptions" : 0,
"requestsOther" : 0
},
"server" : {
"uptime" : 19.310930013656616,
"physicalMemory" : 76161515520
},
"error" : false,
"code" : 200
}
```
`GET /_admin/statistics-description`*(statistics description)*
!SUBSECTION Description
Returns a description of the statistics returned by /_admin/statistics. The returned objects contains a list of statistics groups in the attribute groups and a list of statistics figures in the attribute figures.
A statistics group is described by
* group: The identifier of the group.
* name: The name of the group.
* description: A description of the group.
A statistics figure is described by
* group: The identifier of the group to which this figure belongs.
* identifier: The identifier of the figure. It is unique within the group.
* name: The name of the figure.
* description: A description of the figure.
* type: Either current, accumulated, or distribution.
* cuts: The distribution vector.
* units: Units in which the figure is measured.
!SUBSECTION Return codes
`HTTP 200`
Description was returned successfully.
*Examples*
```
unix> curl --dump - http://localhost:8529/_admin/statistics-description
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"groups" : [
{
"group" : "system",
"name" : "Process Statistics",
"description" : "Statistics about the ArangoDB process"
},
{
"group" : "client",
"name" : "Client Connection Statistics",
"description" : "Statistics about the connections."
},
{
"group" : "http",
"name" : "HTTP Request Statistics",
"description" : "Statistics about the HTTP requests."
},
{
"group" : "server",
"name" : "Server Statistics",
"description" : "Statistics about the ArangoDB server"
}
],
"figures" : [
{
"group" : "system",
"identifier" : "userTime",
"name" : "User Time",
"description" : "Amount of time that this process has been scheduled in user mode, measured in se...",
"type" : "accumulated",
"units" : "seconds"
},
{
"group" : "system",
"identifier" : "systemTime",
"name" : "System Time",
"description" : "Amount of time that this process has been scheduled in kernel mode, measured in ...",
"type" : "accumulated",
"units" : "seconds"
},
{
"group" : "system",
"identifier" : "numberOfThreads",
"name" : "Number of Threads",
"description" : "Number of threads in the arangod process.",
"type" : "current",
"units" : "number"
},
{
"group" : "system",
"identifier" : "residentSize",
"name" : "Resident Set Size",
"description" : "The total size of the number of pages the process has in real memory. This is ju...",
"type" : "current",
"units" : "bytes"
},
{
"group" : "system",
"identifier" : "residentSizePercent",
"name" : "Resident Set Size",
"description" : "The percentage of physical memory used by the process as resident set size.",
"type" : "current",
"units" : "percent"
},
{
"group" : "system",
"identifier" : "virtualSize",
"name" : "Virtual Memory Size",
"description" : "On Windows, this figure contains the total amount of memory that the memory mana...",
"type" : "current",
"units" : "bytes"
},
{
"group" : "system",
"identifier" : "minorPageFaults",
"name" : "Minor Page Faults",
"description" : "The number of minor faults the process has made which have not required loading ...",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "system",
"identifier" : "majorPageFaults",
"name" : "Major Page Faults",
"description" : "On Windows, this figure contains the total number of page faults. On other syste...",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "client",
"identifier" : "httpConnections",
"name" : "Client Connections",
"description" : "The number of connections that are currently open.",
"type" : "current",
"units" : "number"
},
{
"group" : "client",
"identifier" : "totalTime",
"name" : "Total Time",
"description" : "Total time needed to answer a request.",
"type" : "distribution",
"cuts" : [
0.01,
0.05,
0.1,
0.2,
0.5,
1
],
"units" : "seconds"
},
{
"group" : "client",
"identifier" : "requestTime",
"name" : "Request Time",
"description" : "Request time needed to answer a request.",
"type" : "distribution",
"cuts" : [
0.01,
0.05,
0.1,
0.2,
0.5,
1
],
"units" : "seconds"
},
{
"group" : "client",
"identifier" : "queueTime",
"name" : "Queue Time",
"description" : "Queue time needed to answer a request.",
"type" : "distribution",
"cuts" : [
0.01,
0.05,
0.1,
0.2,
0.5,
1
],
"units" : "seconds"
},
{
"group" : "client",
"identifier" : "bytesSent",
"name" : "Bytes Sent",
"description" : "Bytes sents for a request.",
"type" : "distribution",
"cuts" : [
250,
1000,
2000,
5000,
10000
],
"units" : "bytes"
},
{
"group" : "client",
"identifier" : "bytesReceived",
"name" : "Bytes Received",
"description" : "Bytes receiveds for a request.",
"type" : "distribution",
"cuts" : [
250,
1000,
2000,
5000,
10000
],
"units" : "bytes"
},
{
"group" : "client",
"identifier" : "connectionTime",
"name" : "Connection Time",
"description" : "Total connection time of a client.",
"type" : "distribution",
"cuts" : [
0.1,
1,
60
],
"units" : "seconds"
},
{
"group" : "http",
"identifier" : "requestsTotal",
"name" : "Total requests",
"description" : "Total number of HTTP requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsAsync",
"name" : "Async requests",
"description" : "Number of asynchronously executed HTTP requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsGet",
"name" : "HTTP GET requests",
"description" : "Number of HTTP GET requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsHead",
"name" : "HTTP HEAD requests",
"description" : "Number of HTTP HEAD requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsPost",
"name" : "HTTP POST requests",
"description" : "Number of HTTP POST requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsPut",
"name" : "HTTP PUT requests",
"description" : "Number of HTTP PUT requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsPatch",
"name" : "HTTP PATCH requests",
"description" : "Number of HTTP PATCH requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsDelete",
"name" : "HTTP DELETE requests",
"description" : "Number of HTTP DELETE requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsOptions",
"name" : "HTTP OPTIONS requests",
"description" : "Number of HTTP OPTIONS requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "http",
"identifier" : "requestsOther",
"name" : "other HTTP requests",
"description" : "Number of other HTTP requests.",
"type" : "accumulated",
"units" : "number"
},
{
"group" : "server",
"identifier" : "uptime",
"name" : "Server Uptime",
"description" : "Number of seconds elapsed since server start.",
"type" : "current",
"units" : "seconds"
},
{
"group" : "server",
"identifier" : "physicalMemory",
"name" : "Physical Memory",
"description" : "Physical memory in bytes.",
"type" : "current",
"units" : "bytes"
}
],
"error" : false,
"code" : 200
}
```
`GET /_admin/server/role`*(returns the role of a server in a cluster)*
!SUBSECTION Description
Returns the role of a server in a cluster. The role is returned in the role attribute of the result. Possible return values for role are:
* COORDINATOR: the server is a coordinator in a cluster
* PRIMARY: the server is a primary database server in a cluster
* SECONDARY: the server is a secondary database server in a cluster
* UNDEFINED: in a cluster, UNDEFINED is returned if the server role cannot be determined. On a single server, UNDEFINED is the only possible return value.
!SUBSECTION Return codes
`HTTP 200`
Is returned in all cases.
<!--
@NAVIGATE_HttpSystem
@EMBEDTOC{HttpSystemTOC}
This is an introduction to ArangoDB's Http interface for administration and
monitoring of the server.
@anchor HttpSystemLog
@copydetails triagens::admin::RestAdminLogHandler::execute
<!-- lib/Admin/RestAdminLogHandler.cpp -->
@CLEARPAGE
@anchor HttpSystemFlushServerModules
@copydetails JSF_get_admin_modules_flush
@startDocuBlock JSF_get_admin_modules_flush
@CLEARPAGE
@anchor HttpSystemRoutingReloads
@copydetails JSF_get_admin_routing_reloads
@CLEARPAGE
@anchor HttpSystemAdminStatistics
@copydetails JSF_get_admin_statistics
<!-- js/actions/api-system.js -->
@CLEARPAGE
@anchor HttpSystemAdminStatisticsDescription
@copydetails JSF_get_admin_statistics_description
@startDocuBlock JSF_get_admin_routing_reloads
@CLEARPAGE
@anchor HttpSystemAdminServerRole
@copydetails JSF_get_admin_server_role
@BNAVIGATE_HttpSystem
-->
<!-- js/actions/api-system.js -->
@startDocuBlock JSF_get_admin_statistics
<!-- js/actions/api-system.js -->
@startDocuBlock JSF_get_admin_statistics_description
<!-- js/actions/api-system.js -->
@startDocuBlock JSF_get_admin_server_role

View File

@ -1,387 +0,0 @@
!CHAPTER Managing Async Results via HTTP
`PUT /_api/job/job-id`*(Returns the result of an async job)*
!SUBSECTION URL parameters
`job-id (string,required)`
The async job id.
!SUBSECTION Description
Returns the result of an async job identified by job-id. If the async job result is present on the server, the result will be removed from the list of result. That means this method can be called for each job-id once.
The method will return the original job result's headers and body, plus the additional HTTP header x-arango-async-job-id. If this header is present, then the job was found and the response contains the original job's result. If the header is not present, the job was not found and the response contains status information from the job amanger.
!SUBSECTION Return codes
Any HTTP status code might be returned by this method. To tell the original job response from a job manager response apart, check for the HTTP header x-arango-async-id. If it is present, the response contains the original job's result. Otherwise the response is from the job manager.
`HTTP 204`
is returned if the job requested via job-id is still in the queue of pending (or not yet finished) jobs. In this case, no x-arango-async-id HTTP header will be returned.
`HTTP 400`
is returned if no job-id was specified in the request. In this case, no x-arango-async-id HTTP header will be returned.
`HTTP 404`
is returned if the job was not found or already deleted or fetched from the job result list. In this case, no x-arango-async-id HTTP header will be returned.
*Examples*
Not providing a job-id:
```
unix> curl -X PUT --dump - http://localhost:8529/_api/job/
HTTP/1.1 400 Bad Request
content-type: application/json; charset=utf-8
{"error":true,"errorMessage":"bad parameter","code":400,"errorNum":400}
```
Providing a job-id for a non-existing job:
```
unix> curl -X PUT --dump - http://localhost:8529/_api/job/foobar
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8
{"error":true,"errorMessage":"not found","code":404,"errorNum":404}
```
Fetching the result of an HTTP GET job:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 265413601
unix> curl -X PUT --dump - http://localhost:8529/_api/job/265413601
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
x-arango-async-id: 265413601
{"server":"arango","version":"2.1.0"}
```
Fetching the result of an HTTP POST job that failed:
```
unix> curl -X POST --header 'x-arango-async: store' --data-binary @- --dump - http://localhost:8529/_api/collection
{"name":" this name is invalid "}
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 265479137
unix> curl -X PUT --dump - http://localhost:8529/_api/job/265479137
HTTP/1.1 400 Bad Request
content-type: application/json; charset=utf-8
x-arango-async-id: 265479137
{"error":true,"code":400,"errorNum":1208,"errorMessage":"cannot create collection: illegal name"}
```
`PUT /_api/job/job-id/cancel`*(Cancels an async job)*
!SUBSECTION URL parameters
`job-id (string,required)`
The async job id.
!SUBSECTION Description
Cancels the currently running job identified by job-id. Note that it still might take some time to actually cancel the running async job.
!SUBSECTION Return codes
Any HTTP status code might be returned by this method. To tell the original job response from a job manager response apart, check for the HTTP header x-arango-async-id. If it is present, the response contains the original job's result. Otherwise the response is from the job manager.
`HTTP 200`
cancel has been initiated.
`HTTP 400`
is returned if no job-id was specified in the request. In this case, no x-arango-async-id HTTP header will be returned.
`HTTP 404`
is returned if the job was not found or already deleted or fetched from the job result list. In this case, no x-arango-async-id HTTP header will be returned.
*Examples*
```
unix> curl -X POST --header 'x-arango-async: store' --data-binary @- --dump - http://localhost:8529/_api/cursor
{"query": "FOR i IN 1..10 FOR j IN 1..10 LET x = sleep(1.0) FILTER i == 5 && j == 5 RETURN 42"}
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 268952545
unix> curl --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
["268952545"]
unix> curl -X PUT --dump - http://localhost:8529/_api/job/268952545/cancel
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{"result":true}
unix> curl --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
["268952545"]
```
`DELETE /_api/job/type`*(Deletes the result of async jobs)*
!SUBSECTION URL parameters
`type (string,required)`
The type of jobs to delete. type can be:
* all: deletes all jobs results. Currently executing or queued async jobs will not be stopped by this call.
* expired: deletes expired results. To determine the expiration status of a result, pass the stamp URL parameter. stamp needs to be a UNIX timestamp, and all async job results created at a lower timestamp will be deleted.
* an actual job-id: in this case, the call will remove the result of the specified async job. If the job is currently executing or queued, it will not be aborted.
!SUBSECTION Query parameters
`stamp (number,optional)`
A UNIX timestamp specifying the expiration threshold when type is expired.
!SUBSECTION Description
Deletes either all job results, expired job results, or the result of a specific job. Clients can use this method to perform an eventual garbage collection of job results.
!SUBSECTION Return codes
`HTTP 200`
is returned if the deletion operation was carried out successfully. This code will also be returned if no results were deleted.
`HTTP 400`
is returned if type is not specified or has an invalid value.
`HTTP 404`
is returned if type is a job-id but no async job with the specified id was found.
*Examples*
Deleting all jobs:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270132193
unix> curl -X DELETE --dump - http://localhost:8529/_api/job/all
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true
}
```
Deleting expired jobs:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270197729
unix> curl -X DELETE --dump - http://localhost:8529/_api/job/expired?stamp=1401376184
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true
}
```
Deleting the result of a specific job:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270263265
unix> curl -X DELETE --dump - http://localhost:8529/_api/job/270263265
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true
}
```
Deleting the result of a non-existing job:
```
unix> curl -X DELETE --dump - http://localhost:8529/_api/job/foobar
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8
{
"error" : true,
"errorMessage" : "not found",
"code" : 404,
"errorNum" : 404
}
```
`GET /_api/job/job-id`*(Returns the status of the specified job)*
!SUBSECTION URL parameters
`job-id (string,required)`
The async job id.
!SUBSECTION Description
Returns the processing status of the specified job. The processing status can be determined by peeking into the HTTP response code of the response.
!SUBSECTION Return codes
`HTTP 200`
is returned if the job requested via job-id has been executed successfully and its result is ready to fetch.
`HTTP 204`
is returned if the job requested via job-id is still in the queue of pending (or not yet finished) jobs.
`HTTP 400`
is returned if no job-id was specified in the request.
`HTTP 404`
is returned if the job was not found or already deleted or fetched from the job result list.
*Examples*
Querying the status of a done job:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270328801
unix> curl --dump - http://localhost:8529/_api/job/270328801
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
Querying the status of a pending job:
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_admin/sleep?duration=3
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270394337
unix> curl --dump - http://localhost:8529/_api/job/270394337
HTTP/1.1 204 No Content
content-type: text/plain; charset=utf-8
```
`GET /_api/job/type`*(Returns the list of job result ids with a specific status)*
!SUBSECTION URL parameters
`type (string,required)`
The type of jobs to return. The type can be either done or pending. Setting the type to done will make the method return the ids of already completed async jobs for which results can be fetched. Setting the type to pending will return the ids of not yet finished async jobs.
!SUBSECTION Query parameters
`count (number,optional)`
The maximum number of ids to return per call. If not specified, a server-defined maximum value will be used.
!SUBSECTION Description
Returns the list of ids of async jobs with a specific status (either done or pending). The list can be used by the client to get an overview of the job system status and to retrieve completed job results later.
!SUBSECTION Return codes
`HTTP 200`
is returned if the list can be compiled successfully. Note: the list might be empty.
`HTTP 400`
is returned if type is not specified or has an invalid value.
*Examples*
Fetching the list of done jobs:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270459873
unix> curl --dump - http://localhost:8529/_api/job/done
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
[
"270459873"
]
```
Fetching the list of pending jobs:
```
unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain; charset=utf-8
x-arango-async-id: 270525409
unix> curl --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
[ ]
```

View File

@ -105,7 +105,6 @@ then only the code running on the coordinator is stopped, there may
remain tasks within the cluster which have already been distributed to
the DBservers and it is currently not possible to cancel them as well.
!SUBSUBSECTION Async Execution and Authentication
If a request requires authentication, the authentication procedure is run before
@ -113,3 +112,28 @@ queueing. The request will only be queued if it valid credentials and the authen
succeeds. If the request does not contain valid credentials, it will not be queued but
rejected instantly in the same way as a "regular", non-queued request.
!CHAPTER Managing Async Results via HTTP
<!-- lib/HttpServer/AsyncJobManager.h -->
@startDocuBlock JSF_put_api_async_return
<!-- lib/HttpServer/AsyncJobManager.h -->
@startDocuBlock JSF_put_api_async_cancel
<!-- lib/HttpServer/AsyncJobManager.h -->
@startDocuBlock JSF_get_api_async_delete
<!-- lib/HttpServer/AsyncJobManager.h -->
@startDocuBlock JSF_get_api_async_return
<!-- lib/HttpServer/AsyncJobManager.h -->
@startDocuBlock JSF_get_api_async_return_list

View File

@ -57,7 +57,7 @@ creation operations. The boundary used in this example is
*Examples*
```
```js
> curl -X POST --data-binary @- --header "Content-Type: multipart/form-data; boundary=XXXsubpartXXX" http://localhost:8529/_api/batch
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
@ -83,8 +83,6 @@ POST /_api/document?collection=xyz HTTP/1.1
--XXXsubpartXXX--
```
<!--@verbinclude api-batch-simple-->
The server will then respond with one multipart message, containing
the overall status and the individual results for the part
operations. The overall status should be 200 except there was an error
@ -102,7 +100,7 @@ operation might also return arbitrary HTTP headers and a body/payload:
*Examples*
```
```js
HTTP/1.1 200 OK
connection: Keep-Alive
content-type: multipart/form-data; boundary=XXXsubpartXXX
@ -141,8 +139,6 @@ content-length: 53
--XXXsubpartXXX--
```
<!--@verbinclude api-batch-simple-response-->
In the above example, the server returned an overall status code of
200, and each part response contains its own status value (202 in the
example):
@ -155,7 +151,7 @@ requests that produced errors:
*Examples*
```
```js
> curl -X POST --data-binary @- --header "Content-Type: multipart/form-data; boundary=XXXsubpartXXX" http://localhost:8529/_api/batch
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
@ -172,15 +168,13 @@ POST /_api/document?collection=xyz
--XXXsubpartXXX--
```
<!--@verbinclude api-batch-fail-->
In this example, the overall response code is 200, but as some of the
part request failed (with status code 404), the *x-arango-errors*
header of the overall response is *1*:
*Examples*
```
```js
HTTP/1.1 200 OK
x-arango-errors: 1
content-type: multipart/form-data; boundary=XXXsubpartXXX
@ -206,11 +200,8 @@ content-length: 53
--XXXsubpartXXX--
```
<!--@verbinclude api-batch-fail-response-->
Please note that the database used for all part operations of a batch
request is determined by scanning the original URL (the URL that contains
*/_api/batch*). It is not possible to override the database name in
part operations of a batch. When doing so, any other database name used
in a batch part will be ignored.
in a batch part will be ignored.

View File

@ -7,9 +7,9 @@ names for the documents that follow. The following lines are interpreted as the
document data. Each document must be a JSON list of values. No attribute names
are needed or allowed in this data section.
*EXAMPLES*
*Examples*
```
```js
curl --data-binary @- -X POST --dump - "http://localhost:8529/_api/import?collection=test&createCollection=true"
[ "firstName", "lastName", "age", "gender" ]
[ "Joe", "Public", 42, "male" ]
@ -23,8 +23,6 @@ content-type: application/json; charset=utf-8
{"error":false,"created":2,"empty":0,"errors":0}
```
<!--@verbinclude api-import-headers-->
The server will again respond with an HTTP 201 if everything went well. The
number of documents imported will be returned in the *created* attribute of the
response. If any documents were skipped or incorrectly formatted, this will be
@ -36,3 +34,11 @@ also contain an attribute *details* which is a list of details about errors that
occurred on the server side during the import. This list might be empty if no
errors occurred.
!SECTION Importing into Edge Collections
Please note that when importing documents into an edge collection, it is
mandatory that all imported documents contain the *_from* and *_to* attributes,
and that these contain references to existing collections.
Please also note that it is not possible to create a new edge collection on the
fly using the *createCollection* parameter.

View File

@ -1,8 +0,0 @@
!CHAPTER Importing into Edge Collections
Please note that when importing documents into an edge collection, it is
mandatory that all imported documents contain the *_from* and *_to* attributes,
and that these contain references to existing collections.
Please also note that it is not possible to create a new edge collection on the
fly using the *createCollection* parameter.

View File

@ -19,11 +19,13 @@ be imported.
Example input data for this case:
[
{ "_key": "key1", ... },
{ "_key": "key2", ... },
...
]
```js
[
{ "_key": "key1", ... },
{ "_key": "key2", ... },
...
]
```
This format does not require each document to be on a separate line, and any
whitespace in the JSON data is allowed. It can be used to import a
@ -39,7 +41,7 @@ the data are line-wise JSON documents (type = documents) or a JSON list (type =
*Examples*
```
```js
curl --data-binary @- -X POST --dump - "http://localhost:8529/_api/import?type=documents&collection=test&createCollection=true"
{ "name" : "test", "gender" : "male", "age" : 39 }
{ "type" : "bird", "name" : "robin" }
@ -52,8 +54,6 @@ content-type: application/json; charset=utf-8
{"error":false,"created":2,"empty":0,"errors":0}
```
<!--@verbinclude api-import-documents-->
The server will respond with an HTTP 201 if everything went well. The number of
documents imported will be returned in the *created* attribute of the
response. If any documents were skipped or incorrectly formatted, this will be

View File

@ -3,7 +3,7 @@
The ArangoDB server can listen for incoming requests on multiple *endpoints*.
The endpoints are normally specified either in ArangoDB's configuration file or on
the command-line, using the @ref CommandLineArangoEndpoint "--server.endpoint" option.
the command-line, using the "--server.endpoint" option.
The default endpoint for ArangoDB is *tcp://127.0.0.1:8529* or *tcp://localhost:8529*.
The number of endpoints can also be changed at runtime using the API described
@ -23,229 +23,11 @@ the default database (*_system*) and none of the other databases.
!SECTION Managing Endpoints via HTTP
`POST /_api/endpoint`*(adds a new endpoint or reconfigures an existing endpoint)*
<!-- js/actions/api-endpoint.js -->
@startDocuBlock JSF_post_api_endpoint
!SUBSECTION Body parameters
<!-- js/actions/api-endpoint.js -->
@startDocuBlock JSF_delete_api_endpoint
`description (json,required)`
A JSON object describing the endpoint.
!SUBSECTION Description
The request body must be JSON hash with the following attributes:
* endpoint: the endpoint specification, e.g. tcp://127.0.0.1:8530
* databases: a list of database names the endpoint is responsible for.
If databases is an empty list, all databases present in the server will become accessible via the endpoint, with the _system database being the default database.
If databases is non-empty, only the specified databases will become available via the endpoint. The first database name in the databases list will also become the default database for the endpoint. The default database will always be used if a request coming in on the endpoint does not specify the database name explicitly.
*Note*: adding or reconfiguring endpoints is allowed in the system database only. Calling this action in any other database will make the server return an error.
Adding SSL endpoints at runtime is only supported if the server was started with SSL properly configured (e.g. --server.keyfile must have been set).
!SUBSECTION Return codes
`HTTP 200`
is returned when the endpoint was added or changed successfully.
`HTTP 400`
is returned if the request is malformed or if the action is not carried out in the system database.
`HTTP 405`
The server will respond with HTTP 405 if an unsupported HTTP method is used.
*Examples*
```
Adding an endpoint tcp://127.0.0.1:8532 with two mapped databases (mydb1 and mydb2). mydb1 will become the default database for the endpoint.
unix> curl -X POST --data-binary @- --dump - http://localhost:8529/_api/endpoint
{"endpoint":"tcp://127.0.0.1:8532","databases":["mydb1","mydb2"]}
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true,
"error" : false,
"code" : 200
}
```
Adding an endpoint tcp://127.0.0.1:8533 with no database names specified. This will allow access to all databases on this endpoint. The _system database will become the default database for requests that come in on this endpoint and do not specify the database name explicitly.
```
unix> curl -X POST --data-binary @- --dump - http://localhost:8529/_api/endpoint
{"endpoint":"tcp://127.0.0.1:8533","databases":[]}
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true,
"error" : false,
"code" : 200
}
```
Adding an endpoint tcp://127.0.0.1:8533 without any databases first, and then updating the databases for the endpoint to testdb1, testdb2, and testdb3.
```
unix> curl -X POST --data-binary @- --dump - http://localhost:8529/_api/endpoint
{"endpoint":"tcp://127.0.0.1:8533","databases":[]}
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true,
"error" : false,
"code" : 200
}
unix> curl -X POST --data-binary @- --dump - http://localhost:8529/_api/endpoint
{"endpoint":"tcp://127.0.0.1:8533","databases":[],"database":["testdb1","testdb2","testdb3"]}
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true,
"error" : false,
"code" : 200
}
```
`DELETE /_api/endpoint/{endpoint}`*(deletes and disconnects an existing endpoint)*
!SUBSECTION URL parameters
`endpoint (string,required)`
The endpoint to delete, e.g. tcp://127.0.0.1:8529.
!SUBSECTION Description
This operation deletes an existing endpoint from the list of all endpoints, and makes the server stop listening on the endpoint.
Note: deleting and disconnecting an endpoint is allowed in the system database only. Calling this action in any other database will make the server return an error.
Furthermore, the last remaining endpoint cannot be deleted as this would destroy the server.
!SUBSECTION Return codes
`HTTP 200`
is returned when the endpoint was deleted and disconnected successfully.
`HTTP 400`
is returned if the request is malformed or if the action is not carried out in the system database.
`HTTP 404`
is returned if the endpoint is not found.
`HTTP 405`
The server will respond with HTTP 405 if an unsupported HTTP method is used.
*Examples*
Deleting an existing endpoint
```
unix> curl -X DELETE --dump - http://localhost:8529/_api/endpoint/tcp%3A%2F%2F127.0.0.1%3A8532
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"result" : true,
"error" : false,
"code" : 200
}
```
Deleting a non-existing endpoint
```
unix> curl -X DELETE --dump - http://localhost:8529/_api/endpoint/tcp%3A%2F%2F127.0.0.1%3A8532
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8
{
"error" : true,
"code" : 404,
"errorNum" : 1231,
"errorMessage" : "endpoint not found"
}
```
`GET /_api/endpoint`*(returns a list of all endpoints)*
!SUBSECTION Description
Returns a list of all configured endpoints the server is listening on. For each endpoint, the list of allowed databases is returned too if set.
The result is a JSON hash which has the endpoints as keys, and the list of mapped database names as values for each endpoint.
If a list of mapped databases is empty, it means that all databases can be accessed via the endpoint. If a list of mapped databases contains more than one database name, this means that any of the databases might be accessed via the endpoint, and the first database in the list will be treated as the default database for the endpoint. The default database will be used when an incoming request does not specify a database name in the request explicitly.
*Note*: retrieving the list of all endpoints is allowed in the system database only. Calling this action in any other database will make the server return an error.
!SUBSECTION Return codes
`HTTP 200`
is returned when the list of endpoints can be determined successfully.
`HTTP 400`
is returned if the action is not carried out in the system database.
`HTTP 405`
The server will respond with HTTP 405 if an unsupported HTTP method is used.
*Examples*
```
unix> curl --dump - http://localhost:8529/_api/endpoint
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
[
{
"endpoint" : "tcp://127.0.0.1:31653",
"databases" : [ ]
},
{
"endpoint" : "tcp://127.0.0.1:8532",
"databases" : [
"mydb1",
"mydb2"
]
}
]
```
<!--
@anchor HttpEndpointPost
@copydetails JSF_post_api_endpoint
@CLEARPAGE
@anchor HttpEndpointDelete
@copydetails JSF_delete_api_endpoint
@CLEARPAGE
@anchor HttpEndpointGet
@copydetails JSF_get_api_endpoint
-->
<!-- js/actions/api-endpoint.js -->
@startDocuBlock JSF_get_api_endpoint

View File

@ -2,125 +2,21 @@
This is an overview of ArangoDB's HTTP interface for miscellaneous functions.
`GET /_api/version`*(returns the server version)*
<!-- lib/Admin/RestVersionHandler.cpp -->
!SUBSECTION Query parameters
`details (boolean,optional)`
If set to true, the response will contain a details attribute with additional information about included components and their versions. The attribute names and internals of the details object may vary depending on platform and ArangoDB version.
!SUBSECTION Description
* Returns the server name and version number. The response is a JSON object with the following attributes:
* server: will always contain arango
* version: the server version string. The string has the format "<tt>major</tt>.<tt>minor</tt>.<tt>sub</tt>". major and minor will be numeric, and sub may contain a number or a textual version.
* details: an optional JSON object with additional details. This is returned only if the details URL parameter is set to true in the request.
!SUBSECTION Return codes
`HTTP 200`
is returned in all cases.
*Examples*
Returns the version information.
```
unix> curl --dump - http://localhost:8529/_api/version
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"server" : "arango",
"version" : "2.1.0"
}
```
Returns the version information with details.
```
unix> curl --dump - http://localhost:8529/_api/version?details=true
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
{
"server" : "arango",
"version" : "2.1.0",
"details" : {
"build-date" : "May 29 2014 17:00:47",
"configure" : "'./configure' '--enable-maintainer-mode' '--enable-all-in-one-v8' '--enable-all-...",
"icu-version" : "52.1",
"libev-version" : "4.11",
"openssl-version" : "OpenSSL 1.0.1e 11 Feb 2013",
"server-version" : "2.1.0",
"sizeof int" : "4",
"sizeof void*" : "8",
"v8-version" : "3.16.14.1"
}
}
```
`GET /_admin/time`*(returns the system time)*
!SUBSECTION Description
The call returns an object with the attribute time. This contains the current system time as a Unix timestamp with microsecond precision.
!SUBSECTION Return codes
`HTTP 200`
Time was returned successfully.
`GET /_admin/echo`*(returns the current request)*
!SUBSECTION Description
The call returns an object with the following attributes:
* headers: a list of HTTP headers received
* requestType: the HTTP request method (e.g. GET)
* parameters: list of URL parameters received
!SUBSECTION Return codes
`HTTP 200`
Echo was returned successfully.
initiates the shutdown sequence
`GET /_admin/shutdown`*(initiates the shutdown sequence)*
!SUBSECTION Description
This call initiates a clean shutdown sequence.
!SUBSECTION Return codes
`HTTP 200`
is returned in all cases.
@startDocuBlock JSF_get_api_return
<!--
@CLEARPAGE
@anchor HttpMiscVersion
@copydetails triagens::admin::RestVersionHandler::execute
<!-- js/actions/api-system.js -->
@CLEARPAGE
@anchor HttpMiscTime
@copydetails JSF_get_admin_time
@startDocuBlock JSF_get_admin_time
@CLEARPAGE
@anchor HttpMiscEcho
@copydetails JSF_get_admin_echo
@CLEARPAGE
@anchor HttpMiscShutdown
@copydetails triagens::admin::RestShutdownHandler::execute
-->
<!-- js/actions/api-system.js -->
@startDocuBlock JSF_get_admin_echo
<!-- lib/Admin/RestShutdownHandler.cpp -->
@startDocuBlock JSF_get_api_initiate

View File

@ -1,187 +1,44 @@
!CHAPTER HTTP Interface for Sharding
<!-- js/actions/api-cluster.js -->
`GET /_admin/cluster-test`*(executes a cluster roundtrip)*
@startDocuBlock JSF_cluster_test_GET
!SUBSECTION Description
Executes a cluster roundtrip from a coordinator to a DB server and back. This call only works in a coordinator node in a cluster. One can and should append an arbitrary path to the URL and the part after /_admin/cluster-test is used as the path of the HTTP request which is sent from the coordinator to a DB node. Likewise, any form data appended to the URL is forwarded in the request to the DB node. This handler takes care of all request types (see below) and uses the same request type in its request to the DB node.
<!-- js/actions/api-cluster.js -->
The following HTTP headers are interpreted in a special way:
@startDocuBlock JSF_cluster_test_POST
* X-Shard-ID: This specifies the ID of the shard to which the cluster request is sent and thus tells the system to which DB server to send the cluster request. Note that the mapping from the shard ID to the responsible server has to be defined in the agency under Current/ShardLocation/<shardID>. One has to give this header, otherwise the system does not know where to send the request.
* X-Client-Transaction-ID: the value of this header is taken as the client transaction ID for the request
* X-Timeout: specifies a timeout in seconds for the cluster operation. If the answer does not arrive within the specified timeout, an corresponding error is returned and any subsequent real answer is ignored. The default if not given is 24 hours.
* X-Synchronous-Mode: If set to true the test function uses synchronous mode, otherwise the default asynchronous operation mode is used. This is mainly for debugging purposes.
* Host: This header is ignored and not forwarded to the DB server.
* User-Agent: This header is ignored and not forwarded to the DB server.
All other HTTP headers and the body of the request (if present, see other HTTP methods below) are forwarded as given in the original request.
<!-- js/actions/api-cluster.js -->
In asynchronous mode the DB server answers with an HTTP request of its own, in synchronous mode it sends a HTTP response. In both cases the headers and the body are used to produce the HTTP response of this API call.
@startDocuBlock JSF_cluster_test_PUT
!SUBSECTION Return codes
The return code can be anything the cluster request returns, as well as:
<!-- js/actions/api-cluster.js -->
`HTTP 200`
@startDocuBlock JSF_cluster_test_DELETE
is returned when everything went well, or if a timeout occurred. In the latter case a body of type application/json indicating the timeout is returned.
`HTTP 403`
<!-- js/actions/api-cluster.js -->
is returned if ArangoDB is not running in cluster mode.
@startDocuBlock JSF_cluster_test_PATCH
`HTTP 404`
is returned if ArangoDB was not compiled for cluster operation.
<!-- js/actions/api-cluster.js -->
`POST /_admin/cluster-test`*(executes a cluster roundtrip)*
@startDocuBlock JSF_cluster_test_HEAD
!SUBSECTION Body parameters
`body (anything,required)`
<!-- js/actions/api-cluster.js -->
!SUBSECTION Description
@startDocuBlock JSF_cluster_planner_POST
See GET method. The body can be any type and is simply forwarded.
`PUT /_admin/cluster-test`*(executes a cluster roundtrip)*
<!-- js/actions/api-cluster.js -->
!SUBSECTION Body parameters
@startDocuBlock JSF_cluster_dispatcher_POST
`body (anything,required)`
!SUBSECTION Description
<!-- js/actions/api-cluster.js -->
See GET method. The body can be any type and is simply forwarded.
`DELETE /_admin/cluster-test`*(executes a cluster roundtrip)*
!SUBSECTION Description
See GET method. The body can be any type and is simply forwarded.
`PATCH /_admin/cluster-test`*(executes a cluster roundtrip)*
!SUBSECTION Body parameters
`body (anything,required)`
!SUBSECTION Description
See GET method. The body can be any type and is simply forwarded.
`HEAD /_admin/cluster-test`*(executes a cluster roundtrip)*
!SUBSECTION Description
See GET method. The body can be any type and is simply forwarded.
`POST /_admin/clusterPlanner(produce a cluster startup plan)`
!SUBSECTION Body parameters
`body (json,required)`
!SUBSECTION Description
Given a description of a cluster, this plans the details of a cluster and returns a JSON description of a plan to start up this cluster. See JSF_Cluster_Planner_Constructor for details.
!SUBSECTION Return codes
`HTTP 200`
is returned when everything went well.
`HTTP 400`
the posted body was not valid JSON.
`POST /_admin/clusterDispatch`*(execute startup commands)*
!SUBSECTION Query parameters
!SUBSECTION Body parameters
`body (json,required)`
!SUBSECTION Description
The body must be an object with the following properties:
* clusterPlan: is a cluster plan (see JSF_cluster_planner_POST),
* myname: is the ID of this dispatcher, this is used to decide which commands are executed locally and which are forwarded to other dispatchers
* action: can be one of the following:
* "launch": the cluster is launched for the first time, all data directories and log files are cleaned and created
* "shutdown": the cluster is shut down, the additional property runInfo (see below) must be bound as well
* "relaunch": the cluster is launched again, all data directories and log files are untouched and need to be there already
* "cleanup": use this after a shutdown to remove all data in the data directories and all log files, use with caution
* "isHealthy": checks whether or not the processes involved in the cluster are running or not. The additional property runInfo (see above) must be bound as well
* "upgrade": performs an upgrade of a cluster, to this end, the agency is started, and then every server is once started with the "&ndash;upgrade" option, and then normally. Finally, the script "verion-check.js" is run on one of the coordinators for the cluster.
* `runInfo": this is needed for the "shutdown" and "isHealthy" actions only and should be the structure that "launch", "relaunch" or "upgrade" returned. It contains runtime information like process IDs.
This call executes the plan by either doing the work personally or by delegating to other dispatchers.
!SUBSECTION Return codes
`HTTP 200`
is returned when everything went well.
`HTTP 400`
the posted body was not valid JSON, or something went wrong with the startup.
`GET /_admin/clusterCheckPort`*(check whether a given port is usable)*
!SUBSECTION Query parameters
`port (integer,required)`
!SUBSECTION Description
Checks whether the requested port is usable.
!SUBSECTION Return codes
`HTTP 200`
is returned when everything went well.
`HTTP 400`
the parameter port was not given or is no integer.
<!--
@NAVIGATE_HttpSharding
@EMBEDTOC{HttpShardingTOC}
@anchor HttpShardingClusterTestGET
@copydetails JSF_cluster_test_GET
@anchor HttpShardingClusterTestPOST
@copydetails JSF_cluster_test_POST
@anchor HttpShardingClusterTestPUT
@copydetails JSF_cluster_test_PUT
@anchor HttpShardingClusterTestDELETE
@copydetails JSF_cluster_test_DELETE
@anchor HttpShardingClusterTestPATCH
@copydetails JSF_cluster_test_PATCH
@anchor HttpShardingClusterTestHEAD
@copydetails JSF_cluster_test_HEAD
@anchor HttpShardingClusterPlannerPOST
@copydetails JSF_cluster_planner_POST
@anchor HttpShardingClusterDispatcherPOST
@copydetails JSF_cluster_dispatcher_POST
@anchor HttpShardingClusterCheckPortGET
@copydetails JSF_cluster_check_port_GET
-->
@startDocuBlock JSF_cluster_check_port_GET

View File

@ -15,216 +15,27 @@ future for this interface.
Please note that user operations are not included in ArangoDB's replication.
`POST /_api/user`*(creates user)*
!SUBSECTION Body parameters
<!-- js/actions/api-user.js -->
`body (json,required)`
@startDocuBlock JSF_api_user_create
!SUBSECTION Description
The following data need to be passed in a JSON representation in the body of the POST request:
<!-- js/actions/api-user.js -->
* user: The name of the user as a string. This is mandatory.
* passwd: The user password as a string. If no password is specified, the empty string will be used.
* active: an optional flag that specifies whether the user is active. If not specified, this will default to true.
* extra: an optional JSON object with arbitrary extra data about the user.
* changePassword: an optional flag that specifies whethers the user must change the password or not. If not specified, this will default to false.
@startDocuBlock JSF_api_user_replace
If set to true, the only operations allowed are PUT /_api/user or PATCH /_api/user. All other operations will result in a HTTP 403.
If the user can be added by the server, the server will respond with HTTP 201.
In case of success, the returned JSON object has the following properties:
* error: boolean flag to indicate that an error occurred (false in this case)
* code: the HTTP status code
<!-- js/actions/api-user.js -->
If the JSON representation is malformed or mandatory data is missing from the request, the server will respond with HTTP 400.
@startDocuBlock JSF_api_user_update
The body of the response will contain a JSON object with additional error details. The object has the following attributes:
* error: boolean flag to indicate that an error occurred (true in this case)
* code: the HTTP status code
* errorNum: the server error number
* errorMessage: a descriptive error message
<!-- js/actions/api-user.js -->
!SUBSECTION Return codes
@startDocuBlock JSF_api_user_delete
`HTTP 201`
returned if the user can be added by the server.
<!-- js/actions/api-user.js -->
`HTTP 400`
If the JSON representation is malformed or mandatory data is missing from the request.
`PUT /_api/user/{user}`*(replaces user)*
!SUBSECTION URL parameters
`user (string,required)`
The name of the user.
!SUBSECTION Body parameters
`body (json,required)`
!SUBSECTION Description
Replaces the data of an existing user. The name of an existing user must be specified in user.
The following data can to be passed in a JSON representation in the body of the POST request:
* passwd: The user password as a string. Specifying a password is mandatory, but the empty string is allowed for passwords.
* active: an optional flag that specifies whether the user is active. If not specified, this will default to true.
* extra: an optional JSON object with arbitrary extra data about the user.
* changePassword: an optional flag that specifies whether the user must change the password or not. If not specified, this will default to false.
If the user can be replaced by the server, the server will respond with HTTP 200.
In case of success, the returned JSON object has the following properties:
* error: boolean flag to indicate that an error occurred (false in this case)
* code: the HTTP status code
If the JSON representation is malformed or mandatory data is missing from the request, the server will respond with HTTP 400. If the specified user does not exist, the server will respond with HTTP 404.
The body of the response will contain a JSON object with additional error details. The object has the following attributes:
* error: boolean flag to indicate that an error occurred (true in this case)
* code: the HTTP status code
* errorNum: the server error number
* errorMessage: a descriptive error message
!SUBSECTION Return codes
`HTTP 200`
Is returned if the user data can be replaced by the server.
`HTTP 400`
The JSON representation is malformed or mandatory data is missing from the request.
`HTTP 404`
The specified user does not exist.
`PATCH /_api/user/{user}`*(updates user)*
!SUBSECTION URL parameters
`user (string,required)`
The name of the user.
!SUBSECTION Body parameters
`body (json,required)`
!SUBSECTION Description
Partially updates the data of an existing user. The name of an existing user must be specified in user.
The following data can be passed in a JSON representation in the body of the POST request:
* passwd: The user password as a string. Specifying a password is optional. If not specified, the previously existing value will not be modified.
* active: an optional flag that specifies whether the user is active. If not specified, the previously existing value will not be modified.
* extra: an optional JSON object with arbitrary extra data about the user. If not specified, the previously existing value will not be modified.
* changePassword: an optional flag that specifies whether the user must change the password or not. If not specified, the previously existing value will not be modified.
If the user can be updated by the server, the server will respond with HTTP 200.
In case of success, the returned JSON object has the following properties:
* error: boolean flag to indicate that an error occurred (false in this case)
* code: the HTTP status code
If the JSON representation is malformed or mandatory data is missing from the request, the server will respond with HTTP 400. If the specified user does not exist, the server will respond with HTTP 404.
The body of the response will contain a JSON object with additional error details. The object has the following attributes:
* error: boolean flag to indicate that an error occurred (true in this case)
* code: the HTTP status code
* errorNum: the server error number
* errorMessage: a descriptive error message
!SUBSECTION Return codes
`HTTP 200`
Is returned if the user data can be replaced by the server.
`HTTP 400`
The JSON representation is malformed or mandatory data is missing from the request.
`HTTP 404`
The specified user does not exist.
`DELETE /_api/user/{user}`*(removes a user)*
!SUBSECTION URL parameters
`user (string,required)`
The name of the user.
!SUBSECTION Description
Removes an existing user, identified by user.
If the user can be removed, the server will respond with HTTP 202.
In case of success, the returned JSON object has the following properties:
* error: boolean flag to indicate that an error occurred (false in this case)
* code: the HTTP status code
If the specified user does not exist, the server will respond with HTTP 404.
The body of the response will contain a JSON object with additional error details. The object has the following attributes:
* error: boolean flag to indicate that an error occurred (true in this case)
* code: the HTTP status code
* errorNum: the server error number
* errorMessage: a descriptive error message
!SUBSECTION Return codes
`HTTP 202`
Is returned if the user was removed by the server.
`HTTP 404`
The specified user does not exist.
`GET /_api/user/{user}`*(fetches a user)*
!SUBSECTION URL parameters
`user (string,required)`
The name of the user.
!SUBSECTION Description
Fetches data about the specified user.
The call will return a JSON document with at least the following attributes on success:
* user: The name of the user as a string.
* active: an optional flag that specifies whether the user is active.
* extra: an optional JSON object with arbitrary extra data about the user.
* changePassword: an optional flag that specifies whether the user must change the password or not.
!SUBSECTION Return codes
`HTTP 200`
The user was found.
`HTTP 404`
The user with user does not exist.
@startDocuBlock JSF_api_user_fetch

View File

@ -10,7 +10,7 @@ The implementation follows the CommonJS specification
Tests that an expression is *true*. If not, logs a message and throws
an exception.
Example usage:
*Examples*
```js
console.assert(value === "abc", "expected: value === abc, actual:", value);
@ -32,7 +32,7 @@ String substitution patterns, which can be used in *format*.
* *%%f* floating point number
* *%%o* object hyperlink
Example usage:
*Examples*
```js
console.debug("%s", "this is a test");

View File

@ -5,84 +5,47 @@
The implementation follows the CommonJS specification
[Filesystem/A/0](http://wiki.commonjs.org/wiki/Filesystem/A/0).
`fs.exists(path)`
Returns true if a file (of any type) or a directory exists at a given path. If the file is a broken symbolic link, returns false.
<!-- lib/V8/v8-utils.cpp -->
`fs.isDirectory(path)`
Returns true if the path points to a directory.
`fs.isFile(path)`
Returns true if the path points to a file.
@startDocuBlock JS_Exists
`fs.list(path)`
<!-- lib/V8/v8-utils.cpp -->
The functions returns the names of all the files in a directory, in lexically sorted order. Throws an exception if the directory cannot be traversed (or path is not a directory).
Note: this means that list("x") of a directory containing "a" and "b" would return ["a", "b"], not ["x/a", "x/b"].
`fs.listTree(path)`
The function returns an array that starts with the given path, and all of the paths relative to the given path, discovered by a depth first traversal of every directory in any visited directory, reporting but not traversing symbolic links to directories. The first path is always "", the path relative to itself.
@startDocuBlock JS_IsDirectory
`fs.move(source, destination)`
<!-- lib/V8/v8-utils.cpp -->
Moves source to destination. Failure to move the file, or specifying a directory for target when source is a file will throw an exception.
@startDocuBlock JS_IsFile
`fs.read(filename)`
<!-- lib/V8/v8-utils.cpp -->
Reads in a file and returns the content as string. Please note that the file content must be encoded in UTF-8.
@startDocuBlock JS_List
`fs.read64(filename)`
<!-- lib/V8/v8-utils.cpp -->
Reads in a file and returns the content as string. The file content is Base64 encoded.
@startDocuBlock JS_ListTree
`fs.remove(filename)`
<!-- lib/V8/v8-utils.cpp -->
Removes the file filename at the given path. Throws an exception if the path corresponds to anything that is not a file or a symbolic link. If "path" refers to a symbolic link, removes the symbolic link.
@startDocuBlock JS_Move
<!--
@anchor JSModuleFsExists
@copydetails JS_Exists
@CLEARPAGE
@anchor JSModuleFsIsDirectory
@copydetails JS_IsDirectory
<!-- lib/V8/v8-utils.cpp -->
@CLEARPAGE
@anchor JSModuleFsIsFile
@copydetails JS_IsFile
@startDocuBlock JS_Read
@CLEARPAGE
@anchor JSModuleFsList
@copydetails JS_List
@CLEARPAGE
@anchor JSModuleFsListTree
@copydetails JS_ListTree
<!-- lib/V8/v8-utils.cpp -->
@CLEARPAGE
@anchor JSModuleFsMove
@copydetails JS_Move
@startDocuBlock JS_Read64
@CLEARPAGE
@anchor JSModuleFsRead
@copydetails JS_Read
@CLEARPAGE
@anchor JSModuleFsRead64
@copydetails JS_Read64
<!-- lib/V8/v8-utils.cpp -->
@CLEARPAGE
@anchor JSModuleFsRemove
@copydetails JS_Remove
@BNAVIGATE_JSModuleFs
-->
@startDocuBlock JS_Remove

View File

@ -1,5 +1,7 @@
!CHAPTER Module "graph"
**Warning: Deprecated**
!SUBSECTION First Steps with Graphs
A Graph consists of vertices and edges. The vertex collection contains the

View File

@ -120,7 +120,7 @@ arangosh> test1.func1();
*require* follows the specification
[Modules/1.1.1](http://wiki.commonjs.org/wiki/Modules/1.1.1).
!CHAPTER Modules Path versus Modules Collection
!SECTION Modules Path versus Modules Collection
ArangoDB comes with predefined modules defined in the file-system under the path
specified by *startup.startup-directory*. In a standard installation this
@ -158,9 +158,9 @@ follows
content: "...."
}
```
**Note**: The leading */´ is important - even if you call *require* without a
leading */´. If such a document exists, then the value of the *content*
**Note**: The leading */* is important - even if you call *require* without a
leading */*. If such a document exists, then the value of the *content*
attribute must contain the JavaScript code of the module. This string is
executed in a new module context and the value of *exports* object is
returned. This value is also stored in the module cache.

View File

@ -65,21 +65,21 @@
* [Projections and filters](AqlExamples/ProjectionsAndFilters.md)
* [Joins](AqlExamples/Join.md)
* [Grouping](AqlExamples/Grouping.md)
<!-- 13 -->
<!-- 11 -->
* [General Graphs](General-Graphs/README.md)
* [Graph Management](General-Graphs/Management.md)
* [Graph Functions](General-Graphs/Functions.md)
* [Fluent Query Interface](General-Graphs/FluentAQLInterface.md)
<!-- 14 -->
<!-- 12 -->
* [(Deprecated) Blueprint Graphs](Blueprint-Graphs/README.md)
* [Graph Constructor](Blueprint-Graphs/GraphConstructor.md)
* [Vertex Methods](Blueprint-Graphs/VertexMethods.md)
* [Edge Methods](Blueprint-Graphs/EdgeMethods.md)
<!-- 15 -->
<!-- 13 -->
* [Traversals](Traversals/README.md)
* [Using Traversal Objects](Traversals/UsingTraversalObjects.md)
* [Example Data](Traversals/ExampleData.md)
<!-- 16 -->
<!-- 14 -->
* [Foxx](Foxx/README.md)
* [Handling Request](Foxx/HandlingRequest.md)
* [Manifest](Foxx/FoxxManifest.md)
@ -90,32 +90,32 @@
* [Dependency Injection](Foxx/FoxxInjection.md)
* [Foxx Exports](Foxx/FoxxExports.md)
* [Optional Functionality](Foxx/FoxxOptional.md)
<!-- 17 -->
<!-- 15 -->
* [Foxx Manager](FoxxManager/README.md)
* [First Steps](FoxxManager/FirstSteps.md)
* [Behind the scenes](FoxxManager/BehindTheScenes.md)
* [Multiple Databases](FoxxManager/MultipleDatabases.md)
* [Manager Commands](FoxxManager/ManagerCommands.md)
* [Frequently Used Options](FoxxManager/FrequentlyUsedOptions.md)
<!-- 18 -->
<!-- 16 -->
* [ArangoDB's Actions](ArangoActions/README.md)
* [Delivering HTML Pages](ArangoActions/HtmlExample.md)
* [Json Objects](ArangoActions/JsonExample.md)
* [Modifying](ArangoActions/Modifying.md)
<!-- 19 -->
<!-- 17 -->
* [Replication](Replication/README.md)
* [Components](Replication/Components.md)
* [Example Setup](Replication/ExampleSetup.md)
* [Replication Limitations](Replication/Limitations.md)
* [Replication Overhead](Replication/Overhead.md)
* [Replication Events](Replication/Events.md)
<!-- 20 -->
<!-- 18 -->
* [Sharding](Sharding/README.md)
* [How to try it out](Sharding/HowTo.md)
* [Implementation](Sharding/StatusOfImplementation.md)
* [Authentication](Sharding/Authentication.md)
* [Firewall setup](Sharding/FirewallSetup.md)
<!-- 21 -->
<!-- 19 -->
* [Configure ArangoDB](ConfigureArango/README.md)
* [General options](ConfigureArango/GeneralOptions.md)
* [Arangod options](ConfigureArango/Arangod.md)
@ -127,13 +127,13 @@
* [Random numbers](ConfigureArango/RandomNumbers.md)
* [Authentication](ConfigureArango/Authentication.md)
* [Emergency Console](ConfigureArango/EmergencyConsole.md)
<!-- 22 -->
<!-- 20 -->
* [Arangoimp](Arangoimp/README.md)
<!-- 23 -->
<!-- 21 -->
* [Arangodump](Arangodump/README.md)
<!-- 24 -->
<!-- 22 -->
* [Arangorestore](Arangorestore/README.md)
<!-- 25 -->
<!-- 23 -->
* [HTTP API](HttpApi/README.md)
* [Databases](HttpDatabase/README.md)
* [To-Endpoint](HttpDatabase/DatabaseEndpoint.md)
@ -179,21 +179,19 @@
* [Bulk Imports](HttpBulkImports/README.md)
* [JSON Documents](HttpBulkImports/ImportingSelfContained.md)
* [Headers and Values](HttpBulkImports/ImportingHeadersAndValues.md)
* [Edge Collections](HttpBulkImports/ImportingIntoEdges.md)
* [Batch Requests](HttpBatchRequest/README.md)
* [Monitoring](HttpAdministrationAndMonitoring/README.md)
* [User Management](HttpUserManagement/README.md)
* [Async Result](HttpAsyncResultsManagement/README.md)
* [Management](HttpAsyncResultsManagement/ManagingAsyncResults.md)
* [Endpoints](HttpEndpoints/README.md)
* [Sharding](HttpShardingInterface/README.md)
* [Miscellaneous functions](HttpMiscellaneousFunctions/README.md)
* [General Handling](GeneralHttp/README.md)
<!-- 26 -->
<!-- 24 -->
* [Javascript Modules](ModuleJavaScript/README.md)
* ["console"](ModuleConsole/README.md)
* ["fs"](ModuleFs/README.md)
* ["graph"](ModuleGraph/README.md)
* [(Deprecated) "graph"](ModuleGraph/README.md)
* [Graph Constructors](ModuleGraph/GraphConstructor.md)
* [Vertex Methods](ModuleGraph/VertexMethods.md)
* [Edge Methods](ModuleGraph/EdgeMethods.md)
@ -201,9 +199,9 @@
* ["planner"](ModulePlanner/README.md)
* [Task Management](ModuleTasks/README.md)
* [Using jsUnity](UsingJsUnity/README.md)
<!-- 27 -->
<!-- 25 -->
* [Administrating ArangoDB](AdministratingArango/README.md)
<!-- 28 -->
<!-- 26 -->
* [Handling Indexes](IndexHandling/README.md)
* [Cap Constraint](IndexHandling/Cap.md)
* [Geo Indexes](IndexHandling/Geo.md)
@ -211,13 +209,13 @@
* [Hash Indexes](IndexHandling/Hash.md)
* [Skip-Lists](IndexHandling/Skiplist.md)
* [BitArray Indexes](IndexHandling/BitArray.md)
<!-- 29 -->
<!-- 27 -->
* [Datafile Debugger](DatafileDebugger/README.md)
<!-- 30 -->
<!-- 28 -->
* [Naming Conventions](NamingConventions/README.md)
* [Database Names](NamingConventions/DatabaseNames.md)
* [Collection Names](NamingConventions/CollectionNames.md)
* [Document Keys](NamingConventions/DocumentKeys.md)
* [Attribute Names](NamingConventions/AttributeNames.md)
<!-- 31 -->
<!-- 29 -->
* [Error codes and meanings](ErrorCodes/README.md)

View File

@ -192,7 +192,7 @@ def fetch_comments(dirpath):
if __name__ == "__main__":
open("allComments.txt", "w").close()
path = ["arangod/cluster","arangod/RestHandler","arangod/V8Server","arangod/RestServer",
"lib/Admin","lib/HttpServer",
"lib/Admin","lib/HttpServer","lib/V8",
"js/actions","js/client","js/apps/databases","js/apps/system/cerberus","js/apps/system/gharial","js/common","js/server"]
for i in path:
dirpath = os.path.abspath(os.path.join(os.path.dirname( __file__ ), os.pardir,"ArangoDB/../../"+i))

View File

@ -1,14 +0,0 @@
> curl -X POST --data-binary @- --header "Content-Type: multipart/form-data; boundary=XXXsubpartXXX" http://localhost:8529/_api/batch
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
POST /_api/document?collection=nonexisting
{"a":1,"b":2,"c":3}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
POST /_api/document?collection=xyz
{"a":1,"b":2,"c":3,"d":4}
--XXXsubpartXXX--

View File

@ -1,23 +0,0 @@
HTTP/1.1 200 OK
x-arango-errors: 1
content-type: multipart/form-data; boundary=XXXsubpartXXX
content-length: 711
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8
content-length: 111
{"error":true,"code":404,"errorNum":1203,"errorMessage":"collection \/_api\/collection\/nonexisting not found"}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
HTTP/1.1 202 Accepted
content-type: application/json; charset=utf-8
etag: "9841979"
content-length: 53
{"error":false,"_id":"xyz/9841979","_key":"9841979","_rev":"9841979"}
--XXXsubpartXXX--

View File

@ -1,23 +0,0 @@
> curl -X POST --data-binary @- --header "Content-Type: multipart/form-data; boundary=XXXsubpartXXX" http://localhost:8529/_api/batch
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 1
POST /_api/document?collection=xyz&createCollection=true HTTP/1.1
{"a":1,"b":2,"c":3}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 2
POST /_api/document?collection=xyz HTTP/1.1
{"a":1,"b":2,"c":3,"d":4}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 3
POST /_api/document?collection=xyz HTTP/1.1
{"a":1,"b":2,"c":3,"d":4,"e":5}
--XXXsubpartXXX--

View File

@ -1,36 +0,0 @@
HTTP/1.1 200 OK
connection: Keep-Alive
content-type: multipart/form-data; boundary=XXXsubpartXXX
content-length: 1055
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 1
HTTP/1.1 202 Accepted
content-type: application/json; charset=utf-8
etag: "9514299"
content-length: 53
{"error":false,"_id":"xyz/9514299","_key":"9514299","_rev":"9514299"}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 2
HTTP/1.1 202 Accepted
content-type: application/json; charset=utf-8
etag: "9579835"
content-length: 53
{"error":false,"_id":"xyz/9579835","_key":"9579835","_rev":"9579835"}
--XXXsubpartXXX
Content-Type: application/x-arango-batchpart
Content-Id: 3
HTTP/1.1 202 Accepted
content-type: application/json; charset=utf-8
etag: "9645371"
content-length: 53
{"error":false,"_id":"xyz/9645371","_key":"9645371","_rev":"9645371"}
--XXXsubpartXXX--

View File

@ -1,10 +0,0 @@
curl --data-binary @- -X POST --dump - "http://localhost:8529/_api/import?type=documents&collection=test&createCollection=true"
{ "name" : "test", "gender" : "male", "age" : 39 }
{ "type" : "bird", "name" : "robin" }
HTTP/1.1 201 Created
server: triagens GmbH High-Performance HTTP Server
connection: Keep-Alive
content-type: application/json; charset=utf-8
{"error":false,"created":2,"empty":0,"errors":0}

View File

@ -1,11 +0,0 @@
curl --data-binary @- -X POST --dump - "http://localhost:8529/_api/import?collection=test&createCollection=true"
[ "firstName", "lastName", "age", "gender" ]
[ "Joe", "Public", 42, "male" ]
[ "Jane", "Doe", 31, "female" ]
HTTP/1.1 201 Created
server: triagens GmbH High-Performance HTTP Server
connection: Keep-Alive
content-type: application/json; charset=utf-8
{"error":false,"created":2,"empty":0,"errors":0}

View File

@ -208,6 +208,9 @@ unittests-recovery:
@echo "================================================================================"
@echo
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="many-logs"
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="multiple-logs"
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="collection-recreate"
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="drop-indexes"
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="create-indexes"
$(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="create-collections"

View File

@ -564,6 +564,12 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
}
TRI_voc_cid_t const cid = trx.cid();
// If we are a DBserver, we want to use the cluster-wide collection
// name for error reporting:
string collectionName = collection;
if (ServerState::instance()->isDBserver()) {
collectionName = trx.getResolver()->getCollectionName(cid);
}
TRI_doc_mptr_copy_t mptr;
res = trx.read(&mptr, key);
@ -581,7 +587,7 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
TRI_ASSERT(trx.hasBarrier());
if (res != TRI_ERROR_NO_ERROR) {
generateTransactionError(collection, res, (TRI_voc_key_t) key.c_str());
generateTransactionError(collectionName, res, (TRI_voc_key_t) key.c_str());
return false;
}
@ -1336,6 +1342,13 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
}
TRI_voc_cid_t const cid = trx.cid();
// If we are a DBserver, we want to use the cluster-wide collection
// name for error reporting:
string collectionName = collection;
if (ServerState::instance()->isDBserver()) {
collectionName = trx.getResolver()->getCollectionName(cid);
}
TRI_voc_rid_t rid = 0;
TRI_document_collection_t* document = trx.documentCollection();
TRI_ASSERT(document != nullptr);
@ -1344,7 +1357,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
string const&& cidString = StringUtils::itoa(document->_info._planId);
if (trx.orderBarrier(trx.trxCollection()) == nullptr) {
generateTransactionError(collection, TRI_ERROR_OUT_OF_MEMORY);
generateTransactionError(collectionName, TRI_ERROR_OUT_OF_MEMORY);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
}
@ -1374,7 +1387,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
res = trx.read(&oldDocument, key);
if (res != TRI_ERROR_NO_ERROR) {
trx.abort();
generateTransactionError(collection, res, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, res, (TRI_voc_key_t) key.c_str(), rid);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
@ -1382,7 +1395,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
if (oldDocument.getDataPtr() == nullptr) { // PROTECTED by trx here
trx.abort();
generateTransactionError(collection, TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND, (TRI_voc_key_t) key.c_str(), rid);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
@ -1394,7 +1407,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
if (old == nullptr) {
trx.abort();
generateTransactionError(collection, TRI_ERROR_OUT_OF_MEMORY);
generateTransactionError(collectionName, TRI_ERROR_OUT_OF_MEMORY);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
@ -1407,7 +1420,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
trx.abort();
generateTransactionError(collection, TRI_ERROR_CLUSTER_MUST_NOT_CHANGE_SHARDING_ATTRIBUTES);
generateTransactionError(collectionName, TRI_ERROR_CLUSTER_MUST_NOT_CHANGE_SHARDING_ATTRIBUTES);
return false;
}
@ -1419,7 +1432,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
if (patchedJson == nullptr) {
trx.abort();
generateTransactionError(collection, TRI_ERROR_OUT_OF_MEMORY);
generateTransactionError(collectionName, TRI_ERROR_OUT_OF_MEMORY);
return false;
}
@ -1443,7 +1456,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
res = trx.read(&oldDocument, key);
if (res != TRI_ERROR_NO_ERROR) {
trx.abort();
generateTransactionError(collection, res, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, res, (TRI_voc_key_t) key.c_str(), rid);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
@ -1451,7 +1464,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
if (oldDocument.getDataPtr() == nullptr) { // PROTECTED by trx here
trx.abort();
generateTransactionError(collection, TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND, (TRI_voc_key_t) key.c_str(), rid);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return false;
@ -1466,7 +1479,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
trx.abort();
generateTransactionError(collection, TRI_ERROR_CLUSTER_MUST_NOT_CHANGE_SHARDING_ATTRIBUTES);
generateTransactionError(collectionName, TRI_ERROR_CLUSTER_MUST_NOT_CHANGE_SHARDING_ATTRIBUTES);
return false;
}
@ -1487,7 +1500,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
// .............................................................................
if (res != TRI_ERROR_NO_ERROR) {
generateTransactionError(collection, res, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, res, (TRI_voc_key_t) key.c_str(), rid);
return false;
}
@ -1711,6 +1724,12 @@ bool RestDocumentHandler::deleteDocument () {
}
TRI_voc_cid_t const cid = trx.cid();
// If we are a DBserver, we want to use the cluster-wide collection
// name for error reporting:
string collectionName = collection;
if (ServerState::instance()->isDBserver()) {
collectionName = trx.getResolver()->getCollectionName(cid);
}
TRI_voc_rid_t rid = 0;
res = trx.deleteDocument(key, policy, waitForSync, revision, &rid);
@ -1727,7 +1746,7 @@ bool RestDocumentHandler::deleteDocument () {
// .............................................................................
if (res != TRI_ERROR_NO_ERROR) {
generateTransactionError(collection, res, (TRI_voc_key_t) key.c_str(), rid);
generateTransactionError(collectionName, res, (TRI_voc_key_t) key.c_str(), rid);
return false;
}

View File

@ -805,7 +805,7 @@ void RestReplicationHandler::handleCommandLoggerGetConfig () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationLoggerSetConfig1}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// var url = "/_api/replication/logger-config";
/// var body = {
@ -821,7 +821,7 @@ void RestReplicationHandler::handleCommandLoggerGetConfig () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationLoggerSetConfig2}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// var url = "/_api/replication/logger-config";
/// var body = {
@ -3650,7 +3650,7 @@ void RestReplicationHandler::handleCommandApplierGetConfig () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationApplierSetConfig}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// var url = "/_api/replication/applier-config";
/// var body = {
@ -3801,7 +3801,7 @@ void RestReplicationHandler::handleCommandApplierSetConfig () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationApplierStart}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
/// re.applier.properties({
/// endpoint: "tcp://127.0.0.1:8529",
/// username: "replicationApplier",
@ -3812,7 +3812,7 @@ void RestReplicationHandler::handleCommandApplierSetConfig () {
///
/// var url = "/_api/replication/applier-start";
/// var response = logCurlRequest('PUT', url, "");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// assert(response.code === 200);
/// logJsonResponse(response);
@ -3875,7 +3875,7 @@ void RestReplicationHandler::handleCommandApplierStart () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationApplierStop}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
/// re.applier.properties({
/// endpoint: "tcp://127.0.0.1:8529",
/// username: "replicationApplier",
@ -3887,7 +3887,7 @@ void RestReplicationHandler::handleCommandApplierStart () {
/// re.applier.start();
/// var url = "/_api/replication/applier-stop";
/// var response = logCurlRequest('PUT', url, "");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// assert(response.code === 200);
/// logJsonResponse(response);
@ -3999,7 +3999,7 @@ void RestReplicationHandler::handleCommandApplierStop () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationApplierStateNotRunning}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
///
/// var url = "/_api/replication/applier-state";
/// var response = logCurlRequest('GET', url);
@ -4012,12 +4012,12 @@ void RestReplicationHandler::handleCommandApplierStop () {
///
/// @EXAMPLE_ARANGOSH_RUN{RestReplicationApplierStateRunning}
/// var re = require("org/arangodb/replication");
/// re.applier.stop();
/// re.applier.shutdown();
/// re.applier.start();
///
/// var url = "/_api/replication/applier-state";
/// var response = logCurlRequest('GET', url);
/// re.applier.stop();
/// re.applier.shutdown();
///
/// assert(response.code === 200);
/// logJsonResponse(response);

View File

@ -537,8 +537,7 @@ static HttpResponse* ResponseV8ToCpp (TRI_v8_global_t const* v8g,
HttpResponse* response = new HttpResponse(code, compatibility);
if (res->Has(v8g->ContentTypeKey)) {
response->setContentType(
TRI_ObjectToString(res->Get(v8g->ContentTypeKey)));
response->setContentType(TRI_ObjectToString(res->Get(v8g->ContentTypeKey)));
}
// .........................................................................

View File

@ -740,8 +740,8 @@ static bool IsIndexHandle (v8::Handle<v8::Value> const arg,
static void WeakCollectionCallback (v8::Isolate* isolate,
v8::Persistent<v8::Value> object,
void* parameter) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_vocbase_col_t* collection = (TRI_vocbase_col_t*) parameter;
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
TRI_vocbase_col_t* collection = static_cast<TRI_vocbase_col_t*>(parameter);
v8g->_hasDeadObjects = true;
@ -770,7 +770,7 @@ static void WeakCollectionCallback (v8::Isolate* isolate,
static v8::Handle<v8::Object> WrapCollection (TRI_vocbase_col_t const* collection) {
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8::Handle<v8::Object> result = v8g->VocbaseColTempl->NewInstance();
if (! result.IsEmpty()) {
@ -7720,7 +7720,7 @@ static v8::Handle<v8::Value> JS_VersionVocbaseCol (v8::Arguments const& argv) {
static v8::Handle<v8::Object> WrapVocBase (TRI_vocbase_t const* database) {
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8::Handle<v8::Object> result = WrapClass(v8g->VocbaseTempl,
WRP_VOCBASE_TYPE,
const_cast<TRI_vocbase_t*>(database));
@ -7754,7 +7754,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
if (vocbase == nullptr) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
@ -7770,7 +7770,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
// empty or null
if (key == 0 || *key == '\0') {
if (key == nullptr || *key == '\0') {
return scope.Close(v8::Handle<v8::Value>());
}
@ -7780,7 +7780,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
return scope.Close(v8::Handle<v8::Value>());
}
TRI_vocbase_col_t* collection = 0;
TRI_vocbase_col_t* collection = nullptr;
// generate a name under which the cached property is stored
string cacheKey(key, keyLength);
@ -7815,7 +7815,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
collection = TRI_UnwrapClass<TRI_vocbase_col_t>(value, WRP_VOCBASE_COL_TYPE);
// check if the collection is from the same database
if (collection != 0 && collection->_vocbase == vocbase) {
if (collection != nullptr && collection->_vocbase == vocbase) {
TRI_READ_LOCK_STATUS_VOCBASE_COL(collection);
TRI_vocbase_col_status_e status = collection->_status;
TRI_voc_cid_t cid = collection->_cid;
@ -7823,7 +7823,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
// check if the collection is still alive
if (status != TRI_VOC_COL_STATUS_DELETED && cid > 0 && collection->_isLocal) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
if (value->Has(v8g->_IdKey)) {
TRI_voc_cid_t cachedCid = (TRI_voc_cid_t) TRI_ObjectToUInt64(value->Get(v8g->_IdKey), true);
@ -7847,12 +7847,12 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
= ClusterInfo::instance()->getCollection(vocbase->_name, std::string(key));
if ((*ci).empty()) {
collection = 0;
collection = nullptr;
}
else {
collection = CoordinatorCollection(vocbase, *ci);
if (collection != 0 && collection->_cid == 0) {
if (collection != nullptr && collection->_cid == 0) {
FreeCoordinatorCollection(collection);
return scope.Close(v8::Handle<v8::Value>());
}
@ -7862,7 +7862,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
collection = TRI_LookupCollectionByNameVocBase(vocbase, key);
}
if (collection == 0) {
if (collection == nullptr) {
if (*key == '_') {
return scope.Close(v8::Handle<v8::Value>());
}
@ -7876,6 +7876,8 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
return scope.Close(v8::Undefined());
}
// TODO: caching the result makes subsequent results much faster, but
// prevents physical removal of the collection or database
holder->Set(cacheName, result, v8::DontEnum);
return scope.Close(result);
@ -8761,7 +8763,7 @@ static v8::Handle<v8::Value> JS_UseDatabase (v8::Arguments const& argv) {
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
if (vocbase == nullptr) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_INTERNAL);
}
@ -8775,18 +8777,18 @@ static v8::Handle<v8::Value> JS_UseDatabase (v8::Arguments const& argv) {
}
else {
// check if the other database exists, and increase its refcount
vocbase = TRI_UseDatabaseServer((TRI_server_t*) v8g->_server, name.c_str());
vocbase = TRI_UseDatabaseServer(static_cast<TRI_server_t*>(v8g->_server), name.c_str());
}
if (vocbase != 0) {
if (vocbase != nullptr) {
// switch databases
void* orig = v8g->_vocbase;
TRI_ASSERT(orig != 0);
TRI_ASSERT(orig != nullptr);
v8g->_vocbase = vocbase;
if (orig != vocbase) {
TRI_ReleaseDatabaseServer((TRI_server_t*) v8g->_server, (TRI_vocbase_t*) orig);
TRI_ReleaseDatabaseServer(static_cast<TRI_server_t*>(v8g->_server), (TRI_vocbase_t*) orig);
}
return scope.Close(WrapVocBase(vocbase));
@ -9151,7 +9153,7 @@ static v8::Handle<v8::Value> JS_CreateDatabase (v8::Arguments const& argv) {
TRI_V8_EXCEPTION(scope, res);
}
TRI_ASSERT(database != 0);
TRI_ASSERT(database != nullptr);
// copy users into context
if (argv.Length() >= 3 && argv[2]->IsArray()) {
@ -9252,7 +9254,7 @@ static v8::Handle<v8::Value> JS_DropDatabase (v8::Arguments const& argv) {
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
if (vocbase == nullptr) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
@ -9266,9 +9268,9 @@ static v8::Handle<v8::Value> JS_DropDatabase (v8::Arguments const& argv) {
}
string const name = TRI_ObjectToString(argv[0]);
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
int res = TRI_DropDatabaseServer((TRI_server_t*) v8g->_server, name.c_str(), true);
int res = TRI_DropDatabaseServer(static_cast<TRI_server_t*>(v8g->_server), name.c_str(), true);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, res);
@ -9986,7 +9988,7 @@ bool TRI_V8RunVersionCheck (void* vocbase,
TRI_ASSERT(startupLoader != nullptr);
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
void* orig = v8g->_vocbase;
v8g->_vocbase = vocbase;
@ -10012,7 +10014,7 @@ int TRI_V8RunUpgradeCheck (void* vocbase,
TRI_ASSERT(startupLoader != nullptr);
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
void* orig = v8g->_vocbase;
v8g->_vocbase = vocbase;
@ -10034,7 +10036,7 @@ void TRI_V8InitialiseFoxx (void* vocbase,
{
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
orig = v8g->_vocbase;
v8g->_vocbase = vocbase;
}
@ -10046,7 +10048,7 @@ void TRI_V8InitialiseFoxx (void* vocbase,
false);
{
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_vocbase = orig;
}
}

View File

@ -2643,12 +2643,11 @@ TRI_document_collection_t* TRI_OpenDocumentCollection (TRI_vocbase_t* vocbase,
char const* path = col->_path;
// first open the document collection
TRI_document_collection_t* document;
TRI_document_collection_t* document = nullptr;
try {
document = new TRI_document_collection_t();
}
catch (std::exception&) {
document = nullptr;
}
if (document == nullptr) {

View File

@ -898,7 +898,6 @@ int TRI_ShutdownReplicationApplier (TRI_replication_applier_t* applier) {
int TRI_ConfigureReplicationApplier (TRI_replication_applier_t* applier,
TRI_replication_applier_configuration_t const* config) {
int res;
if (applier->_vocbase->_type == TRI_VOCBASE_TYPE_COORDINATOR) {
return TRI_ERROR_CLUSTER_UNSUPPORTED;
@ -923,7 +922,7 @@ int TRI_ConfigureReplicationApplier (TRI_replication_applier_t* applier,
return TRI_ERROR_REPLICATION_RUNNING;
}
res = TRI_SaveConfigurationReplicationApplier(applier->_vocbase, config, true);
int res = TRI_SaveConfigurationReplicationApplier(applier->_vocbase, config, true);
if (res == TRI_ERROR_NO_ERROR) {
res = LoadConfiguration(applier->_vocbase, &applier->_configuration);
@ -1106,11 +1105,11 @@ void TRI_InitStateReplicationApplier (TRI_replication_applier_state_t* state) {
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyStateReplicationApplier (TRI_replication_applier_state_t* state) {
if (state->_progressMsg != NULL) {
if (state->_progressMsg != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, state->_progressMsg);
}
if (state->_lastError._msg != NULL) {
if (state->_lastError._msg != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, state->_lastError._msg);
}
}
@ -1129,7 +1128,7 @@ int TRI_RemoveStateReplicationApplier (TRI_vocbase_t* vocbase) {
filename = GetStateFilename(vocbase);
if (filename == NULL) {
if (filename == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
}
@ -1163,7 +1162,7 @@ int TRI_SaveStateReplicationApplier (TRI_vocbase_t* vocbase,
json = JsonApplyState(state);
if (json == NULL) {
if (json == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
}
@ -1201,7 +1200,7 @@ int TRI_LoadStateReplicationApplier (TRI_vocbase_t* vocbase,
TRI_InitStateReplicationApplier(state);
filename = GetStateFilename(vocbase);
if (filename == NULL) {
if (filename == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
}
@ -1215,11 +1214,11 @@ int TRI_LoadStateReplicationApplier (TRI_vocbase_t* vocbase,
LOG_TRACE("replication state file '%s' found", filename);
json = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, NULL);
json = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, nullptr);
TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
if (! TRI_IsArrayJson(json)) {
if (json != NULL) {
if (json != nullptr) {
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
}
@ -1261,10 +1260,10 @@ int TRI_LoadStateReplicationApplier (TRI_vocbase_t* vocbase,
void TRI_InitConfigurationReplicationApplier (TRI_replication_applier_configuration_t* config) {
memset(config, 0, sizeof(TRI_replication_applier_configuration_t));
config->_endpoint = NULL;
config->_database = NULL;
config->_username = NULL;
config->_password = NULL;
config->_endpoint = nullptr;
config->_database = nullptr;
config->_username = nullptr;
config->_password = nullptr;
config->_requestTimeout = 300.0;
config->_connectTimeout = 10.0;
@ -1280,24 +1279,24 @@ void TRI_InitConfigurationReplicationApplier (TRI_replication_applier_configurat
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyConfigurationReplicationApplier (TRI_replication_applier_configuration_t* config) {
if (config->_endpoint != NULL) {
if (config->_endpoint != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, config->_endpoint);
config->_endpoint = NULL;
config->_endpoint = nullptr;
}
if (config->_database != NULL) {
if (config->_database != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, config->_database);
config->_database = NULL;
config->_database = nullptr;
}
if (config->_username != NULL) {
if (config->_username != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, config->_username);
config->_username = NULL;
config->_username = nullptr;
}
if (config->_password != NULL) {
if (config->_password != nullptr) {
TRI_FreeString(TRI_CORE_MEM_ZONE, config->_password);
config->_password = NULL;
config->_password = nullptr;
}
}

View File

@ -140,6 +140,9 @@ struct TRI_replication_applier_t {
}
void abortRunningRemoteTransactions () {
size_t const n = _runningRemoteTransactions.size();
triagens::arango::TransactionBase::increaseNumbers(n, n);
for (auto it = _runningRemoteTransactions.begin(); it != _runningRemoteTransactions.end(); ++it) {
auto trx = (*it).second;

View File

@ -35,6 +35,7 @@
#include "BasicsC/logging.h"
#include "BasicsC/tri-strings.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/collection.h"
#include "VocBase/datafile.h"
#include "VocBase/document-collection.h"
@ -44,6 +45,7 @@
#include "Wal/Logfile.h"
#include "Wal/LogfileManager.h"
#include "Wal/Marker.h"
#include "Cluster/ServerState.h"
using namespace triagens;
@ -110,7 +112,7 @@ df_entry_t;
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief translate a collection id into a collection name
/// @brief translate a (local) collection id into a collection name
////////////////////////////////////////////////////////////////////////////////
char const* NameFromCid (TRI_replication_dump_t* dump,
@ -143,15 +145,19 @@ char const* NameFromCid (TRI_replication_dump_t* dump,
static bool AppendCollection (TRI_replication_dump_t* dump,
TRI_voc_cid_t cid,
bool translateCollectionIds) {
bool translateCollectionIds,
triagens::arango::CollectionNameResolver* resolver) {
if (translateCollectionIds) {
if (cid > 0) {
char const* name = NameFromCid(dump, cid);
if (name != nullptr) {
APPEND_STRING(dump->_buffer, name);
return true;
std::string name;
if (triagens::arango::ServerState::instance()->isDBserver()) {
name = resolver->getCollectionNameCluster(cid);
}
else {
name = resolver->getCollectionName(cid);
}
APPEND_STRING(dump->_buffer, name.c_str());
return true;
}
APPEND_STRING(dump->_buffer, "_unknown");
@ -272,7 +278,8 @@ static bool StringifyMarkerDump (TRI_replication_dump_t* dump,
TRI_document_collection_t* document,
TRI_df_marker_t const* marker,
bool withTicks,
bool translateCollectionIds) {
bool translateCollectionIds,
triagens::arango::CollectionNameResolver* resolver) {
// This covers two cases:
// 1. document is not nullptr and marker points into a data file
// 2. document is a nullptr and marker points into a WAL file
@ -401,13 +408,13 @@ static bool StringifyMarkerDump (TRI_replication_dump_t* dump,
}
APPEND_STRING(buffer, ",\"" TRI_VOC_ATTRIBUTE_FROM "\":\"");
if (! AppendCollection(dump, fromCid, translateCollectionIds)) {
if (! AppendCollection(dump, fromCid, translateCollectionIds, resolver)) {
return false;
}
APPEND_STRING(buffer, "\\/");
APPEND_STRING(buffer, fromKey);
APPEND_STRING(buffer, "\",\"" TRI_VOC_ATTRIBUTE_TO "\":\"");
if (! AppendCollection(dump, toCid, translateCollectionIds)) {
if (! AppendCollection(dump, toCid, translateCollectionIds, resolver)) {
return false;
}
APPEND_STRING(buffer, "\\/");
@ -962,7 +969,8 @@ static int DumpCollection (TRI_replication_dump_t* dump,
TRI_voc_tick_t dataMin,
TRI_voc_tick_t dataMax,
bool withTicks,
bool translateCollectionIds) {
bool translateCollectionIds,
triagens::arango::CollectionNameResolver* resolver) {
TRI_vector_t datafiles;
TRI_string_buffer_t* buffer;
TRI_voc_tick_t lastFoundTick;
@ -1109,7 +1117,7 @@ static int DumpCollection (TRI_replication_dump_t* dump,
}
if (! StringifyMarkerDump(dump, document, marker, withTicks, translateCollectionIds)) {
if (! StringifyMarkerDump(dump, document, marker, withTicks, translateCollectionIds, resolver)) {
res = TRI_ERROR_INTERNAL;
goto NEXT_DF;
@ -1178,6 +1186,7 @@ int TRI_DumpCollectionReplication (TRI_replication_dump_t* dump,
TRI_ASSERT(col != nullptr);
TRI_ASSERT(col->_collection != nullptr);
triagens::arango::CollectionNameResolver resolver(col->_vocbase);
TRI_document_collection_t* document = col->_collection;
// create a barrier so the underlying collection is not unloaded
@ -1190,7 +1199,8 @@ int TRI_DumpCollectionReplication (TRI_replication_dump_t* dump,
// block compaction
TRI_ReadLockReadWriteLock(&document->_compactionLock);
int res = DumpCollection(dump, document, dataMin, dataMax, withTicks, translateCollectionIds);
int res = DumpCollection(dump, document, dataMin, dataMax, withTicks,
translateCollectionIds, &resolver);
TRI_ReadUnlockReadWriteLock(&document->_compactionLock);

View File

@ -218,6 +218,18 @@ namespace triagens {
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief increase counters, used in replication client in shutdown to
/// kill transactions of other threads.
////////////////////////////////////////////////////////////////////////////////
static void increaseNumbers (int numberInScope, int numberActive) {
#ifdef TRI_ENABLE_MAINTAINER_MODE
_numberTrxInScope += numberInScope;
_numberTrxActive += numberActive;
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief assert that a transaction object is in scope in the current thread
////////////////////////////////////////////////////////////////////////////////

View File

@ -282,10 +282,11 @@ TRI_vocbase_col_t* RecoverState::useCollection (TRI_vocbase_t* vocbase,
if (collection == nullptr) {
return nullptr;
}
TRI_document_collection_t* document = collection->_collection;
TRI_ASSERT(document != nullptr);
// disable secondary indexes for the moment
document->useSecondaryIndexes(false);
openedCollections.insert(it, std::make_pair(collectionId, collection));
@ -303,14 +304,16 @@ TRI_document_collection_t* RecoverState::getCollection (TRI_voc_tick_t databaseI
TRI_voc_cid_t collectionId) {
TRI_vocbase_t* vocbase = useDatabase(databaseId);
if (vocbase == nullptr) {
LOG_WARNING("database %llu not found", (unsigned long long) databaseId);
LOG_TRACE("database %llu not found", (unsigned long long) databaseId);
return nullptr;
}
TRI_vocbase_col_t* collection = useCollection(vocbase, collectionId);
if (collection == nullptr) {
LOG_WARNING("collection %llu of database %llu not found", (unsigned long long) collectionId, (unsigned long long) databaseId);
LOG_TRACE("collection %llu of database %llu not found", (unsigned long long) collectionId, (unsigned long long) databaseId);
return nullptr;
}
@ -396,7 +399,6 @@ int RecoverState::executeSingleOperation (TRI_voc_tick_t databaseId,
TRI_vocbase_col_t* collection = useCollection(vocbase, collectionId);
if (collection == nullptr) {
LOG_WARNING("collection %llu of database %llu not found", (unsigned long long) collectionId, (unsigned long long) databaseId);
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
}
@ -533,7 +535,7 @@ bool RecoverState::InitialScanMarker (TRI_df_marker_t const* marker,
state->remoteTransactions.erase(m->_transactionId);
break;
}
/*
// -----------------------------------------------------------------------------
// create markers
// -----------------------------------------------------------------------------
@ -579,7 +581,7 @@ bool RecoverState::InitialScanMarker (TRI_df_marker_t const* marker,
// ignored
break;
}
*/
}
return true;
@ -623,7 +625,7 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
return res;
});
if (res != TRI_ERROR_NO_ERROR) {
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_DATABASE_NOT_FOUND && res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
LOG_WARNING("could not apply attribute marker: %s", TRI_errno_string(res));
return state->canContinue();
}
@ -649,7 +651,7 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
return res;
});
if (res != TRI_ERROR_NO_ERROR) {
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_DATABASE_NOT_FOUND && res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
LOG_WARNING("could not apply shape marker: %s", TRI_errno_string(res));
return state->canContinue();
}
@ -725,7 +727,10 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
res = TRI_ERROR_TRANSACTION_INTERNAL;
}
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_CONFLICT) {
if (res != TRI_ERROR_NO_ERROR &&
res != TRI_ERROR_ARANGO_CONFLICT &&
res != TRI_ERROR_ARANGO_DATABASE_NOT_FOUND &&
res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
LOG_WARNING("unable to insert document in collection %llu of database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
@ -805,7 +810,10 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
res = TRI_ERROR_TRANSACTION_INTERNAL;
}
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_CONFLICT) {
if (res != TRI_ERROR_NO_ERROR &&
res != TRI_ERROR_ARANGO_CONFLICT &&
res != TRI_ERROR_ARANGO_DATABASE_NOT_FOUND &&
res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
LOG_WARNING("unable to insert edge in collection %llu of database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
@ -869,7 +877,10 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
res = TRI_ERROR_TRANSACTION_INTERNAL;
}
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_CONFLICT) {
if (res != TRI_ERROR_NO_ERROR &&
res != TRI_ERROR_ARANGO_CONFLICT &&
res != TRI_ERROR_ARANGO_DATABASE_NOT_FOUND &&
res != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
LOG_WARNING("unable to remove document in collection %llu of database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
@ -938,22 +949,25 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
}
TRI_vocbase_t* vocbase = state->useDatabase(databaseId);
if (vocbase == nullptr) {
LOG_WARNING("cannot create index for collection %llu in database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
TRI_errno_string(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND));
return state->canContinue();
// if the underlying database is gone, we can go on
LOG_TRACE("cannot create index for collection %llu in database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
TRI_errno_string(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND));
return true;
}
TRI_document_collection_t* document = state->getCollection(databaseId, collectionId);
if (document == nullptr) {
// collection not there anymore
LOG_WARNING("cannot create index for collection %llu in database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
TRI_errno_string(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND));
return state->canContinue();
// if the underlying collection is gone, we can go on
LOG_TRACE("cannot create index for collection %llu in database %llu: %s",
(unsigned long long) collectionId,
(unsigned long long) databaseId,
TRI_errno_string(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND));
return true;
}
char const* properties = reinterpret_cast<char const*>(m) + sizeof(index_create_marker_t);
@ -1011,8 +1025,9 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
TRI_vocbase_t* vocbase = state->useDatabase(databaseId);
if (vocbase == nullptr) {
LOG_WARNING("cannot open database %llu", (unsigned long long) databaseId);
return state->canContinue();
// if the underlying database is gone, we can go on
LOG_TRACE("cannot open database %llu", (unsigned long long) databaseId);
return true;
}
TRI_vocbase_col_t* collection = state->releaseCollection(collectionId);
@ -1155,13 +1170,15 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
TRI_vocbase_t* vocbase = state->useDatabase(databaseId);
if (vocbase == nullptr) {
LOG_WARNING("cannot open database %llu", (unsigned long long) databaseId);
return state->canContinue();
// if the underlying database is gone, we can go on
LOG_TRACE("cannot open database %llu", (unsigned long long) databaseId);
return true;
}
TRI_document_collection_t* document = state->getCollection(databaseId, collectionId);
if (document == nullptr) {
return state->canContinue();
// if the underlying collection gone, we can go on
return true;
}
// fake transaction to satisfy assertions
@ -1247,9 +1264,6 @@ bool RecoverState::ReplayMarker (TRI_df_marker_t const* marker,
int RecoverState::replayLogfile (Logfile* logfile) {
LOG_TRACE("replaying logfile '%s'", logfile->filename().c_str());
droppedCollections.clear();
droppedDatabases.clear();
if (! TRI_IterateDatafile(logfile->df(), &RecoverState::ReplayMarker, static_cast<void*>(this))) {
LOG_WARNING("WAL inspection failed when scanning logfile '%s'", logfile->filename().c_str());
return TRI_ERROR_ARANGO_RECOVERY;
@ -1263,6 +1277,9 @@ int RecoverState::replayLogfile (Logfile* logfile) {
////////////////////////////////////////////////////////////////////////////////
int RecoverState::replayLogfiles () {
droppedCollections.clear();
droppedDatabases.clear();
for (auto it = logfilesToProcess.begin(); it != logfilesToProcess.end(); ++it) {
Logfile* logfile = (*it);
@ -1360,9 +1377,11 @@ int RecoverState::fillIndexes () {
TRI_ASSERT(document != nullptr);
// activate secondary indexes
document->useSecondaryIndexes(true);
int res = TRI_FillIndexesDocumentCollection(document);
if (res != TRI_ERROR_NO_ERROR) {
return res;
}

View File

@ -103,11 +103,13 @@ int Slots::flush (bool waitForSync) {
int res = closeLogfile(lastTick, worked);
if (res == TRI_ERROR_NO_ERROR) {
if (worked && waitForSync) {
_logfileManager->signalSync();
_logfileManager->signalSync();
if (waitForSync) {
// wait until data has been committed to disk
waitForTick(lastTick);
if (! waitForTick(lastTick)) {
res = TRI_ERROR_ARANGO_SYNC_TIMEOUT;
}
}
else if (! worked) {
// logfile to flush was still empty and thus not flushed
@ -249,6 +251,8 @@ void Slots::returnUsed (SlotInfo& slotInfo,
TRI_ASSERT(slotInfo.slot != nullptr);
Slot::TickType tick = slotInfo.slot->tick();
TRI_ASSERT(tick > 0);
{
MUTEX_LOCKER(_lock);
slotInfo.slot->setReturned(waitForSync);
@ -294,6 +298,7 @@ SyncRegion Slots::getSyncRegion () {
else {
if (slot->logfileId() != region.logfileId) {
// got a different logfile
region.checkMore = true;
break;
}
@ -581,17 +586,23 @@ Slot::TickType Slots::handout () {
/// @brief wait until all data has been synced up to a certain marker
////////////////////////////////////////////////////////////////////////////////
void Slots::waitForTick (Slot::TickType tick) {
bool Slots::waitForTick (Slot::TickType tick) {
static uint64_t const SleepTime = 20 * 1000;
static int const MaxIterations = 15 * 1000 * 1000 / SleepTime;
int iterations = 0;
// wait until data has been committed to disk
while (true) {
while (++iterations < MaxIterations) {
CONDITION_LOCKER(guard, _condition);
if (lastCommittedTick() >= tick) {
return;
return true;
}
guard.wait(100 * 1000);
guard.wait(SleepTime);
}
return false;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -232,7 +232,7 @@ namespace triagens {
/// @brief wait until all data has been synced up to a certain marker
////////////////////////////////////////////////////////////////////////////////
void waitForTick (Slot::TickType);
bool waitForTick (Slot::TickType);
////////////////////////////////////////////////////////////////////////////////
/// @brief request a new logfile which can satisfy a marker of the

View File

@ -45,7 +45,8 @@ namespace triagens {
size(0),
firstSlotIndex(0),
lastSlotIndex(0),
waitForSync(false) {
waitForSync(false),
checkMore(false) {
}
~SyncRegion () {
@ -58,6 +59,7 @@ namespace triagens {
size_t firstSlotIndex;
size_t lastSlotIndex;
bool waitForSync;
bool checkMore;
};
}

View File

@ -123,7 +123,15 @@ void SynchroniserThread::run () {
if (waiting > 0) {
try {
doSync();
// sync as much as we can in this loop
bool checkMore = false;
while (true) {
int res = doSync(checkMore);
if (res != TRI_ERROR_NO_ERROR || ! checkMore) {
break;
}
}
}
catch (triagens::arango::Exception const& ex) {
int res = ex.code();
@ -166,7 +174,9 @@ void SynchroniserThread::run () {
/// @brief synchronise an unsynchronized region
////////////////////////////////////////////////////////////////////////////////
int SynchroniserThread::doSync () {
int SynchroniserThread::doSync (bool& checkMore) {
checkMore = false;
// get region to sync
SyncRegion region = _logfileManager->slots()->getSyncRegion();
Logfile::IdType const id = region.logfileId;
@ -205,6 +215,8 @@ int SynchroniserThread::doSync () {
// additionally seal the logfile
_logfileManager->setLogfileSealed(id);
}
checkMore = region.checkMore;
_logfileManager->slots()->returnSyncRegion(region);
return TRI_ERROR_NO_ERROR;

View File

@ -114,7 +114,7 @@ namespace triagens {
/// @brief synchronise an unsynchronized region
////////////////////////////////////////////////////////////////////////////////
int doSync ();
int doSync (bool&);
////////////////////////////////////////////////////////////////////////////////
/// @brief get a logfile descriptor (it caches the descriptor for performance)

View File

@ -42,17 +42,17 @@ var console = require("console");
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_GET
/// @startDocuBlock JSF_cluster_test_GET
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{GET /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{GET /_admin/cluster-test, Execute cluster roundtrip}
///
/// @RESTDESCRIPTION
///
/// Executes a cluster roundtrip from a coordinator to a DB server and
/// back. This call only works in a coordinator node in a cluster.
/// One can and should append an arbitrary path to the URL and the
/// part after `/_admin/cluster-test` is used as the path of the HTTP
/// part after */_admin/cluster-test* is used as the path of the HTTP
/// request which is sent from the coordinator to a DB node. Likewise,
/// any form data appended to the URL is forwarded in the request to the
/// DB node. This handler takes care of all request types (see below)
@ -60,24 +60,24 @@ var console = require("console");
///
/// The following HTTP headers are interpreted in a special way:
///
/// - `X-Shard-ID`: This specifies the ID of the shard to which the
/// - *X-Shard-ID*: This specifies the ID of the shard to which the
/// cluster request is sent and thus tells the system to which DB server
/// to send the cluster request. Note that the mapping from the
/// shard ID to the responsible server has to be defined in the
/// agency under `Current/ShardLocation/<shardID>`. One has to give
/// agency under *Current/ShardLocation/<shardID>*. One has to give
/// this header, otherwise the system does not know where to send
/// the request.
/// - `X-Client-Transaction-ID`: the value of this header is taken
/// - *X-Client-Transaction-ID*: the value of this header is taken
/// as the client transaction ID for the request
/// - `X-Timeout`: specifies a timeout in seconds for the cluster
/// - *X-Timeout*: specifies a timeout in seconds for the cluster
/// operation. If the answer does not arrive within the specified
/// timeout, an corresponding error is returned and any subsequent
/// real answer is ignored. The default if not given is 24 hours.
/// - `X-Synchronous-Mode`: If set to `true` the test function uses
/// - *X-Synchronous-Mode*: If set to *true* the test function uses
/// synchronous mode, otherwise the default asynchronous operation
/// mode is used. This is mainly for debugging purposes.
/// - `Host`: This header is ignored and not forwarded to the DB server.
/// - `User-Agent`: This header is ignored and not forwarded to the DB
/// - *Host*: This header is ignored and not forwarded to the DB server.
/// - *User-Agent*: This header is ignored and not forwarded to the DB
/// server.
///
/// All other HTTP headers and the body of the request (if present, see
@ -102,62 +102,68 @@ var console = require("console");
///
/// @RESTRETURNCODE{404}
/// is returned if ArangoDB was not compiled for cluster operation.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_POST
/// @startDocuBlock JSF_cluster_test_POST
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{POST /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{POST /_admin/cluster-test, Execute cluster roundtrip}
///
/// @RESTBODYPARAM{body,anything,required}
///
/// @RESTDESCRIPTION
/// See GET method. The body can be any type and is simply forwarded.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_PUT
/// @startDocuBlock JSF_cluster_test_PUT
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{PUT /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{PUT /_admin/cluster-test, Execute cluster roundtrip}
///
/// @RESTBODYPARAM{body,anything,required}
///
/// @RESTDESCRIPTION
/// See GET method. The body can be any type and is simply forwarded.
// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_DELETE
/// @startDocuBlock JSF_cluster_test_DELETE
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{DELETE /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{DELETE /_admin/cluster-test, Delete cluster roundtrip}
///
/// @RESTDESCRIPTION
/// See GET method. The body can be any type and is simply forwarded.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_PATCH
/// @startDocuBlock JSF_cluster_test_PATCH
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{PATCH /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{PATCH /_admin/cluster-test, Update cluster roundtrip}
///
/// @RESTBODYPARAM{body,anything,required}
///
/// @RESTDESCRIPTION
/// See GET method. The body can be any type and is simply forwarded.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_test_HEAD
/// @startDocuBlock JSF_cluster_test_HEAD
/// @brief executes a cluster roundtrip for sharding
///
/// @RESTHEADER{HEAD /_admin/cluster-test,executes a cluster roundtrip}
/// @RESTHEADER{HEAD /_admin/cluster-test, Execute cluster roundtrip}
///
/// @RESTDESCRIPTION
/// See GET method. The body can be any type and is simply forwarded.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -272,10 +278,10 @@ function parseAuthorization (authorization) {
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_planner_POST
/// @startDocuBlock JSF_cluster_planner_POST
/// @brief exposes the cluster planning functionality
///
/// @RESTHEADER{POST /_admin/clusterPlanner,produce a cluster startup plan}
/// @RESTHEADER{POST /_admin/clusterPlanner, Produce cluster startup plan}
///
/// @RESTBODYPARAM{body,json,required}
///
@ -288,6 +294,7 @@ function parseAuthorization (authorization) {
/// @RESTRETURNCODE{200} is returned when everything went well.
///
/// @RESTRETURNCODE{400} the posted body was not valid JSON.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -328,7 +335,7 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_dispatcher_POST
/// @startDocuBlock JSF_cluster_dispatcher_POST
/// @brief exposes the dispatcher functionality to start up, shutdown,
/// relaunch, upgrade or cleanup a cluster according to a cluster plan
/// as for example provided by the kickstarter.
@ -341,30 +348,30 @@ actions.defineHttp({
///
/// @RESTDESCRIPTION The body must be an object with the following properties:
///
/// - `clusterPlan`: is a cluster plan (see JSF_cluster_planner_POST),
/// - `myname`: is the ID of this dispatcher, this is used to decide
/// - *clusterPlan*: is a cluster plan (see JSF_cluster_planner_POST),
/// - *myname*: is the ID of this dispatcher, this is used to decide
/// which commands are executed locally and which are forwarded
/// to other dispatchers
/// - `action`: can be one of the following:
/// - *action*: can be one of the following:
///
/// - "launch": the cluster is launched for the first time, all
/// data directories and log files are cleaned and created
/// - "shutdown": the cluster is shut down, the additional property
/// `runInfo` (see below) must be bound as well
/// *runInfo* (see below) must be bound as well
/// - "relaunch": the cluster is launched again, all data directories
/// and log files are untouched and need to be there already
/// - "cleanup": use this after a shutdown to remove all data in the
/// data directories and all log files, use with caution
/// - "isHealthy": checks whether or not the processes involved
/// in the cluster are running or not. The additional property
/// `runInfo` (see above) must be bound as well
/// *runInfo* (see above) must be bound as well
/// - "upgrade": performs an upgrade of a cluster, to this end,
/// the agency is started, and then every server is once started
/// with the "--upgrade" option, and then normally. Finally,
/// the script "verion-check.js" is run on one of the coordinators
/// for the cluster.
///
/// - `runInfo": this is needed for the "shutdown" and "isHealthy" actions
/// - *runInfo": this is needed for the "shutdown" and "isHealthy" actions
/// only and should be the structure that "launch", "relaunch" or
/// "upgrade" returned. It contains runtime information like process
/// IDs.
@ -378,6 +385,7 @@ actions.defineHttp({
///
/// @RESTRETURNCODE{400} the posted body was not valid JSON, or something
/// went wrong with the startup.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -512,10 +520,10 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_check_port_GET
/// @startDocuBlock JSF_cluster_check_port_GET
/// @brief allows to check whether a given port is usable
///
/// @RESTHEADER{GET /_admin/clusterCheckPort,check whether a given port is usable}
/// @RESTHEADER{GET /_admin/clusterCheckPort, Check port}
///
/// @RESTQUERYPARAMETERS
///
@ -528,6 +536,7 @@ actions.defineHttp({
/// @RESTRETURNCODE{200} is returned when everything went well.
///
/// @RESTRETURNCODE{400} the parameter port was not given or is no integer.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -574,10 +583,10 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_cluster_statistics_GET
/// @startDocuBlock JSF_cluster_statistics_GET
/// @brief allows to query the statistics of a DBserver in the cluster
///
/// @RESTHEADER{GET /_admin/clusterStatistics,queries statistics of a DBserver}
/// @RESTHEADER{GET /_admin/clusterStatistics, Queries statistics of DBserver}
///
/// @RESTQUERYPARAMETERS
///
@ -593,6 +602,7 @@ actions.defineHttp({
/// ID of a DBserver
///
/// @RESTRETURNCODE{403} server is not a coordinator.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({

View File

@ -42,10 +42,10 @@ var internal = require("internal");
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_api_endpoint
/// @startDocuBlock JSF_get_api_endpoint
/// @brief returns a list of all endpoints
///
/// @RESTHEADER{GET /_api/endpoint,returns a list of all endpoints}
/// @RESTHEADER{GET /_api/endpoint, Return list of all endpoints}
///
/// @RESTDESCRIPTION
/// Returns a list of all configured endpoints the server is listening on. For
@ -62,7 +62,7 @@ var internal = require("internal");
/// when an incoming request does not specify a database name in the request
/// explicitly.
///
/// Note: retrieving the list of all endpoints is allowed in the system database
/// **Note**: retrieving the list of all endpoints is allowed in the system database
/// only. Calling this action in any other database will make the server return
/// an error.
///
@ -75,9 +75,9 @@ var internal = require("internal");
/// is returned if the action is not carried out in the system database.
///
/// @RESTRETURNCODE{405}
/// The server will respond with `HTTP 405` if an unsupported HTTP method is used.
/// The server will respond with *HTTP 405* if an unsupported HTTP method is used.
///
/// *Examples*
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestEndpointGet}
/// var url = "/_api/endpoint";
@ -95,13 +95,14 @@ var internal = require("internal");
/// logJsonResponse(response);
/// curlRequest('DELETE', url + '/' + encodeURIComponent(endpoint));
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_post_api_endpoint
/// @startDocuBlock JSF_post_api_endpoint
/// @brief connects a new endpoint or reconfigures an existing endpoint
///
/// @RESTHEADER{POST /_api/endpoint,adds a new endpoint or reconfigures an existing endpoint}
/// @RESTHEADER{POST /_api/endpoint, Add new endpoint or reconfigures an existing endpoint}
///
/// @RESTBODYPARAM{description,json,required}
/// A JSON object describing the endpoint.
@ -109,26 +110,26 @@ var internal = require("internal");
/// @RESTDESCRIPTION
/// The request body must be JSON hash with the following attributes:
///
/// - `endpoint`: the endpoint specification, e.g. `tcp://127.0.0.1:8530`
/// - *endpoint*: the endpoint specification, e.g. *tcp://127.0.0.1:8530*
///
/// - `databases`: a list of database names the endpoint is responsible for.
/// - *databases*: a list of database names the endpoint is responsible for.
///
/// If `databases` is an empty list, all databases present in the server will
/// become accessible via the endpoint, with the `_system` database being the
/// If *databases* is an empty list, all databases present in the server will
/// become accessible via the endpoint, with the *_system* database being the
/// default database.
///
/// If `databases` is non-empty, only the specified databases will become
/// available via the endpoint. The first database name in the `databases`
/// If *databases* is non-empty, only the specified databases will become
/// available via the endpoint. The first database name in the *databases*
/// list will also become the default database for the endpoint. The default
/// database will always be used if a request coming in on the endpoint does
/// not specify the database name explicitly.
///
/// Note: adding or reconfiguring endpoints is allowed in the system database
/// **Note**: adding or reconfiguring endpoints is allowed in the system database
/// only. Calling this action in any other database will make the server
/// return an error.
///
/// Adding SSL endpoints at runtime is only supported if the server was started
/// with SSL properly configured (e.g. `--server.keyfile` must have been set).
/// with SSL properly configured (e.g. *--server.keyfile* must have been set).
///
/// @RESTRETURNCODES
///
@ -140,11 +141,11 @@ var internal = require("internal");
/// in the system database.
///
/// @RESTRETURNCODE{405}
/// The server will respond with `HTTP 405` if an unsupported HTTP method is used.
/// The server will respond with *HTTP 405* if an unsupported HTTP method is used.
///
/// *Examples*
/// Adding an endpoint `tcp://127.0.0.1:8532` with two mapped databases
/// (`mydb1` and `mydb2`). `mydb1` will become the default database for the
/// @EXAMPLES
/// Adding an endpoint *tcp://127.0.0.1:8532* with two mapped databases
/// (*mydb1* and *mydb2*). *mydb1* will become the default database for the
/// endpoint.
///
/// @EXAMPLE_ARANGOSH_RUN{RestEndpointPostOne}
@ -162,8 +163,8 @@ var internal = require("internal");
/// curlRequest('DELETE', url + '/' + encodeURIComponent(endpoint));
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Adding an endpoint `tcp://127.0.0.1:8533` with no database names specified.
/// This will allow access to all databases on this endpoint. The `_system`
/// Adding an endpoint *tcp://127.0.0.1:8533* with no database names specified.
/// This will allow access to all databases on this endpoint. The *_system*
/// database will become the default database for requests that come in on this
/// endpoint and do not specify the database name explicitly.
///
@ -182,9 +183,9 @@ var internal = require("internal");
/// curlRequest('DELETE', url + '/' + encodeURIComponent(endpoint));
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Adding an endpoint `tcp://127.0.0.1:8533` without any databases first,
/// and then updating the databases for the endpoint to `testdb1`, `testdb2`, and
/// `testdb3`.
/// Adding an endpoint *tcp://127.0.0.1:8533* without any databases first,
/// and then updating the databases for the endpoint to *testdb1*, *testdb2*, and
/// *testdb3*.
///
/// @EXAMPLE_ARANGOSH_RUN{RestEndpointPostChange}
/// var url = "/_api/endpoint";
@ -207,24 +208,25 @@ var internal = require("internal");
/// logJsonResponse(response);
/// curlRequest('DELETE', url + '/' + encodeURIComponent(endpoint));
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_delete_api_endpoint
/// @startDocuBlock JSF_delete_api_endpoint
/// @brief disconnects an existing endpoint
///
/// @RESTHEADER{DELETE /_api/endpoint/{endpoint},deletes and disconnects an existing endpoint}
/// @RESTHEADER{DELETE /_api/endpoint/{endpoint}, Delete and disconnects an existing endpoint}
///
/// @RESTURLPARAMETERS
///
/// @RESTURLPARAM{endpoint,string,required}
/// The endpoint to delete, e.g. `tcp://127.0.0.1:8529`.
/// The endpoint to delete, e.g. *tcp://127.0.0.1:8529*.
///
/// @RESTDESCRIPTION
/// This operation deletes an existing endpoint from the list of all endpoints,
/// and makes the server stop listening on the endpoint.
///
/// Note: deleting and disconnecting an endpoint is allowed in the system
/// **Note**: deleting and disconnecting an endpoint is allowed in the system
/// database only. Calling this action in any other database will make the server
/// return an error.
///
@ -244,9 +246,9 @@ var internal = require("internal");
/// is returned if the endpoint is not found.
///
/// @RESTRETURNCODE{405}
/// The server will respond with `HTTP 405` if an unsupported HTTP method is used.
/// The server will respond with *HTTP 405* if an unsupported HTTP method is used.
///
/// *Examples*
/// @EXAMPLES
///
/// Deleting an existing endpoint
///
@ -276,6 +278,7 @@ var internal = require("internal");
///
/// logJsonResponse(response);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({

View File

@ -70,27 +70,28 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_server_role
/// @startDocuBlock JSF_get_admin_server_role
/// @brief returns the role of a server in a cluster
///
/// @RESTHEADER{GET /_admin/server/role,returns the role of a server in a cluster}
/// @RESTHEADER{GET /_admin/server/role, Return role of a server in a cluster}
///
/// @RESTDESCRIPTION
///
/// Returns the role of a server in a cluster.
/// The role is returned in the `role` attribute of the result.
/// Possible return values for `role` are:
/// - `COORDINATOR`: the server is a coordinator in a cluster
/// - `PRIMARY`: the server is a primary database server in a cluster
/// - `SECONDARY`: the server is a secondary database server in a cluster
/// - `UNDEFINED`: in a cluster, `UNDEFINED` is returned if the server role cannot be
/// determined. On a single server, `UNDEFINED` is the only possible return
/// The role is returned in the *role* attribute of the result.
/// Possible return values for *role* are:
/// - *COORDINATOR*: the server is a coordinator in a cluster
/// - *PRIMARY*: the server is a primary database server in a cluster
/// - *SECONDARY*: the server is a secondary database server in a cluster
/// - *UNDEFINED*: in a cluster, *UNDEFINED* is returned if the server role cannot be
/// determined. On a single server, *UNDEFINED* is the only possible return
/// value.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Is returned in all cases.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -187,20 +188,20 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_routing_reloads
/// @startDocuBlock JSF_get_admin_routing_reloads
/// @brief reloads the routing information
///
/// @RESTHEADER{POST /_admin/routing/reload,reloads the routing collection}
/// @RESTHEADER{POST /_admin/routing/reload, Reload routing collection}
///
/// @RESTDESCRIPTION
///
/// Reloads the routing information from the collection `routing`.
/// Reloads the routing information from the collection *routing*.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Routing information was reloaded successfully.
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -230,21 +231,21 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_modules_flush
/// @startDocuBlock JSF_get_admin_modules_flush
/// @brief flushes the modules cache
///
/// @RESTHEADER{POST /_admin/modules/flush,flushs the module cache}
/// @RESTHEADER{POST /_admin/modules/flush, Flush module cache}
///
/// @RESTDESCRIPTION
///
/// The call flushes the modules cache on the server. See `JSModulesCache`
/// The call flushes the modules cache on the server. See *JSModulesCache*
/// for details about this cache.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Module cache was flushed successfully.
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -260,21 +261,21 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_time
/// @startDocuBlock JSF_get_admin_time
/// @brief returns the system time
///
/// @RESTHEADER{GET /_admin/time,returns the system time}
/// @RESTHEADER{GET /_admin/time, Return system time}
///
/// @RESTDESCRIPTION
///
/// The call returns an object with the attribute `time`. This contains the
/// The call returns an object with the attribute *time*. This contains the
/// current system time as a Unix timestamp with microsecond precision.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Time was returned successfully.
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -288,21 +289,21 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_sleep
/// @startDocuBlock JSF_get_admin_sleep
/// @brief sleeps, this is useful for timeout tests
///
/// @RESTHEADER{GET /_admin/sleep?duration=5,sleeps for 5 seconds}
/// @RESTHEADER{GET /_admin/sleep?duration=5, Sleep for 5 seconds}
///
/// @RESTDESCRIPTION
///
/// The call returns an object with the attribute `duration`. This takes
/// The call returns an object with the attribute *duration*. This takes
/// as many seconds as the duration argument says.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Sleep was conducted successfully.
///
/// @DendocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -321,26 +322,26 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_echo
/// @startDocuBlock JSF_get_admin_echo
/// @brief returns the request
///
/// @RESTHEADER{GET /_admin/echo,returns the current request}
/// @RESTHEADER{GET /_admin/echo, Return current request}
///
/// @RESTDESCRIPTION
///
/// The call returns an object with the following attributes:
///
/// - `headers`: a list of HTTP headers received
/// - *headers*: a list of HTTP headers received
///
/// - `requestType`: the HTTP request method (e.g. GET)
/// - *requestType*: the HTTP request method (e.g. GET)
///
/// - `parameters`: list of URL parameters received
/// - *parameters*: list of URL parameters received
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Echo was returned successfully.
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -356,30 +357,30 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_statistics
/// @startDocuBlock JSF_get_admin_statistics
/// @brief returns system status information for the server
///
/// @RESTHEADER{GET /_admin/statistics,reads the statistics}
/// @RESTHEADER{GET /_admin/statistics, Read the statistics}
///
/// @RESTDESCRIPTION
///
/// Returns the statistics information. The returned object contains the
/// statistics figures grouped together according to the description returned by
/// `_admin/statistics-description`. For instance, to access a figure `userTime`
/// from the group `system`, you first select the sub-object describing the
/// group stored in `system` and in that sub-object the value for `userTime` is
/// *_admin/statistics-description*. For instance, to access a figure *userTime*
/// from the group *system*, you first select the sub-object describing the
/// group stored in *system* and in that sub-object the value for *userTime* is
/// stored in the attribute of the same name.
///
/// In case of a distribution, the returned object contains the total count in
/// `count` and the distribution list in `counts`. The sum (or total) of the
/// individual values is returned in `sum`.
/// *count* and the distribution list in *counts*. The sum (or total) of the
/// individual values is returned in *sum*.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Statistics were returned successfully.
///
/// *Examples*
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestAdminStatistics1}
/// var url = "/_admin/statistics";
@ -389,6 +390,7 @@ actions.defineHttp({
///
/// logJsonResponse(response);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -416,39 +418,39 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_statistics_description
/// @startDocuBlock JSF_get_admin_statistics_description
/// @brief returns statistics description
///
/// @RESTHEADER{GET /_admin/statistics-description,statistics description}
/// @RESTHEADER{GET /_admin/statistics-description, Statistics description}
///
/// @RESTDESCRIPTION
///
/// Returns a description of the statistics returned by `/_admin/statistics`.
/// Returns a description of the statistics returned by */_admin/statistics*.
/// The returned objects contains a list of statistics groups in the attribute
/// `groups` and a list of statistics figures in the attribute `figures`.
/// *groups* and a list of statistics figures in the attribute *figures*.
///
/// A statistics group is described by
///
/// - `group`: The identifier of the group.
/// - `name`: The name of the group.
/// - `description`: A description of the group.
/// - *group*: The identifier of the group.
/// - *name*: The name of the group.
/// - *description*: A description of the group.
///
/// A statistics figure is described by
///
/// - `group`: The identifier of the group to which this figure belongs.
/// - `identifier`: The identifier of the figure. It is unique within the group.
/// - `name`: The name of the figure.
/// - `description`: A description of the figure.
/// - `type`: Either `current`, `accumulated`, or `distribution`.
/// - `cuts`: The distribution vector.
/// - `units`: Units in which the figure is measured.
/// - *group*: The identifier of the group to which this figure belongs.
/// - *identifier*: The identifier of the figure. It is unique within the group.
/// - *name*: The name of the figure.
/// - *description*: A description of the figure.
/// - *type*: Either *current*, *accumulated*, or *distribution*.
/// - *cuts*: The distribution vector.
/// - *units*: Units in which the figure is measured.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Description was returned successfully.
///
/// *Examples*
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestAdminStatisticsDescription1}
/// var url = "/_admin/statistics-description";
@ -458,6 +460,7 @@ actions.defineHttp({
///
/// logJsonResponse(response);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -786,10 +789,10 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_post_admin_test
/// @startDocuBlock JSF_post_admin_test
/// @brief executes one or multiple tests on the server
///
/// @RESTHEADER{POST /_admin/test,runs tests on the server}
/// @RESTHEADER{POST /_admin/test, Runs tests on the server}
///
/// @RESTBODYPARAM{body,javascript,required}
/// A JSON body containing an attribute "tests" which lists the files
@ -801,6 +804,7 @@ actions.defineHttp({
/// test results. The object has an attribute "error" which states whether
/// any error occurred. The object also has an attribute "passed" which
/// indicates which tests passed and which did not.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -844,10 +848,10 @@ actions.defineHttp({
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_get_admin_execute
/// @startDocuBlock JSF_get_admin_execute
/// @brief executes a JavaScript program on the server
///
/// @RESTHEADER{POST /_admin/execute,executes a program}
/// @RESTHEADER{POST /_admin/execute, Execute program}
///
/// @RESTBODYPARAM{body,javascript,required}
/// The body to be executed.
@ -855,12 +859,13 @@ actions.defineHttp({
/// @RESTDESCRIPTION
///
/// Executes the javascript code in the body on the server as the body
/// of a function with no arguments. If you have a `return` statement
/// of a function with no arguments. If you have a *return* statement
/// then the return value you produce will be returned as content type
/// `application/json`. If the parameter `returnAsJSON` is set to
/// `true`, the result will be a JSON object describing the return value
/// *application/json*. If the parameter *returnAsJSON* is set to
/// *true*, the result will be a JSON object describing the return value
/// directly, otherwise a string produced by JSON.stringify will be
/// returned.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({

View File

@ -40,6 +40,34 @@ var users = require("org/arangodb/users");
/// @brief fetches a user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_api_user_fetch
///
/// @RESTHEADER{GET /_api/user/{user}, Fetch User}
///
/// @RESTDESCRIPTION
///
/// Fetches data about the specified user.
///
/// The call will return a JSON document with at least the following attributes on success:
///
/// * *user*: The name of the user as a string.
/// * *active*: An optional flag that specifies whether the user is active.
/// * *extra*: An optional JSON object with arbitrary extra data about the user.
/// * *changePassword*: An optional flag that specifies whether the user must
/// change the password or not.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// The user was found
///
/// @RESTRETURNCODE{404}
/// The user with user does not exist
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
function get_api_user (req, res) {
if (req.suffix.length === 0) {
actions.resultOk(req, res, actions.HTTP_OK, { result: users.all() });
@ -70,6 +98,55 @@ function get_api_user (req, res) {
/// @brief creates a new user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_api_user_create
///
/// @RESTHEADER{POST /_api/user, Create User}
///
/// @RESTDESCRIPTION
///
/// The following data need to be passed in a JSON representation in the body
/// of the POST request:
///
/// * *user*: The name of the user as a string. This is mandatory
/// * *passwd*: The user password as a string. If no password is specified,
/// the empty string will be used
/// * *active*: An optional flag that specifies whether the user is active.
/// If not specified, this will default to true
/// * *extra*: An optional JSON object with arbitrary extra data about the user
/// * *changePassword*: An optional flag that specifies whethers the user must
/// change the password or not. If not specified, this will default to false
///
/// If set to true, the only operations allowed are PUT /_api/user or PATCH /_api/user.
/// All other operations will result in a HTTP 403.
/// If the user can be added by the server, the server will respond with HTTP 201.
/// In case of success, the returned JSON object has the following properties:
///
/// * *error*: Boolean flag to indicate that an error occurred (false in this case)
/// * *code*: The HTTP status code
///
/// If the JSON representation is malformed or mandatory data is missing from the request,
/// the server will respond with HTTP 400.
///
/// The body of the response will contain a JSON object with additional error details.
/// The object has the following attributes:
///
/// * *error*: Boolean flag to indicate that an error occurred (true in this case)
/// * *code*: The HTTP status code
/// * *errorNum*: The server error number
/// * *errorMessage*: A descriptive error message
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// Returned if the user can be added by the server
///
/// @RESTRETURNCODE{400}
/// If the JSON representation is malformed or mandatory data is missing from the request.
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
function post_api_user (req, res) {
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
@ -120,6 +197,58 @@ function post_api_user (req, res) {
/// @brief replaces an existing user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_api_user_replace
///
/// @RESTHEADER{PUT /_api/user/{user}, Replace User}
///
/// @RESTDESCRIPTION
///
/// Replaces the data of an existing user. The name of an existing user must be specified in user.
///
/// The following data can to be passed in a JSON representation in the body of the POST request:
///
/// * *passwd*: The user password as a string. Specifying a password is mandatory,
/// but the empty string is allowed for passwords
/// * *active*: An optional flag that specifies whether the user is active.
/// If not specified, this will default to true
/// * *extra*: An optional JSON object with arbitrary extra data about the user
/// * *changePassword*: An optional flag that specifies whether the user must change
/// the password or not. If not specified, this will default to false
///
/// If the user can be replaced by the server, the server will respond with HTTP 200.
///
/// In case of success, the returned JSON object has the following properties:
///
/// * *error*: Boolean flag to indicate that an error occurred (false in this case)
/// * *code*: The HTTP status code
///
/// If the JSON representation is malformed or mandatory data is missing from the request,
/// the server will respond with HTTP 400. If the specified user does not exist,
/// the server will respond with HTTP 404.
///
/// The body of the response will contain a JSON object with additional
/// error details. The object has the following attributes:
///
/// * *error*: Boolean flag to indicate that an error occurred (true in this case)
/// * *code*: The HTTP status code
/// * *errorNum*: The server error number
/// * *errorMessage*: A descriptive error message
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Is returned if the user data can be replaced by the server
///
/// @RESTRETURNCODE{400}
/// The JSON representation is malformed or mandatory data is missing from the request
///
/// @RESTRETURNCODE{404}
/// The specified user does not exist
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
function put_api_user (req, res) {
if (req.suffix.length !== 1) {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
@ -154,6 +283,61 @@ function put_api_user (req, res) {
/// @brief partially updates an existing user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_api_user_update
///
/// @RESTHEADER{PATCH /_api/user/{user}, Update User}
///
/// @RESTDESCRIPTION
///
/// Partially updates the data of an existing user. The name of an existing
/// user must be specified in user.
///
/// The following data can be passed in a JSON representation in the body of the
/// POST request:
///
/// * *passwd*: The user password as a string. Specifying a password is optional.
/// If not specified, the previously existing value will not be modified.
/// * *active*: An optional flag that specifies whether the user is active.
/// If not specified, the previously existing value will not be modified.
/// * *extra*: An optional JSON object with arbitrary extra data about the user.
/// If not specified, the previously existing value will not be modified.
/// * *changePassword*: An optional flag that specifies whether the user must change
/// the password or not. If not specified, the previously existing value will not be modified.
///
/// If the user can be updated by the server, the server will respond with HTTP 200.
///
/// In case of success, the returned JSON object has the following properties:
///
/// * *error*: Boolean flag to indicate that an error occurred (false in this case)
/// * *code*: The HTTP status code
///
/// If the JSON representation is malformed or mandatory data is missing from the request,
/// the server will respond with HTTP 400. If the specified user does not exist,
/// the server will respond with HTTP 404.
///
/// The body of the response will contain a JSON object with additional error details.
/// The object has the following attributes:
///
/// * *error*: Boolean flag to indicate that an error occurred (true in this case)
/// * *code*: The HTTP status code
/// * *errorNum*: The server error number
/// * *errorMessage*: A descriptive error message
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// Is returned if the user data can be replaced by the server
///
/// @RESTRETURNCODE{400}
/// The JSON representation is malformed or mandatory data is missing from the request
///
/// @RESTRETURNCODE{404}
/// The specified user does not exist
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
function patch_api_user (req, res) {
if (req.suffix.length !== 1) {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
@ -187,6 +371,42 @@ function patch_api_user (req, res) {
/// @brief removes an existing user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_api_user_delete
///
/// @RESTHEADER{DELETE /_api/user/{user}, Remove User}
///
/// @RESTDESCRIPTION
///
/// Removes an existing user, identified by user.
///
/// If the user can be removed, the server will respond with HTTP 202.
/// In case of success, the returned JSON object has the following properties:
///
/// * *error*: Boolean flag to indicate that an error occurred (false in this case)
/// * *code*: The HTTP status code
///
/// If the specified user does not exist, the server will respond with HTTP 404.
///
/// The body of the response will contain a JSON object with additional error details.
/// The object has the following attributes:
///
/// * *error*: Boolean flag to indicate that an error occurred (true in this case)
/// * *code*: The HTTP status code
/// * *errorNum*: The server error number
/// * *errorMessage*: A descriptive error message
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{202}
/// Is returned if the user was removed by the server
///
/// @RESTRETURNCODE{404}
/// The specified user does not exist
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
function delete_api_user (req, res) {
if (req.suffix.length !== 1) {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);

View File

@ -37,11 +37,11 @@ var FoxxController = require("org/arangodb/foxx").Controller,
underscore = require("underscore"),
notifications = require("org/arangodb/configuration").notifications,
db = require("internal").db;
var foxxes = new (require("lib/foxxes").Foxxes)();
var FoxxManager = require("org/arangodb/foxx/manager");
var docus = new (require("lib/swagger").Swagger)();
controller.get("/whoAmI", function(req, res) {
res.json({
name: req.user
@ -96,8 +96,9 @@ controller.put("/foxxes/install", function (req, res) {
var content = JSON.parse(req.requestBody),
name = content.name,
mount = content.mount,
version = content.version;
res.json(foxxes.install(name, mount, version));
version = content.version,
options = content.options;
res.json(foxxes.install(name, mount, version, options));
}).summary("Installs a new foxx")
.notes("This function is used to install a new foxx.");
@ -229,7 +230,7 @@ controller.del("/foxxes/:key", function (req, res) {
/** Update a Foxx
*
* Update the Foxx with the given information.
*/
*/
controller.put("/foxxes/:key", function (req, res) {
var content = JSON.parse(req.requestBody),
@ -247,9 +248,9 @@ controller.put("/foxxes/:key", function (req, res) {
allowMultiple: false
}).summary("Update a foxx.")
.notes("Used to either activate/deactivate a foxx, or change the mount point.");
/** Get the thubmail of a Foxx
*
*
* Request the Thumbnail stored for a Foxx
*/
@ -269,7 +270,7 @@ controller.get("/foxxes/thumbnail/:app", function (req, res) {
allowMultiple: false
}).summary("Get the thumbnail of a foxx.")
.notes("Used to request the thumbnail of the given Foxx in order to display it on the screen.");
/** List all Foxxes
*
* Get a List of all Foxxes available and running
@ -279,7 +280,7 @@ controller.get('/foxxes', function (req, res) {
res.json(foxxes.viewAll());
}).summary("List of all foxxes.")
.notes("This function simply returns the list of all running foxxes");
/** List available Documentation
*
* Get the list of all running Foxxes with links to their documentation
@ -303,7 +304,7 @@ controller.get("/docu/:key",function (req, res) {
}).summary("List documentation of all foxxes.")
.notes("This function simply returns one specific"
+ " foxx and supplies the paths for the swagger documentation");
/** Subroutes for API Documentation
*
* Get the Elements of the API Documentation subroutes
@ -345,7 +346,7 @@ controller.put('/foxx/move/:key', function(req, res) {
})
.summary("Move one foxx to another moint point")
.notes ("This function moves one installed foxx"
+ " to a given mount point.");
+ " to a given mount point.");
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE

View File

@ -69,6 +69,7 @@
"ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS" : { "code" : 1108, "message" : "cannot create/rename collection because directory already exists" },
"ERROR_ARANGO_MSYNC_FAILED" : { "code" : 1109, "message" : "msync failed" },
"ERROR_ARANGO_DATADIR_UNLOCKABLE" : { "code" : 1110, "message" : "cannot lock database directory" },
"ERROR_ARANGO_SYNC_TIMEOUT" : { "code" : 1111, "message" : "sync timeout" },
"ERROR_ARANGO_CONFLICT" : { "code" : 1200, "message" : "conflict" },
"ERROR_ARANGO_DATADIR_INVALID" : { "code" : 1201, "message" : "invalid database directory" },
"ERROR_ARANGO_DOCUMENT_NOT_FOUND" : { "code" : 1202, "message" : "document not found" },

View File

@ -3876,14 +3876,11 @@ var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollectio
var graphObj = _graph(graph._key);
var eDs = graph.edgeDefinitions;
var gotAHit = false;
require("internal").print("Graph: " + graph._key);
//replace edgeDefintion
eDs.forEach(
function(eD, id) {
if(eD.collection === edgeDefinition.collection) {
require("internal").print("eD.collection");
require("internal").print(eD.collection);
gotAHit = true;
oldCollections = _.union(oldCollections, eD.from);
oldCollections = _.union(oldCollections, eD.to);
@ -3921,11 +3918,7 @@ var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollectio
//move unused collections to orphanage
possibleOrphans.forEach(
function(po) {
require("internal").print(po);
require("internal").print(graphCollections.indexOf(po));
require("internal").print(gotAHit);
if (graphCollections.indexOf(po) === -1 && gotAHit) {
require("internal").print("B I N D R I N ! ! !");
delete graphObj.__vertexCollections[po];
graphObj._addVertexCollection(po);
}

View File

@ -135,7 +135,7 @@ applier.start = function (initialTick) {
/// @brief stops the replication applier
////////////////////////////////////////////////////////////////////////////////
applier.stop = function () {
applier.stop = applier.shutdown = function () {
'use strict';
var db = internal.db;

View File

@ -1,23 +1,31 @@
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true regexp: true*/
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true regexp: true, es5: true*/
/*global Backbone, $, window, _, templateEngine, alert*/
(function() {
"use strict";
function splitSnakeCase(snakeCase) {
var str = snakeCase.replace(/([a-z])([A-Z])/g, "$1 $3");
str = str.replace(/([a-z])([0-9])/gi, "$1 $3");
str = str.replace(/_+/, " ");
return _.map(str.split(/\s+/), function(s) {
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}).join(" ");
}
window.FoxxInstalledView = Backbone.View.extend({
tagName: 'div',
tagName: "div",
className: "tile",
template: templateEngine.createTemplate("foxxInstalledView.ejs"),
events: {
//'click .install': 'installDialog',
//'click .purge': 'removeDialog',
'click .icon_arangodb_settings2': 'infoDialog'
//"click .install": "installDialog",
//"click .purge": "removeDialog",
"click .icon_arangodb_settings3": "infoDialog"
},
renderVersion: function(e) {
var name = this.model.get("name"),
selectOptions = this.model.get("selectOptions"),
versionToRender = $('#'+name+'Select').val();
versionToRender = $("#"+name+"Select").val();
this.model.set("activeVersion", versionToRender);
var toRender = this.model.collection.findWhere({
@ -28,7 +36,7 @@
},
initialize: function(){
_.bindAll(this, 'render');
_.bindAll(this, "render");
var buttonConfig = [
window.modalView.createSuccessButton(
"Install", this.install.bind(this)
@ -192,6 +200,32 @@
"mount-path",
true
));
var configs = this.model.get("manifest").configuration;
if (configs && _.keys(configs).length) {
_.each(_.keys(configs), function(key) {
var opt = configs[key];
var prettyKey = opt.label || splitSnakeCase(key);
if (opt.type === "boolean") {
list.push(window.modalView.createCheckboxEntry(
"foxx_configs_" + key,
prettyKey,
true,
opt.description,
opt.default
));
} else {
list.push(window.modalView.createTextEntry(
"foxx_configs_" + key,
prettyKey,
opt.default || "",
opt.description,
splitSnakeCase(key).toLowerCase().replace(/\s+/g, "-"),
opt.default === undefined
));
}
});
}
if (this.model.get("selectOptions")) {
list.push(window.modalView.createSelectEntry(
"foxx-version",
@ -337,7 +371,7 @@
installDialog: function(event) {
var currentVersion = $('.modalSelect').val();
var currentVersion = $(".modalSelect").val();
window.modalView.hide();
event.stopPropagation();
@ -348,11 +382,11 @@
update: function() {
var url = this.model.get("gitUrl"),
version = 'master',
name = '',
version = "master",
name = "",
result;
if (url === undefined || url === '') {
if (url === undefined || url === "") {
// if no git is defined
return;
}
@ -381,6 +415,57 @@
version = this.model.get("version");
}
var cfg = {};
var opts = this.model.get("manifest").configuration;
if (opts && _.keys(opts).length) {
try {
_.each(_.keys(opts), function(key) {
var opt = opts[key];
var $el = $("#foxx_configs_" + key);
var val = $el.val();
if (opt.type === "boolean") {
cfg[key] = $el.is(":checked");
return;
}
if (val === "" && !opt.hasOwnProperty("default")) {
throw new SyntaxError(
"Must specify value for field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
if (opt.type === "number") {
cfg[key] = parseFloat(val);
} else if (opt.type === "integer") {
cfg[key] = parseInt(val, 10);
} else {
cfg[key] = val;
return;
}
if (_.isNaN(cfg[key])) {
throw new SyntaxError(
"Invalid value for field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
if (opt.type === "integer" && cfg[key] !== Math.floor(parseFloat(val))) {
throw new SyntaxError(
"Expected non-decimal value in field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
});
} catch (err) {
if (err instanceof SyntaxError) {
alert(err.message);
return false;
}
throw err;
}
}
//find correct app install version
var toCreate = this.model.collection.findWhere({
name: self.model.get("name"),
@ -391,7 +476,10 @@
toCreate.collection.create({
mount: mountPoint,
name: toCreate.get("name"),
version: toCreate.get("version")
version: toCreate.get("version"),
options: {
configuration: cfg
}
},
{
success: function() {
@ -401,8 +489,7 @@
error: function(e, info) {
if (info.responseText.indexOf("already used by") > -1) {
alert("Mount-Path already in use.");
}
else if (info.responseText.indexOf("app is not defined") > -1) {
} else if (info.responseText.indexOf("app is not defined") > -1) {
//temp ignore this message, fix needs to be server-side
window.modalView.hide();
self.appsView.reload();
@ -414,7 +501,7 @@
},
selectSpecificVersion: function(version) {
$('.modalSelect').val(version);
$(".modalSelect").val(version);
},
selectHighestVersion: function() {
@ -427,7 +514,7 @@
}
});
$('.modalSelect').val(toRender);
$(".modalSelect").val(toRender);
},
render: function(){

File diff suppressed because one or more lines are too long

View File

@ -67,6 +67,15 @@ describe("Arango Helper", function () {
expect(window.scrollBy).toHaveBeenCalledWith(0, 180);
});
it("check showHotkeysModal function", function() {
window.modalView = new window.ModalView();
spyOn(window.modalView, "show");
window.arangoHelper.allHotkeys = [1];
arangoHelper.hotkeysFunctions.showHotkeysModal();
expect(window.modalView.show).toHaveBeenCalledWith(
"modalHotkeys.ejs", "Keyboard Shortcuts", [], [1]);
});
it("check enabling keyboard hotkeys scrollUp function", function() {
spyOn(window, "scrollBy");
arangoHelper.hotkeysFunctions.scrollUp();

View File

@ -21,6 +21,7 @@
collectionsViewDummy,
databaseDummy,
userBarDummy,
graphManagementView,
documentViewDummy,
statisticsDescriptionCollectionDummy,
statisticsCollectionDummy,
@ -171,6 +172,11 @@
throw "should be a spy";
}
};
graphManagementView = {
render: function () {
throw "should be a spy";
}
};
documentsViewDummy = {
render: function () {
throw "should be a spy";
@ -184,6 +190,7 @@
};
spyOn(window, "DocumentsView").andReturn(documentsViewDummy);
spyOn(window, "GraphManagementView").andReturn(graphManagementView);
spyOn(window, "DocumentView").andReturn(documentViewDummy);
spyOn(window, "arangoCollections").andReturn(storeDummy);
spyOn(window, "ArangoUsers").andReturn(sessionDummy);
@ -263,6 +270,24 @@
expect(window.CurrentDatabase).toHaveBeenCalled();
expect(fakeDB.fetch).toHaveBeenCalled();
});
it("should handle resize", function () {
r.dashboardView = {
resize : function () {
}
};
r.graphManagementView = {
handleResize : function () {
}
};
spyOn(r.dashboardView , "resize");
spyOn(r.graphManagementView , "handleResize");
r.handleResize();
expect(r.dashboardView.resize).toHaveBeenCalled();
expect(r.graphManagementView.handleResize).toHaveBeenCalled();
});
});
describe("navigation", function () {
@ -410,6 +435,25 @@
});
it("should route to graphManagement", function () {
spyOn(graphManagementView, "render");
simpleNavigationCheck(
{
url: "graph"
},
"GraphManagementView",
"graphviewer-menu",
{
collection: new window.GraphCollection(),
collectionCollection: storeDummy
},
{
},
true
);
});
it("should route to document", function () {
var colid = 5,
docid = 6;

View File

@ -307,6 +307,7 @@
/// assert(response.code === 400);
///
/// logJsonResponse(response);
/// db._drop("male");
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// @endDocuBlock
@ -507,6 +508,7 @@
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop("relation");
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////

View File

@ -134,7 +134,7 @@ applier.start = function (initialTick) {
/// @brief stops the replication applier
////////////////////////////////////////////////////////////////////////////////
applier.stop = function () {
applier.stop = applier.shutdown = function () {
'use strict';
var db = internal.db;

View File

@ -69,6 +69,7 @@
"ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS" : { "code" : 1108, "message" : "cannot create/rename collection because directory already exists" },
"ERROR_ARANGO_MSYNC_FAILED" : { "code" : 1109, "message" : "msync failed" },
"ERROR_ARANGO_DATADIR_UNLOCKABLE" : { "code" : 1110, "message" : "cannot lock database directory" },
"ERROR_ARANGO_SYNC_TIMEOUT" : { "code" : 1111, "message" : "sync timeout" },
"ERROR_ARANGO_CONFLICT" : { "code" : 1200, "message" : "conflict" },
"ERROR_ARANGO_DATADIR_INVALID" : { "code" : 1201, "message" : "invalid database directory" },
"ERROR_ARANGO_DOCUMENT_NOT_FOUND" : { "code" : 1202, "message" : "document not found" },

View File

@ -3920,11 +3920,7 @@ var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollectio
//move unused collections to orphanage
possibleOrphans.forEach(
function(po) {
require("internal").print(po);
require("internal").print(graphCollections.indexOf(po));
require("internal").print(gotAHit);
if (graphCollections.indexOf(po) === -1 && gotAHit) {
require("internal").print("B I N D R I N ! ! !");
delete graphObj.__vertexCollections[po];
graphObj._addVertexCollection(po);
}

View File

@ -396,7 +396,7 @@ function createLocalCollections (plannedCollections) {
var ourselves = ArangoServerState.id();
var createCollectionAgency = function (database, shard, payload) {
ArangoAgency.set("Current/Collections/" + database + "/" + payload.id + "/" + shard,
ArangoAgency.set("Current/Collections/" + database + "/" + payload.planId + "/" + shard,
payload);
};
@ -429,6 +429,9 @@ function createLocalCollections (plannedCollections) {
var shards = payload.shards;
var shard;
payload.planId = payload.id;
delete payload.id; // must not actually set it here
for (shard in shards) {
if (shards.hasOwnProperty(shard)) {
if (shards[shard] === ourselves) {
@ -436,13 +439,11 @@ function createLocalCollections (plannedCollections) {
if (! localCollections.hasOwnProperty(shard)) {
// must create this shard
payload.planId = payload.id;
console.info("creating local shard '%s/%s' for central '%s/%s'",
database,
shard,
database,
payload.id);
payload.planId);
try {
if (payload.type === ArangoCollection.TYPE_EDGE) {
@ -464,7 +465,7 @@ function createLocalCollections (plannedCollections) {
database,
shard,
database,
payload.id,
payload.planId,
JSON.stringify(err2));
}

View File

@ -966,6 +966,10 @@ function checkConfiguration (app, options) {
var expectedType = expected[att].type;
var actualType = Array.isArray(value) ? "array" : typeof(value);
if (expectedType === "integer" && actualType === "number") {
actualType = (value === Math.floor(value) ? "integer" : "number");
}
if (actualType !== expectedType) {
throw new Error(
"configuration for '" + app._manifest.name + "' uses "
@ -979,7 +983,7 @@ function checkConfiguration (app, options) {
else {
throw new Error(
"configuration for '" + app._manifest.name + "' is "
+ "missing a value for attribute '" + att + "'");
+ "missing a value for attribute '" + att + "'");
}
}
}
@ -988,8 +992,8 @@ function checkConfiguration (app, options) {
for (att in configuration) {
if (configuration.hasOwnProperty(att)) {
if (! expected.hasOwnProperty(att)) {
console.warn("configuration for '%s' contains an unknown attribute '%s'",
app._manifest.name,
console.warn("configuration for '%s' contains an unknown attribute '%s'",
app._manifest.name,
att);
}
}
@ -1725,14 +1729,14 @@ exports.initializeFoxx = function () {
catch (err) {
console.error("cannot initialize Foxx application: %s", String(err));
}
var aal = getStorage();
if (aal !== null) {
var systemAppPath = module.systemAppPath();
var fs = require("fs");
var apps = fs.list(systemAppPath);
var apps = fs.list(systemAppPath);
// make sure the aardvark app is always there
if (apps.indexOf("aardvark") === -1) {
@ -1746,7 +1750,7 @@ exports.initializeFoxx = function () {
if (! mount && ! fs.isDirectory(fs.join(systemAppPath, appName))) {
return;
}
try {
if (! mount) {
mount = '/_system/' + appName;

View File

@ -101,21 +101,11 @@ applier.start = function (initialTick) {
return internal.startReplicationApplier(initialTick);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief stops the replication applier
////////////////////////////////////////////////////////////////////////////////
applier.stop = function () {
'use strict';
throw "stop is not supported anymore - please use shutdown";
};
////////////////////////////////////////////////////////////////////////////////
/// @brief shuts down the replication applier
////////////////////////////////////////////////////////////////////////////////
applier.shutdown = function () {
applier.shutdown = applier.stop = function () {
'use strict';
return internal.shutdownReplicationApplier();

View File

@ -0,0 +1,74 @@
var db = require("org/arangodb").db;
var internal = require("internal");
var jsunity = require("jsunity");
function runSetup () {
internal.debugClearFailAt();
db._drop("UnitTestsRecovery");
var c = db._create("UnitTestsRecovery"), i;
for (i = 0; i < 1000; ++i) {
c.save({ _key: "test" + i, value1: "test" + i });
}
// make sure the next operations go into a separate log
internal.wal.flush(true, true);
db._drop("UnitTestsRecovery");
c = db._create("UnitTestsRecovery");
for (i = 0; i < 100; ++i) {
c.save({ _key: "test" + i, value1: i });
}
c.save({ _key: "foo" }, true);
internal.debugSegfault("crashing server");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function recoverySuite () {
jsunity.jsUnity.attachAssertions();
return {
setUp: function () {
},
tearDown: function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test whether we can restore the trx data
////////////////////////////////////////////////////////////////////////////////
testCollectionRecreate : function () {
var c = db._collection("UnitTestsRecovery"), i;
assertEqual(101, c.count());
for (i = 0; i < 100; ++i) {
assertEqual(i, c.document("test" + i).value1);
}
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
function main (argv) {
if (argv[1] === "setup") {
runSetup();
return 0;
}
else {
jsunity.run(recoverySuite);
return jsunity.done() ? 0 : 1;
}
}

View File

@ -0,0 +1,76 @@
var db = require("org/arangodb").db;
var internal = require("internal");
var jsunity = require("jsunity");
function runSetup () {
internal.debugClearFailAt();
// disable collector
internal.debugSetFailAt("CollectorThreadProcessQueuedOperations");
var c = db._create("UnitTestsRecovery"), i, j;
for (i = 0; i < 10; ++i) {
for (j = 0; j < 1000; ++j) {
c.save({ _key: "test-" + i + "-" + j, value1: "test" + i, value2: "test" + j });
}
// make sure the next operations go into a separate log
internal.wal.flush(true, false);
}
c.save({ _key: "foo" }, true);
internal.debugSegfault("crashing server");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function recoverySuite () {
jsunity.jsUnity.attachAssertions();
return {
setUp: function () {
},
tearDown: function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test whether we can restore the trx data
////////////////////////////////////////////////////////////////////////////////
testManyLogs : function () {
var c = db._collection("UnitTestsRecovery"), i, j;
assertEqual(10001, c.count());
for (i = 0; i < 10; ++i) {
for (j = 0; j < 1000; ++j) {
var doc = c.document("test-" + i + "-" + j);
assertEqual("test" + i, doc.value1);
assertEqual("test" + j, doc.value2);
}
}
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
function main (argv) {
if (argv[1] === "setup") {
runSetup();
return 0;
}
else {
jsunity.run(recoverySuite);
return jsunity.done() ? 0 : 1;
}
}

View File

@ -0,0 +1,70 @@
var db = require("org/arangodb").db;
var internal = require("internal");
var jsunity = require("jsunity");
function runSetup () {
internal.debugClearFailAt();
// disable collector
internal.debugSetFailAt("CollectorThreadProcessQueuedOperations");
db._drop("UnitTestsRecovery");
var c = db._create("UnitTestsRecovery"), i;
for (i = 0; i < 1000; ++i) {
c.save({ _key: "test" + i, value1: "test" + i });
}
// make sure the next operations go into a separate log
internal.wal.flush(true, false);
db._drop("UnitTestsRecovery");
c = db._create("UnitTestsRecovery2");
c.save({ _key: "foo" }, true);
internal.debugSegfault("crashing server");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function recoverySuite () {
jsunity.jsUnity.attachAssertions();
return {
setUp: function () {
},
tearDown: function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test whether we can restore the trx data
////////////////////////////////////////////////////////////////////////////////
testMultipleLogs : function () {
assertNull(db._collection("UnitTestsRecovery"));
assertEqual(1, db._collection("UnitTestsRecovery2").count());
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
function main (argv) {
if (argv[1] === "setup") {
runSetup();
return 0;
}
else {
jsunity.run(recoverySuite);
return jsunity.done() ? 0 : 1;
}
}

View File

@ -131,7 +131,7 @@ function walFailureSuite () {
db._drop(cn);
c = db._create(cn);
internal.wal.flush(true, false);
internal.wal.flush(true, true);
internal.wait(5);
internal.debugSetFailAt("CollectorThreadProcessQueuedOperations");
@ -142,7 +142,7 @@ function walFailureSuite () {
c.save({ _key: "test" + i, a: i });
}
internal.wal.flush(true, false);
internal.wal.flush(true, true);
c.save({ _key: "foo" });
assertEqual("foo", c.document("foo")._key);
@ -150,7 +150,7 @@ function walFailureSuite () {
internal.debugClearFailAt();
},
/*
////////////////////////////////////////////////////////////////////////////////
/// @brief test write throttling
////////////////////////////////////////////////////////////////////////////////
@ -161,7 +161,7 @@ function walFailureSuite () {
db._drop(cn);
c = db._create(cn);
internal.wal.flush(true, false);
internal.wal.flush(true, true);
internal.debugSetFailAt("CollectorThreadProcessQueuedOperations");
internal.wal.properties({ throttleWait: 1000, throttleWhenPending: 1000 });
@ -171,7 +171,7 @@ function walFailureSuite () {
c.save({ _key: "test" + i, a: i });
}
internal.wal.flush(true, false);
internal.wal.flush(true, true);
internal.wait(5);
try {
@ -185,7 +185,7 @@ function walFailureSuite () {
internal.debugClearFailAt();
assertEqual(1005, c.count());
}
*/
};
}

View File

@ -583,17 +583,6 @@
});
});
////////////////////////////////////////////////////////////////////////////////
/// @brief setupReplication
////////////////////////////////////////////////////////////////////////////////
if (! cluster.isCoordinator()) {
// set up the collection _replication
addTask("setupReplication", "setup _replication collection", function () {
return createSystemCollection("_replication", { waitForSync : false });
});
}
////////////////////////////////////////////////////////////////////////////////
/// @brief migrateAqlFunctions
////////////////////////////////////////////////////////////////////////////////
@ -696,15 +685,16 @@
// move all _api apps to _api and all system apps to system
addTask("systemAppEndpoints", "mount system apps on correct endpoints", function () {
var aal = db._collection("_aal");
var didWork = true;
db._aal.byExample(
aal.byExample(
{
type: "mount",
isSystem: true
}
).toArray().forEach(function(app) {
try {
db._aal.remove(app._key);
aal.remove(app._key);
} catch (e) {
didWork = false;
}

View File

@ -89,72 +89,74 @@ bool RestAdminLogHandler::isDirect () {
}
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_admin_modules_flush
/// @brief returns the log files
///
/// @RESTHEADER{GET /_admin/log,reads the global log from the server}
/// @RESTHEADER{GET /_admin/log, Read global log from the server}
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{upto,string,optional}
/// Returns all log entries up to log level `upto`. Note that `upto` must be:
/// - `fatal` or `0`
/// - `error` or `1`
/// - `warning` or `2`
/// - `info` or `3`
/// - `debug` or `4`
/// The default value is `info`.
/// Returns all log entries up to log level *upto*. Note that *upto* must be:
/// - *fatal* or *0*
/// - *error* or *1*
/// - *warning* or *2*
/// - *info* or *3*
/// - *debug* or *4*
/// The default value is *info*.
///
/// @RESTQUERYPARAM{level,string,optional}
/// Returns all log entries of log level `level`. Note that the URL parameters
/// `upto` and `level` are mutually exclusive.
/// Returns all log entries of log level *level*. Note that the URL parameters
/// *upto* and *level* are mutually exclusive.
///
/// @RESTQUERYPARAM{start,number,optional}
/// Returns all log entries such that their log entry identifier (`lid` value)
/// is greater or equal to `start`.
/// Returns all log entries such that their log entry identifier (*lid* value)
/// is greater or equal to *start*.
///
/// @RESTQUERYPARAM{size,number,optional}
/// Restricts the result to at most `size` log entries.
/// Restricts the result to at most *size* log entries.
///
/// @RESTQUERYPARAM{offset,number,optional}
/// Starts to return log entries skipping the first `offset` log entries. `offset`
/// and `size` can be used for pagination.
/// Starts to return log entries skipping the first *offset* log entries. *offset*
/// and *size* can be used for pagination.
///
/// @RESTQUERYPARAM{search,string,optional}
/// Only return the log entries containing the text specified in `search`.
/// Only return the log entries containing the text specified in *search*.
///
/// @RESTQUERYPARAM{sort,string,optional}
/// Sort the log entries either ascending (if `sort` is `asc`) or descending
/// (if `sort` is `desc`) according to their `lid` values. Note that the `lid`
/// imposes a chronological order. The default value is `asc`.
/// Sort the log entries either ascending (if *sort* is *asc*) or descending
/// (if *sort* is *desc*) according to their *lid* values. Note that the *lid*
/// imposes a chronological order. The default value is *asc*.
///
/// @RESTDESCRIPTION
/// Returns fatal, error, warning or info log messages from the server's global log.
/// The result is a JSON object with the following attributes:
///
/// - `lid`: a list of log entry identifiers. Each log message is uniquely
/// - *lid*: a list of log entry identifiers. Each log message is uniquely
/// identified by its @LIT{lid} and the identifiers are in ascending
/// order.
///
/// - `level`: a list of the log-levels for all log entries.
/// - *level*: a list of the log-levels for all log entries.
///
/// - `timestamp`: a list of the timestamps as seconds since 1970-01-01 for all log
/// - *timestamp*: a list of the timestamps as seconds since 1970-01-01 for all log
/// entries.
///
/// - `text` a list of the texts of all log entries
/// - *text* a list of the texts of all log entries
///
/// - `totalAmount`: the total amount of log entries before pagination.
/// - *totalAmount*: the total amount of log entries before pagination.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{400}
/// is returned if invalid values are specified for `upto` or `level`.
/// is returned if invalid values are specified for *upto* or *level*.
///
/// @RESTRETURNCODE{403}
/// is returned if the log is requested for any database other than `_system`.
/// is returned if the log is requested for any database other than *_system*.
///
/// @RESTRETURNCODE{500}
/// is returned if the server cannot generate the result due to an out-of-memory
/// error.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
HttpHandler::status_t RestAdminLogHandler::execute () {

View File

@ -83,9 +83,10 @@ string const& RestShutdownHandler::queue () const {
}
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_api_initiate
/// @brief initiates the shutdown sequence
///
/// @RESTHEADER{GET /_admin/shutdown,initiates the shutdown sequence}
/// @RESTHEADER{GET /_admin/shutdown, Initiate shutdown sequence}
///
/// @RESTDESCRIPTION
/// This call initiates a clean shutdown sequence.
@ -94,6 +95,7 @@ string const& RestShutdownHandler::queue () const {
///
/// @RESTRETURNCODE{200}
/// is returned in all cases.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
HttpHandler::status_t RestShutdownHandler::execute () {

View File

@ -79,30 +79,31 @@ string const& RestVersionHandler::queue () const {
}
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_api_return
/// @brief returns the server version number
///
/// @RESTHEADER{GET /_api/version,returns the server version}
/// @RESTHEADER{GET /_api/version, Return server version}
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{details,boolean,optional}
/// If set to `true`, the response will contain a `details` attribute with
/// If set to *true*, the response will contain a *details* attribute with
/// additional information about included components and their versions. The
/// attribute names and internals of the `details` object may vary depending on
/// attribute names and internals of the *details* object may vary depending on
/// platform and ArangoDB version.
///
/// @RESTDESCRIPTION
/// Returns the server name and version number. The response is a JSON object
/// with the following attributes:
///
/// - `server`: will always contain `arango`
/// - *server*: will always contain *arango*
///
/// - `version`: the server version string. The string has the format
/// "`major`.`minor`.`sub`". `major` and `minor` will be numeric, and `sub`
/// - *version*: the server version string. The string has the format
/// "*major*.*minor*.*sub*". *major* and *minor* will be numeric, and *sub*
/// may contain a number or a textual version.
///
/// - `details`: an optional JSON object with additional details. This is
/// returned only if the `details` URL parameter is set to `true` in the
/// - *details*: an optional JSON object with additional details. This is
/// returned only if the *details* URL parameter is set to *true* in the
/// request.
///
/// @RESTRETURNCODES
@ -131,6 +132,7 @@ string const& RestVersionHandler::queue () const {
///
/// logJsonResponse(response);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
HttpHandler::status_t RestVersionHandler::execute () {

View File

@ -3137,7 +3137,7 @@ namespace triagens {
charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
charArray4[3] = charArray3[2] & 0x3f;
for (size_t j = 0; (j < i + 1); j++) {
for (int j = 0; (j < i + 1); j++) {
ret += BASE64U_CHARS[charArray4[j]];
}
@ -3197,7 +3197,7 @@ namespace triagens {
charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2);
charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];
for (size_t j = 0; j < i - 1; j++) {
for (int j = 0; j < i - 1; j++) {
ret += charArray3[j];
}
}

View File

@ -80,6 +80,7 @@ ERROR_ARANGO_DATADIR_LOCKED,1107,"database directory is locked","Will be raised
ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS,1108,"cannot create/rename collection because directory already exists","Will be raised when the collection cannot be created because a directory of the same name already exists."
ERROR_ARANGO_MSYNC_FAILED,1109,"msync failed","Will be raised when the system call msync failed."
ERROR_ARANGO_DATADIR_UNLOCKABLE,1110,"cannot lock database directory","Will be raised when the server cannot lock the database directory on startup."
ERROR_ARANGO_SYNC_TIMEOUT,1111,"sync timeout","Will be raised when the server waited too long for a datafile to be synced to disk."
################################################################################
## ArangoDB storage errors

View File

@ -342,7 +342,7 @@ void TRI_InitStringBuffer (TRI_string_buffer_t * self, TRI_memory_zone_t* zone)
self->_current = 0;
self->_len = 0;
Reserve(self, 100);
Reserve(self, 120);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -65,6 +65,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS, "cannot create/rename collection because directory already exists");
REG_ERROR(ERROR_ARANGO_MSYNC_FAILED, "msync failed");
REG_ERROR(ERROR_ARANGO_DATADIR_UNLOCKABLE, "cannot lock database directory");
REG_ERROR(ERROR_ARANGO_SYNC_TIMEOUT, "sync timeout");
REG_ERROR(ERROR_ARANGO_CONFLICT, "conflict");
REG_ERROR(ERROR_ARANGO_DATADIR_INVALID, "invalid database directory");
REG_ERROR(ERROR_ARANGO_DOCUMENT_NOT_FOUND, "document not found");

View File

@ -130,6 +130,9 @@ extern "C" {
/// - 1110: @LIT{cannot lock database directory}
/// Will be raised when the server cannot lock the database directory on
/// startup.
/// - 1111: @LIT{sync timeout}
/// Will be raised when the server waited too long for a datafile to be
/// synced to disk.
/// - 1200: @LIT{conflict}
/// Will be raised when updating or deleting a document and a conflict has
/// been detected.
@ -1143,6 +1146,17 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_ARANGO_DATADIR_UNLOCKABLE (1110)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1111: ERROR_ARANGO_SYNC_TIMEOUT
///
/// sync timeout
///
/// Will be raised when the server waited too long for a datafile to be synced
/// to disk.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_ARANGO_SYNC_TIMEOUT (1111)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1200: ERROR_ARANGO_CONFLICT
///

View File

@ -281,6 +281,106 @@ namespace triagens {
///
/// Get the result of an async job, and optionally remove it from the list of
/// done jobs if it is completed.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_put_api_async_return
/// @brief Returns the result of an async job
///
/// @RESTHEADER{PUT /_api/job/job-id, Return result of an async job}
///
/// @RESTURLPARAMS
///
/// @RESTURLPARAM{job-id,string,required}
/// The async job id.
///
/// @RESTDESCRIPTION
/// Returns the result of an async job identified by job-id. If the async job
/// result is present on the server, the result will be removed from the list of
/// result. That means this method can be called for each job-id once.
/// The method will return the original job result's headers and body, plus the
/// additional HTTP header x-arango-async-job-id. If this header is present, then
/// the job was found and the response contains the original job's result. If
/// the header is not present, the job was not found and the response contains
/// status information from the job manager.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{204}
/// is returned if the job requested via job-id is still in the queue of pending
/// (or not yet finished) jobs. In this case, no x-arango-async-id HTTP header
/// will be returned.
///
/// @RESTRETURNCODE{400}
/// is returned if no job-id was specified in the request. In this case,
/// no x-arango-async-id HTTP header will be returned.
///
/// @RESTRETURNCODE{404}
/// is returned if the job was not found or already deleted or fetched from
/// the job result list. In this case, no x-arango-async-id HTTP header will
/// be returned.
///
/// @EXAMPLES
/// Not providing a job-id:
///
/// ```js
/// unix> curl -X PUT --dump - http://localhost:8529/_api/job/
///
/// HTTP/1.1 400 Bad Request
/// content-type: application/json; charset=utf-8
///
/// {"error":true,"errorMessage":"bad parameter","code":400,"errorNum":400}
/// ```
///
/// Providing a job-id for a non-existing job:
///
/// ```js
/// unix> curl -X PUT --dump - http://localhost:8529/_api/job/foobar
///
/// HTTP/1.1 404 Not Found
/// content-type: application/json; charset=utf-8
///
/// {"error":true,"errorMessage":"not found","code":404,"errorNum":404}
/// ```
///
/// Fetching the result of an HTTP GET job:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 265413601
///
/// unix> curl -X PUT --dump - http://localhost:8529/_api/job/265413601
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
/// x-arango-async-id: 265413601
///
/// {"server":"arango","version":"2.1.0"}
/// ```
///
/// Fetching the result of an HTTP POST job that failed:
///
/// ```js
/// unix> curl -X POST --header 'x-arango-async: store' --data-binary @- --dump - http://localhost:8529/_api/collection
/// {"name":" this name is invalid "}
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 265479137
///
/// unix> curl -X PUT --dump - http://localhost:8529/_api/job/265479137
///
/// HTTP/1.1 400 Bad Request
/// content-type: application/json; charset=utf-8
/// x-arango-async-id: 265479137
///
/// {"error":true,"code":400,"errorNum":1208,"errorMessage":"cannot create collection: illegal name"}
/// ```
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
HttpResponse* getJobResult (AsyncJobResult::IdType jobId,
@ -313,6 +413,188 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes the result of an async job, without returning it
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_put_api_async_cancel
/// @brief Cancels the result an async job
///
/// @RESTHEADER{PUT /_api/job/job-id/cancel, Cancel async job}
///
/// @RESTURLPARAMS
///
/// @RESTURLPARAM{job-id,string,required}
/// The async job id.
///
/// @RESTDESCRIPTION
/// Cancels the currently running job identified by job-id. Note that it still
/// might take some time to actually cancel the running async job.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// cancel has been initiated.
///
/// @RESTRETURNCODE{400}
/// is returned if no job-id was specified in the request. In this case,
/// no x-arango-async-id HTTP header will be returned.
///
/// @RESTRETURNCODE{404}
/// is returned if the job was not found or already deleted or fetched from
/// the job result list. In this case, no x-arango-async-id HTTP header will
/// be returned.
///
/// @EXAMPLES
///
/// ```js
/// unix> curl -X POST --header 'x-arango-async: store' --data-binary @- --dump - http://localhost:8529/_api/cursor
/// {"query": "FOR i IN 1..10 FOR j IN 1..10 LET x = sleep(1.0) FILTER i == 5 && j == 5 RETURN 42"}
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 268952545
///
/// unix> curl --dump - http://localhost:8529/_api/job/pending
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// ["268952545"]
///
/// unix> curl -X PUT --dump - http://localhost:8529/_api/job/268952545/cancel
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// {"result":true}
///
/// unix> curl --dump - http://localhost:8529/_api/job/pending
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// ["268952545"]
/// ```
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_api_async_delete
/// @brief Deletes the result of an async job
///
/// @RESTHEADER{DELETE /_api/job/type, Deletes async job}
///
/// @RESTURLPARAMS
///
/// @RESTURLPARAM{type,string,required}
/// The type of jobs to delete. type can be:
/// * *all*: Deletes all jobs results. Currently executing or queued async
/// jobs will not be stopped by this call.
/// * *expired*: Deletes expired results. To determine the expiration status of a
/// result, pass the stamp URL parameter. stamp needs to be a UNIX timestamp,
/// and all async job results created at a lower timestamp will be deleted.
/// * *an actual job-id*: In this case, the call will remove the result of the
/// specified async job. If the job is currently executing or queued, it will not be aborted.
///
/// @RESTQUERYPARAMS
///
/// @RESTPARAM{stamp, number, optional}
///
/// A UNIX timestamp specifying the expiration threshold when type is expired.
///
/// @RESTDESCRIPTION
/// Deletes either all job results, expired job results, or the result of a specific job.
/// Clients can use this method to perform an eventual garbage collection of job results.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the deletion operation was carried out successfully.
/// This code will also be returned if no results were deleted.
///
/// @RESTRETURNCODE{400}
/// is returned if type is not specified or has an invalid value.
///
/// @RESTRETURNCODE{404}
/// is returned if type is a job-id but no async job with the specified id was found.
///
/// @EXAMPLES
///
/// Deleting all jobs:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270132193
///
/// unix> curl -X DELETE --dump - http://localhost:8529/_api/job/all
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// {
/// "result" : true
/// }
/// ```
///
/// Deleting expired jobs:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270197729
///
/// unix> curl -X DELETE --dump - http://localhost:8529/_api/job/expired?stamp=1401376184
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// {
/// "result" : true
/// }
/// ```
///
/// Deleting the result of a specific job:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270263265
///
/// unix> curl -X DELETE --dump - http://localhost:8529/_api/job/270263265
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// {
/// "result" : true
/// }
/// ```
///
/// Deleting the result of a non-existing job:
///
/// ```js
/// unix> curl -X DELETE --dump - http://localhost:8529/_api/job/foobar
///
/// HTTP/1.1 404 Not Found
/// content-type: application/json; charset=utf-8
///
/// {
/// "error" : true,
/// "errorMessage" : "not found",
/// "code" : 404,
/// "errorNum" : 404
/// }
/// ```
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
bool deleteJobResult (AsyncJobResult::IdType jobId) {
@ -402,6 +684,142 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the list of jobs by status
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_api_async_return
/// @brief Returns the status of an async job
///
/// @RESTHEADER{GET /_api/job/job-id, Returns async job}
///
/// @RESTURLPARAMS
///
/// @RESTURLPARAM{job-id,string,required}
/// The async job id.
///
/// @RESTDESCRIPTION
/// Returns the processing status of the specified job. The processing status can be
/// determined by peeking into the HTTP response code of the response.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the job requested via job-id has been executed successfully
/// and its result is ready to fetch.
///
/// @RESTRETURNCODE{204}
/// is returned if the job requested via job-id is still in the queue of pending
/// (or not yet finished) jobs.
///
/// @RESTRETURNCODE{404}
/// is returned if the job was not found or already deleted or fetched from the job result list.
///
/// @EXAMPLES
///
/// Querying the status of a done job:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270328801
///
/// unix> curl --dump - http://localhost:8529/_api/job/270328801
///
/// HTTP/1.1 200 OK
/// content-type: text/plain; charset=utf-8
///
/// Querying the status of a pending job:
///
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_admin/sleep?duration=3
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270394337
///
/// unix> curl --dump - http://localhost:8529/_api/job/270394337
///
/// HTTP/1.1 204 No Content
/// content-type: text/plain; charset=utf-8
/// ```
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_get_api_async_return_list
/// @brief Returns the list of job result id with a specific status
///
/// @RESTHEADER{GET /_api/job/type, Returns list of async job}
///
/// @RESTURLPARAMS
///
/// @RESTURLPARAM{type,string,required}
/// The type of jobs to return. The type can be either done or pending. Setting
/// the type to done will make the method return the ids of already completed async
/// jobs for which results can be fetched. Setting the type to pending will return
/// the ids of not yet finished async jobs.
///
/// @RESTQUERYPARAMS
///
/// @RESTPARAM{count, number, optional}
///
/// The maximum number of ids to return per call. If not specified, a
/// server-defined maximum value will be used.
///
/// @RESTDESCRIPTION
/// Returns the list of ids of async jobs with a specific status (either done or pending).
/// The list can be used by the client to get an overview of the job system status and
/// to retrieve completed job results later.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the list can be compiled successfully. Note: the list might be empty.
///
/// @RESTRETURNCODE{400}
/// is returned if type is not specified or has an invalid value.
///
/// @EXAMPLES
///
/// Fetching the list of done jobs:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270459873
///
/// unix> curl --dump - http://localhost:8529/_api/job/done
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// [
/// "270459873"
/// ]
/// ```
///
/// Fetching the list of pending jobs:
///
/// ```js
/// unix> curl --header 'x-arango-async: store' --dump - http://localhost:8529/_api/version
///
/// HTTP/1.1 202 Accepted
/// content-type: text/plain; charset=utf-8
/// x-arango-async-id: 270525409
///
/// unix> curl --dump - http://localhost:8529/_api/job/pending
///
/// HTTP/1.1 200 OK
/// content-type: application/json; charset=utf-8
///
/// [ ]
/// ```
///
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
const std::vector<AsyncJobResult::IdType> byStatus (AsyncJobResult::Status status,

View File

@ -382,7 +382,7 @@ static v8::Handle<v8::Value> JS_Base64Encode (v8::Arguments const& argv) {
/// @FUN{internal.parse(@FA{script})}
///
/// Parses the @FA{script} code, but does not execute it.
/// Will return @LIT{true} if the code does not have a parse error, and throw
/// Will return *true* if the code does not have a parse error, and throw
/// an exception otherwise.
////////////////////////////////////////////////////////////////////////////////
@ -446,7 +446,7 @@ static v8::Handle<v8::Value> JS_Parse (v8::Arguments const& argv) {
/// - @LIT{followRedirects}: whether or not to follow redirects
///
/// - @LIT{maxRedirects}: maximum number of redirects to follow, only useful
/// if @LIT{followRedirects} is @LIT{true}.
/// if @LIT{followRedirects} is *true*.
///
/// - @LIT{returnBodyOnError}: whether or not to return / save body on HTTP
/// error
@ -747,11 +747,11 @@ static v8::Handle<v8::Value> JS_Download (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief executes a script
///
/// @FUN{internal.execute(@FA{script}, @FA{sandbox}, @FA{filename})}
/// @FUN{internal.execute(@FA{script}, @FA{sandbox}, *filename*)}
///
/// Executes the @FA{script} with the @FA{sandbox} as context. Global variables
/// assigned inside the @FA{script}, will be visible in the @FA{sandbox} object
/// after execution. The @FA{filename} is used for displaying error
/// after execution. The *filename* is used for displaying error
/// messages.
///
/// If @FA{sandbox} is undefined, then @FN{execute} uses the current context.
@ -909,11 +909,12 @@ static v8::Handle<v8::Value> JS_RegisterExecuteFile (v8::Arguments const& argv)
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a file of any type or directory exists
///
/// @FUN{fs.exists(@FA{path})}
/// @startDocuBlock JS_Exists
/// `fs.exists(path)`
///
/// Returns true if a file (of any type) or a directory exists at a given
/// path. If the file is a broken symbolic link, returns false.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Exists (v8::Arguments const& argv) {
@ -935,10 +936,11 @@ static v8::Handle<v8::Value> JS_Exists (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief gets the size of a file
/// @startDocuBlock JS_Size
/// `fs.size(path)`
///
/// @FUN{fs.size(@FA{path})}
///
/// Returns the size of the file specified by @FA{path}.
/// Returns the size of the file specified by *path*.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_SizeFile (v8::Arguments const& argv) {
@ -983,10 +985,11 @@ static v8::Handle<v8::Value> JS_Getline (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the temporary directory
///
/// @FUN{fs.getTempPath()}
/// @startDocuBlock JS_GetTempPath
/// `fs.getTempPath()`
///
/// Returns the absolute path of the temporary directory
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_GetTempPath (v8::Arguments const& argv) {
@ -1010,14 +1013,15 @@ static v8::Handle<v8::Value> JS_GetTempPath (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the name for a (new) temporary file
/// @startDocuBlock JS_GetTempFile
/// `fs.getTempFile(directory, createFile)`
///
/// @FUN{fs.getTempFile(@FA{directory}, @FA{createFile})}
///
/// Returns the name for a new temporary file in directory @FA{directory}.
/// If @FA{createFile} is @LIT{true}, an empty file will be created so no other
/// Returns the name for a new temporary file in directory *directory*.
/// If *createFile* is *true*, an empty file will be created so no other
/// process can create a file of the same name.
///
/// Note that the directory @FA{directory} must exist.
/// **Note**: The directory *directory* must exist.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_GetTempFile (v8::Arguments const& argv) {
@ -1054,10 +1058,11 @@ static v8::Handle<v8::Value> JS_GetTempFile (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief tests if path is a directory
/// @startDocuBlock JS_IsDirectory
/// `fs.isDirectory(path)`
///
/// @FUN{fs.isDirectory(@FA{path})}
///
/// Returns true if the @FA{path} points to a directory.
/// Returns true if the *path* points to a directory.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_IsDirectory (v8::Arguments const& argv) {
@ -1080,10 +1085,11 @@ static v8::Handle<v8::Value> JS_IsDirectory (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief tests if path is a file
/// @startDocuBlock JS_IsFile
/// `fs.isFile(path)`
///
/// @FUN{fs.isFile(@FA{path})}
///
/// Returns true if the @FA{path} points to a file.
/// Returns true if the *path* points to a file.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_IsFile (v8::Arguments const& argv) {
@ -1106,11 +1112,12 @@ static v8::Handle<v8::Value> JS_IsFile (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief makes a given path absolute
///
/// @FUN{fs.makeAbsolute(@FA{path})}
/// @startDocuBlock JS_MakeAbsolute
/// `fs.makeAbsolute(path)`
///
/// Returns the given string if it is an absolute path, otherwise an
/// absolute path to the same location is returned.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_MakeAbsolute(v8::Arguments const& argv) {
@ -1151,15 +1158,16 @@ static v8::Handle<v8::Value> JS_MakeAbsolute(v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the directory listing
///
/// @FUN{fs.list(@FA{path})}
/// @startDocuBlock JS_List
/// `fs.list(path`
///
/// The functions returns the names of all the files in a directory, in
/// lexically sorted order. Throws an exception if the directory cannot be
/// traversed (or path is not a directory).
///
/// Note: this means that list("x") of a directory containing "a" and "b" would
/// **Note**: this means that list("x") of a directory containing "a" and "b" would
/// return ["a", "b"], not ["x/a", "x/b"].
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_List (v8::Arguments const& argv) {
@ -1195,14 +1203,15 @@ static v8::Handle<v8::Value> JS_List (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the directory tree
///
/// @FUN{fs.listTree(@FA{path})}
/// @startDocuBlock JS_ListTree
/// `fs.listTree(path)`
///
/// The function returns an array that starts with the given path, and all of
/// the paths relative to the given path, discovered by a depth first traversal
/// of every directory in any visited directory, reporting but not traversing
/// symbolic links to directories. The first path is always @LIT{""}, the path
/// symbolic links to directories. The first path is always *""*, the path
/// relative to itself.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ListTree (v8::Arguments const& argv) {
@ -1238,10 +1247,11 @@ static v8::Handle<v8::Value> JS_ListTree (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a directory
/// @startDocuBlock JS_MakeDirectory
/// `fs.makeDirectory(path)`
///
/// @FUN{fs.makeDirectory(@FA{path})}
///
/// Creates the directory specified by @FA{path}.
/// Creates the directory specified by *path*.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_MakeDirectory (v8::Arguments const& argv) {
@ -1271,14 +1281,15 @@ static v8::Handle<v8::Value> JS_MakeDirectory (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief unzips a file
/// @startDocuBlock JS_Unzip
/// `fs.unzip(filename, outpath, skipPaths, overwrite, password)`
///
/// @FUN{fs.unzip(@FA{filename}, @FA{outpath}, @FA{skipPaths}, @FA{overwrite}, @FA{password})}
/// Unzips the zip file specified by *filename* into the path specified by
/// * outpath*. Overwrites any existing target files if *overwrite* is set
/// to *true*.
///
/// Unzips the zip file specified by @FA{filename} into the path specified by
/// @FA{outpath}. Overwrites any existing target files if @FA{overwrite} is set
/// to @LIT{true}.
///
/// Returns @LIT{true} if the file was unzipped successfully.
/// Returns *true* if the file was unzipped successfully.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_UnzipFile (v8::Arguments const& argv) {
@ -1323,12 +1334,13 @@ static v8::Handle<v8::Value> JS_UnzipFile (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief zips a file
/// @startDocuBlock JS_Zip
/// `fs.zip(filename, files)`
///
/// @FUN{fs.zip(@FA{filename}, @FA{files})}
/// Stores the files specified by *files* in the zip file *filename*.
///
/// Stores the files specified by @FA{files} in the zip file @FA{filename}.
///
/// Returns @LIT{true} if the file was zipped successfully.
/// Returns *true* if the file was zipped successfully.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ZipFile (v8::Arguments const& argv) {
@ -1393,7 +1405,7 @@ static v8::Handle<v8::Value> JS_ZipFile (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief reads a file and executes it
///
/// @FUN{internal.load(@FA{filename})}
/// @FUN{internal.load(*filename*)}
///
/// Reads in a files and executes the contents in the current context.
////////////////////////////////////////////////////////////////////////////////
@ -1677,12 +1689,13 @@ static v8::Handle<v8::Value> JS_MarkNonce (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief renames a file
/// @startDocuBlock JS_Move
/// `fs.move(source, destination)`
///
/// @FUN{fs.move(@FA{source}, @FA{destination})}
///
/// Moves @FA{source} to @FA{destination}. Failure to move the file, or
/// Moves *source to destination. Failure to move the file, or
/// specifying a directory for target when source is a file will throw an
/// exception.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Move (v8::Arguments const& argv) {
@ -1852,11 +1865,12 @@ static v8::Handle<v8::Value> JS_Rand (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief reads in a file
///
/// @FUN{fs.read(@FA{filename})}
/// @startDocuBlock JS_Read
/// `fs.read(filename)`
///
/// Reads in a file and returns the content as string. Please note that the
/// file content must be encoded in UTF-8.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Read (v8::Arguments const& argv) {
@ -1888,11 +1902,12 @@ static v8::Handle<v8::Value> JS_Read (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief reads in a file as base64
///
/// @FUN{fs.read64(@FA{filename})}
/// @startDocuBlock JS_Read64
/// `fs.read64(filename)`
///
/// Reads in a file and returns the content as string. The file content is
/// Base64 encoded.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Read64 (v8::Arguments const& argv) {
@ -1924,7 +1939,7 @@ static v8::Handle<v8::Value> JS_Read64 (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief writes to a file
///
/// @FUN{internal.save(@FA{filename})}
/// @FUN{internal.save(*filename*)}
///
/// Writes the content into a file.
////////////////////////////////////////////////////////////////////////////////
@ -1963,12 +1978,13 @@ static v8::Handle<v8::Value> JS_Save (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a file
/// @startDocuBlock JS_Remove
/// `fs.remove(filename)`
///
/// @FUN{fs.remove(@FA{filename})}
///
/// Removes the file @FA{filename} at the given path. Throws an exception if the
/// Removes the file *filename* at the given path. Throws an exception if the
/// path corresponds to anything that is not a file or a symbolic link. If
/// "path" refers to a symbolic link, removes the symbolic link.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Remove (v8::Arguments const& argv) {
@ -1996,11 +2012,12 @@ static v8::Handle<v8::Value> JS_Remove (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief removes an empty directory
///
/// @FUN{fs.removeDirectory(@FA{path})}
/// @startDocuBlock JS_RemoveDirectory
/// `fs.removeDirectory(path)`
///
/// Removes a directory if it is empty. Throws an exception if the path is not
/// an empty directory.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_RemoveDirectory (v8::Arguments const& argv) {
@ -2032,11 +2049,12 @@ static v8::Handle<v8::Value> JS_RemoveDirectory (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a directory
///
/// @FUN{fs.removeDirectoryRecursive(@FA{path})}
/// @startDocuBlock JS_RemoveDirectoryRecursive
/// `fs.removeDirectoryRecursive(path)`
///
/// Removes a directory with all subelements. Throws an exception if the path
/// is not a directory.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_RemoveRecursiveDirectory (v8::Arguments const& argv) {

View File

@ -26,6 +26,7 @@ test -f ${OUTPUT} || exit 1
#############################################################################
cat ${OUTPUT} \
| sed -e 's:( i = 0; i < _yybytes_len;:( i = 0; i < (int) _yybytes_len;:' \
| sed -e 's:yy_n_chars, (size_t) num_to_read );:yy_n_chars, (int) num_to_read );:' \
| sed -e 's:register ::g' \
> ${OUTPUT}.tmp