diff --git a/CHANGELOG b/CHANGELOG index 1a61f9a43f..187f48f2bc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -40,6 +40,12 @@ v2.6.0 (XXXX-XX-XX) * removed remainders of MRuby integration, removed arangoirb +v2.5.2 (XXXX-XX-XX) +------------------- + +* moved /_api/query to C++ + + v2.5.1 (2015-03-19) ------------------- diff --git a/Documentation/Books/Users/AqlExamples/DataModificationQueries.mdpp b/Documentation/Books/Users/AqlExamples/DataModificationQueries.mdpp index dbbd431e03..3ffbe4c39e 100644 --- a/Documentation/Books/Users/AqlExamples/DataModificationQueries.mdpp +++ b/Documentation/Books/Users/AqlExamples/DataModificationQueries.mdpp @@ -163,3 +163,97 @@ FOR u IN users This will continue execution of the query even if errors occur during the *REPLACE* operation. It works similar for *UPDATE*, *INSERT*, and *REMOVE*. + + +###Altering substructures + +To modify lists in documents we have to work with temporary variables. +We will collect the sublist in there and alter it. We choose a simple +boolean filter condition to make the query better comprehensible. + +First lets create a collection with a sample: + +```js +database = db._create('complexCollection') +database.save({ + "topLevelAttribute" : "a", + "subList" : [ + { + "attributeToAlter" : "oldValue", + "filterByMe" : true + }, + { + "attributeToAlter" : "moreOldValues", + "filterByMe" : true + }, + { + "attributeToAlter" : "unchangedValue", + "filterByMe" : false + } + ] +}) +``` + +Heres the Query which keeps the *subList* on *alteredList* to update it later: + +```js +FOR document in complexCollection + LET alteredList = ( + FOR element IN document.subList + LET newItem = (! element.filterByMe ? + element : + MERGE(element, { attributeToAlter: "shiny New Value" })) + RETURN newItem) + UPDATE document WITH { subList: alteredList } IN complexCollection +``` + +While the query as it is is now functional: + +```js +db.complexCollection.toArray() +[ + { + "_id" : "complexCollection/392671569467", + "_key" : "392671569467", + "_rev" : "392799430203", + "topLevelAttribute" : "a", + "subList" : [ + { + "filterByMe" : true, + "attributeToAlter" : "shiny New Value" + }, + { + "filterByMe" : true, + "attributeToAlter" : "shiny New Value" + }, + { + "filterByMe" : false, + "attributeToAlter" : "unchangedValue" + } + ] + } +] +``` + +It will probably be soonish a performance bottleneck, since it **modifies** +all documents in the collection **regardless whether the values change or not**. +Therefore we want to only *UPDATE* the documents if we really change their value. +Hence we employ a second *FOR* to test whether *subList* will be altered or not: + +```js +FOR document in complexCollection + LET willUpdateDocument = ( + FOR element IN docToAlter.subList + FILTER element.filterByMe LIMIT 1 RETURN 1) + + FILTER LENGTH(willUpdateDocument) > 0 + + LET alteredList = ( + FOR element IN document.subList + LET newItem = (! element.filterByMe ? + element : + MERGE(element, { attributeToAlter: "shiny New Value" })) + RETURN newItem) + + UPDATE document WITH { subList: alteredList } IN complexCollection +``` diff --git a/Documentation/Books/Users/HttpAqlQuery/README.mdpp b/Documentation/Books/Users/HttpAqlQuery/README.mdpp index d5d49d1b00..3085b254f7 100644 --- a/Documentation/Books/Users/HttpAqlQuery/README.mdpp +++ b/Documentation/Books/Users/HttpAqlQuery/README.mdpp @@ -13,9 +13,62 @@ inspect it and return meta information about it. @startDocuBlock JSF_post_api_explain - -@startDocuBlock JSF_post_api_query + +@RESTHEADER{POST /_api/query, Parse an AQL query} +@RESTBODYPARAM{query,json,required} +To validate a query string without executing it, the query string can be +passed to the server via an HTTP POST request. + +The query string needs to be passed in the attribute *query* of a JSON +object as the body of the POST request. + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +If the query is valid, the server will respond with *HTTP 200* and +return the names of the bind parameters it found in the query (if any) in +the *bindVars* attribute of the response. It will also return an array +of the collections used in the query in the *collections* attribute. +If a query can be parsed successfully, the *ast* attribute of the returned +JSON will contain the abstract syntax tree representation of the query. +The format of the *ast* is subject to change in future versions of +ArangoDB, but it can be used to inspect how ArangoDB interprets a given +query. Note that the abstract syntax tree will be returned without any +optimizations applied to it. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request, +or if the query contains a parse error. The body of the response will +contain the error details embedded in a JSON object. + +@EXAMPLES + +Valid query: + +@EXAMPLE_ARANGOSH_RUN{RestQueryValid} + var url = "/_api/query"; + var body = '{ "query" : "FOR p IN products FILTER p.name == @name LIMIT 2 RETURN p.n" }'; + + var response = logCurlRequest('POST', url, body); + + assert(response.code === 200); + + logJsonResponse(response); +@END_EXAMPLE_ARANGOSH_RUN + +Invalid query: + +@EXAMPLE_ARANGOSH_RUN{RestQueryInvalid} + var url = "/_api/query"; + var body = '{ "query" : "FOR p IN products FILTER p.name = @name LIMIT 2 RETURN p.n" }'; + + var response = logCurlRequest('POST', url, body); + + assert(response.code === 400); + + logJsonResponse(response); +@END_EXAMPLE_ARANGOSH_RUN !SUBSECTION Query tracking @@ -24,16 +77,148 @@ executing AQL queries and the list of slow AQL queries. In order to make meaning use of these APIs, query tracking needs to be enabled in the database the HTTP request is executed for. -@startDocuBlock GetApiQueryProperties + +@RESTHEADER{GET /_api/query/properties, Returns the properties for the AQL query tracking} -@startDocuBlock PutApiQueryProperties +Returns the current query tracking configuration. The configuration is a +JSON object with the following properties: -@startDocuBlock GetApiQueryCurrent +- *enabled*: if set to *true*, then queries will be tracked. If set to + *false*, neither queries nor slow queries will be tracked. -@startDocuBlock GetApiQuerySlow +- *trackSlowQueries*: if set to *true*, then slow queries will be tracked + in the list of slow queries if their runtime exceeds the value set in + *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* + property must also be set to *true*. -@startDocuBlock DeleteApiQuerySlow +- *maxSlowQueries*: the maximum number of slow queries to keep in the list + of slow queries. If the list of slow queries is full, the oldest entry in + it will be discarded when additional slow queries occur. +- *slowQueryThreshold*: the threshold value for treating a query as slow. A + query with a runtime greater or equal to this threshold value will be + put into the list of slow queries when slow query tracking is enabled. + The value for *slowQueryThreshold* is specified in seconds. + +- *maxQueryStringLength*: the maximum query string length to keep in the + list of queries. Query strings can have arbitrary lengths, and this property + can be used to save memory in case very long query strings are used. The + value is specified in bytes. + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Is returned when the list of queries can be retrieved successfully. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request, + + +@RESTHEADER{PUT /_api/query/properties, Changes the properties for the AQL query tracking} + +@RESTBODYPARAM{properties,json,required} +The properties for query tracking in the current database. + +The properties need to be passed in the attribute *properties* in the body +of the HTTP request. *properties* needs to be a JSON object with the following +properties: + +- *enabled*: if set to *true*, then queries will be tracked. If set to + *false*, neither queries nor slow queries will be tracked. + +- *trackSlowQueries*: if set to *true*, then slow queries will be tracked + in the list of slow queries if their runtime exceeds the value set in + *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* + property must also be set to *true*. + +- *maxSlowQueries*: the maximum number of slow queries to keep in the list + of slow queries. If the list of slow queries is full, the oldest entry in + it will be discarded when additional slow queries occur. + +- *slowQueryThreshold*: the threshold value for treating a query as slow. A + query with a runtime greater or equal to this threshold value will be + put into the list of slow queries when slow query tracking is enabled. + The value for *slowQueryThreshold* is specified in seconds. + +- *maxQueryStringLength*: the maximum query string length to keep in the + list of queries. Query strings can have arbitrary lengths, and this property + can be used to save memory in case very long query strings are used. The + value is specified in bytes. + +After the properties have been changed, the current set of properties will +be returned in the HTTP response. + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Is returned if the properties were changed successfully. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request, + + +@RESTHEADER{GET /_api/query/current, Returns the currently running AQL queries} + +Returns an array containing the AQL queries currently running in the selected +database. Each query is a JSON object with the following attributes: + +- *id*: the query's id + +- *query*: the query string (potentially truncated) + +- *started*: the date and time when the query was started + +- *runTime*: the query's run time up to the point the list of queries was + queried + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Is returned when the list of queries can be retrieved successfully. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request, + + +@RESTHEADER{GET /_api/query/slow, Returns the list of slow AQL queries} + +Returns an array containing the last AQL queries that exceeded the slow +query threshold in the selected database. +The maximum amount of queries in the list can be controlled by setting +the query tracking property `maxSlowQueries`. The threshold for treating +a query as *slow* can be adjusted by setting the query tracking property +`slowQueryThreshold`. + +Each query is a JSON object with the following attributes: + +- *id*: the query's id + +- *query*: the query string (potentially truncated) + +- *started*: the date and time when the query was started + +- *runTime*: the query's run time up to the point the list of queries was + queried + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Is returned when the list of queries can be retrieved successfully. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request, + + +@RESTHEADER{DELETE /_api/query/slow, Clears the list of slow AQL queries} + +@RESTRETURNCODES + +@RESTRETURNCODE{204} +The server will respond with *HTTP 200* when the list of queries was +cleared successfully. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request. !SUBSECTION Killing queries @@ -42,5 +227,18 @@ via an Http interface. To kill a running query, its id (as returned for the quer list of currently running queries) must be specified. The kill flag of the query will then be set, and the query will be aborted as soon as it reaches a cancellation point. -@startDocuBlock DeleteApiQueryKill - + +@RESTHEADER{DELETE /_api/query/{query-id}, Kills a running AQL query} + +@RESTRETURNCODES + +@RESTRETURNCODE{200} +The server will respond with *HTTP 200* when the query was still running when +the kill request was executed and the query's kill flag was set. + +@RESTRETURNCODE{400} +The server will respond with *HTTP 400* in case of a malformed request. + +@RESTRETURNCODE{404} +The server will respond with *HTTP 404* when no query with the specified +id was found. diff --git a/Installation/ARM/rc.arangodb b/Installation/ARM/rc.arangodb index 2e535584e0..055b779113 100644 --- a/Installation/ARM/rc.arangodb +++ b/Installation/ARM/rc.arangodb @@ -42,11 +42,11 @@ start () { RETVAL=$? log_end_msg $RETVAL else - $DAEMON -c $CONF --uid arangodb --gid arangodb --no-server --check-version + $DAEMON -c $CONF --uid arangodb --gid arangodb --no-server --log.tty "" --check-version RETVAL=$? if [ "$RETVAL" -eq 0 ]; then - $DAEMON -c $CONF --uid arangodb --gid arangodb --pid-file "$PIDFILE" --temp-path "/var/tmp/arangod" --supervisor $@ + $DAEMON -c $CONF --uid arangodb --gid arangodb --pid-file "$PIDFILE" --temp-path "/var/tmp/arangod" --log.tty "" --supervisor $@ RETVAL=$? log_end_msg $RETVAL else diff --git a/Installation/Debian/postinst b/Installation/Debian/postinst deleted file mode 100755 index 125e895900..0000000000 --- a/Installation/Debian/postinst +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -update-rc.d arangodb start 99 2 3 4 5 . stop 00 0 1 6 . >/dev/null -/etc/init.d/arangodb start - -echo " -ArangoDB 2 (http://www.arangodb.com) - A multi-purpose open-source database with a flexible data model for documents, - graphs, and key-values. - -First Steps with ArangoDB: - https://docs.arangodb.com/FirstSteps/README.html - -Upgrading ArangoDB: - https://docs.arangodb.com/Installing/Upgrading.html - -Upgrading ArangoDB database files: - > /etc/init.d/arangodb upgrade - -Configuration file: - /etc/arangodb/arangod.conf - -Start ArangoDB shell client: - > /usr/bin/arangosh - -Start ArangoDB service: - > /etc/init.d/arangodb start - -Remote access to the ArangoDB server is disabled for security reasons. -In order to enable it, please change the server endpoint from '127.0.0.1' -to '0.0.0.0' in ArangoDB's configuration file '/etc/init.d/arangod.conf'. -" diff --git a/Installation/Debian/postrm b/Installation/Debian/postrm deleted file mode 100755 index 04f639c32c..0000000000 --- a/Installation/Debian/postrm +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -if [ purge = "$1" ]; then - update-rc.d arangodb remove >/dev/null - - rm -rf /usr/share/arangodb/js/apps - rm -rf /var/log/arangodb - rm -rf /var/lib/arangodb - rm -rf /var/lib/arangodb-apps -fi diff --git a/Installation/Debian/preinst b/Installation/Debian/preinst deleted file mode 100755 index 445c877fa1..0000000000 --- a/Installation/Debian/preinst +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -getent group arangodb >/dev/null || groupadd -r arangodb -getent passwd arangodb >/dev/null || useradd -r -g arangodb -d /usr/share/arangodb -s /bin/false -c "ArangoDB Application User" arangodb - -install -o arangodb -g arangodb -m 755 -d /var/lib/arangodb -install -o arangodb -g arangodb -m 755 -d /var/lib/arangodb-apps -install -o arangodb -g arangodb -m 755 -d /var/run/arangodb -install -o arangodb -g arangodb -m 755 -d /var/log/arangodb diff --git a/Installation/Debian/prerm b/Installation/Debian/prerm deleted file mode 100755 index f551d37a41..0000000000 --- a/Installation/Debian/prerm +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/etc/init.d/arangodb stop diff --git a/Installation/Debian/rc.arangodb b/Installation/Debian/rc.arangodb deleted file mode 100644 index fa94a673e8..0000000000 --- a/Installation/Debian/rc.arangodb +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: arangodb -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: arangodb -# Description: arango database server -### END INIT INFO - -. /lib/lsb/init-functions - -PATH=/bin:/usr/bin:/sbin:/usr/sbin -DAEMON=/usr/sbin/arangod -DESC="arango database server" -NAME="arangod" -PIDDIR=/var/run/arangodb -PIDFILE=/var/run/arangodb/arangod.pid -CONF=/etc/arangodb/arangod.conf - -test -x $DAEMON || exit 0 - -if [ `id -u` -ne 0 ]; then - echo "You need root privileges to run this script" - exit 1 -fi - -start () { - [ -d $PIDDIR ] || mkdir $PIDDIR || exit 1 - [ -d /var/run/arangodb ] || mkdir /var/run/arangodb || exit 1 - - ( cd /var/log/arangodb && chown -R arangodb:arangodb . ) || exit 1 - ( cd /var/lib/arangodb && chown -R arangodb:arangodb . ) || exit 1 - ( cd /var/lib/arangodb-apps && chown -R arangodb:arangodb . ) || exit 1 - ( cd /var/run/arangodb && chown -R arangodb:arangodb . ) || exit 1 - ( cd $PIDDIR && chown arangodb:arangodb . ) || exit 1 - - if [ "$1" = "--upgrade" ]; then - $DAEMON -c $CONF --uid arangodb --gid arangodb --no-server $@ - RETVAL=$? - log_end_msg $RETVAL - else - $DAEMON -c $CONF --uid arangodb --gid arangodb --no-server --check-version - RETVAL=$? - - if [ "$RETVAL" -eq 0 ]; then - $DAEMON -c $CONF --uid arangodb --gid arangodb --pid-file "$PIDFILE" --temp-path "/var/tmp/arangod" --supervisor $@ - RETVAL=$? - log_end_msg $RETVAL - else - log_failure_msg "database version check failed, maybe need to run 'upgrade'?" - fi - fi - - return $RETVAL -} - -case "$1" in - start) - log_daemon_msg "Starting $DESC" "$NAME" - - start - exit $? - ;; - - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - - start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON - RETVAL=$? - log_end_msg $RETVAL - - log_daemon_msg "Waiting for shutdown" "" - - c=0 - - while test -f $PIDFILE -a $c -lt 30 && ps --pid `cat $PIDFILE` > /dev/null; do - log_progress_msg "." - sleep 2 - c=`expr $c + 1` - done - - log_progress_msg "done" - log_end_msg 0 - - rm -f $PIDFILE - exit $RETVAL - ;; - - restart) - $0 stop - sleep 3 - $0 start - exit $? - ;; - - force-reload) - $0 restart - exit $? - ;; - - status) - status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $? - ;; - - upgrade) - log_daemon_msg "Upgrading $DESC" "$NAME" - - start --upgrade - exit $? - ;; - - *) - log_success_msg "Usage: /etc/init.d/arangodb {start|stop|restart|force-reload|status|upgrade}" - exit 1 - ;; -esac - -exit 0 diff --git a/README b/README index 01ad53c6d6..ec271ca083 100644 --- a/README +++ b/README @@ -1,17 +1,44 @@ ArangoDB -ArangoDB is a multi-purpose, open-source database with flexible data models for +ArangoDB is a multi-model, open-source database with flexible data models for documents, graphs, and key-values. Build high performance applications using a convenient SQL-like query language or JavaScript extensions. Use ACID transactions if you require them. Scale horizontally and vertically with a few mouse clicks. +ArangoDB is Polyglot Persistence done right. The supported data models can be +mixed in queries and allow ArangoDB to be the aggregation point for the data +request you have in mind. +To get started, try one of our 10 Minutes Tutorials in your favourite +programming language or try one of our ArangoDB_Cookbook_recipes. +For the impatient: download and install ArangoDB. Start the server arangod and +point your browser to http://127.0.0.1:8529/. + +Key Features in ArangoDB + +Multi-Model Documents, graphs and key-value pairs — model your data as you +see fit for your application. +Joins Conveniently join what belongs together for flexible ad-hoc querying, +less data redundancy. +Transactions Easy application development keeping your data consistent and +safe. No hassle in your client. +Here is an AQL query that makes use of all those features: AQL Query Example +Joins and Transactions are key features for flexible, secure data designs, +widely used in RDBMSs that you won’t want to miss in NoSQL products. You +decide how and when to use Joins and strong consistency guarantees, keeping all +the power for scaling and performance as choice. +Furthermore, ArangoDB offers a microservice framework called Foxx to build your +own Rest API with a few lines of code. +Microservice Example Microservice Example +Next step, bundle your Foxx application as a docker_container and get it +running in the cloud. Key features include: + * Schema-free schemata let you combine the space efficiency of MySQL with the performance power of NoSQL -* Use ArangoDB as an application server and fuse your application and database - together for maximal throughput +* Use a data-centric microservices approach with ArangoDB Foxx and fuse your + application-logic and database together for maximal throughput * JavaScript for all: no language zoo, you can use one language from your browser to your back-end * ArangoDB is multi-threaded - exploit the power of all your cores @@ -23,52 +50,37 @@ Key features include: durability or more performance * No-nonsense storage: ArangoDB uses all of the power of modern storage hardware, like SSD and large caches -* Powerful query language (AQL) to retrieve data +* Powerful query language (AQL) to retrieve and modify data * Transactions: run queries on multiple documents or collections with optional transactional consistency and isolation * Replication and Sharding: set up the database in a master-slave configuration or spread bigger datasets across multiple servers * It is open source (Apache Licence 2.0) -For more in-depth information +For more in-depth information read the design_goals_of_ArangoDB -* read more on the design_goals_of_ArangoDB -* watch_the_video - Martin Schoenert, architect of ArangoDB, gives an - introduction of what the ArangoDB project is about. -* or give it a try. - - -For the Impatient - -For Mac OSX users: execute - - brew install arangodb - -For Windows and Linux users: use the installer script or distribution package -from our download_page. -If the package manager has not already started the ArangoDB server, use - - unix> /path/to/sbin/arangod - 2012-03-30T12:54:19Z [11794] INFO ArangoDB (version 2.x.y) is ready for - business - 2012-03-30T12:54:19Z [11794] INFO Have Fun! - -/path/to/sbin is OS dependent. It will normally by either /usr/sbin or /user/ -local/sbin. Point your browser to - - http://localhost:8529/ - -and select Tools / JS Shell. You can now use the Arango shell from within your -browser. Alternative, it is available as command-line tool arangosh. - - arangosh> db._create("hello"); - arangosh> db.hello.save({ world: "earth" }); - -Congratulations! You have created your first collection called hello and your -first document. To verify your achievements, type: - - arangosh> db.hello.toArray(); +Latest Release - ArangoDB 2.5 +The full changelog could be found in the documentation. +Sparse Indizes: In ArangoDB 2.5, hash and skiplist indexes can optionally be +made sparse. Here is a performance_comparison that shows how you can benefit +from great savings in memory and index creation CPU time declaring indexes as +sparse. +We’ve added some small but useful AQL language improvements plus several AQL +optimizer improvements. +Object attribute names in ArangoDB 2.5 can be specified using static string +literals, bind parameters, and dynamic expressions. +Function RANDOM_TOKEN(length): produces a pseudo-random string of the specified +length. Such strings can be used for id or token generation. +One example implementation is the API-Key_management that restricts access to +certain routes of an API. You can use this custom Foxx library to start +charging your valuable data right away. +Streamlined development process: ArangoDB 2.5 improves the development process +of data-centric microservices with the Foxx framework. +Installing an app is now as easy as it should be: * install: get your Foxx app +up and running * uninstall: shut it down and erase it from disk +Developers can enable the new development mode for a single app. This +deactivates caching and provides fine-graded debugging information. More Information @@ -76,21 +88,11 @@ Please check the Installation_Manual for installation and compilation instructions. The User_Manual has an introductory chapter showing the basic operations of ArangoDB. -Or you can use the online_tutorial to play with ArangoDB without installing it -locally. Stay in Contact -Please note that there will be bugs and we'd really appreciate it if you report -them: +Please note that there will be bugs and we’d really appreciate it if you +report them: https://github.com/arangodb/arangodb/issues You can use the Google group for improvements, feature requests, comments http://www.arangodb.com/community - -Citing ArangoDB - -Please kindly cite ArangoDB in your publications if it helps your research: -bibtex @misc{ArangoDB2014, Author = {ArangoDB}, Title = { {ArangoDB 2.2}: An -Open Source multi-purpose database supporting flexible data models for -documents, graphs, and key-values.}, Year = {2014}, Howpublished = {\url{http:/ -/arangodb.com/} } diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index 3b92d3aa23..8b2cf26774 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -32,7 +32,7 @@ #include "Aql/Collection.h" #include "Aql/Executor.h" #include "Basics/tri-strings.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/collection.h" using namespace triagens::aql; diff --git a/arangod/Aql/AstNode.h b/arangod/Aql/AstNode.h index 2c8f7df186..430d726268 100644 --- a/arangod/Aql/AstNode.h +++ b/arangod/Aql/AstNode.h @@ -31,10 +31,10 @@ #define ARANGODB_AQL_ASTNODE_H 1 #include "Basics/Common.h" +#include "Basics/Exceptions.h" #include "Basics/json.h" #include "Basics/vector.h" #include "Basics/JsonHelper.h" -#include "Utils/Exception.h" #include "Aql/Query.h" namespace triagens { diff --git a/arangod/Aql/BindParameters.cpp b/arangod/Aql/BindParameters.cpp index 3b777133d7..f5aabb12f8 100644 --- a/arangod/Aql/BindParameters.cpp +++ b/arangod/Aql/BindParameters.cpp @@ -29,7 +29,7 @@ #include "Aql/BindParameters.h" #include "Basics/json.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; diff --git a/arangod/Aql/Collection.cpp b/arangod/Aql/Collection.cpp index 70b1bd13ad..f903d85aec 100644 --- a/arangod/Aql/Collection.cpp +++ b/arangod/Aql/Collection.cpp @@ -30,10 +30,10 @@ #include "Collection.h" #include "Aql/ExecutionEngine.h" #include "Basics/StringUtils.h" +#include "Basics/Exceptions.h" #include "Cluster/ClusterInfo.h" #include "Cluster/ClusterMethods.h" #include "Cluster/ServerState.h" -#include "Utils/Exception.h" #include "VocBase/document-collection.h" #include "VocBase/transaction.h" #include "VocBase/vocbase.h" diff --git a/arangod/Aql/Collections.h b/arangod/Aql/Collections.h index 90a91f6625..30c6a63a71 100644 --- a/arangod/Aql/Collections.h +++ b/arangod/Aql/Collections.h @@ -31,8 +31,8 @@ #define ARANGODB_AQL_COLLECTIONS_H 1 #include "Basics/Common.h" +#include "Basics/Exceptions.h" #include "Aql/Collection.h" -#include "Utils/Exception.h" struct TRI_vocbase_s; diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index b5856e9ba2..3df7779cbe 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -32,8 +32,8 @@ #include "Basics/StringUtils.h" #include "Basics/StringBuffer.h" #include "Basics/json-utilities.h" +#include "Basics/Exceptions.h" #include "HashIndex/hash-index.h" -#include "Utils/Exception.h" #include "V8/v8-globals.h" #include "VocBase/edge-collection.h" #include "VocBase/index.h" diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index db76699bd6..102c707e58 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -34,7 +34,7 @@ #include "Aql/QueryRegistry.h" #include "Aql/WalkerWorker.h" #include "Cluster/ClusterComm.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "Basics/logging.h" using namespace triagens::aql; diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index ae72d82977..c0cc52947c 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -38,7 +38,7 @@ #include "Aql/Variable.h" #include "Aql/WalkerWorker.h" #include "Basics/JsonHelper.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; using namespace triagens::basics; diff --git a/arangod/Aql/ExecutionStats.cpp b/arangod/Aql/ExecutionStats.cpp index fd42769adb..c05167a88f 100644 --- a/arangod/Aql/ExecutionStats.cpp +++ b/arangod/Aql/ExecutionStats.cpp @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/ExecutionStats.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; using Json = triagens::basics::Json; diff --git a/arangod/Aql/Executor.cpp b/arangod/Aql/Executor.cpp index 59382773a5..cf14d51198 100644 --- a/arangod/Aql/Executor.cpp +++ b/arangod/Aql/Executor.cpp @@ -33,7 +33,7 @@ #include "Aql/V8Expression.h" #include "Aql/Variable.h" #include "Basics/StringBuffer.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "V8/v8-conv.h" #include "V8/v8-globals.h" diff --git a/arangod/Aql/Expression.cpp b/arangod/Aql/Expression.cpp index edd24f8942..e7fed5d9f9 100644 --- a/arangod/Aql/Expression.cpp +++ b/arangod/Aql/Expression.cpp @@ -38,7 +38,7 @@ #include "Basics/json.h" #include "ShapedJson/shaped-json.h" #include "VocBase/document-collection.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; using Json = triagens::basics::Json; @@ -169,7 +169,7 @@ AqlValue Expression::execute (triagens::arango::AqlTransaction* trx, // std::cout << triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, _node->toJson(TRI_UNKNOWN_MEM_ZONE, true)).toString()<< "\n"; return _func->execute(isolate, _ast->query(), trx, docColls, argv, startPos, vars, regs); } - catch (triagens::arango::Exception& ex) { + catch (triagens::basics::Exception& ex) { if (_ast->query()->verboseErrors()) { ex.addToMessage(" while evaluating expression "); auto json = _node->toJson(TRI_UNKNOWN_MEM_ZONE, false); diff --git a/arangod/Aql/Function.cpp b/arangod/Aql/Function.cpp index 544f68b1e9..90ac9a08c4 100644 --- a/arangod/Aql/Function.cpp +++ b/arangod/Aql/Function.cpp @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/Function.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; diff --git a/arangod/Aql/Functions.cpp b/arangod/Aql/Functions.cpp index 0708714fad..b11deadca0 100644 --- a/arangod/Aql/Functions.cpp +++ b/arangod/Aql/Functions.cpp @@ -30,7 +30,7 @@ #include "Aql/Functions.h" #include "Basics/fpconv.h" #include "Basics/JsonHelper.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; using Json = triagens::basics::Json; diff --git a/arangod/Aql/Index.h b/arangod/Aql/Index.h index e8977851a5..9a7c593095 100644 --- a/arangod/Aql/Index.h +++ b/arangod/Aql/Index.h @@ -31,10 +31,10 @@ #define ARANGODB_AQL_INDEX_H 1 #include "Basics/Common.h" +#include "Basics/Exceptions.h" #include "Basics/json.h" #include "Basics/JsonHelper.h" #include "HashIndex/hash-index.h" -#include "Utils/Exception.h" #include "VocBase/index.h" namespace triagens { diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index 8bebfe7675..cd2fb81d53 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -38,10 +38,10 @@ #include "Basics/JsonHelper.h" #include "Basics/json.h" #include "Basics/tri-strings.h" +#include "Basics/Exceptions.h" #include "Cluster/ServerState.h" #include "Utils/AqlTransaction.h" #include "Utils/CollectionNameResolver.h" -#include "Utils/Exception.h" #include "Utils/StandaloneTransactionContext.h" #include "Utils/V8TransactionContext.h" #include "V8Server/ApplicationV8.h" @@ -597,7 +597,7 @@ QueryResult Query::prepare (QueryRegistry* registry) { _engine = engine; return QueryResult(); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { cleanupPlanAndEngine(ex.code()); return QueryResult(ex.code(), ex.message() + getStateString()); } @@ -667,7 +667,7 @@ QueryResult Query::execute (QueryRegistry* registry) { return result; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { cleanupPlanAndEngine(ex.code()); return QueryResult(ex.code(), ex.message() + getStateString()); } @@ -739,7 +739,7 @@ QueryResultV8 Query::executeV8 (v8::Isolate* isolate, QueryRegistry* registry) { return result; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { cleanupPlanAndEngine(ex.code()); return QueryResultV8(ex.code(), ex.message() + getStateString()); } @@ -766,7 +766,7 @@ QueryResult Query::parse () { Parser parser(this); return parser.parse(true); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return QueryResult(ex.code(), ex.message()); } catch (...) { @@ -854,7 +854,7 @@ QueryResult Query::explain () { return result; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return QueryResult(ex.code(), ex.message() + getStateString()); } catch (std::bad_alloc const&) { diff --git a/arangod/Aql/QueryList.cpp b/arangod/Aql/QueryList.cpp index c284a3551b..60d2e8b93f 100644 --- a/arangod/Aql/QueryList.cpp +++ b/arangod/Aql/QueryList.cpp @@ -32,7 +32,7 @@ #include "Basics/logging.h" #include "Basics/ReadLocker.h" #include "Basics/WriteLocker.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/vocbase.h" using namespace triagens::aql; diff --git a/arangod/Aql/RestAqlHandler.cpp b/arangod/Aql/RestAqlHandler.cpp index d4ea4f9a50..0d901b032a 100644 --- a/arangod/Aql/RestAqlHandler.cpp +++ b/arangod/Aql/RestAqlHandler.cpp @@ -434,7 +434,7 @@ void RestAqlHandler::useQuery (std::string const& operation, } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { _queryRegistry->close(_vocbase, _qId); generateError(HttpResponse::SERVER_ERROR, ex.code(), @@ -549,7 +549,7 @@ void RestAqlHandler::getInfoQuery (std::string const& operation, return; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { _queryRegistry->close(_vocbase, _qId); LOG_ERROR("failed during use of query: %s", ex.message().c_str()); generateError(HttpResponse::SERVER_ERROR, diff --git a/arangod/Aql/Scopes.cpp b/arangod/Aql/Scopes.cpp index 24feeac63b..00e77a730c 100644 --- a/arangod/Aql/Scopes.cpp +++ b/arangod/Aql/Scopes.cpp @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/Scopes.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; diff --git a/arangod/Aql/VariableGenerator.cpp b/arangod/Aql/VariableGenerator.cpp index 1ee83e41e8..49dde4ce6a 100644 --- a/arangod/Aql/VariableGenerator.cpp +++ b/arangod/Aql/VariableGenerator.cpp @@ -27,8 +27,8 @@ /// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -#include "Utils/Exception.h" #include "Aql/VariableGenerator.h" +#include "Basics/Exceptions.h" using namespace triagens::aql; using Json = triagens::basics::Json; diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index 64f15b8931..5dd268f0ed 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -115,7 +115,6 @@ add_executable( RestServer/arangod.cpp SkipLists/skiplistIndex.cpp Utils/DocumentHelper.cpp - Utils/Exception.cpp Utils/StandaloneTransactionContext.cpp Utils/Transaction.cpp Utils/TransactionContext.cpp diff --git a/arangod/CapConstraint/cap-constraint.cpp b/arangod/CapConstraint/cap-constraint.cpp index cf1abe318f..4dcf6facbf 100644 --- a/arangod/CapConstraint/cap-constraint.cpp +++ b/arangod/CapConstraint/cap-constraint.cpp @@ -31,7 +31,7 @@ #include "Basics/logging.h" #include "Basics/tri-strings.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "Utils/transactions.h" #include "VocBase/document-collection.h" #include "VocBase/headers.h" diff --git a/arangod/Makefile.files b/arangod/Makefile.files index 1750535e8a..6616eb7f33 100644 --- a/arangod/Makefile.files +++ b/arangod/Makefile.files @@ -79,6 +79,7 @@ arangod_libarangod_a_SOURCES = \ arangod/RestHandler/RestEdgeHandler.cpp \ arangod/RestHandler/RestImportHandler.cpp \ arangod/RestHandler/RestPleaseUpgradeHandler.cpp \ + arangod/RestHandler/RestQueryHandler.cpp \ arangod/RestHandler/RestReplicationHandler.cpp \ arangod/RestHandler/RestUploadHandler.cpp \ arangod/RestHandler/RestVocbaseBaseHandler.cpp \ @@ -88,7 +89,6 @@ arangod_libarangod_a_SOURCES = \ arangod/RestServer/arangod.cpp \ arangod/SkipLists/skiplistIndex.cpp \ arangod/Utils/DocumentHelper.cpp \ - arangod/Utils/Exception.cpp \ arangod/Utils/StandaloneTransactionContext.cpp \ arangod/Utils/Transaction.cpp \ arangod/Utils/TransactionContext.cpp \ diff --git a/arangod/Replication/ContinuousSyncer.cpp b/arangod/Replication/ContinuousSyncer.cpp index 0c62a33518..ddd5a17e7e 100644 --- a/arangod/Replication/ContinuousSyncer.cpp +++ b/arangod/Replication/ContinuousSyncer.cpp @@ -29,6 +29,7 @@ #include "ContinuousSyncer.h" +#include "Basics/Exceptions.h" #include "Basics/json.h" #include "Basics/JsonHelper.h" #include "Basics/StringBuffer.h" @@ -38,7 +39,6 @@ #include "SimpleHttpClient/SimpleHttpClient.h" #include "SimpleHttpClient/SimpleHttpResult.h" #include "Utils/CollectionGuard.h" -#include "Utils/Exception.h" #include "Utils/transactions.h" #include "VocBase/document-collection.h" #include "VocBase/transaction.h" @@ -647,7 +647,7 @@ int ContinuousSyncer::changeCollection (TRI_json_t const* json) { bool doSync = _vocbase->_settings.forceSyncProperties; return TRI_UpdateCollectionInfo(_vocbase, guard.collection()->_collection, ¶meters, doSync); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { diff --git a/arangod/Replication/InitialSyncer.cpp b/arangod/Replication/InitialSyncer.cpp index fab84d756f..3d42a2edb7 100644 --- a/arangod/Replication/InitialSyncer.cpp +++ b/arangod/Replication/InitialSyncer.cpp @@ -29,6 +29,7 @@ #include "InitialSyncer.h" +#include "Basics/Exceptions.h" #include "Basics/json.h" #include "Basics/logging.h" #include "Basics/tri-strings.h" @@ -37,7 +38,6 @@ #include "SimpleHttpClient/SimpleHttpClient.h" #include "SimpleHttpClient/SimpleHttpResult.h" #include "Utils/CollectionGuard.h" -#include "Utils/Exception.h" #include "Utils/transactions.h" #include "VocBase/index.h" #include "VocBase/document-collection.h" @@ -858,7 +858,7 @@ int InitialSyncer::handleCollection (TRI_json_t const* parameters, TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/Replication/Syncer.cpp b/arangod/Replication/Syncer.cpp index bfbef7ecd5..10d6795e98 100644 --- a/arangod/Replication/Syncer.cpp +++ b/arangod/Replication/Syncer.cpp @@ -33,13 +33,13 @@ #include "Basics/json.h" #include "Basics/tri-strings.h" #include "Basics/JsonHelper.h" +#include "Basics/Exceptions.h" #include "Rest/HttpRequest.h" #include "SimpleHttpClient/GeneralClientConnection.h" #include "SimpleHttpClient/SimpleHttpClient.h" #include "SimpleHttpClient/SimpleHttpResult.h" #include "Utils/CollectionGuard.h" #include "Utils/DocumentHelper.h" -#include "Utils/Exception.h" #include "Utils/transactions.h" #include "VocBase/collection.h" #include "VocBase/document-collection.h" @@ -291,7 +291,7 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti return res; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -313,7 +313,7 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti res = TRI_ERROR_NO_ERROR; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -501,7 +501,7 @@ int Syncer::createIndex (TRI_json_t const* json) { return res; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -542,7 +542,7 @@ int Syncer::dropIndex (TRI_json_t const* json) { return TRI_ERROR_NO_ERROR; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { diff --git a/arangod/RestHandler/RestPleaseUpgradeHandler.cpp b/arangod/RestHandler/RestPleaseUpgradeHandler.cpp index 0276572801..dbe34fb48c 100644 --- a/arangod/RestHandler/RestPleaseUpgradeHandler.cpp +++ b/arangod/RestHandler/RestPleaseUpgradeHandler.cpp @@ -83,7 +83,14 @@ HttpHandler::status_t RestPleaseUpgradeHandler::execute () { /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// -void RestPleaseUpgradeHandler::handleError (TriagensError const&) { +void RestPleaseUpgradeHandler::handleError (const TriagensError&) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +void RestPleaseUpgradeHandler::handleError (const Exception&) { } // ----------------------------------------------------------------------------- diff --git a/arangod/RestHandler/RestPleaseUpgradeHandler.h b/arangod/RestHandler/RestPleaseUpgradeHandler.h index 6ca72b9af9..d938919b18 100644 --- a/arangod/RestHandler/RestPleaseUpgradeHandler.h +++ b/arangod/RestHandler/RestPleaseUpgradeHandler.h @@ -81,7 +81,13 @@ namespace triagens { /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// - void handleError (basics::TriagensError const&); + void handleError (const basics::TriagensError&); + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + void handleError (const basics::Exception&); }; } } diff --git a/arangod/RestHandler/RestQueryHandler.cpp b/arangod/RestHandler/RestQueryHandler.cpp new file mode 100644 index 0000000000..f8170ac50c --- /dev/null +++ b/arangod/RestHandler/RestQueryHandler.cpp @@ -0,0 +1,467 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief query request handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2010-2014, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "RestQueryHandler.h" + +#include "Aql/Query.h" +#include "Aql/QueryList.h" +#include "Basics/StringUtils.h" +#include "Basics/conversions.h" +#include "Basics/json.h" +#include "Basics/string-buffer.h" +#include "Basics/json-utilities.h" +#include "Rest/HttpRequest.h" +#include "VocBase/document-collection.h" +#include "VocBase/vocbase.h" +#include "Cluster/ServerState.h" +#include "Cluster/ClusterInfo.h" +#include "Cluster/ClusterComm.h" +#include "Cluster/ClusterMethods.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::rest; +using namespace triagens::arango; +using namespace triagens::aql; + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + +RestQueryHandler::RestQueryHandler (HttpRequest* request, ApplicationV8* applicationV8) + : RestVocbaseBaseHandler(request), + _applicationV8(applicationV8) { +} + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::isDirect () { + return _request->requestType() != HttpRequest::HTTP_REQUEST_POST; +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_t RestQueryHandler::execute () { + + // extract the sub-request type + HttpRequest::HttpRequestType type = _request->requestType(); + + // execute one of the CRUD methods + switch (type) { + case HttpRequest::HTTP_REQUEST_DELETE: deleteQuery(); break; + case HttpRequest::HTTP_REQUEST_GET: readQuery(); break; + case HttpRequest::HTTP_REQUEST_PUT: replaceProperties(); break; + case HttpRequest::HTTP_REQUEST_POST: parseQuery(); break; + + case HttpRequest::HTTP_REQUEST_HEAD: + case HttpRequest::HTTP_REQUEST_PATCH: + case HttpRequest::HTTP_REQUEST_ILLEGAL: + default: { + generateNotImplemented("ILLEGAL " + DOCUMENT_PATH); + break; + } + } + + // this handler is done + return status_t(HANDLER_DONE); +} + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the list of properties +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::readQueryProperties () { + try { + auto queryList = static_cast(_vocbase->_queries); + + Json result(Json::Object); + + result + .set("error", Json(false)) + .set("code", Json(HttpResponse::OK)) + .set("enabled", Json(queryList->enabled())) + .set("trackSlowQueries", Json(queryList->trackSlowQueries())) + .set("maxSlowQueries", Json(static_cast(queryList->maxSlowQueries()))) + .set("slowQueryThreshold", Json(queryList->slowQueryThreshold())) + .set("maxQueryStringLength", Json(static_cast(queryList->maxQueryStringLength()))); + + generateResult(HttpResponse::OK, result.json()); + } + catch (const TriagensError& err) { + handleError(err); + } + catch (const Exception& err) { + handleError(err); + } + catch (std::exception const& ex) { + triagens::basics::InternalError err(ex, __FILE__, __LINE__); + handleError(err); + } + catch (...) { + triagens::basics::InternalError err("executeDirectHandler", __FILE__, __LINE__); + handleError(err); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the list of slow queries +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::readQuery (bool slow) { + try { + auto queryList = static_cast(_vocbase->_queries); + auto const&& queries = slow ? queryList->listSlow() : queryList->listCurrent(); + Json result(Json::Array); + + for (auto it : queries) { + const auto&& timeString = TRI_StringTimeStamp(it.started); + const auto& queryString = it.queryString; + + Json entry(Json::Object); + + entry + .set("id", Json(StringUtils::itoa(it.id))) + .set("query", Json(queryString)) + .set("started", Json(timeString)) + .set("runTime", Json(it.runTime)); + + result.add(entry); + } + + generateResult(HttpResponse::OK, result.json()); + } + catch (const TriagensError& err) { + handleError(err); + } + catch (const Exception& err) { + handleError(err); + } + catch (std::exception const& ex) { + triagens::basics::InternalError err(ex, __FILE__, __LINE__); + handleError(err); + } + catch (...) { + triagens::basics::InternalError err("executeDirectHandler", __FILE__, __LINE__); + handleError(err); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns AQL query tracking +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::readQuery () { + const auto& suffix = _request->suffix(); + + if (suffix.size() != 1) { + generateError(HttpResponse::BAD, + TRI_ERROR_HTTP_BAD_PARAMETER, + "expecting GET /_api/query/"); + return true; + } + + const auto& name = suffix[0]; + + if (name == "slow") { + return readQuery(true); + } + else if (name == "current") { + return readQuery(false); + } + else if (name == "properties") { + return readQueryProperties(); + } + + generateError(HttpResponse::NOT_FOUND, + TRI_ERROR_HTTP_NOT_FOUND, + "unknown type '" + name + "', expecting 'slow', 'current', or 'properties'"); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes the slow log +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::deleteQuerySlow () { + auto queryList = static_cast(_vocbase->_queries); + queryList->clearSlow(); + + Json result(Json::Object); + + // added a "generateOk"? + + result + .set("error", Json(false)) + .set("code", Json(HttpResponse::OK)); + + generateResult(HttpResponse::OK, result.json()); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief interrupts a named query +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::deleteQuery (const string& name) { + auto id = StringUtils::uint64(name); + auto queryList = static_cast(_vocbase->_queries); + TRI_ASSERT(queryList != nullptr); + + auto res = queryList->kill(id); + + if (res == TRI_ERROR_NO_ERROR) { + Json result(Json::Object); + + result + .set("error", Json(false)) + .set("code", Json(HttpResponse::OK)); + + generateResult(HttpResponse::OK, result.json()); + } + else { + generateError(HttpResponse::BAD, res, "cannot kill query '" + name + "'"); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief interrupts a query +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::deleteQuery () { + const auto& suffix = _request->suffix(); + + if (suffix.size() != 1) { + generateError(HttpResponse::BAD, + TRI_ERROR_HTTP_BAD_PARAMETER, + "expecting DELETE /_api/query/ or /_api/query/slow"); + return true; + } + + const auto& name = suffix[0]; + + if (name == "slow") { + return deleteQuerySlow(); + } + else { + return deleteQuery(name); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the settings +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::replaceProperties () { + const auto& suffix = _request->suffix(); + + if (suffix.size() != 1 || suffix[0] != "properties") { + generateError(HttpResponse::BAD, + TRI_ERROR_HTTP_BAD_PARAMETER, + "expecting PUT /_api/query/properties"); + return true; + } + + unique_ptr body(parseJsonBody()); + + if (body == nullptr) { + // error message generated in parseJsonBody + return true; + } + + auto queryList = static_cast(_vocbase->_queries); + + try { + bool enabled = queryList->enabled(); + bool trackSlowQueries = queryList->trackSlowQueries(); + size_t maxSlowQueries = queryList->maxSlowQueries(); + double slowQueryThreshold = queryList->slowQueryThreshold(); + size_t maxQueryStringLength = queryList->maxQueryStringLength(); + + // TODO(fc) add a "hasSomething" to JsonHelper? + + if (JsonHelper::getObjectElement(body.get(), "enabled") != nullptr) { + enabled = JsonHelper::checkAndGetBooleanValue(body.get(), "enabled"); + } + + if (JsonHelper::getObjectElement(body.get(), "trackSlowQueries") != nullptr) { + trackSlowQueries = JsonHelper::checkAndGetBooleanValue(body.get(), "trackSlowQueries"); + } + + if (JsonHelper::getObjectElement(body.get(), "maxSlowQueries") != nullptr) { + maxSlowQueries = JsonHelper::checkAndGetNumericValue(body.get(), "maxSlowQueries"); + } + + if (JsonHelper::getObjectElement(body.get(), "slowQueryThreshold") != nullptr) { + slowQueryThreshold = JsonHelper::checkAndGetNumericValue(body.get(), "slowQueryThreshold"); + } + + if (JsonHelper::getObjectElement(body.get(), "maxQueryStringLength") != nullptr) { + maxQueryStringLength = JsonHelper::checkAndGetNumericValue(body.get(), "maxQueryStringLength"); + } + + queryList->enabled(enabled); + queryList->trackSlowQueries(trackSlowQueries); + queryList->maxSlowQueries(maxSlowQueries); + queryList->slowQueryThreshold(slowQueryThreshold); + queryList->maxQueryStringLength(maxQueryStringLength); + + return readQueryProperties(); + } + catch (const TriagensError& err) { + handleError(err); + } + catch (const Exception& err) { + handleError(err); + } + catch (std::exception const& ex) { + triagens::basics::InternalError err(ex, __FILE__, __LINE__); + handleError(err); + } + catch (...) { + triagens::basics::InternalError err("executeDirectHandler", __FILE__, __LINE__); + handleError(err); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief parses a query +//////////////////////////////////////////////////////////////////////////////// + +bool RestQueryHandler::parseQuery () { + const auto& suffix = _request->suffix(); + + if (! suffix.empty()) { + generateError(HttpResponse::BAD, + TRI_ERROR_HTTP_BAD_PARAMETER, + "expecting POST /_api/query"); + return true; + } + + unique_ptr body(parseJsonBody()); + + if (body.get() == nullptr) { + // error message generated in parseJsonBody + return true; + } + + try { + const string&& queryString = JsonHelper::checkAndGetStringValue(body.get(), "query"); + + Query query(_applicationV8, true, _vocbase, queryString.c_str(), queryString.size(), nullptr, nullptr, PART_MAIN); + + auto parseResult = query.parse(); + + if (parseResult.code != TRI_ERROR_NO_ERROR) { + generateError(HttpResponse::BAD, + parseResult.code, + parseResult.details); + return true; + } + + Json collections(Json::Array); + + for (const auto& it : parseResult.collectionNames) { + collections.add(Json(it)); + } + + Json bindVars(Json::Array); + + for (const auto& it : parseResult.bindParameters) { + bindVars.add(Json(it)); + } + + Json result(Json::Object); + + result + .set("error", Json(false)) + .set("code", Json(HttpResponse::OK)) + .set("parsed", Json(true)) + .set("collections", collections) + .set("bindVars", bindVars) + .set("ast", Json(TRI_UNKNOWN_MEM_ZONE, parseResult.json, Json::NOFREE).copy()); + + if (parseResult.warnings == nullptr) { + result.set("warnings", Json(Json::Array)); + } + else { + result.set("warnings", Json(TRI_UNKNOWN_MEM_ZONE, parseResult.warnings, Json::NOFREE).copy()); + } + + generateResult(HttpResponse::OK, result.json()); + } + catch (const TriagensError& err) { + handleError(err); + } + catch (const Exception& err) { + handleError(err); + } + catch (std::exception const& ex) { + triagens::basics::InternalError err(ex, __FILE__, __LINE__); + handleError(err); + } + catch (...) { + triagens::basics::InternalError err("executeDirectHandler", __FILE__, __LINE__); + handleError(err); + } + + return true; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/RestHandler/RestQueryHandler.h b/arangod/RestHandler/RestQueryHandler.h new file mode 100644 index 0000000000..50078cd6da --- /dev/null +++ b/arangod/RestHandler/RestQueryHandler.h @@ -0,0 +1,163 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief query request handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2010-2014, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef ARANGODB_REST_HANDLER_REST_QUERY_HANDLER_H +#define ARANGODB_REST_HANDLER_REST_QUERY_HANDLER_H 1 + +#include "Basics/Common.h" + +#include "RestHandler/RestVocbaseBaseHandler.h" + +// ----------------------------------------------------------------------------- +// --SECTION-- forward declarations +// ----------------------------------------------------------------------------- + +namespace triagens { + namespace arango { + class ApplicationV8; + +// ----------------------------------------------------------------------------- +// --SECTION-- class RestQueryHandler +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief document request handler +//////////////////////////////////////////////////////////////////////////////// + + class RestQueryHandler : public RestVocbaseBaseHandler { + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + RestQueryHandler (rest::HttpRequest*, ApplicationV8*); + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + bool isDirect (); + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + status_t execute (); + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the list of properties +//////////////////////////////////////////////////////////////////////////////// + + bool readQueryProperties (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the list of slow queries +//////////////////////////////////////////////////////////////////////////////// + + bool readQuery (bool slow); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns AQL query tracking +//////////////////////////////////////////////////////////////////////////////// + + bool readQuery (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes the slow log +//////////////////////////////////////////////////////////////////////////////// + + bool deleteQuerySlow (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief interrupts a named query +//////////////////////////////////////////////////////////////////////////////// + + bool deleteQuery (const std::string& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief interrupts a query +//////////////////////////////////////////////////////////////////////////////// + + bool deleteQuery (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the settings +//////////////////////////////////////////////////////////////////////////////// + + bool replaceProperties (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief parses a query +//////////////////////////////////////////////////////////////////////////////// + + bool parseQuery (); + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief application V8 +//////////////////////////////////////////////////////////////////////////////// + + ApplicationV8* _applicationV8; + }; + } +} + +#endif + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 136a31b62f..4bc60dce75 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -1073,7 +1073,7 @@ void RestReplicationHandler::handleCommandLoggerFollow () { insertClient(dump._lastFoundTick); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -1987,7 +1987,7 @@ int RestReplicationHandler::processRestoreIndexes (TRI_json_t const* collection, } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { errorMsg = "could not create index: " + string(TRI_errno_string(ex.code())); } catch (...) { @@ -2161,7 +2161,7 @@ int RestReplicationHandler::applyCollectionDumpMarker (CollectionNameResolver co return res; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { TRI_FreeShapedJson(zone, shaped); return ex.code(); } @@ -2186,7 +2186,7 @@ int RestReplicationHandler::applyCollectionDumpMarker (CollectionNameResolver co res = TRI_ERROR_NO_ERROR; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -2960,7 +2960,7 @@ void RestReplicationHandler::handleCommandDump () { // avoid double freeing TRI_StealStringBuffer(dump._buffer); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index 9de7aed1d2..7af57d9931 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -62,6 +62,7 @@ #include "RestHandler/RestEdgeHandler.h" #include "RestHandler/RestImportHandler.h" #include "RestHandler/RestPleaseUpgradeHandler.h" +#include "RestHandler/RestQueryHandler.h" #include "RestHandler/RestReplicationHandler.h" #include "RestHandler/RestUploadHandler.h" #include "RestServer/ConsoleThread.h" @@ -99,6 +100,7 @@ bool IGNORE_DATAFILE_ERRORS; //////////////////////////////////////////////////////////////////////////////// void ArangoServer::defineHandlers (HttpHandlerFactory* factory) { + // First the "_api" handlers: // add "/version" handler @@ -145,6 +147,11 @@ void ArangoServer::defineHandlers (HttpHandlerFactory* factory) { RestHandlerCreator::createData*>, _pairForAql); + factory->addPrefixHandler("/_api/query", + RestHandlerCreator::createData, + _applicationV8); + + // And now the "_admin" handlers // add "/_admin/version" handler @@ -1083,7 +1090,6 @@ int ArangoServer::runConsole (TRI_vocbase_t* vocbase) { //////////////////////////////////////////////////////////////////////////////// int ArangoServer::runUnitTests (TRI_vocbase_t* vocbase) { - ApplicationV8::V8Context* context = _applicationV8->enterContext("STANDARD", vocbase, true); auto isolate = context->isolate; diff --git a/arangod/Utils/CollectionGuard.h b/arangod/Utils/CollectionGuard.h index cc00c9eaee..10973fb626 100644 --- a/arangod/Utils/CollectionGuard.h +++ b/arangod/Utils/CollectionGuard.h @@ -31,7 +31,7 @@ #define ARANGODB_UTILS_COLLECTION_GUARD_H 1 #include "Basics/Common.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/vocbase.h" namespace triagens { diff --git a/arangod/Utils/DatabaseGuard.h b/arangod/Utils/DatabaseGuard.h index bd99df8841..447e289144 100644 --- a/arangod/Utils/DatabaseGuard.h +++ b/arangod/Utils/DatabaseGuard.h @@ -31,7 +31,7 @@ #define ARANGODB_UTILS_DATABASE_GUARD_H 1 #include "Basics/Common.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/server.h" struct TRI_vocbase_s; diff --git a/arangod/Utils/Exception.cpp b/arangod/Utils/Exception.cpp deleted file mode 100644 index 94c376909c..0000000000 --- a/arangod/Utils/Exception.cpp +++ /dev/null @@ -1,188 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief arango exceptions -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2014 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany -/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#include "Exception.h" -#include "Basics/StringUtils.h" - -using namespace std; -using namespace triagens::arango; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief controls if backtraces are printed with exceptions -//////////////////////////////////////////////////////////////////////////////// - -static bool WithBackTrace = false; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief constructor, without format string -//////////////////////////////////////////////////////////////////////////////// - -Exception::Exception (int code, - char const* file, - int line) - : _errorMessage(TRI_errno_string(code)), - _file(file), - _line(line), - _code(code) { -#ifdef TRI_ENABLE_MAINTAINER_MODE -#if HAVE_BACKTRACE - if (WithBackTrace) { - _errorMessage += std::string("\n\n"); - TRI_GetBacktrace(_errorMessage); - _errorMessage += std::string("\n\n"); - } -#endif -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief constructor, for creating an exception with an already created -/// error message (normally based on error templates containing %s, %d etc.) -//////////////////////////////////////////////////////////////////////////////// - -Exception::Exception (int code, - string const& errorMessage, - char const* file, - int line) - : _errorMessage(errorMessage), - _file(file), - _line(line), - _code(code) { - -#ifdef TRI_ENABLE_MAINTAINER_MODE -#if HAVE_BACKTRACE - if (WithBackTrace) { - _errorMessage += std::string("\n\n"); - TRI_GetBacktrace(_errorMessage); - _errorMessage += std::string("\n\n"); - } -#endif -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief destructor -//////////////////////////////////////////////////////////////////////////////// - -Exception::~Exception () throw () { -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return exception message -//////////////////////////////////////////////////////////////////////////////// - -char const* Exception::what () const throw () { - // we have to use an instance member here because we should not return a - // pointer (c_str()) to the internals of a stack object (stack object will - // be destroyed when function is left...) - // additionally, we should not create new string values here as this might - // throw exceptions - but this function is marked to throw no exceptions! - /* - std::string message = "exception in '"; - message.append(_file); - message.append("' at line "); - message.append(basics::StringUtils::itoa(_line)); - message.append(": "); - message += this->message(); - - return message.c_str(); - */ - - return _errorMessage.c_str(); -} - - - - -//////////////////////////////////////////////////////////////////////////////// -/// @brief construct an error message from a template string -//////////////////////////////////////////////////////////////////////////////// - -std::string Exception::FillExceptionString (int code, - ...) { - char const* format = TRI_errno_string(code); - TRI_ASSERT(format != nullptr); - -#ifdef TRI_ENABLE_MAINTAINER_MODE - // Obviously the formatstring of the error code has to support parameters. - TRI_ASSERT(strchr(format, '%') != nullptr); -#endif - - char buffer[1024]; - va_list ap; - va_start(ap, code); - vsnprintf(buffer, sizeof(buffer) - 1, format, ap); - va_end(ap); - buffer[sizeof(buffer) - 1] = '\0'; // Windows - - return std::string(buffer); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief construct an error message from a template string -//////////////////////////////////////////////////////////////////////////////// - -std::string Exception::FillFormatExceptionString (char const* format, - ...) { - TRI_ASSERT(format != nullptr); - -#ifdef TRI_ENABLE_MAINTAINER_MODE - // Format #1 should come from the macro... - TRI_ASSERT(strchr(format, '%') != nullptr); - // Obviously the user has to give us a format string. - TRI_ASSERT(strchr(strchr(format, '%'), '%') != nullptr); -#endif - - char buffer[1024]; - va_list ap; - va_start(ap, format); - vsnprintf(buffer, sizeof(buffer) - 1, format, ap); - va_end(ap); - buffer[sizeof(buffer) - 1] = '\0'; // Windows - - return std::string(buffer); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// @brief controls whether a backtrace is created for each exception -//////////////////////////////////////////////////////////////////////////////// - -void Exception::SetVerbose (bool verbose) { - WithBackTrace = verbose; -} - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- - -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" -// End: diff --git a/arangod/Utils/Exception.h b/arangod/Utils/Exception.h deleted file mode 100644 index a4e8fa98fd..0000000000 --- a/arangod/Utils/Exception.h +++ /dev/null @@ -1,151 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief arango exceptions -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2014 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany -/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ARANGODB_UTILS_EXCEPTION_H -#define ARANGODB_UTILS_EXCEPTION_H 1 - -#include "Basics/Common.h" -#include "Basics/Exceptions.h" - -#include - -// ----------------------------------------------------------------------------- -// --SECTION-- public macros -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief throws an arango exception with an error code -//////////////////////////////////////////////////////////////////////////////// - -#define THROW_ARANGO_EXCEPTION(code) \ - throw triagens::arango::Exception(code, __FILE__, __LINE__) - -//////////////////////////////////////////////////////////////////////////////// -/// @brief throws an arango exception with an error code and arbitrary -/// arguments (to be inserted in printf-style manner) -//////////////////////////////////////////////////////////////////////////////// - -#define THROW_ARANGO_EXCEPTION_PARAMS(code, ...) \ - throw triagens::arango::Exception(code, triagens::arango::Exception::FillExceptionString(code, __VA_ARGS__), __FILE__, __LINE__) - - - -//////////////////////////////////////////////////////////////////////////////// -/// @brief throws an arango exception with an error code and arbitrary -/// arguments (to be inserted in printf-style manner) -//////////////////////////////////////////////////////////////////////////////// - -#define THROW_ARANGO_EXCEPTION_FORMAT(code, format, ...) \ - throw triagens::arango::Exception(code, \ - triagens::arango::Exception::FillFormatExceptionString( \ - "%s: " format,\ - TRI_errno_string(code), \ - __VA_ARGS__),\ - __FILE__, __LINE__) - -//////////////////////////////////////////////////////////////////////////////// -/// @brief throws an arango exception with an error code and an already-built -/// error message -//////////////////////////////////////////////////////////////////////////////// - -#define THROW_ARANGO_EXCEPTION_MESSAGE(code, message) \ - throw triagens::arango::Exception(code, message, __FILE__, __LINE__) - -// ----------------------------------------------------------------------------- -// --SECTION-- public types -// ----------------------------------------------------------------------------- - -namespace triagens { - namespace arango { - -//////////////////////////////////////////////////////////////////////////////// -/// @brief arango exception type -//////////////////////////////////////////////////////////////////////////////// - - class Exception : public virtual std::exception { - - public: - - Exception (int code, - char const* file, - int line); - - Exception (int code, - std::string const& errorMessage, - char const* file, - int line); - - ~Exception () throw (); - - public: - - char const * what () const throw (); - - std::string message () const throw () { - return _errorMessage; - } - - int code () const throw () { - return _code; - } - - void addToMessage(std::string More) { - _errorMessage += More; - } - - static std::string FillExceptionString (int, ...); - static std::string FillFormatExceptionString (char const * format, - ...); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief controls whether a backtrace is created for each exception -//////////////////////////////////////////////////////////////////////////////// - - static void SetVerbose (bool); - - protected: - std::string _errorMessage; - char const* _file; - int const _line; - int const _code; - }; - - } -} - -#endif - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- - -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" -// End: diff --git a/arangod/Utils/Transaction.h b/arangod/Utils/Transaction.h index 1b6c660b7c..f0bb948508 100644 --- a/arangod/Utils/Transaction.h +++ b/arangod/Utils/Transaction.h @@ -34,7 +34,7 @@ #include "Cluster/ServerState.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/barrier.h" #include "VocBase/collection.h" #include "VocBase/document-collection.h" @@ -542,7 +542,7 @@ namespace triagens { ! isLocked(trxCollection, TRI_TRANSACTION_WRITE), forceSync); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -648,7 +648,7 @@ namespace triagens { mptr, ! isLocked(trxCollection, TRI_TRANSACTION_READ)); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -1179,7 +1179,7 @@ namespace triagens { forceSync, false); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -1218,7 +1218,7 @@ namespace triagens { ! isLocked(trxCollection, TRI_TRANSACTION_WRITE), forceSync); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { return ex.code(); } catch (...) { @@ -1270,7 +1270,7 @@ namespace triagens { } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 3550e8f500..6840aff61a 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -2257,7 +2257,7 @@ static void JS_PropertiesVocbaseCol (const v8::FunctionCallbackInfo& THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/V8Server/v8-user-structures.cpp b/arangod/V8Server/v8-user-structures.cpp index f0555566a1..4555a61a46 100644 --- a/arangod/V8Server/v8-user-structures.cpp +++ b/arangod/V8Server/v8-user-structures.cpp @@ -28,6 +28,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "v8-user-structures.h" +#include "Basics/Exceptions.h" #include "Basics/ReadWriteLock.h" #include "Basics/ReadLocker.h" #include "Basics/WriteLocker.h" @@ -35,7 +36,6 @@ #include "Basics/json.h" #include "Basics/json-utilities.h" #include "Basics/tri-strings.h" -#include "Utils/Exception.h" #include "VocBase/vocbase.h" #include "V8/v8-conv.h" #include "V8/v8-utils.h" diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 9abf35ce2d..395c1428d3 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -582,7 +582,7 @@ static void JS_EnableNativeBacktraces (const v8::FunctionCallbackInfo TRI_V8_THROW_EXCEPTION_USAGE("ENABLE_NATIVE_BACKTRACES()"); } - triagens::arango::Exception::SetVerbose(TRI_ObjectToBoolean(args[0])); + triagens::basics::Exception::SetVerbose(TRI_ObjectToBoolean(args[0])); TRI_V8_RETURN_UNDEFINED(); } diff --git a/arangod/VocBase/document-collection.cpp b/arangod/VocBase/document-collection.cpp index 5edb1cfc21..f86731437c 100644 --- a/arangod/VocBase/document-collection.cpp +++ b/arangod/VocBase/document-collection.cpp @@ -35,6 +35,7 @@ #include "Basics/logging.h" #include "Basics/tri-strings.h" #include "Basics/ThreadPool.h" +#include "Basics/Exceptions.h" #include "CapConstraint/cap-constraint.h" #include "FulltextIndex/fulltext-index.h" #include "GeoIndex/geo-index.h" @@ -44,7 +45,6 @@ #include "Utils/transactions.h" #include "Utils/CollectionReadLocker.h" #include "Utils/CollectionWriteLocker.h" -#include "Utils/Exception.h" #include "VocBase/edge-collection.h" #include "VocBase/index.h" #include "VocBase/key-generator.h" @@ -3505,7 +3505,7 @@ bool TRI_DropIndexDocumentCollection (TRI_document_collection_t* document, return true; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/index.cpp b/arangod/VocBase/index.cpp index 369497f3bb..0ee37b7747 100644 --- a/arangod/VocBase/index.cpp +++ b/arangod/VocBase/index.cpp @@ -39,6 +39,7 @@ #include "Basics/fasthash.h" #include "Basics/json-utilities.h" #include "Basics/JsonHelper.h" +#include "Basics/Exceptions.h" #include "CapConstraint/cap-constraint.h" #include "FulltextIndex/fulltext-index.h" #include "FulltextIndex/fulltext-wordlist.h" @@ -46,7 +47,6 @@ #include "HashIndex/hash-index.h" #include "ShapedJson/shape-accessor.h" #include "ShapedJson/shaped-json.h" -#include "Utils/Exception.h" #include "VocBase/document-collection.h" #include "VocBase/edge-collection.h" #include "VocBase/server.h" @@ -386,7 +386,7 @@ int TRI_SaveIndex (TRI_document_collection_t* document, TRI_FreeJson(TRI_CORE_MEM_ZONE, json); return TRI_ERROR_NO_ERROR; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/replication-dump.cpp b/arangod/VocBase/replication-dump.cpp index dfaff341f7..9b3074b219 100644 --- a/arangod/VocBase/replication-dump.cpp +++ b/arangod/VocBase/replication-dump.cpp @@ -1442,7 +1442,7 @@ int TRI_DumpLogReplication (TRI_replication_dump_t* dump, } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/replication-dump.h b/arangod/VocBase/replication-dump.h index 689ae4ffab..3fdfd0a9d6 100644 --- a/arangod/VocBase/replication-dump.h +++ b/arangod/VocBase/replication-dump.h @@ -34,8 +34,8 @@ #include "Basics/associative.h" #include "Basics/string-buffer.h" +#include "Basics/Exceptions.h" #include "ShapedJson/shaped-json.h" -#include "Utils/Exception.h" #include "VocBase/replication-common.h" #include "VocBase/voc-types.h" #include "VocBase/vocbase.h" diff --git a/arangod/VocBase/server.cpp b/arangod/VocBase/server.cpp index 73f2e6e8c4..bf784a2134 100644 --- a/arangod/VocBase/server.cpp +++ b/arangod/VocBase/server.cpp @@ -46,7 +46,7 @@ #include "Basics/random.h" #include "Basics/tri-strings.h" #include "Basics/JsonHelper.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/auth.h" #include "VocBase/replication-applier.h" #include "VocBase/vocbase.h" @@ -1503,7 +1503,7 @@ static int WriteCreateMarker (TRI_voc_tick_t id, THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -1533,7 +1533,7 @@ static int WriteDropMarker (TRI_voc_tick_t id) { THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/transaction.cpp b/arangod/VocBase/transaction.cpp index e428eada04..20d4a30ff1 100644 --- a/arangod/VocBase/transaction.cpp +++ b/arangod/VocBase/transaction.cpp @@ -32,8 +32,7 @@ #include "Basics/conversions.h" #include "Basics/logging.h" #include "Basics/tri-strings.h" - -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/collection.h" #include "VocBase/document-collection.h" #include "VocBase/server.h" @@ -648,7 +647,7 @@ static int WriteBeginMarker (TRI_transaction_t* trx) { trx->_beginWritten = true; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -695,7 +694,7 @@ static int WriteAbortMarker (TRI_transaction_t* trx) { res = GetLogfileManager()->allocateAndWrite(marker, false).errorCode; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -738,7 +737,7 @@ static int WriteCommitMarker (TRI_transaction_t* trx) { res = GetLogfileManager()->allocateAndWrite(marker, false).errorCode; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/voc-shaper.cpp b/arangod/VocBase/voc-shaper.cpp index 3b3c5e939e..7341566d01 100644 --- a/arangod/VocBase/voc-shaper.cpp +++ b/arangod/VocBase/voc-shaper.cpp @@ -41,7 +41,7 @@ #include "Basics/logging.h" #include "Basics/tri-strings.h" #include "Basics/utf8-helper.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/document-collection.h" #include "Wal/LogfileManager.h" @@ -218,7 +218,7 @@ static TRI_shape_aid_t FindOrCreateAttributeByName (TRI_shaper_t* shaper, return aid; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -387,7 +387,7 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape); return result; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/VocBase/vocbase.cpp b/arangod/VocBase/vocbase.cpp index 602e6afef3..fe5513d3b1 100644 --- a/arangod/VocBase/vocbase.cpp +++ b/arangod/VocBase/vocbase.cpp @@ -45,8 +45,7 @@ #include "Basics/random.h" #include "Basics/tri-strings.h" #include "Basics/threads.h" - -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "Utils/transactions.h" #include "VocBase/auth.h" #include "VocBase/barrier.h" @@ -182,7 +181,7 @@ static int WriteDropCollectionMarker (TRI_vocbase_t* vocbase, THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -682,7 +681,7 @@ static TRI_vocbase_col_t* CreateCollection (TRI_vocbase_t* vocbase, TRI_FreeJson(TRI_CORE_MEM_ZONE, json); return collection; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -833,7 +832,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase, return TRI_ERROR_NO_ERROR; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/Wal/AllocatorThread.cpp b/arangod/Wal/AllocatorThread.cpp index 16c608e33a..b12a736ffd 100644 --- a/arangod/Wal/AllocatorThread.cpp +++ b/arangod/Wal/AllocatorThread.cpp @@ -30,7 +30,7 @@ #include "AllocatorThread.h" #include "Basics/logging.h" #include "Basics/ConditionLocker.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "Wal/LogfileManager.h" using namespace triagens::wal; @@ -157,7 +157,7 @@ void AllocatorThread::run () { LOG_ERROR("unable to create new WAL reserve logfile"); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { int res = ex.code(); LOG_ERROR("got unexpected error in allocatorThread: %s", TRI_errno_string(res)); } diff --git a/arangod/Wal/CollectorThread.cpp b/arangod/Wal/CollectorThread.cpp index 9b5263265d..5bb5869b46 100644 --- a/arangod/Wal/CollectorThread.cpp +++ b/arangod/Wal/CollectorThread.cpp @@ -28,13 +28,14 @@ //////////////////////////////////////////////////////////////////////////////// #include "CollectorThread.h" + #include "Basics/MutexLocker.h" #include "Basics/hashes.h" #include "Basics/logging.h" #include "Basics/ConditionLocker.h" +#include "Basics/Exceptions.h" #include "Utils/CollectionGuard.h" #include "Utils/DatabaseGuard.h" -#include "Utils/Exception.h" #include "Utils/transactions.h" #include "VocBase/document-collection.h" #include "VocBase/server.h" @@ -365,7 +366,7 @@ void CollectorThread::run () { throw; } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { int res = ex.code(); LOG_ERROR("got unexpected error in collectorThread::run: %s", TRI_errno_string(res)); } @@ -468,7 +469,7 @@ bool CollectorThread::processQueuedOperations () { try { res = processCollectionOperations((*it2)); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } @@ -704,7 +705,7 @@ int CollectorThread::processCollectionOperations (CollectorCache* cache) { res = TRI_ERROR_NO_ERROR; } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -807,7 +808,7 @@ int CollectorThread::collect (Logfile* logfile) { try { res = transferMarkers(logfile, cid, state.collections[cid], state.operationsCount[cid], sortedOperations); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -886,7 +887,7 @@ int CollectorThread::transferMarkers (Logfile* logfile, queueOperations(logfile, cache); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index f90165ce07..73af4a1b29 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -38,7 +38,6 @@ #include "Basics/ReadLocker.h" #include "Basics/StringUtils.h" #include "Basics/WriteLocker.h" -#include "Utils/Exception.h" #include "VocBase/server.h" #include "Wal/AllocatorThread.h" #include "Wal/CollectorThread.h" diff --git a/arangod/Wal/RecoverState.cpp b/arangod/Wal/RecoverState.cpp index c3214a96c9..b176ca8231 100644 --- a/arangod/Wal/RecoverState.cpp +++ b/arangod/Wal/RecoverState.cpp @@ -31,12 +31,12 @@ #include "Basics/FileUtils.h" #include "Basics/conversions.h" #include "Basics/files.h" +#include "Basics/Exceptions.h" #include "VocBase/collection.h" #include "VocBase/replication-applier.h" #include "VocBase/voc-shaper.h" #include "Wal/LogfileManager.h" #include "Wal/Slots.h" -#include "Utils/Exception.h" using namespace triagens::wal; @@ -452,7 +452,7 @@ int RecoverState::executeRemoteOperation (TRI_voc_tick_t databaseId, THROW_ARANGO_EXCEPTION(res); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -536,7 +536,7 @@ int RecoverState::executeSingleOperation (TRI_voc_tick_t databaseId, // commit the operation res = trx->commit(); } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { @@ -1620,7 +1620,7 @@ int RecoverState::abortOpenTransactions () { } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { res = ex.code(); } catch (...) { diff --git a/arangod/Wal/RemoverThread.cpp b/arangod/Wal/RemoverThread.cpp index cc95a386bb..ee3a434b46 100644 --- a/arangod/Wal/RemoverThread.cpp +++ b/arangod/Wal/RemoverThread.cpp @@ -28,9 +28,10 @@ //////////////////////////////////////////////////////////////////////////////// #include "RemoverThread.h" + #include "Basics/logging.h" #include "Basics/ConditionLocker.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "Wal/LogfileManager.h" using namespace triagens::wal; @@ -108,7 +109,7 @@ void RemoverThread::run () { worked = _logfileManager->removeLogfiles(); } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { int res = ex.code(); LOG_ERROR("got unexpected error in removerThread::run: %s", TRI_errno_string(res)); } diff --git a/arangod/Wal/SynchroniserThread.cpp b/arangod/Wal/SynchroniserThread.cpp index 4ec4966f5c..8123e31175 100644 --- a/arangod/Wal/SynchroniserThread.cpp +++ b/arangod/Wal/SynchroniserThread.cpp @@ -28,9 +28,10 @@ //////////////////////////////////////////////////////////////////////////////// #include "SynchroniserThread.h" + #include "Basics/logging.h" #include "Basics/ConditionLocker.h" -#include "Utils/Exception.h" +#include "Basics/Exceptions.h" #include "VocBase/server.h" #include "Wal/LogfileManager.h" #include "Wal/Slots.h" @@ -137,7 +138,7 @@ void SynchroniserThread::run () { } } } - catch (triagens::arango::Exception const& ex) { + catch (triagens::basics::Exception const& ex) { int res = ex.code(); LOG_ERROR("got unexpected error in synchroniserThread: %s", TRI_errno_string(res)); } diff --git a/arangosh/Benchmark/BenchmarkCounter.h b/arangosh/Benchmark/BenchmarkCounter.h index a9744e0a33..d247b66151 100644 --- a/arangosh/Benchmark/BenchmarkCounter.h +++ b/arangosh/Benchmark/BenchmarkCounter.h @@ -61,6 +61,7 @@ namespace triagens { _mutex(), _value(initialValue), _maxValue(maxValue), + _incompleteFailures(0), _failures(0), _done(0) { } @@ -96,6 +97,15 @@ namespace triagens { return _failures; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the failures value +//////////////////////////////////////////////////////////////////////////////// + + size_t incompleteFailures () { + MUTEX_LOCKER(this->_mutex); + return _incompleteFailures; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief get the next x until the max is reached //////////////////////////////////////////////////////////////////////////////// @@ -148,6 +158,15 @@ namespace triagens { _failures += value; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief register a failure +//////////////////////////////////////////////////////////////////////////////// + + void incIncompleteFailures (const size_t value) { + MUTEX_LOCKER(this->_mutex); + _incompleteFailures += value; + } + // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- @@ -172,6 +191,12 @@ namespace triagens { const T _maxValue; +//////////////////////////////////////////////////////////////////////////////// +/// @brief the number of incomplete replies +//////////////////////////////////////////////////////////////////////////////// + + size_t _incompleteFailures; + //////////////////////////////////////////////////////////////////////////////// /// @brief the number of errors //////////////////////////////////////////////////////////////////////////////// diff --git a/arangosh/Benchmark/BenchmarkThread.h b/arangosh/Benchmark/BenchmarkThread.h index 7f92beba45..ca39ea6421 100644 --- a/arangosh/Benchmark/BenchmarkThread.h +++ b/arangosh/Benchmark/BenchmarkThread.h @@ -77,7 +77,8 @@ namespace triagens { double connectTimeout, uint32_t sslProtocol, bool keepAlive, - bool async) + bool async, + bool verbose) : Thread("arangob"), _operation(operation), _startCondition(condition), @@ -100,7 +101,8 @@ namespace triagens { _connection(0), _offset(0), _counter(0), - _time(0.0) { + _time(0.0), + _verbose(verbose) { _errorHeader = StringUtils::tolower(rest::HttpResponse::getBatchErrorHeader()); } @@ -296,6 +298,9 @@ namespace triagens { _time += TRI_microtime() - start; if (result == nullptr || ! result->isComplete()) { + if (result != nullptr){ + _operationsCounter->incIncompleteFailures(numOperations); + } _operationsCounter->incFailures(numOperations); if (result != nullptr) { delete result; @@ -333,6 +338,13 @@ namespace triagens { if (errorCount > 0) { _operationsCounter->incFailures(errorCount); + _warningCount++; + if (_warningCount < MaxWarnings) { + LOG_WARNING("Server side warning count: %lu", errorCount); + if (_verbose) { + LOG_WARNING("Server reply: %s", result->getBody().c_str()); + } + } } } } @@ -369,6 +381,7 @@ namespace triagens { if (result == nullptr || ! result->isComplete()) { _operationsCounter->incFailures(1); if (result != nullptr) { + _operationsCounter->incIncompleteFailures(1); delete result; } _warningCount++; @@ -564,6 +577,12 @@ namespace triagens { static const int MaxWarnings = 5; +//////////////////////////////////////////////////////////////////////////////// +/// @brief output replies if error count in http relpy > 0 +//////////////////////////////////////////////////////////////////////////////// + + bool _verbose; + }; } } diff --git a/arangosh/Benchmark/arangob.cpp b/arangosh/Benchmark/arangob.cpp index b3ce819e1c..521b87e60f 100644 --- a/arangosh/Benchmark/arangob.cpp +++ b/arangosh/Benchmark/arangob.cpp @@ -139,12 +139,19 @@ static bool Progress = true; static string TestCase = "version"; +//////////////////////////////////////////////////////////////////////////////// +/// @brief print out replies on error +//////////////////////////////////////////////////////////////////////////////// + +static bool verbose = false; + //////////////////////////////////////////////////////////////////////////////// /// @brief includes all the test cases //////////////////////////////////////////////////////////////////////////////// #include "Benchmark/test-cases.h" + // ----------------------------------------------------------------------------- // --SECTION-- private functions // ----------------------------------------------------------------------------- @@ -194,6 +201,7 @@ static void ParseProgramOptions (int argc, char* argv[]) { ("complexity", &Complexity, "complexity parameter for the test") ("delay", &Delay, "use a startup delay (necessary only when run in series)") ("progress", &Progress, "show progress") + ("verbose", &verbose, "print out replies if the http-header indicates db-errors") ; BaseClient.setupGeneral(description); @@ -355,7 +363,8 @@ int main (int argc, char* argv[]) { BaseClient.connectTimeout(), BaseClient.sslProtocol(), KeepAlive, - Async); + Async, + verbose); threads.push_back(thread); thread->setOffset((size_t) (i * realStep)); @@ -412,6 +421,7 @@ int main (int argc, char* argv[]) { } size_t failures = operationsCounter.failures(); + size_t incomplete = operationsCounter.incompleteFailures(); cout << endl; cout << "Total number of operations: " << Operations << @@ -437,6 +447,9 @@ int main (int argc, char* argv[]) { if (failures > 0) { cerr << "WARNING: " << failures << " arangob request(s) failed!!" << endl; } + if (incomplete > 0) { + cerr << "WARNING: " << incomplete << " arangob requests with incomplete results!!" << endl; + } testCase->tearDown(); diff --git a/js/actions/api-query.js b/js/actions/api-query.js deleted file mode 100644 index 57b0392428..0000000000 --- a/js/actions/api-query.js +++ /dev/null @@ -1,453 +0,0 @@ -/*jshint strict: false */ -/*global require, AQL_PARSE, AQL_QUERIES_CURRENT, AQL_QUERIES_SLOW, - AQL_QUERIES_PROPERTIES, AQL_QUERIES_KILL */ - -//////////////////////////////////////////////////////////////////////////////// -/// @brief query actions -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2014 ArangoDB GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany -/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -var arangodb = require("org/arangodb"); -var actions = require("org/arangodb/actions"); -var ArangoError = arangodb.ArangoError; - -// ----------------------------------------------------------------------------- -// --SECTION-- HTTP methods -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock GetApiQueryCurrent -/// @brief returns a list of currently running AQL queries -/// -/// @RESTHEADER{GET /_api/query/current, Returns the currently running AQL queries} -/// -/// Returns an array containing the AQL queries currently running in the selected -/// database. Each query is a JSON object with the following attributes: -/// -/// - *id*: the query's id -/// -/// - *query*: the query string (potentially truncated) -/// -/// - *started*: the date and time when the query was started -/// -/// - *runTime*: the query's run time up to the point the list of queries was -/// queried -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// Is returned when the list of queries can be retrieved successfully. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request, -/// -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock GetApiQuerySlow -/// @brief returns a list of slow running AQL queries -/// -/// @RESTHEADER{GET /_api/query/slow, Returns the list of slow AQL queries} -/// -/// Returns an array containing the last AQL queries that exceeded the slow -/// query threshold in the selected database. -/// The maximum amount of queries in the list can be controlled by setting -/// the query tracking property `maxSlowQueries`. The threshold for treating -/// a query as *slow* can be adjusted by setting the query tracking property -/// `slowQueryThreshold`. -/// -/// Each query is a JSON object with the following attributes: -/// -/// - *id*: the query's id -/// -/// - *query*: the query string (potentially truncated) -/// -/// - *started*: the date and time when the query was started -/// -/// - *runTime*: the query's run time up to the point the list of queries was -/// queried -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// Is returned when the list of queries can be retrieved successfully. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request, -/// -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock GetApiQueryProperties -/// @brief returns the configuration for the AQL query tracking -/// -/// @RESTHEADER{GET /_api/query/properties, Returns the properties for the AQL query tracking} -/// -/// Returns the current query tracking configuration. The configuration is a -/// JSON object with the following properties: -/// -/// - *enabled*: if set to *true*, then queries will be tracked. If set to -/// *false*, neither queries nor slow queries will be tracked. -/// -/// - *trackSlowQueries*: if set to *true*, then slow queries will be tracked -/// in the list of slow queries if their runtime exceeds the value set in -/// *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* -/// property must also be set to *true*. -/// -/// - *maxSlowQueries*: the maximum number of slow queries to keep in the list -/// of slow queries. If the list of slow queries is full, the oldest entry in -/// it will be discarded when additional slow queries occur. -/// -/// - *slowQueryThreshold*: the threshold value for treating a query as slow. A -/// query with a runtime greater or equal to this threshold value will be -/// put into the list of slow queries when slow query tracking is enabled. -/// The value for *slowQueryThreshold* is specified in seconds. -/// -/// - *maxQueryStringLength*: the maximum query string length to keep in the -/// list of queries. Query strings can have arbitrary lengths, and this property -/// can be used to save memory in case very long query strings are used. The -/// value is specified in bytes. -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// Is returned when the list of queries can be retrieved successfully. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request, -/// -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -function get_api_query (req, res) { - var suffixes = [ "slow", "current", "properties" ]; - - if (req.suffix.length !== 1 || - suffixes.indexOf(req.suffix[0]) === -1) { - actions.resultNotFound(req, - res, - arangodb.ERROR_HTTP_NOT_FOUND, - arangodb.errors.ERROR_HTTP_NOT_FOUND.message); - return; - } - - var result; - if (req.suffix[0] === "slow") { - result = AQL_QUERIES_SLOW(); - } - else if (req.suffix[0] === "current") { - result = AQL_QUERIES_CURRENT(); - } - else if (req.suffix[0] === "properties") { - result = AQL_QUERIES_PROPERTIES(); - } - - if (result instanceof ArangoError) { - actions.resultBad(req, res, result.errorNum, result.errorMessage); - return; - } - - actions.resultOk(req, res, actions.HTTP_OK, result); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock DeleteApiQuerySlow -/// @brief clears the list of slow AQL queries -/// -/// @RESTHEADER{DELETE /_api/query/slow, Clears the list of slow AQL queries} -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{204} -/// The server will respond with *HTTP 200* when the list of queries was -/// cleared successfully. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request. -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock DeleteApiQueryKill -/// @brief kills an AQL query -/// -/// @RESTHEADER{DELETE /_api/query/{query-id}, Kills a running AQL query} -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// The server will respond with *HTTP 200* when the query was still running when -/// the kill request was executed and the query's kill flag was set. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request. -/// -/// @RESTRETURNCODE{404} -/// The server will respond with *HTTP 404* when no query with the specified -/// id was found. -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -function delete_api_query (req, res) { - if (req.suffix.length !== 1) { - actions.resultNotFound(req, - res, - arangodb.ERROR_HTTP_NOT_FOUND, - arangodb.errors.ERROR_HTTP_NOT_FOUND.message); - return; - } - - if (req.suffix[0] === "slow") { - // erase the slow log - AQL_QUERIES_SLOW(true); - actions.resultOk(req, res, actions.HTTP_NO_CONTENT); - } - else { - // kill a single query - AQL_QUERIES_KILL(req.suffix[0]); - actions.resultOk(req, res, actions.HTTP_OK); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock PutApiQueryProperties -/// @brief changes the configuration for the AQL query tracking -/// -/// @RESTHEADER{PUT /_api/query/properties, Changes the properties for the AQL query tracking} -/// -/// @RESTBODYPARAM{properties,json,required} -/// The properties for query tracking in the current database. -/// -/// The properties need to be passed in the attribute *properties* in the body -/// of the HTTP request. *properties* needs to be a JSON object with the following -/// properties: -/// -/// - *enabled*: if set to *true*, then queries will be tracked. If set to -/// *false*, neither queries nor slow queries will be tracked. -/// -/// - *trackSlowQueries*: if set to *true*, then slow queries will be tracked -/// in the list of slow queries if their runtime exceeds the value set in -/// *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* -/// property must also be set to *true*. -/// -/// - *maxSlowQueries*: the maximum number of slow queries to keep in the list -/// of slow queries. If the list of slow queries is full, the oldest entry in -/// it will be discarded when additional slow queries occur. -/// -/// - *slowQueryThreshold*: the threshold value for treating a query as slow. A -/// query with a runtime greater or equal to this threshold value will be -/// put into the list of slow queries when slow query tracking is enabled. -/// The value for *slowQueryThreshold* is specified in seconds. -/// -/// - *maxQueryStringLength*: the maximum query string length to keep in the -/// list of queries. Query strings can have arbitrary lengths, and this property -/// can be used to save memory in case very long query strings are used. The -/// value is specified in bytes. -/// -/// After the properties have been changed, the current set of properties will -/// be returned in the HTTP response. -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// Is returned if the properties were changed successfully. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request, -/// -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -function put_api_query (req, res) { - - if (req.suffix.length !== 1 || - req.suffix[0] !== "properties") { - actions.resultNotFound(req, - res, - arangodb.ERROR_HTTP_NOT_FOUND, - arangodb.errors.ERROR_HTTP_NOT_FOUND.message); - return; - } - - var json = actions.getJsonBody(req, res); - - if (json === undefined) { - return; - } - - var result = AQL_QUERIES_PROPERTIES(json); - - if (result instanceof ArangoError) { - actions.resultBad(req, res, result.errorNum, result.errorMessage); - return; - } - - actions.resultOk(req, res, actions.HTTP_OK, result); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @startDocuBlock JSF_post_api_query -/// @brief parse an AQL query and return information about it -/// -/// @RESTHEADER{POST /_api/query, Parse an AQL query} -/// -/// @RESTBODYPARAM{query,json,required} -/// To validate a query string without executing it, the query string can be -/// passed to the server via an HTTP POST request. -/// -/// The query string needs to be passed in the attribute *query* of a JSON -/// object as the body of the POST request. -/// -/// @RESTRETURNCODES -/// -/// @RESTRETURNCODE{200} -/// If the query is valid, the server will respond with *HTTP 200* and -/// return the names of the bind parameters it found in the query (if any) in -/// the *bindVars* attribute of the response. It will also return an array -/// of the collections used in the query in the *collections* attribute. -/// If a query can be parsed successfully, the *ast* attribute of the returned -/// JSON will contain the abstract syntax tree representation of the query. -/// The format of the *ast* is subject to change in future versions of -/// ArangoDB, but it can be used to inspect how ArangoDB interprets a given -/// query. Note that the abstract syntax tree will be returned without any -/// optimizations applied to it. -/// -/// @RESTRETURNCODE{400} -/// The server will respond with *HTTP 400* in case of a malformed request, -/// or if the query contains a parse error. The body of the response will -/// contain the error details embedded in a JSON object. -/// -/// @EXAMPLES -/// -/// Valid query: -/// -/// @EXAMPLE_ARANGOSH_RUN{RestQueryValid} -/// var url = "/_api/query"; -/// var body = '{ "query" : "FOR p IN products FILTER p.name == @name LIMIT 2 RETURN p.n" }'; -/// -/// var response = logCurlRequest('POST', url, body); -/// -/// assert(response.code === 200); -/// -/// logJsonResponse(response); -/// @END_EXAMPLE_ARANGOSH_RUN -/// -/// Invalid query: -/// -/// @EXAMPLE_ARANGOSH_RUN{RestQueryInvalid} -/// var url = "/_api/query"; -/// var body = '{ "query" : "FOR p IN products FILTER p.name = @name LIMIT 2 RETURN p.n" }'; -/// -/// var response = logCurlRequest('POST', url, body); -/// -/// assert(response.code === 400); -/// -/// logJsonResponse(response); -/// @END_EXAMPLE_ARANGOSH_RUN -/// @endDocuBlock -//////////////////////////////////////////////////////////////////////////////// - -function post_api_query (req, res) { - if (req.suffix.length !== 0) { - actions.resultNotFound(req, - res, - arangodb.ERROR_HTTP_NOT_FOUND, - arangodb.errors.ERROR_HTTP_NOT_FOUND.message); - return; - } - - var json = actions.getJsonBody(req, res); - - if (json === undefined) { - return; - } - - var result = AQL_PARSE(json.query); - - if (result instanceof ArangoError) { - actions.resultBad(req, res, result.errorNum, result.errorMessage); - return; - } - - result = { - bindVars: result.parameters, - collections: result.collections, - ast: result.ast - }; - - actions.resultOk(req, res, actions.HTTP_OK, result); -} - -// ----------------------------------------------------------------------------- -// --SECTION-- initialiser -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief query actions gateway -//////////////////////////////////////////////////////////////////////////////// - -actions.defineHttp({ - url: "_api/query", - - callback : function (req, res) { - try { - switch (req.requestType) { - case actions.GET: - get_api_query(req, res); - break; - - case actions.PUT: - put_api_query(req, res); - break; - - case actions.POST: - post_api_query(req, res); - break; - - case actions.DELETE: - delete_api_query(req, res); - break; - - default: - actions.resultUnsupported(req, res); - } - } - catch (err) { - actions.resultException(req, res, err, undefined, false); - } - } -}); - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- - -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" -// End: diff --git a/js/common/tests/shell-env.js b/js/common/tests/shell-env.js new file mode 100644 index 0000000000..3c368801c4 --- /dev/null +++ b/js/common/tests/shell-env.js @@ -0,0 +1,103 @@ +/*jshint strict: true, sub: true */ +/*global require, assertTrue, assertFalse, assertEqual, assertNotEqual */ +//////////////////////////////////////////////////////////////////////////////// +/// @brief test filesystem functions +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Wilfried Goesgens +/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var jsunity = require("jsunity"); + +// ----------------------------------------------------------------------------- +// --SECTION-- filesystem +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test attributes +//////////////////////////////////////////////////////////////////////////////// + +function EnvironmentSuite () { + "use strict"; + var env = require("process").env; + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set up +//////////////////////////////////////////////////////////////////////////////// + + setUp : function () { + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief exists() - test if a file / directory exists +//////////////////////////////////////////////////////////////////////////////// + + testEnv : function () { + assertNotEqual(Object.keys(env).length, 0); + + assertFalse(env.hasOwnProperty('UNITTEST')); + + env['UNITTEST'] = 1; + + assertTrue(env.hasOwnProperty('UNITTEST')); + + assertEqual(env['UNITTEST'], 1); + + assertEqual(env.UNITTEST, 1); + + assertEqual(typeof env.UNITTEST, "string"); + + delete env.UNITTEST; + + assertFalse(env.hasOwnProperty('UNITTEST')); + + assertEqual(typeof env.UNITTEST, "undefined"); + } + }; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- main +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(EnvironmentSuite); + +return jsunity.done(); + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: diff --git a/js/node/process.js b/js/node/process.js index 0052e05f48..12e3280c9e 100644 --- a/js/node/process.js +++ b/js/node/process.js @@ -1,5 +1,5 @@ /*jshint esnext: true, strict: false, unused: false, -W051: true */ -/*global require */ +/*global require, exports */ exports.env = require("internal").env; exports.stdout = { isTTY: false diff --git a/js/server/modules/org/arangodb/testing.js b/js/server/modules/org/arangodb/testing.js index 5201906165..8c681f8583 100644 --- a/js/server/modules/org/arangodb/testing.js +++ b/js/server/modules/org/arangodb/testing.js @@ -71,6 +71,8 @@ var optionsDocumentation = [ ' - `jasmineReportFormat`: this option is passed on to the `format`', ' option of the Jasmine options object, only for Jasmine tests.', '', + ' - benchargs : additional commandline arguments to arangob', + '', ' - `valgrind`: if set to true the arangods are run with the valgrind', ' memory checker', ' - `valgrindXmlFileBase`: string to prepend to the xml report name', @@ -177,6 +179,10 @@ function printUsage () { } function filterTestcaseByOptions (testname, options, whichFilter) { + if (options.hasOwnProperty('test')) { + whichFilter.filter = "testcase"; + return testname === options.test; + } if ((testname.indexOf("-cluster") !== -1) && (options.cluster === false)) { whichFilter.filter = 'noncluster'; return false; @@ -1362,14 +1368,20 @@ function runArangoDumpRestore (options, instanceInfo, which, database) { } function runArangoBenchmark (options, instanceInfo, cmds) { - var args = ["--configuration", "none", - "--quiet", - "--server.username", options.username, - "--server.password", options.password, - "--server.endpoint", instanceInfo.endpoint]; - args = args.concat(cmds); + var args = { + "configuration": "none", + "server.username": options.username, + "server.password": options.password, + "server.endpoint": instanceInfo.endpoint, + }; + + args = _.extend(args, cmds); + + if (!args.hasOwnProperty('verbose')) { + args.quiet = "true"; + } var exe = fs.join("bin","arangob"); - return executeAndWait(exe, args); + return executeAndWait(exe, toArgv(args)); } var impTodo = [ @@ -1575,24 +1587,23 @@ testFuncs.dump = function (options) { }; var benchTodo = [ - ["--requests","10000","--concurrency","2","--test","version", "--keep-alive","false"], - ["--requests","10000","--concurrency","2","--test","version", "--async","true"], - ["--requests","20000","--concurrency","1","--test","version", "--async","true"], - ["--requests","100000","--concurrency","2","--test","shapes", "--batch-size","16", "--complexity","2"], - ["--requests","100000","--concurrency","2","--test","shapes-append", "--batch-size","16", "--complexity","4"], - ["--requests","100000","--concurrency","2","--test","random-shapes", "--batch-size","16", "--complexity","2"], - ["--requests","1000","--concurrency","2","--test","version", "--batch-size", "16"], - ["--requests","100","--concurrency","1","--test","version", "--batch-size", "0"], - ["--requests","100","--concurrency","2","--test","document", "--batch-size", - "10", "--complexity", "1"], - ["--requests","2000","--concurrency","2","--test","crud", "--complexity", "1"], - ["--requests","4000","--concurrency","2","--test","crud-append", "--complexity", "4"], - ["--requests","4000","--concurrency","2","--test","edge", "--complexity", "4"], - ["--requests","5000","--concurrency","2","--test","hash","--complexity","1"], - ["--requests","5000","--concurrency","2","--test","skiplist","--complexity","1"], - ["--requests","500","--concurrency","3","--test","aqltrx","--complexity","1"], - ["--requests","100","--concurrency","3","--test","counttrx"], - ["--requests","500","--concurrency","3","--test","multitrx"] + {"requests":"10000", "concurrency":"2", "test":"version", "keep-alive":"false"}, + {"requests":"10000", "concurrency":"2", "test":"version", "async":"true"}, + {"requests":"20000", "concurrency":"1", "test":"version", "async":"true"}, + {"requests":"100000","concurrency":"2", "test":"shapes", "batch-size":"16", "complexity":"2"}, + {"requests":"100000","concurrency":"2", "test":"shapes-append", "batch-size":"16", "complexity":"4"}, + {"requests":"100000","concurrency":"2", "test":"random-shapes", "batch-size":"16", "complexity":"2"}, + {"requests":"1000", "concurrency":"2", "test":"version", "batch-size":"16"}, + {"requests":"100", "concurrency":"1", "test":"version", "batch-size": "0"}, + {"requests":"100", "concurrency":"2", "test":"document", "batch-size":"10", "complexity":"1"}, + {"requests":"2000", "concurrency":"2", "test":"crud", "complexity":"1"}, + {"requests":"4000", "concurrency":"2", "test":"crud-append", "complexity":"4"}, + {"requests":"4000", "concurrency":"2", "test":"edge", "complexity":"4"}, + {"requests":"5000", "concurrency":"2", "test":"hash", "complexity":"1"}, + {"requests":"5000", "concurrency":"2", "test":"skiplist", "complexity":"1"}, + {"requests":"500", "concurrency":"3", "test":"aqltrx", "complexity":"1"}, + {"requests":"100", "concurrency":"3", "test":"counttrx"}, + {"requests":"500", "concurrency":"3", "test":"multitrx"} ]; testFuncs.arangob = function (options) { @@ -1617,8 +1628,11 @@ testFuncs.arangob = function (options) { instanceInfo.exitStatus = "server is gone."; continue; } - - r = runArangoBenchmark(options, instanceInfo, benchTodo[i]); + var args = benchTodo[i]; + if (options.hasOwnProperty('benchargs')) { + args = _.extend(args, options.benchargs); + } + r = runArangoBenchmark(options, instanceInfo, args); results[i] = r; continueTesting = checkInstanceAlive(instanceInfo, options); diff --git a/lib/Admin/RestBaseHandler.cpp b/lib/Admin/RestBaseHandler.cpp index 6fdd4d5a13..d8295a5296 100644 --- a/lib/Admin/RestBaseHandler.cpp +++ b/lib/Admin/RestBaseHandler.cpp @@ -53,15 +53,29 @@ RestBaseHandler::RestBaseHandler (HttpRequest* request) } // ----------------------------------------------------------------------------- -// --SECTION-- HttpHandler methods +// --SECTION-- Handler methods // ----------------------------------------------------------------------------- -void RestBaseHandler::handleError (TriagensError const& error) { +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +void RestBaseHandler::handleError (const TriagensError& error) { generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, DIAGNOSTIC_INFORMATION(error)); } +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +void RestBaseHandler::handleError (const Exception& error) { + generateError(HttpResponse::responseCode(error.code()), + error.code(), + DIAGNOSTIC_INFORMATION(error)); +} + // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- diff --git a/lib/Admin/RestBaseHandler.h b/lib/Admin/RestBaseHandler.h index 477ae473e6..907f3262a8 100644 --- a/lib/Admin/RestBaseHandler.h +++ b/lib/Admin/RestBaseHandler.h @@ -63,7 +63,7 @@ namespace triagens { RestBaseHandler (rest::HttpRequest* request); // ----------------------------------------------------------------------------- -// --SECTION-- HttpHandler methods +// --SECTION-- Handler methods // ----------------------------------------------------------------------------- public: @@ -74,6 +74,12 @@ namespace triagens { void handleError (basics::TriagensError const&); +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + void handleError (basics::Exception const&); + // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- diff --git a/lib/ApplicationServer/ApplicationServer.cpp b/lib/ApplicationServer/ApplicationServer.cpp index 588ea99baf..24aa94d528 100644 --- a/lib/ApplicationServer/ApplicationServer.cpp +++ b/lib/ApplicationServer/ApplicationServer.cpp @@ -985,7 +985,7 @@ bool ApplicationServer::readConfigurationFile () { } } else { - LOG_DEBUG("no system init override file '%s' found", sysDir.c_str()); + LOG_DEBUG("no system init override file '%s' found", localSysDir.c_str()); } // check and see if file exists diff --git a/lib/Basics/Exceptions.cpp b/lib/Basics/Exceptions.cpp index 8f9f791156..30f55728e5 100644 --- a/lib/Basics/Exceptions.cpp +++ b/lib/Basics/Exceptions.cpp @@ -32,10 +32,24 @@ using namespace std; using namespace triagens::basics; +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief controls if backtraces are printed with exceptions +//////////////////////////////////////////////////////////////////////////////// + +static bool WithBackTrace = false; + // ----------------------------------------------------------------------------- // --SECTION-- public types // ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// --SECTION-- class TriagensError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief base class for all errors //////////////////////////////////////////////////////////////////////////////// @@ -57,20 +71,27 @@ TriagensError::TriagensError (string const& type, string const& details, char co TRI_GetBacktrace(_message); #endif #endif - } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// TriagensError::~TriagensError () throw () { } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the error messages +//////////////////////////////////////////////////////////////////////////////// char const * TriagensError::what () const throw() { return _message.c_str(); } +// ----------------------------------------------------------------------------- +// --SECTION-- class InternalError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for internal errors //////////////////////////////////////////////////////////////////////////////// @@ -79,12 +100,25 @@ InternalError::InternalError (string const& details, char const* file, int line) : TriagensError("internal error", details, file, line) { } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief exception for internal errors +//////////////////////////////////////////////////////////////////////////////// InternalError::InternalError (std::exception const& ex, char const* file, int line) : TriagensError("internal exception", ex.what(), file, line) { } +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// + +InternalError::~InternalError () throw () { +} + +// ----------------------------------------------------------------------------- +// --SECTION-- class OutOfMemoryError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for out-of-memory errors //////////////////////////////////////////////////////////////////////////////// @@ -93,6 +127,17 @@ OutOfMemoryError::OutOfMemoryError (char const* file, int line) : TriagensError("out-of-memory", "", file, line) { } +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// + +OutOfMemoryError::~OutOfMemoryError () throw () { +} + +// ----------------------------------------------------------------------------- +// --SECTION-- class FileError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for file errors //////////////////////////////////////////////////////////////////////////////// @@ -122,12 +167,16 @@ FileError::FileError (string const& func, } } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// FileError::~FileError () throw () { } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the filename +//////////////////////////////////////////////////////////////////////////////// void FileError::setFilename (string const& filename) { _filename = filename; @@ -137,6 +186,10 @@ void FileError::setFilename (string const& filename) { } } +// ----------------------------------------------------------------------------- +// --SECTION-- class ParseError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for parse errors //////////////////////////////////////////////////////////////////////////////// @@ -152,7 +205,16 @@ ParseError::ParseError (string const& details, } } +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// +ParseError::~ParseError () throw () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the line number +//////////////////////////////////////////////////////////////////////////////// void ParseError::setLineNumber (int lineNumber) { _lineNumber = lineNumber; @@ -162,6 +224,10 @@ void ParseError::setLineNumber (int lineNumber) { } } +// ----------------------------------------------------------------------------- +// --SECTION-- class ParameterError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for parameter errors //////////////////////////////////////////////////////////////////////////////// @@ -181,11 +247,160 @@ ParameterError::ParameterError (string const& parameter, } } - +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// ParameterError::~ParameterError () throw () { } +// ----------------------------------------------------------------------------- +// --SECTION-- class Exception +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief controls whether a backtrace is created for each exception +//////////////////////////////////////////////////////////////////////////////// + +void Exception::SetVerbose (bool verbose) { + WithBackTrace = verbose; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor, without format string +//////////////////////////////////////////////////////////////////////////////// + +Exception::Exception (int code, + char const* file, + int line) + : _errorMessage(TRI_errno_string(code)), + _file(file), + _line(line), + _code(code) { + +#ifdef TRI_ENABLE_MAINTAINER_MODE +#if HAVE_BACKTRACE + if (WithBackTrace) { + _errorMessage += std::string("\n\n"); + TRI_GetBacktrace(_errorMessage); + _errorMessage += std::string("\n\n"); + } +#endif +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the error message +//////////////////////////////////////////////////////////////////////////////// + +string Exception::message () const throw () { + return _errorMessage; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the error code +//////////////////////////////////////////////////////////////////////////////// + +int Exception::code () const throw () { + return _code; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds to the message +//////////////////////////////////////////////////////////////////////////////// + +void Exception::addToMessage (string More) { + _errorMessage += More; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor, for creating an exception with an already created +/// error message (normally based on error templates containing %s, %d etc.) +//////////////////////////////////////////////////////////////////////////////// + +Exception::Exception (int code, + string const& errorMessage, + char const* file, + int line) + : _errorMessage(errorMessage), + _file(file), + _line(line), + _code(code) { + +#ifdef TRI_ENABLE_MAINTAINER_MODE +#if HAVE_BACKTRACE + if (WithBackTrace) { + _errorMessage += std::string("\n\n"); + TRI_GetBacktrace(_errorMessage); + _errorMessage += std::string("\n\n"); + } +#endif +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// + +Exception::~Exception () throw () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return exception message +//////////////////////////////////////////////////////////////////////////////// + +const char* Exception::what () const throw () { + return _errorMessage.c_str(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief construct an error message from a template string +//////////////////////////////////////////////////////////////////////////////// + +std::string Exception::FillExceptionString (int code, ...) { + char const* format = TRI_errno_string(code); + TRI_ASSERT(format != nullptr); + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // Obviously the formatstring of the error code has to support parameters. + TRI_ASSERT(strchr(format, '%') != nullptr); +#endif + + char buffer[1024]; + va_list ap; + va_start(ap, code); + vsnprintf(buffer, sizeof(buffer) - 1, format, ap); + va_end(ap); + buffer[sizeof(buffer) - 1] = '\0'; // Windows + + return std::string(buffer); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief construct an error message from a template string +//////////////////////////////////////////////////////////////////////////////// + +std::string Exception::FillFormatExceptionString (char const* format, ...) { + TRI_ASSERT(format != nullptr); + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // Format #1 should come from the macro... + TRI_ASSERT(strchr(format, '%') != nullptr); + // Obviously the user has to give us a format string. + TRI_ASSERT(strchr(strchr(format, '%'), '%') != nullptr); +#endif + + char buffer[1024]; + va_list ap; + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer) - 1, format, ap); + va_end(ap); + buffer[sizeof(buffer) - 1] = '\0'; // Windows + + return std::string(buffer); +} + + // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- diff --git a/lib/Basics/Exceptions.h b/lib/Basics/Exceptions.h index 46f21e912d..841f3a19e7 100644 --- a/lib/Basics/Exceptions.h +++ b/lib/Basics/Exceptions.h @@ -5,7 +5,7 @@ /// /// DISCLAIMER /// -/// Copyright 2014 ArangoDB GmbH, Cologne, Germany +/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany /// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,8 @@ /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Dr. Frank Celler -/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany +/// @author Jan Steemann +/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany /// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// @@ -130,6 +131,48 @@ #define THROW_PARAMETER_ERROR(parameter, details, func) \ throw triagens::basics::ParameterError(parameter, details, func, __FILE__, __LINE__) +//////////////////////////////////////////////////////////////////////////////// +/// @brief throws an arango exception with an error code +//////////////////////////////////////////////////////////////////////////////// + +#define THROW_ARANGO_EXCEPTION(code) \ + throw triagens::basics::Exception(code, __FILE__, __LINE__) + +//////////////////////////////////////////////////////////////////////////////// +/// @brief throws an arango exception with an error code and arbitrary +/// arguments (to be inserted in printf-style manner) +//////////////////////////////////////////////////////////////////////////////// + +#define THROW_ARANGO_EXCEPTION_PARAMS(code, ...) \ + throw triagens::basics::Exception( \ + code, \ + triagens::basics::Exception::FillExceptionString( \ + code, \ + __VA_ARGS__), \ + __FILE__, __LINE__) + +//////////////////////////////////////////////////////////////////////////////// +/// @brief throws an arango exception with an error code and arbitrary +/// arguments (to be inserted in printf-style manner) +//////////////////////////////////////////////////////////////////////////////// + +#define THROW_ARANGO_EXCEPTION_FORMAT(code, format, ...) \ + throw triagens::basics::Exception( \ + code, \ + triagens::basics::Exception::FillFormatExceptionString( \ + "%s: " format, \ + TRI_errno_string(code), \ + __VA_ARGS__), \ + __FILE__, __LINE__) + +//////////////////////////////////////////////////////////////////////////////// +/// @brief throws an arango exception with an error code and an already-built +/// error message +//////////////////////////////////////////////////////////////////////////////// + +#define THROW_ARANGO_EXCEPTION_MESSAGE(code, message) \ + throw triagens::basics::Exception(code, message, __FILE__, __LINE__) + // ----------------------------------------------------------------------------- // --SECTION-- public types // ----------------------------------------------------------------------------- @@ -137,6 +180,10 @@ namespace triagens { namespace basics { +// ----------------------------------------------------------------------------- +// --SECTION-- class TriagensError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief base class for all errors //////////////////////////////////////////////////////////////////////////////// @@ -161,6 +208,10 @@ namespace triagens { int _line; }; +// ----------------------------------------------------------------------------- +// --SECTION-- class InternalError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for internal errors //////////////////////////////////////////////////////////////////////////////// @@ -169,8 +220,14 @@ namespace triagens { public: InternalError (std::string const& details, char const* file, int line); InternalError (std::exception const& ex, char const* file, int line); + + ~InternalError () throw (); }; +// ----------------------------------------------------------------------------- +// --SECTION-- class OutOfMemoryError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for out-of-memory errors //////////////////////////////////////////////////////////////////////////////// @@ -178,8 +235,14 @@ namespace triagens { class OutOfMemoryError : public TriagensError { public: OutOfMemoryError (char const* file, int line); + + ~OutOfMemoryError () throw (); }; +// ----------------------------------------------------------------------------- +// --SECTION-- class FileError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for file errors //////////////////////////////////////////////////////////////////////////////// @@ -206,6 +269,10 @@ namespace triagens { int _error; }; +// ----------------------------------------------------------------------------- +// --SECTION-- class ParseError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for parse errors //////////////////////////////////////////////////////////////////////////////// @@ -217,6 +284,8 @@ namespace triagens { char const* file, int line); + ~ParseError () throw (); + public: void setLineNumber (int); @@ -224,6 +293,10 @@ namespace triagens { int _lineNumber; }; +// ----------------------------------------------------------------------------- +// --SECTION-- class ParameterError +// ----------------------------------------------------------------------------- + //////////////////////////////////////////////////////////////////////////////// /// @brief exception for parameter errors //////////////////////////////////////////////////////////////////////////////// @@ -242,6 +315,45 @@ namespace triagens { std::string _parameter; std::string _func; }; + +// ----------------------------------------------------------------------------- +// --SECTION-- class Exception +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief arango exception type +//////////////////////////////////////////////////////////////////////////////// + + class Exception : public virtual std::exception { + public: + static std::string FillExceptionString (int, ...); + static std::string FillFormatExceptionString (char const * format, ...); + static void SetVerbose (bool); + + public: + Exception (int code, + char const* file, + int line); + + Exception (int code, + std::string const& errorMessage, + char const* file, + int line); + + ~Exception () throw (); + + public: + char const * what () const throw (); + std::string message () const throw (); + int code () const throw (); + void addToMessage (std::string More); + + protected: + std::string _errorMessage; + char const* _file; + int const _line; + int const _code; + }; } } diff --git a/lib/Basics/JsonHelper.cpp b/lib/Basics/JsonHelper.cpp index 1fedfd6e4f..b8fe1a1d6f 100644 --- a/lib/Basics/JsonHelper.cpp +++ b/lib/Basics/JsonHelper.cpp @@ -297,7 +297,7 @@ bool JsonHelper::checkAndGetBooleanValue (TRI_json_t const* json, if (! isBoolean(sub)) { std::string msg = "The attribute '" + std::string(name) + "' was not found or is not a boolean."; - THROW_INTERNAL_ERROR(msg); + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg); } return sub->_value._boolean; @@ -315,7 +315,7 @@ std::string JsonHelper::checkAndGetStringValue (TRI_json_t const* json, if (! isString(sub)) { std::string msg = "The attribute '" + std::string(name) + "' was not found or is not a string."; - THROW_INTERNAL_ERROR(msg); + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg); } return string(sub->_value._string.data, sub->_value._string.length - 1); } @@ -332,7 +332,7 @@ TRI_json_t const* JsonHelper::checkAndGetObjectValue (TRI_json_t const* json, if (! isObject(sub)) { std::string msg = "The attribute '" + std::string(name) + "' was not found or is not an object."; - THROW_INTERNAL_ERROR(msg); + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg); } return sub; @@ -350,7 +350,7 @@ TRI_json_t const* JsonHelper::checkAndGetArrayValue (TRI_json_t const* json, if (! isArray(sub)) { std::string msg = "The attribute '" + std::string(name) + "' was not found or is not an array."; - THROW_INTERNAL_ERROR(msg); + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg); } return sub; diff --git a/lib/HttpServer/HttpHandlerFactory.cpp b/lib/HttpServer/HttpHandlerFactory.cpp index 770ce7595f..ed4b9ddf0f 100644 --- a/lib/HttpServer/HttpHandlerFactory.cpp +++ b/lib/HttpServer/HttpHandlerFactory.cpp @@ -72,7 +72,11 @@ namespace { return status_t(HANDLER_DONE); }; - void handleError (TriagensError const& error) { + void handleError (const TriagensError& error) { + _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE); + }; + + void handleError (const Exception& error) { _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE); }; }; diff --git a/lib/HttpServer/PathHandler.cpp b/lib/HttpServer/PathHandler.cpp index c48a3d6874..f718d8dd1d 100644 --- a/lib/HttpServer/PathHandler.cpp +++ b/lib/HttpServer/PathHandler.cpp @@ -204,7 +204,11 @@ namespace triagens { - void PathHandler::handleError (TriagensError const&) { + void PathHandler::handleError (const TriagensError&) { + _response = createResponse(HttpResponse::SERVER_ERROR); + } + + void PathHandler::handleError (const Exception&) { _response = createResponse(HttpResponse::SERVER_ERROR); } } diff --git a/lib/HttpServer/PathHandler.h b/lib/HttpServer/PathHandler.h index c8b4b92271..d86783e018 100644 --- a/lib/HttpServer/PathHandler.h +++ b/lib/HttpServer/PathHandler.h @@ -108,7 +108,13 @@ namespace triagens { /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// - void handleError (basics::TriagensError const&); + void handleError (const basics::TriagensError&); + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + void handleError (const basics::Exception&); private: std::string path; diff --git a/lib/Rest/Handler.h b/lib/Rest/Handler.h index 7c44eec609..edfea984d1 100644 --- a/lib/Rest/Handler.h +++ b/lib/Rest/Handler.h @@ -187,7 +187,13 @@ namespace triagens { /// @brief handles error //////////////////////////////////////////////////////////////////////////////// - virtual void handleError (basics::TriagensError const&) = 0; + virtual void handleError (const basics::TriagensError&) = 0; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief handles error +//////////////////////////////////////////////////////////////////////////////// + + virtual void handleError (const basics::Exception&) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief creates a job diff --git a/lib/Rest/HttpResponse.cpp b/lib/Rest/HttpResponse.cpp index 2fa240dcab..0ea8efee19 100644 --- a/lib/Rest/HttpResponse.cpp +++ b/lib/Rest/HttpResponse.cpp @@ -190,6 +190,53 @@ HttpResponse::HttpResponseCode HttpResponse::responseCode (const string& str) { } } +//////////////////////////////////////////////////////////////////////////////// +/// @brief get http response code from integer error code +//////////////////////////////////////////////////////////////////////////////// + +HttpResponse::HttpResponseCode HttpResponse::responseCode (int code) { + TRI_ASSERT(code != TRI_ERROR_NO_ERROR); + + switch (code) { + case TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD: + case TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED: + case TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID: + case TRI_ERROR_BAD_PARAMETER: + case TRI_ERROR_CLUSTER_MUST_NOT_CHANGE_SHARDING_ATTRIBUTES: + case TRI_ERROR_CLUSTER_MUST_NOT_SPECIFY_KEY: + return BAD; + + case TRI_ERROR_ARANGO_READ_ONLY: + return FORBIDDEN; + + case TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND: + case TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND: + return NOT_FOUND; + + case TRI_ERROR_REQUEST_CANCELED: + case TRI_ERROR_QUERY_KILLED: + return REQUEST_TIMEOUT; + + case TRI_ERROR_ARANGO_CONFLICT: + case TRI_ERROR_ARANGO_GEO_INDEX_VIOLATED: + case TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED: + return CONFLICT; + + case TRI_ERROR_ARANGO_OUT_OF_KEYS: + case TRI_ERROR_CLUSTER_SHARD_GONE: + case TRI_ERROR_CLUSTER_TIMEOUT: + return SERVER_ERROR; + + case TRI_ERROR_CLUSTER_UNSUPPORTED: + return NOT_IMPLEMENTED; + + case TRI_ERROR_OUT_OF_MEMORY: + case TRI_ERROR_INTERNAL: + default: + return SERVER_ERROR; + } +} + //////////////////////////////////////////////////////////////////////////////// /// @brief return the batch error count header //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/Rest/HttpResponse.h b/lib/Rest/HttpResponse.h index ab35758c41..14392d6084 100644 --- a/lib/Rest/HttpResponse.h +++ b/lib/Rest/HttpResponse.h @@ -150,6 +150,12 @@ namespace triagens { static HttpResponseCode responseCode (std::string const& str); +//////////////////////////////////////////////////////////////////////////////// +/// @brief get http response code from integer error code +//////////////////////////////////////////////////////////////////////////////// + + static HttpResponseCode responseCode (int); + //////////////////////////////////////////////////////////////////////////////// /// @brief return the batch response error count header //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/V8/v8-environment.cpp b/lib/V8/v8-environment.cpp index b6a5959001..2894c89716 100644 --- a/lib/V8/v8-environment.cpp +++ b/lib/V8/v8-environment.cpp @@ -28,10 +28,17 @@ #ifdef _WIN32 #include "Basics/win-utils.h" -#endif +#else #include "v8-utils.h" +#ifdef __APPLE__ +#include +#define environ (*_NSGetEnviron()) +#elif !defined(_MSC_VER) +extern char **environ; +#endif +#endif static void EnvGetter(v8::Local property,