1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into array_indexing

This commit is contained in:
Michael Hackstein 2015-08-19 11:56:34 +02:00
commit 59e8ea3fad
163 changed files with 2383 additions and 1247 deletions

16
.gitignore vendored
View File

@ -53,6 +53,22 @@ core
TAGS
tags
CMakeCache.txt
CMakeFiles/
CPackConfig.cmake
CPackSourceConfig.cmake
CTestTestfile.cmake
UnitTests/CMakeFiles/
UnitTests/CTestTestfile.cmake
UnitTests/cmake_install.cmake
arangod/CMakeFiles/
arangod/cmake_install.cmake
arangosh/CMakeFiles/
arangosh/cmake_install.cmake
cmake_install.cmake
lib/CMakeFiles/
lib/cmake_install.cmake
Documentation/Examples/*.generated
Documentation/Books/Users/book.json
Documentation/Books/Users/manual.epub

View File

@ -20,7 +20,7 @@ clean64:
./v8-clean.bat cmd x86_amd64 x64 x64 64
clean32:
./v8-clean.bat x86 ia32 Win32 32
./v8-clean.bat x86 ia32 Win32 32 32
distclean: distclean32 distclean64
@ -37,7 +37,7 @@ install:
$(MAKE) -f Makefile.v8-windows install_bits BITS=64
install_bits:
mkdir -p ../WindowsLibraries/$(BITS)/lib
mkdir -p ../WindowsLibraries/$(BITS)/lib/RelWithDebInfo
mkdir -p ../WindowsLibraries/$(BITS)/include/unicode
for i in `find $(V8)/build -name $(PDBNAME) | grep $(BITS)`; do \
LIBNAME=`echo $$i|sed "s;.*/\(.*\)/$(PDBNAME);\1;"`; \

View File

@ -42,6 +42,7 @@ echo %CMD%
cd V8-%V8_VERSION%
set PATH=.\third_party\python_26\;%PATH%
.\third_party\python_26\python.exe build\gyp_v8 %CMD%
cd build

View File

@ -26,7 +26,6 @@ project(arangodb)
set(LIB_ARANGO arango)
set(LIB_ARANGO_CLIENT arango_client)
set(LIB_ARANGO_FE arango_fe)
set(LIB_ARANGO_V8 arango_v8)
set(BIN_ARANGOB arangob)

View File

@ -13,6 +13,9 @@ The values of *_from* and *_to* are immutable once saved.
are connection documents that reference other documents. The type of a collection
must be specified when a collection is created and cannot be changed afterwards.
To change edge endpoints you would need to remove old document/edge and insert new one.
Other fields can be updated as in default collection.
!SECTION Working with Edges
!SUBSECTION Insert

View File

@ -1,4 +1,4 @@
!CHAPTER Details on FoxxController
!CHAPTER Details on Controller
!SUBSECTION Create
<!-- js/server/modules/org/arangodb/foxx/controller.js -->
@ -86,12 +86,16 @@ API by chaining the following methods onto your path definition:
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContext_notes
!SUBSECTION pathParams in buffer
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParams in buffer
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
!SUBSECTION extend
In many use-cases several of the functions are always used in a certain combination (e.g.: `onlyIf` with `errorResponse`).
In order to avoid duplicating this equal usage for several routes in your application you can
extend the controller with your own functions.
These functions can simply combine several of the above on a single name, so you only have to
invoke your self defined single function on all routes using these extensions.
@startDocuBlock JSF_foxx_controller_extend
!SECTION Documenting and constraining all routes
@ -123,18 +127,24 @@ ctrl.get('/another/route', function (req, res) {
}); // no errorResponse needed here either
```
!SUBSECTION Buffer errorResponse
!SUBSECTION errorResponse
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse
!SUBSECTION Buffer onlyIf
!SUBSECTION onlyIf
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf
!SUBSECTION Buffer onlyIfAuthenticated
!SUBSECTION onlyIfAuthenticated
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated
!SUBSECTION pathParam
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParam
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
!SECTION Before and After Hooks
@ -222,9 +232,6 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_rawBodyBuffer
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_requestParts
!SUBSECTION params
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_params
@ -233,6 +240,10 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_cookie
!SUBSECTION requestParts
Only useful for multi-part requests.
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_requestParts
!SECTION The Response Object
@ -341,6 +352,3 @@ To use the application-specific authentication in your own app, first activate i
!SUBSUBSECTION Restricting routes
To restrict routes, see the documentation for Documenting and Restraining the routes.
@startDocuBlock JSF_foxx_controller_extend

View File

@ -3,7 +3,6 @@
Foxx provides some convenience methods to make working with sessions easier.
!SUBSECTION Activate sessions
@startDocuBlock JSF_foxx_controller_activateSessions
Enables session features for the controller.
@ -102,5 +101,3 @@ When using cookie sessions, this function will clear the session cookie (if *aut
* *method* (optional): HTTP method to handle. Default: `"post"`.
* *before* (optional): function to execute before the session is destroyed. Receives the same arguments as a regular route handler.
* *after* (optional): function to execute after the session is destroyed. Receives the same arguments as a regular route handler. Default: a function that sends a *{"message": "logged out"}* JSON response.
@startDocuBlock JSF_foxx_controller_destroySession

View File

@ -1,3 +0,0 @@
@startDocuBlock JSF_foxx_TemplateMiddleware_initializer
@startDocuBlock JSF_foxx_TemplateMiddleware_response_render

View File

@ -5,7 +5,7 @@
* [Windows](Installing/Windows.md)
* [Compiling](Installing/Compiling.md)
* [Upgrading](Installing/Upgrading.md)
* [Incompatible changes in 2.6](Upgrading/UpgradingChanges27.md)
* [Incompatible changes in 2.7](Upgrading/UpgradingChanges27.md)
* [Incompatible changes in 2.6](Upgrading/UpgradingChanges26.md)
* [Upgrading to 2.6](Upgrading/Upgrading26.md)
* [Incompatible changes in 2.5](Upgrading/UpgradingChanges25.md)
@ -112,7 +112,6 @@
* [Controller](Foxx/Develop/Controller.md)
* [Scripts](Foxx/Develop/Scripts.md)
* [Model](Foxx/Develop/Model.md)
* [View](Foxx/Develop/View.md)
* [Repository](Foxx/Develop/Repository.md)
* [Queries](Foxx/Develop/Queries.md)
* [Sessions](Foxx/Develop/Sessions.md)

View File

@ -1,8 +1,19 @@
arangosh> db.example.save({ Hello : "world" });
arangosh> db.example.save({ Hello : "world", foo : "bar" });
{
"_id" : "example/450753419",
"_rev" : "450753419",
"_key" : "450753419"
"_id" : "example/450817260",
"_rev" : "450817260",
"_key" : "450817260"
}
arangosh> db.example.updateByExample({ Hello: "world" }, { Hello: "foo", World: "bar" }, false);
1
arangosh> db.example.byExample({ Hello: "foo" }).toArray()
[
{
"_id" : "example/450817260",
"_key" : "450817260",
"_rev" : "451144940",
"Hello" : "foo",
"foo" : "bar",
"World" : "bar"
}
]

View File

@ -161,7 +161,6 @@ LIBS = \
noinst_LIBRARIES = \
lib/libarango.a \
lib/libarango_v8.a \
lib/libarango_fe.a \
lib/libarango_client.a \
arangod/libarangod.a

View File

@ -144,9 +144,24 @@ start-server:
@test -d "$(VOCDIR)"
($(VALGRIND) @builddir@/bin/arangod "$(VOCDIR)" $(SERVER_OPT) --pid-file $(PIDFILE) --watch-process $(PID) && rm -rf "$(VOCDIR)") &
# Wait for http/https server endpoints:
@test "$(PROTO)" == "unix" || \
( \
rm -f "$(STARTFILE)"; \
while [ ! -s "$(STARTFILE)" ]; do \
$(CURL) $(CURL_OPT) --insecure -X GET -s "$(PROTO)://$(VOCHOST):$(VOCPORT)/_api/version" > "$(STARTFILE)" || \
sleep 2; \
done)
# wait for unix domain socket enpoints:
@(test "$(PROTO)" == "unix" && \
while ! ./bin/arangosh \
--server.endpoint unix://$(VOCDIR)/arango.sock \
--javascript.execute-string 'if (arango.GET("/_api/version").server === "arango") { 0; } else {1; }'; do \
sleep 1; \
echo .; \
done;) ||\
true
@test "$(PROTO)" == "unix" || (rm -f "$(STARTFILE)"; while [ ! -s "$(STARTFILE)" ]; do $(CURL) $(CURL_OPT) --insecure -X GET -s "$(PROTO)://$(VOCHOST):$(VOCPORT)/_api/version" > "$(STARTFILE)" || sleep 2; done)
@(test "$(PROTO)" == "unix" && sleep 8) || true
@rm -f "$(STARTFILE)"
@echo "server has been started."
@if [ "$(VALGRIND)" != "" ]; then echo "adding valgrind memorial time..."; sleep 75; else sleep 2; fi
@ -1010,7 +1025,6 @@ unittests-arangob:
@echo "<< ARANGOB TESTS >>"
@echo "================================================================================"
@echo
@builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 10000 --concurrency 2 --test version --keep-alive false || test "x$(FORCE)" == "x1"
@builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 10000 --concurrency 2 --test version --async true || test "x$(FORCE)" == "x1"
@builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 20000 --concurrency 1 --test version --async true || test "x$(FORCE)" == "x1"

View File

@ -137,6 +137,29 @@ Variable const* Scope::getVariable (std::string const& name) const {
return (*it).second;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a variable, allowing usage of special pseudo vars such
/// as OLD and NEW
////////////////////////////////////////////////////////////////////////////////
Variable const* Scope::getVariable (char const* name,
bool allowSpecial) const {
auto variable = getVariable(name);
if (variable == nullptr && allowSpecial) {
// variable does not exist
// now try variable aliases OLD (= $OLD) and NEW (= $NEW)
if (strcmp(name, "OLD") == 0) {
variable = getVariable(Variable::NAME_OLD);
}
else if (strcmp(name, "NEW") == 0) {
variable = getVariable(Variable::NAME_NEW);
}
}
return variable;
}
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
@ -268,6 +291,25 @@ Variable const* Scopes::getVariable (char const* name) const {
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a variable by name - this respects the current scopes
////////////////////////////////////////////////////////////////////////////////
Variable const* Scopes::getVariable (char const* name,
bool allowSpecial) const {
TRI_ASSERT(! _activeScopes.empty());
for (auto it = _activeScopes.rbegin(); it != _activeScopes.rend(); ++it) {
auto variable = (*it)->getVariable(name, allowSpecial);
if (variable != nullptr) {
return variable;
}
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the $CURRENT variable
////////////////////////////////////////////////////////////////////////////////

View File

@ -127,6 +127,13 @@ namespace triagens {
Variable const* getVariable (std::string const&) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief return a variable, allowing usage of special pseudo vars such
/// as OLD and NEW
////////////////////////////////////////////////////////////////////////////////
Variable const* getVariable (char const*, bool) const;
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
@ -242,6 +249,13 @@ namespace triagens {
Variable const* getVariable (char const*) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief return a variable by name - this respects the current scopes
/// this also allows using special pseudo vars such as OLD and NEW
////////////////////////////////////////////////////////////////////////////////
Variable const* getVariable (char const*, bool) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief get the $CURRENT variable
////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.0.2. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -110,20 +110,18 @@ extern int Aqldebug;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
#line 17 "arangod/Aql/grammar.y" /* yacc.c:1915 */
#line 17 "arangod/Aql/grammar.y" /* yacc.c:1909 */
triagens::aql::AstNode* node;
char* strval;
bool boolval;
int64_t intval;
#line 124 "arangod/Aql/grammar.hpp" /* yacc.c:1915 */
#line 124 "arangod/Aql/grammar.hpp" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif

View File

@ -972,7 +972,7 @@ object_element:
T_STRING {
// attribute-name-only (comparable to JS enhanced object literals, e.g. { foo, bar })
auto ast = parser->ast();
auto variable = ast->scopes()->getVariable($1);
auto variable = ast->scopes()->getVariable($1, true);
if (variable == nullptr) {
// variable does not exist
@ -1051,33 +1051,23 @@ reference:
auto ast = parser->ast();
AstNode* node = nullptr;
auto variable = ast->scopes()->getVariable($1);
auto variable = ast->scopes()->getVariable($1, true);
if (variable != nullptr) {
// variable exists, now use it
node = ast->createNodeReference(variable);
}
else {
if (variable == nullptr) {
// variable does not exist
// now try variable aliases OLD (= $OLD) and NEW (= $NEW)
if (strcmp($1, "OLD") == 0) {
variable = ast->scopes()->getVariable(Variable::NAME_OLD);
}
else if (strcmp($1, "NEW") == 0) {
variable = ast->scopes()->getVariable(Variable::NAME_NEW);
}
else if (ast->scopes()->canUseCurrentVariable() && strcmp($1, "CURRENT") == 0) {
// now try special variables
if (ast->scopes()->canUseCurrentVariable() && strcmp($1, "CURRENT") == 0) {
variable = ast->scopes()->getCurrentVariable();
}
else if (strcmp($1, Variable::NAME_CURRENT) == 0) {
variable = ast->scopes()->getCurrentVariable();
}
}
if (variable != nullptr) {
// variable alias exists, now use it
node = ast->createNodeReference(variable);
}
}
if (node == nullptr) {
// variable not found. so it must have been a collection

View File

@ -57,6 +57,16 @@ add_executable(
${ProductVersionFiles}
Actions/actions.cpp
Actions/RestActionHandler.cpp
Admin/ApplicationAdminServer.cpp
Admin/RestAdminBaseHandler.cpp
Admin/RestAdminLogHandler.cpp
Admin/RestBaseHandler.cpp
Admin/RestDebugHelperHandler.cpp
Admin/RestJobHandler.cpp
Admin/RestShutdownHandler.cpp
Admin/RestVersionHandler.cpp
ApplicationServer/ApplicationFeature.cpp
ApplicationServer/ApplicationServer.cpp
Aql/AggregationOptions.cpp
Aql/AqlItemBlock.cpp
Aql/AqlItemBlockManager.cpp
@ -105,6 +115,12 @@ add_executable(
Cluster/ServerJob.cpp
Cluster/ServerState.cpp
Cluster/v8-cluster.cpp
Dispatcher/ApplicationDispatcher.cpp
Dispatcher/Dispatcher.cpp
Dispatcher/DispatcherQueue.cpp
Dispatcher/DispatcherThread.cpp
Dispatcher/Job.cpp
Dispatcher/RequeueTask.cpp
FulltextIndex/fulltext-handles.cpp
FulltextIndex/fulltext-index.cpp
FulltextIndex/fulltext-list.cpp
@ -113,6 +129,17 @@ add_executable(
FulltextIndex/fulltext-wordlist.cpp
GeoIndex/GeoIndex.cpp
HashIndex/hash-array.cpp
HttpServer/ApplicationEndpointServer.cpp
HttpServer/AsyncJobManager.cpp
HttpServer/HttpCommTask.cpp
HttpServer/HttpHandler.cpp
HttpServer/HttpHandlerFactory.cpp
HttpServer/HttpListenTask.cpp
HttpServer/HttpServer.cpp
HttpServer/HttpServerJob.cpp
HttpServer/HttpsCommTask.cpp
HttpServer/HttpsServer.cpp
HttpServer/PathHandler.cpp
Indexes/CapConstraint.cpp
Indexes/EdgeIndex.cpp
Indexes/FulltextIndex.cpp
@ -125,6 +152,8 @@ add_executable(
Replication/ContinuousSyncer.cpp
Replication/InitialSyncer.cpp
Replication/Syncer.cpp
Rest/AnyServer.cpp
Rest/Handler.cpp
RestHandler/RestBatchHandler.cpp
RestHandler/RestCursorHandler.cpp
RestHandler/RestDocumentHandler.cpp
@ -143,7 +172,19 @@ add_executable(
RestServer/ConsoleThread.cpp
RestServer/VocbaseContext.cpp
RestServer/arangod.cpp
Scheduler/ApplicationScheduler.cpp
Scheduler/ListenTask.cpp
Scheduler/PeriodicTask.cpp
Scheduler/Scheduler.cpp
Scheduler/SchedulerLibev.cpp
Scheduler/SchedulerThread.cpp
Scheduler/SignalTask.cpp
Scheduler/SocketTask.cpp
Scheduler/Task.cpp
Scheduler/TaskManager.cpp
Scheduler/TimerTask.cpp
SkipLists/skiplistIndex.cpp
Statistics/statistics.cpp
Utils/CollectionExport.cpp
Utils/Cursor.cpp
Utils/CursorRepository.cpp
@ -165,6 +206,7 @@ add_executable(
V8Server/v8-query.cpp
V8Server/v8-replication.cpp
V8Server/v8-shape-conv.cpp
V8Server/v8-statistics.cpp
V8Server/v8-user-structures.cpp
V8Server/v8-util.cpp
V8Server/v8-vocbase.cpp

View File

@ -15,6 +15,16 @@ arangod_libarangod_a_CPPFLAGS = \
arangod_libarangod_a_SOURCES = \
arangod/Actions/actions.cpp \
arangod/Actions/RestActionHandler.cpp \
arangod/Admin/ApplicationAdminServer.cpp \
arangod/Admin/RestAdminBaseHandler.cpp \
arangod/Admin/RestAdminLogHandler.cpp \
arangod/Admin/RestBaseHandler.cpp \
arangod/Admin/RestDebugHelperHandler.cpp \
arangod/Admin/RestJobHandler.cpp \
arangod/Admin/RestShutdownHandler.cpp \
arangod/Admin/RestVersionHandler.cpp \
arangod/ApplicationServer/ApplicationFeature.cpp \
arangod/ApplicationServer/ApplicationServer.cpp \
arangod/Aql/AggregationOptions.cpp \
arangod/Aql/AqlItemBlock.cpp \
arangod/Aql/AqlItemBlockManager.cpp \
@ -63,6 +73,12 @@ arangod_libarangod_a_SOURCES = \
arangod/Cluster/ServerState.cpp \
arangod/Cluster/v8-cluster.cpp \
arangod/Cluster/ClusterMethods.cpp \
arangod/Dispatcher/ApplicationDispatcher.cpp \
arangod/Dispatcher/Dispatcher.cpp \
arangod/Dispatcher/DispatcherQueue.cpp \
arangod/Dispatcher/DispatcherThread.cpp \
arangod/Dispatcher/Job.cpp \
arangod/Dispatcher/RequeueTask.cpp \
arangod/FulltextIndex/fulltext-handles.cpp \
arangod/FulltextIndex/fulltext-index.cpp \
arangod/FulltextIndex/fulltext-list.cpp \
@ -71,6 +87,17 @@ arangod_libarangod_a_SOURCES = \
arangod/FulltextIndex/fulltext-wordlist.cpp \
arangod/GeoIndex/GeoIndex.cpp \
arangod/HashIndex/hash-array.cpp \
arangod/HttpServer/ApplicationEndpointServer.cpp \
arangod/HttpServer/AsyncJobManager.cpp \
arangod/HttpServer/HttpCommTask.cpp \
arangod/HttpServer/HttpHandler.cpp \
arangod/HttpServer/HttpHandlerFactory.cpp \
arangod/HttpServer/HttpListenTask.cpp \
arangod/HttpServer/HttpServer.cpp \
arangod/HttpServer/HttpServerJob.cpp \
arangod/HttpServer/HttpsCommTask.cpp \
arangod/HttpServer/HttpsServer.cpp \
arangod/HttpServer/PathHandler.cpp \
arangod/Indexes/CapConstraint.cpp \
arangod/Indexes/EdgeIndex.cpp \
arangod/Indexes/FulltextIndex.cpp \
@ -83,6 +110,8 @@ arangod_libarangod_a_SOURCES = \
arangod/Replication/ContinuousSyncer.cpp \
arangod/Replication/InitialSyncer.cpp \
arangod/Replication/Syncer.cpp \
arangod/Rest/AnyServer.cpp \
arangod/Rest/Handler.cpp \
arangod/RestHandler/RestBatchHandler.cpp \
arangod/RestHandler/RestCursorHandler.cpp \
arangod/RestHandler/RestDocumentHandler.cpp \
@ -101,7 +130,19 @@ arangod_libarangod_a_SOURCES = \
arangod/RestServer/ConsoleThread.cpp \
arangod/RestServer/VocbaseContext.cpp \
arangod/RestServer/arangod.cpp \
arangod/Scheduler/ApplicationScheduler.cpp \
arangod/Scheduler/ListenTask.cpp \
arangod/Scheduler/PeriodicTask.cpp \
arangod/Scheduler/Scheduler.cpp \
arangod/Scheduler/SchedulerLibev.cpp \
arangod/Scheduler/SchedulerThread.cpp \
arangod/Scheduler/SignalTask.cpp \
arangod/Scheduler/SocketTask.cpp \
arangod/Scheduler/Task.cpp \
arangod/Scheduler/TaskManager.cpp \
arangod/Scheduler/TimerTask.cpp \
arangod/SkipLists/skiplistIndex.cpp \
arangod/Statistics/statistics.cpp \
arangod/Utils/CollectionExport.cpp \
arangod/Utils/Cursor.cpp \
arangod/Utils/CursorRepository.cpp \
@ -123,6 +164,7 @@ arangod_libarangod_a_SOURCES = \
arangod/V8Server/v8-query.cpp \
arangod/V8Server/v8-replication.cpp \
arangod/V8Server/v8-shape-conv.cpp \
arangod/V8Server/v8-statistics.cpp \
arangod/V8Server/v8-vocbase.cpp \
arangod/V8Server/v8-vocindex.cpp \
arangod/V8Server/v8-voccursor.cpp \

View File

@ -52,25 +52,6 @@ using namespace triagens::rest;
using namespace triagens::arango;
using namespace triagens::httpclient;
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
static inline void LocalGetline (char const*& p,
string& line,
char delim) {
char const* q = p;
while (*p != 0 && *p != delim) {
p++;
}
line.assign(q, p - q);
if (*p == delim) {
p++;
}
}
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
@ -91,7 +72,8 @@ ContinuousSyncer::ContinuousSyncer (TRI_server_t* server,
_restrictType(RESTRICT_NONE),
_initialTick(initialTick),
_useTick(useTick),
_includeSystem(configuration->_includeSystem) {
_includeSystem(configuration->_includeSystem),
_requireFromPresent(configuration->_requireFromPresent) {
uint64_t c = configuration->_chunkSize;
if (c == 0) {
@ -102,11 +84,6 @@ ContinuousSyncer::ContinuousSyncer (TRI_server_t* server,
_chunkSize = StringUtils::itoa(c);
// get number of running remote transactions so we can forge the transaction
// statistics
int const n = static_cast<int>(_applier->_runningRemoteTransactions.size());
triagens::arango::TransactionBase::setNumbers(n, n);
if (configuration->_restrictType == "include") {
_restrictType = RESTRICT_INCLUDE;
}
@ -166,7 +143,7 @@ int ContinuousSyncer::run () {
if (connectRetries <= _configuration._maxConnectRetries) {
// check if we are aborted externally
if (TRI_WaitReplicationApplier(_applier, 10 * 1000 * 1000)) {
if (_applier->wait(10 * 1000 * 1000)) {
continue;
}
@ -291,12 +268,10 @@ bool ContinuousSyncer::excludeCollection (std::string const& masterName) const {
////////////////////////////////////////////////////////////////////////////////
int ContinuousSyncer::getLocalState (string& errorMsg) {
int res;
uint64_t oldTotalRequests = _applier->_state._totalRequests;
uint64_t oldTotalFailedConnects = _applier->_state._totalFailedConnects;
res = TRI_LoadStateReplicationApplier(_vocbase, &_applier->_state);
int res = TRI_LoadStateReplicationApplier(_vocbase, &_applier->_state);
_applier->_state._active = true;
_applier->_state._totalRequests = oldTotalRequests;
_applier->_state._totalFailedConnects = oldTotalFailedConnects;
@ -465,15 +440,16 @@ int ContinuousSyncer::startTransaction (TRI_json_t const* json) {
}
// transaction id
// note: this is the remote trasnaction id!
// note: this is the remote transaction id!
TRI_voc_tid_t tid = static_cast<TRI_voc_tid_t>(StringUtils::uint64(id.c_str(), id.size()));
auto it = _applier->_runningRemoteTransactions.find(tid);
if (it != _applier->_runningRemoteTransactions.end()) {
auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second;
// abort ongoing trx
delete trx;
}
@ -527,8 +503,8 @@ int ContinuousSyncer::abortTransaction (TRI_json_t const* json) {
LOG_TRACE("abort replication transaction %llu", (unsigned long long) tid);
_applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid);
int res = trx->abort();
delete trx;
@ -562,9 +538,8 @@ int ContinuousSyncer::commitTransaction (TRI_json_t const* json) {
LOG_TRACE("committing replication transaction %llu", (unsigned long long) tid);
_applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid);
int res = trx->commit();
delete trx;
@ -733,27 +708,40 @@ int ContinuousSyncer::applyLogMarker (TRI_json_t const* json,
////////////////////////////////////////////////////////////////////////////////
int ContinuousSyncer::applyLog (SimpleHttpResult* response,
string& errorMsg,
std::string& errorMsg,
uint64_t& processedMarkers,
uint64_t& ignoreCount) {
StringBuffer& data = response->getBody();
char* p = data.begin();
char* end = p + data.length();
char const* p = data.c_str();
// buffer must end with a NUL byte
TRI_ASSERT(*end == '\0');
while (true) {
string line;
while (p < end) {
char* q = strchr(p, '\n');
LocalGetline(p, line, '\n');
if (q == nullptr) {
q = end;
}
if (line.size() < 2) {
char const* lineStart = p;
size_t const lineLength = q - p;
if (lineLength < 2) {
// we are done
return TRI_ERROR_NO_ERROR;
}
TRI_ASSERT(q <= end);
*q = '\0';
processedMarkers++;
TRI_json_t* json = TRI_JsonString(TRI_CORE_MEM_ZONE, line.c_str());
std::unique_ptr<TRI_json_t> json(TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, p));
p = q + 1;
if (json == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
@ -761,18 +749,16 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
int res;
bool skipped;
if (excludeCollection(json)) {
if (excludeCollection(json.get())) {
// entry is skipped
res = TRI_ERROR_NO_ERROR;
skipped = true;
}
else {
res = applyLogMarker(json, errorMsg);
res = applyLogMarker(json.get(), errorMsg);
skipped = false;
}
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
if (res != TRI_ERROR_NO_ERROR) {
// apply error
@ -782,11 +768,11 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
}
if (ignoreCount == 0) {
if (line.size() > 256) {
errorMsg += ", offending marker: " + line.substr(0, 256) + "...";
if (lineLength > 256) {
errorMsg += ", offending marker: " + std::string(lineStart, 256) + "...";
}
else {
errorMsg += ", offending marker: " + line;;
errorMsg += ", offending marker: " + std::string(lineStart, lineLength);
}
return res;
@ -810,6 +796,9 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
++_applier->_state._skippedOperations;
}
}
// reached the end
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@ -847,6 +836,8 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
return TRI_ERROR_REPLICATION_NO_START_TICK;
}
// TODO: get the applier into a sensible start state...
// run in a loop. the loop is terminated when the applier is stopped or an
// error occurs
while (true) {
@ -929,7 +920,7 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
// this will make the applier thread sleep if there is nothing to do,
// but will also check for cancellation
if (! TRI_WaitReplicationApplier(_applier, sleepTime)) {
if (! _applier->wait(sleepTime)) {
return TRI_ERROR_REPLICATION_APPLIER_STOPPED;
}
}
@ -995,6 +986,7 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
int res;
bool checkMore = false;
bool active = false;
bool fromIncluded = false;
TRI_voc_tick_t tick;
bool found;
@ -1004,6 +996,12 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
checkMore = StringUtils::boolean(header);
res = TRI_ERROR_NO_ERROR;
// was the specified from value included the result?
header = response->getHeaderField(TRI_REPLICATION_HEADER_FROMPRESENT, found);
if (found) {
fromIncluded = StringUtils::boolean(header);
}
header = response->getHeaderField(TRI_REPLICATION_HEADER_ACTIVE, found);
if (found) {
active = StringUtils::boolean(header);
@ -1038,6 +1036,12 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
": required header is missing";
}
if (res == TRI_ERROR_NO_ERROR &&
! fromIncluded &&
_requireFromPresent) {
res = TRI_ERROR_REPLICATION_START_TICK_NOT_PRESENT;
errorMsg = "required tick value '" + tickString + "' is not present on master at " + string(_masterInfo._endpoint);
}
if (res == TRI_ERROR_NO_ERROR) {
TRI_voc_tick_t lastAppliedTick;

View File

@ -98,6 +98,14 @@ namespace triagens {
int run ();
////////////////////////////////////////////////////////////////////////////////
/// @brief return the syncer's replication applier
////////////////////////////////////////////////////////////////////////////////
TRI_replication_applier_t* applier () const {
return _applier;
}
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
@ -252,6 +260,13 @@ namespace triagens {
bool _includeSystem;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the specified from tick must be present when fetching
/// data from a master
////////////////////////////////////////////////////////////////////////////////
bool _requireFromPresent;
};
}

View File

@ -31,11 +31,9 @@
#define ARANGODB_REST_HANDLER_H 1
#include "Basics/Common.h"
#include "Statistics/StatisticsAgent.h"
#include "Basics/Exceptions.h"
#include "Dispatcher/Job.h"
#include "Statistics/StatisticsAgent.h"
// -----------------------------------------------------------------------------
// --SECTION-- forward declarations

View File

@ -107,12 +107,30 @@ Handler::status_t RestReplicationHandler::execute () {
}
handleCommandLoggerState();
}
else if (command == "logger-tick-ranges") {
if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL;
}
handleCommandLoggerTickRanges();
}
else if (command == "logger-first-tick") {
if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL;
}
handleCommandLoggerFirstTick();
}
else if (command == "logger-follow") {
if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL;
}
handleCommandLoggerFollow();
}
else if (command == "determine-open-transactions") {
if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL;
}
handleCommandDetermineOpenTransactions();
}
else if (command == "batch") {
if (ServerState::instance()->isCoordinator()) {
@ -510,6 +528,87 @@ void RestReplicationHandler::handleCommandLoggerState () {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the available logfile range
////////////////////////////////////////////////////////////////////////////////
void RestReplicationHandler::handleCommandLoggerTickRanges () {
auto const& ranges = triagens::wal::LogfileManager::instance()->ranges();
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, ranges.size());
if (json == nullptr) {
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
return;
}
for (auto& it : ranges) {
auto r = TRI_CreateObjectJson(TRI_UNKNOWN_MEM_ZONE);
if (r == nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
return;
}
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, r, "datafile", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, it.filename.c_str(), it.filename.size()));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, r, "status", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, it.state.c_str(), it.state.size()));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, r, "tickMin", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, static_cast<double>(it.tickMin)));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, r, "tickMax", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, static_cast<double>(it.tickMax)));
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, r);
}
generateResult(json);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the first tick available in a logfile
////////////////////////////////////////////////////////////////////////////////
void RestReplicationHandler::handleCommandLoggerFirstTick () {
auto const& ranges = triagens::wal::LogfileManager::instance()->ranges();
TRI_json_t* json = TRI_CreateObjectJson(TRI_UNKNOWN_MEM_ZONE, 1);
if (json == nullptr) {
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
return;
}
TRI_voc_tick_t tick = UINT64_MAX;
for (auto& it : ranges) {
auto r = TRI_CreateObjectJson(TRI_UNKNOWN_MEM_ZONE);
if (r == nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
return;
}
if (it.tickMin == 0) {
continue;
}
if (it.tickMin < tick) {
tick = it.tickMin;
}
}
if (tick == UINT64_MAX) {
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "firstTick", TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE));
}
else {
auto tickString = std::to_string(tick);
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "firstTick", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, tickString.c_str(), tickString.size()));
}
generateResult(json);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief handle a dump batch command
///
@ -1070,6 +1169,10 @@ void RestReplicationHandler::handleCommandLoggerFollow () {
strlen(TRI_REPLICATION_HEADER_ACTIVE),
"true");
_response->setHeader(TRI_REPLICATION_HEADER_FROMPRESENT,
strlen(TRI_REPLICATION_HEADER_FROMPRESENT),
dump._fromTickIncluded ? "true" : "false");
if (length > 0) {
// transfer ownership of the buffer contents
_response->body().set(dump._buffer);
@ -1093,6 +1196,76 @@ void RestReplicationHandler::handleCommandLoggerFollow () {
}
}
void RestReplicationHandler::handleCommandDetermineOpenTransactions () {
// determine start and end tick
triagens::wal::LogfileManagerState state = triagens::wal::LogfileManager::instance()->state();
TRI_voc_tick_t tickStart = 0;
TRI_voc_tick_t tickEnd = state.lastDataTick;
bool found;
char const* value;
value = _request->value("from", found);
if (found) {
tickStart = static_cast<TRI_voc_tick_t>(StringUtils::uint64(value));
}
// determine end tick for dump
value = _request->value("to", found);
if (found) {
tickEnd = static_cast<TRI_voc_tick_t>(StringUtils::uint64(value));
}
if (found && (tickStart > tickEnd || tickEnd == 0)) {
generateError(HttpResponse::BAD,
TRI_ERROR_HTTP_BAD_PARAMETER,
"invalid from/to values");
return;
}
int res = TRI_ERROR_NO_ERROR;
try {
// initialize the dump container
TRI_replication_dump_t dump(_vocbase, (size_t) determineChunkSize(), false);
// and dump
res = TRI_DetermineOpenTransactionsReplication(&dump, tickStart, tickEnd);
if (res == TRI_ERROR_NO_ERROR) {
// generate the result
size_t const length = TRI_LengthStringBuffer(dump._buffer);
if (length == 0) {
_response = createResponse(HttpResponse::NO_CONTENT);
}
else {
_response = createResponse(HttpResponse::OK);
}
_response->setContentType("application/x-arango-dump; charset=utf-8");
if (length > 0) {
// transfer ownership of the buffer contents
_response->body().set(dump._buffer);
// to avoid double freeing
TRI_StealStringBuffer(dump._buffer);
}
}
}
catch (triagens::basics::Exception const& ex) {
res = ex.code();
}
catch (...) {
res = TRI_ERROR_INTERNAL;
}
if (res != TRI_ERROR_NO_ERROR) {
generateError(HttpResponse::SERVER_ERROR, res);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_put_api_replication_inventory
/// @brief Returns an overview of collections and their indexes

View File

@ -137,12 +137,31 @@ namespace triagens {
void handleCommandLoggerState ();
////////////////////////////////////////////////////////////////////////////////
/// @brief return the available logfile range
////////////////////////////////////////////////////////////////////////////////
void handleCommandLoggerTickRanges ();
////////////////////////////////////////////////////////////////////////////////
/// @brief return the first tick available in a logfile
////////////////////////////////////////////////////////////////////////////////
void handleCommandLoggerFirstTick ();
////////////////////////////////////////////////////////////////////////////////
/// @brief handle a follow command for the replication log
////////////////////////////////////////////////////////////////////////////////
void handleCommandLoggerFollow ();
////////////////////////////////////////////////////////////////////////////////
/// @brief handle the command to determine the transactions that were open
/// at a certain point in time
////////////////////////////////////////////////////////////////////////////////
void handleCommandDetermineOpenTransactions ();
////////////////////////////////////////////////////////////////////////////////
/// @brief handle a batch command
////////////////////////////////////////////////////////////////////////////////

View File

@ -1141,6 +1141,11 @@ int ArangoServer::startupServer () {
shutDownBegins();
#if 0
// stop the replication appliers so all replication transactions can end
TRI_StopReplicationAppliersServer(_server);
#endif
_applicationServer->stop();
_server->_queryRegistry = nullptr;

View File

@ -30,13 +30,13 @@
#include <iostream>
#include "Basics/Common.h"
#include "Basics/messages.h"
#include "Basics/logging.h"
#include "Basics/tri-strings.h"
#include "Rest/InitialiseRest.h"
#include "Basics/files.h"
#include "Basics/logging.h"
#include "Basics/messages.h"
//#include "Basics/tri-strings.h"
#include "Rest/InitialiseRest.h"
#include "RestServer/ArangoServer.h"
#include "Statistics/statistics.h"
#include <signal.h>
using namespace triagens;
@ -111,6 +111,8 @@ int main (int argc, char* argv[]) {
TRI_GlobalEntryFunction();
TRIAGENS_REST_INITIALISE(argc, argv);
TRI_InitialiseStatistics();
if (startAsService) {
TRI_StartService(argc, argv);
}
@ -134,6 +136,8 @@ int main (int argc, char* argv[]) {
ArangoInstance = nullptr;
}
TRI_ShutdownStatistics();
// shutdown sub-systems
TRIAGENS_REST_SHUTDOWN;
TRI_GlobalExitFunction(res, nullptr);

Some files were not shown because too many files have changed in this diff Show More