mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into array_indexing
This commit is contained in:
commit
59e8ea3fad
|
@ -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
|
||||
|
|
|
@ -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;"`; \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
@startDocuBlock JSF_foxx_TemplateMiddleware_initializer
|
||||
|
||||
@startDocuBlock JSF_foxx_TemplateMiddleware_response_render
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue