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
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/Examples/*.generated
Documentation/Books/Users/book.json Documentation/Books/Users/book.json
Documentation/Books/Users/manual.epub Documentation/Books/Users/manual.epub

View File

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

View File

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

View File

@ -26,7 +26,6 @@ project(arangodb)
set(LIB_ARANGO arango) set(LIB_ARANGO arango)
set(LIB_ARANGO_CLIENT arango_client) set(LIB_ARANGO_CLIENT arango_client)
set(LIB_ARANGO_FE arango_fe)
set(LIB_ARANGO_V8 arango_v8) set(LIB_ARANGO_V8 arango_v8)
set(BIN_ARANGOB arangob) 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 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. 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 !SECTION Working with Edges
!SUBSECTION Insert !SUBSECTION Insert

View File

@ -1,4 +1,4 @@
!CHAPTER Details on FoxxController !CHAPTER Details on Controller
!SUBSECTION Create !SUBSECTION Create
<!-- js/server/modules/org/arangodb/foxx/controller.js --> <!-- 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 --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContext_notes @startDocuBlock JSF_foxx_RequestContext_notes
!SUBSECTION pathParams in buffer
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParams in buffer !SUBSECTION extend
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
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 !SECTION Documenting and constraining all routes
@ -123,18 +127,24 @@ ctrl.get('/another/route', function (req, res) {
}); // no errorResponse needed here either }); // no errorResponse needed here either
``` ```
!SUBSECTION Buffer errorResponse !SUBSECTION errorResponse
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse @startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse
!SUBSECTION Buffer onlyIf !SUBSECTION onlyIf
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf
!SUBSECTION Buffer onlyIfAuthenticated !SUBSECTION onlyIfAuthenticated
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated
!SUBSECTION pathParam
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParam
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
!SECTION Before and After Hooks !SECTION Before and After Hooks
@ -222,9 +232,6 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_rawBodyBuffer @startDocuBlock JSF_foxx_BaseMiddleware_request_rawBodyBuffer
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_requestParts
!SUBSECTION params !SUBSECTION params
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_params @startDocuBlock JSF_foxx_BaseMiddleware_request_params
@ -233,6 +240,10 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_cookie @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 !SECTION The Response Object
@ -341,6 +352,3 @@ To use the application-specific authentication in your own app, first activate i
!SUBSUBSECTION Restricting routes !SUBSUBSECTION Restricting routes
To restrict routes, see the documentation for Documenting and Restraining the 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. Foxx provides some convenience methods to make working with sessions easier.
!SUBSECTION Activate sessions !SUBSECTION Activate sessions
@startDocuBlock JSF_foxx_controller_activateSessions
Enables session features for the controller. 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"`. * *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. * *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. * *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) * [Windows](Installing/Windows.md)
* [Compiling](Installing/Compiling.md) * [Compiling](Installing/Compiling.md)
* [Upgrading](Installing/Upgrading.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) * [Incompatible changes in 2.6](Upgrading/UpgradingChanges26.md)
* [Upgrading to 2.6](Upgrading/Upgrading26.md) * [Upgrading to 2.6](Upgrading/Upgrading26.md)
* [Incompatible changes in 2.5](Upgrading/UpgradingChanges25.md) * [Incompatible changes in 2.5](Upgrading/UpgradingChanges25.md)
@ -112,7 +112,6 @@
* [Controller](Foxx/Develop/Controller.md) * [Controller](Foxx/Develop/Controller.md)
* [Scripts](Foxx/Develop/Scripts.md) * [Scripts](Foxx/Develop/Scripts.md)
* [Model](Foxx/Develop/Model.md) * [Model](Foxx/Develop/Model.md)
* [View](Foxx/Develop/View.md)
* [Repository](Foxx/Develop/Repository.md) * [Repository](Foxx/Develop/Repository.md)
* [Queries](Foxx/Develop/Queries.md) * [Queries](Foxx/Develop/Queries.md)
* [Sessions](Foxx/Develop/Sessions.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", "_id" : "example/450817260",
"_rev" : "450753419", "_rev" : "450817260",
"_key" : "450753419" "_key" : "450817260"
} }
arangosh> db.example.updateByExample({ Hello: "world" }, { Hello: "foo", World: "bar" }, false); arangosh> db.example.updateByExample({ Hello: "world" }, { Hello: "foo", World: "bar" }, false);
1 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 = \ noinst_LIBRARIES = \
lib/libarango.a \ lib/libarango.a \
lib/libarango_v8.a \ lib/libarango_v8.a \
lib/libarango_fe.a \
lib/libarango_client.a \ lib/libarango_client.a \
arangod/libarangod.a arangod/libarangod.a

View File

@ -144,9 +144,24 @@ start-server:
@test -d "$(VOCDIR)" @test -d "$(VOCDIR)"
($(VALGRIND) @builddir@/bin/arangod "$(VOCDIR)" $(SERVER_OPT) --pid-file $(PIDFILE) --watch-process $(PID) && rm -rf "$(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)" @rm -f "$(STARTFILE)"
@echo "server has been started." @echo "server has been started."
@if [ "$(VALGRIND)" != "" ]; then echo "adding valgrind memorial time..."; sleep 75; else sleep 2; fi @if [ "$(VALGRIND)" != "" ]; then echo "adding valgrind memorial time..."; sleep 75; else sleep 2; fi
@ -1010,7 +1025,6 @@ unittests-arangob:
@echo "<< ARANGOB TESTS >>" @echo "<< ARANGOB TESTS >>"
@echo "================================================================================" @echo "================================================================================"
@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 --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 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" @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; 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 // --SECTION-- constructors / destructors
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -268,6 +291,25 @@ Variable const* Scopes::getVariable (char const* name) const {
return nullptr; 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 /// @brief get the $CURRENT variable
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -127,6 +127,13 @@ namespace triagens {
Variable const* getVariable (std::string const&) const; 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 // --SECTION-- private variables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -242,6 +249,13 @@ namespace triagens {
Variable const* getVariable (char const*) const; 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 /// @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 /* 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 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 it under the terms of the GNU General Public License as published by
@ -110,20 +110,18 @@ extern int Aqldebug;
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union 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; triagens::aql::AstNode* node;
char* strval; char* strval;
bool boolval; bool boolval;
int64_t intval; 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_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
#endif #endif

View File

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

View File

@ -57,6 +57,16 @@ add_executable(
${ProductVersionFiles} ${ProductVersionFiles}
Actions/actions.cpp Actions/actions.cpp
Actions/RestActionHandler.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/AggregationOptions.cpp
Aql/AqlItemBlock.cpp Aql/AqlItemBlock.cpp
Aql/AqlItemBlockManager.cpp Aql/AqlItemBlockManager.cpp
@ -105,6 +115,12 @@ add_executable(
Cluster/ServerJob.cpp Cluster/ServerJob.cpp
Cluster/ServerState.cpp Cluster/ServerState.cpp
Cluster/v8-cluster.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-handles.cpp
FulltextIndex/fulltext-index.cpp FulltextIndex/fulltext-index.cpp
FulltextIndex/fulltext-list.cpp FulltextIndex/fulltext-list.cpp
@ -113,6 +129,17 @@ add_executable(
FulltextIndex/fulltext-wordlist.cpp FulltextIndex/fulltext-wordlist.cpp
GeoIndex/GeoIndex.cpp GeoIndex/GeoIndex.cpp
HashIndex/hash-array.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/CapConstraint.cpp
Indexes/EdgeIndex.cpp Indexes/EdgeIndex.cpp
Indexes/FulltextIndex.cpp Indexes/FulltextIndex.cpp
@ -125,6 +152,8 @@ add_executable(
Replication/ContinuousSyncer.cpp Replication/ContinuousSyncer.cpp
Replication/InitialSyncer.cpp Replication/InitialSyncer.cpp
Replication/Syncer.cpp Replication/Syncer.cpp
Rest/AnyServer.cpp
Rest/Handler.cpp
RestHandler/RestBatchHandler.cpp RestHandler/RestBatchHandler.cpp
RestHandler/RestCursorHandler.cpp RestHandler/RestCursorHandler.cpp
RestHandler/RestDocumentHandler.cpp RestHandler/RestDocumentHandler.cpp
@ -143,7 +172,19 @@ add_executable(
RestServer/ConsoleThread.cpp RestServer/ConsoleThread.cpp
RestServer/VocbaseContext.cpp RestServer/VocbaseContext.cpp
RestServer/arangod.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 SkipLists/skiplistIndex.cpp
Statistics/statistics.cpp
Utils/CollectionExport.cpp Utils/CollectionExport.cpp
Utils/Cursor.cpp Utils/Cursor.cpp
Utils/CursorRepository.cpp Utils/CursorRepository.cpp
@ -165,6 +206,7 @@ add_executable(
V8Server/v8-query.cpp V8Server/v8-query.cpp
V8Server/v8-replication.cpp V8Server/v8-replication.cpp
V8Server/v8-shape-conv.cpp V8Server/v8-shape-conv.cpp
V8Server/v8-statistics.cpp
V8Server/v8-user-structures.cpp V8Server/v8-user-structures.cpp
V8Server/v8-util.cpp V8Server/v8-util.cpp
V8Server/v8-vocbase.cpp V8Server/v8-vocbase.cpp

View File

@ -15,6 +15,16 @@ arangod_libarangod_a_CPPFLAGS = \
arangod_libarangod_a_SOURCES = \ arangod_libarangod_a_SOURCES = \
arangod/Actions/actions.cpp \ arangod/Actions/actions.cpp \
arangod/Actions/RestActionHandler.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/AggregationOptions.cpp \
arangod/Aql/AqlItemBlock.cpp \ arangod/Aql/AqlItemBlock.cpp \
arangod/Aql/AqlItemBlockManager.cpp \ arangod/Aql/AqlItemBlockManager.cpp \
@ -63,6 +73,12 @@ arangod_libarangod_a_SOURCES = \
arangod/Cluster/ServerState.cpp \ arangod/Cluster/ServerState.cpp \
arangod/Cluster/v8-cluster.cpp \ arangod/Cluster/v8-cluster.cpp \
arangod/Cluster/ClusterMethods.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-handles.cpp \
arangod/FulltextIndex/fulltext-index.cpp \ arangod/FulltextIndex/fulltext-index.cpp \
arangod/FulltextIndex/fulltext-list.cpp \ arangod/FulltextIndex/fulltext-list.cpp \
@ -71,6 +87,17 @@ arangod_libarangod_a_SOURCES = \
arangod/FulltextIndex/fulltext-wordlist.cpp \ arangod/FulltextIndex/fulltext-wordlist.cpp \
arangod/GeoIndex/GeoIndex.cpp \ arangod/GeoIndex/GeoIndex.cpp \
arangod/HashIndex/hash-array.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/CapConstraint.cpp \
arangod/Indexes/EdgeIndex.cpp \ arangod/Indexes/EdgeIndex.cpp \
arangod/Indexes/FulltextIndex.cpp \ arangod/Indexes/FulltextIndex.cpp \
@ -83,6 +110,8 @@ arangod_libarangod_a_SOURCES = \
arangod/Replication/ContinuousSyncer.cpp \ arangod/Replication/ContinuousSyncer.cpp \
arangod/Replication/InitialSyncer.cpp \ arangod/Replication/InitialSyncer.cpp \
arangod/Replication/Syncer.cpp \ arangod/Replication/Syncer.cpp \
arangod/Rest/AnyServer.cpp \
arangod/Rest/Handler.cpp \
arangod/RestHandler/RestBatchHandler.cpp \ arangod/RestHandler/RestBatchHandler.cpp \
arangod/RestHandler/RestCursorHandler.cpp \ arangod/RestHandler/RestCursorHandler.cpp \
arangod/RestHandler/RestDocumentHandler.cpp \ arangod/RestHandler/RestDocumentHandler.cpp \
@ -101,7 +130,19 @@ arangod_libarangod_a_SOURCES = \
arangod/RestServer/ConsoleThread.cpp \ arangod/RestServer/ConsoleThread.cpp \
arangod/RestServer/VocbaseContext.cpp \ arangod/RestServer/VocbaseContext.cpp \
arangod/RestServer/arangod.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/SkipLists/skiplistIndex.cpp \
arangod/Statistics/statistics.cpp \
arangod/Utils/CollectionExport.cpp \ arangod/Utils/CollectionExport.cpp \
arangod/Utils/Cursor.cpp \ arangod/Utils/Cursor.cpp \
arangod/Utils/CursorRepository.cpp \ arangod/Utils/CursorRepository.cpp \
@ -123,6 +164,7 @@ arangod_libarangod_a_SOURCES = \
arangod/V8Server/v8-query.cpp \ arangod/V8Server/v8-query.cpp \
arangod/V8Server/v8-replication.cpp \ arangod/V8Server/v8-replication.cpp \
arangod/V8Server/v8-shape-conv.cpp \ arangod/V8Server/v8-shape-conv.cpp \
arangod/V8Server/v8-statistics.cpp \
arangod/V8Server/v8-vocbase.cpp \ arangod/V8Server/v8-vocbase.cpp \
arangod/V8Server/v8-vocindex.cpp \ arangod/V8Server/v8-vocindex.cpp \
arangod/V8Server/v8-voccursor.cpp \ arangod/V8Server/v8-voccursor.cpp \

View File

@ -52,25 +52,6 @@ using namespace triagens::rest;
using namespace triagens::arango; using namespace triagens::arango;
using namespace triagens::httpclient; 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 // --SECTION-- constructors and destructors
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -91,7 +72,8 @@ ContinuousSyncer::ContinuousSyncer (TRI_server_t* server,
_restrictType(RESTRICT_NONE), _restrictType(RESTRICT_NONE),
_initialTick(initialTick), _initialTick(initialTick),
_useTick(useTick), _useTick(useTick),
_includeSystem(configuration->_includeSystem) { _includeSystem(configuration->_includeSystem),
_requireFromPresent(configuration->_requireFromPresent) {
uint64_t c = configuration->_chunkSize; uint64_t c = configuration->_chunkSize;
if (c == 0) { if (c == 0) {
@ -102,11 +84,6 @@ ContinuousSyncer::ContinuousSyncer (TRI_server_t* server,
_chunkSize = StringUtils::itoa(c); _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") { if (configuration->_restrictType == "include") {
_restrictType = RESTRICT_INCLUDE; _restrictType = RESTRICT_INCLUDE;
} }
@ -166,7 +143,7 @@ int ContinuousSyncer::run () {
if (connectRetries <= _configuration._maxConnectRetries) { if (connectRetries <= _configuration._maxConnectRetries) {
// check if we are aborted externally // check if we are aborted externally
if (TRI_WaitReplicationApplier(_applier, 10 * 1000 * 1000)) { if (_applier->wait(10 * 1000 * 1000)) {
continue; continue;
} }
@ -291,12 +268,10 @@ bool ContinuousSyncer::excludeCollection (std::string const& masterName) const {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int ContinuousSyncer::getLocalState (string& errorMsg) { int ContinuousSyncer::getLocalState (string& errorMsg) {
int res;
uint64_t oldTotalRequests = _applier->_state._totalRequests; uint64_t oldTotalRequests = _applier->_state._totalRequests;
uint64_t oldTotalFailedConnects = _applier->_state._totalFailedConnects; 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._active = true;
_applier->_state._totalRequests = oldTotalRequests; _applier->_state._totalRequests = oldTotalRequests;
_applier->_state._totalFailedConnects = oldTotalFailedConnects; _applier->_state._totalFailedConnects = oldTotalFailedConnects;
@ -465,15 +440,16 @@ int ContinuousSyncer::startTransaction (TRI_json_t const* json) {
} }
// transaction id // 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())); TRI_voc_tid_t tid = static_cast<TRI_voc_tid_t>(StringUtils::uint64(id.c_str(), id.size()));
auto it = _applier->_runningRemoteTransactions.find(tid); auto it = _applier->_runningRemoteTransactions.find(tid);
if (it != _applier->_runningRemoteTransactions.end()) { if (it != _applier->_runningRemoteTransactions.end()) {
auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid); _applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second;
// abort ongoing trx // abort ongoing trx
delete 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); LOG_TRACE("abort replication transaction %llu", (unsigned long long) tid);
_applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second; auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid);
int res = trx->abort(); int res = trx->abort();
delete trx; delete trx;
@ -562,9 +538,8 @@ int ContinuousSyncer::commitTransaction (TRI_json_t const* json) {
LOG_TRACE("committing replication transaction %llu", (unsigned long long) tid); LOG_TRACE("committing replication transaction %llu", (unsigned long long) tid);
_applier->_runningRemoteTransactions.erase(tid);
auto trx = (*it).second; auto trx = (*it).second;
_applier->_runningRemoteTransactions.erase(tid);
int res = trx->commit(); int res = trx->commit();
delete trx; delete trx;
@ -733,27 +708,40 @@ int ContinuousSyncer::applyLogMarker (TRI_json_t const* json,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int ContinuousSyncer::applyLog (SimpleHttpResult* response, int ContinuousSyncer::applyLog (SimpleHttpResult* response,
string& errorMsg, std::string& errorMsg,
uint64_t& processedMarkers, uint64_t& processedMarkers,
uint64_t& ignoreCount) { uint64_t& ignoreCount) {
StringBuffer& data = response->getBody(); 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) { while (p < end) {
string line; 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 // we are done
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
TRI_ASSERT(q <= end);
*q = '\0';
processedMarkers++; 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) { if (json == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
@ -761,18 +749,16 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
int res; int res;
bool skipped; bool skipped;
if (excludeCollection(json)) { if (excludeCollection(json.get())) {
// entry is skipped // entry is skipped
res = TRI_ERROR_NO_ERROR; res = TRI_ERROR_NO_ERROR;
skipped = true; skipped = true;
} }
else { else {
res = applyLogMarker(json, errorMsg); res = applyLogMarker(json.get(), errorMsg);
skipped = false; skipped = false;
} }
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
// apply error // apply error
@ -782,11 +768,11 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
} }
if (ignoreCount == 0) { if (ignoreCount == 0) {
if (line.size() > 256) { if (lineLength > 256) {
errorMsg += ", offending marker: " + line.substr(0, 256) + "..."; errorMsg += ", offending marker: " + std::string(lineStart, 256) + "...";
} }
else { else {
errorMsg += ", offending marker: " + line;; errorMsg += ", offending marker: " + std::string(lineStart, lineLength);
} }
return res; return res;
@ -810,6 +796,9 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
++_applier->_state._skippedOperations; ++_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; 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 // run in a loop. the loop is terminated when the applier is stopped or an
// error occurs // error occurs
while (true) { while (true) {
@ -929,7 +920,7 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
// this will make the applier thread sleep if there is nothing to do, // this will make the applier thread sleep if there is nothing to do,
// but will also check for cancellation // but will also check for cancellation
if (! TRI_WaitReplicationApplier(_applier, sleepTime)) { if (! _applier->wait(sleepTime)) {
return TRI_ERROR_REPLICATION_APPLIER_STOPPED; return TRI_ERROR_REPLICATION_APPLIER_STOPPED;
} }
} }
@ -993,8 +984,9 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
} }
int res; int res;
bool checkMore = false; bool checkMore = false;
bool active = false; bool active = false;
bool fromIncluded = false;
TRI_voc_tick_t tick; TRI_voc_tick_t tick;
bool found; bool found;
@ -1004,6 +996,12 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
checkMore = StringUtils::boolean(header); checkMore = StringUtils::boolean(header);
res = TRI_ERROR_NO_ERROR; 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); header = response->getHeaderField(TRI_REPLICATION_HEADER_ACTIVE, found);
if (found) { if (found) {
active = StringUtils::boolean(header); active = StringUtils::boolean(header);
@ -1038,6 +1036,12 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
": required header is missing"; ": 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) { if (res == TRI_ERROR_NO_ERROR) {
TRI_voc_tick_t lastAppliedTick; TRI_voc_tick_t lastAppliedTick;

View File

@ -98,6 +98,14 @@ namespace triagens {
int run (); int run ();
////////////////////////////////////////////////////////////////////////////////
/// @brief return the syncer's replication applier
////////////////////////////////////////////////////////////////////////////////
TRI_replication_applier_t* applier () const {
return _applier;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private methods // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -252,6 +260,13 @@ namespace triagens {
bool _includeSystem; 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 #define ARANGODB_REST_HANDLER_H 1
#include "Basics/Common.h" #include "Basics/Common.h"
#include "Statistics/StatisticsAgent.h"
#include "Basics/Exceptions.h" #include "Basics/Exceptions.h"
#include "Dispatcher/Job.h" #include "Dispatcher/Job.h"
#include "Statistics/StatisticsAgent.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- forward declarations // --SECTION-- forward declarations

View File

@ -107,12 +107,30 @@ Handler::status_t RestReplicationHandler::execute () {
} }
handleCommandLoggerState(); 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") { else if (command == "logger-follow") {
if (type != HttpRequest::HTTP_REQUEST_GET) { if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL; goto BAD_CALL;
} }
handleCommandLoggerFollow(); handleCommandLoggerFollow();
} }
else if (command == "determine-open-transactions") {
if (type != HttpRequest::HTTP_REQUEST_GET) {
goto BAD_CALL;
}
handleCommandDetermineOpenTransactions();
}
else if (command == "batch") { else if (command == "batch") {
if (ServerState::instance()->isCoordinator()) { if (ServerState::instance()->isCoordinator()) {
@ -510,6 +528,87 @@ void RestReplicationHandler::handleCommandLoggerState () {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); 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 /// @brief handle a dump batch command
/// ///
@ -1070,6 +1169,10 @@ void RestReplicationHandler::handleCommandLoggerFollow () {
strlen(TRI_REPLICATION_HEADER_ACTIVE), strlen(TRI_REPLICATION_HEADER_ACTIVE),
"true"); "true");
_response->setHeader(TRI_REPLICATION_HEADER_FROMPRESENT,
strlen(TRI_REPLICATION_HEADER_FROMPRESENT),
dump._fromTickIncluded ? "true" : "false");
if (length > 0) { if (length > 0) {
// transfer ownership of the buffer contents // transfer ownership of the buffer contents
_response->body().set(dump._buffer); _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 /// @startDocuBlock JSF_put_api_replication_inventory
/// @brief Returns an overview of collections and their indexes /// @brief Returns an overview of collections and their indexes

View File

@ -137,12 +137,31 @@ namespace triagens {
void handleCommandLoggerState (); 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 /// @brief handle a follow command for the replication log
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void handleCommandLoggerFollow (); 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 /// @brief handle a batch command
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

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