mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' into HLC
This commit is contained in:
commit
18925faf8f
30
CHANGELOG
30
CHANGELOG
|
@ -23,12 +23,24 @@ devel
|
|||
|
||||
* When disabling Foxx development mode the setup script is now re-run
|
||||
|
||||
* Foxx now provides an easy way to directly serve GraphQL requests using the
|
||||
`@arangodb/foxx/graphql` module and the bundled `graphql-sync` dependency
|
||||
|
||||
|
||||
v3.0.3 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* fixed AQL MERGE() function with External objects originating from traversals
|
||||
|
||||
* fixed some logfile recovery errors with error message "document not found"
|
||||
|
||||
* fixed issue #1937
|
||||
|
||||
* fixed issue #1936
|
||||
|
||||
* improved performance of arangorestore in clusters with synchronous
|
||||
replication
|
||||
|
||||
|
||||
v3.0.2 (2016-07-09)
|
||||
-------------------
|
||||
|
@ -442,9 +454,25 @@ v3.0.0-rc1 (2015-06-10)
|
|||
using a backwards-compatible "legacy mode"
|
||||
|
||||
|
||||
v2.8.10 (XXXX-XX-XX)
|
||||
v2.8.11 (XXXX-XX-XX)
|
||||
--------------------
|
||||
|
||||
* fixed issue #1937
|
||||
|
||||
|
||||
v2.8.10 (2016-07-01)
|
||||
--------------------
|
||||
|
||||
* make sure next local _rev value used for a document is at least as high as the
|
||||
_rev value supplied by external sources such as replication
|
||||
|
||||
* make adding a collection in both read- and write-mode to a transaction behave as
|
||||
expected (write includes read). This prevents the `unregister collection used in
|
||||
transaction` error
|
||||
|
||||
* fixed sometimes invalid result for `byExample(...).count()` when an index plus
|
||||
post-filtering was used
|
||||
|
||||
* fixed "collection is a nullptr" issue when starting a traversal from a transaction
|
||||
|
||||
* honor the value of startup option `--database.wait-for-sync` (that is used to control
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
!CHAPTER Using GraphQL in Foxx
|
||||
|
||||
`const createGraphQLRouter = require('@arangodb/foxx/graphql');`
|
||||
|
||||
Foxx bundles the [`graphql-sync` module](https://github.com/arangodb/graphql-sync), which is a synchronous wrapper for the official JavaScript GraphQL reference implementation, to allow writing GraphQL schemas directly inside Foxx.
|
||||
|
||||
Additionally the `@arangodb/foxx/graphql` lets you create routers for serving GraphQL requests, which closely mimicks the behaviour of the [`express-graphql` module](https://github.com/graphql/express-graphql).
|
||||
|
||||
For more information on `graphql-sync` see the [`graphql-js` API reference](http://graphql.org/docs/api-reference-graphql/) (note that `graphql-sync` always uses raw values instead of wrapping them in promises).
|
||||
|
||||
For an example of a GraphQL schema in Foxx that resolves fields using the database see [the GraphQL example service](https://github.com/arangodb-foxx/demo-graphql) (also available from the Foxx store).
|
||||
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
const graphql = require('graphql-sync');
|
||||
const graphqlSchema = new graphql.GraphQLSchema({
|
||||
// ...
|
||||
});
|
||||
|
||||
// Mounting a graphql endpoint directly in a service:
|
||||
module.context.use('/graphql', createGraphQLRouter({
|
||||
schema: graphqlSchema,
|
||||
graphiql: true
|
||||
}));
|
||||
|
||||
// Or at the service's root URL:
|
||||
module.context.use(createGraphQLRouter({
|
||||
schema: graphqlSchema,
|
||||
graphiql: true
|
||||
}));
|
||||
|
||||
// Or inside an existing router:
|
||||
router.get('/hello', function (req, res) {
|
||||
res.write('Hello world!');
|
||||
});
|
||||
router.use('/graphql', createGraphQLRouter({
|
||||
schema: graphqlSchema,
|
||||
graphiql: true
|
||||
}));
|
||||
```
|
||||
|
||||
!SECTION Creating a router
|
||||
|
||||
`createGraphQLRouter(options): Router`
|
||||
|
||||
This returns a new router object with POST and GET routes for serving GraphQL requests.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* **options**: `object`
|
||||
|
||||
An object with any of the following properties:
|
||||
|
||||
* **schema**: `GraphQLSchema`
|
||||
|
||||
A GraphQL Schema object from `graphql-sync`.
|
||||
|
||||
* **context**: `any` (optional)
|
||||
|
||||
The GraphQL context that will be passed to the `graphql()` function from `graphql-sync` to handle GraphQL queries.
|
||||
|
||||
* **rootValue**: `object` (optional)
|
||||
|
||||
The GraphQL root value that will be passed to the `graphql()` function from `graphql-sync` to handle GraphQL queries.
|
||||
|
||||
* **pretty**: `boolean` (Default: `false`)
|
||||
|
||||
If `true`, JSON responses will be pretty-printed.
|
||||
|
||||
* **formatError**: `Function` (optional)
|
||||
|
||||
A function that will be used to format errors produced by `graphql-sync`. If omitted, the `formatError` function from `graphql-sync` will be used instead.
|
||||
|
||||
* **validationRules**: `Array<any>` (optional)
|
||||
|
||||
Additional validation rules queries must satisfy in addition to those defined in the GraphQL spec.
|
||||
|
||||
* **graphiql**: `boolean` (Default: `false`)
|
||||
|
||||
If `true`, the [GraphiQL](https://github.com/graphql/graphiql) explorer will be served when loaded directly from a browser.
|
||||
|
||||
If a GraphQL Schema object is passed instead of an options object it will be interpreted as the *schema* option.
|
||||
|
||||
!SECTION Generated routes
|
||||
|
||||
The router handles GET and POST requests to its root path and accepts the following parameters, which can be provided either as query parameters or as the POST request body:
|
||||
|
||||
* **query**: `string`
|
||||
|
||||
A GraphQL query that will be executed.
|
||||
|
||||
* **variables**: `object | string` (optional)
|
||||
|
||||
An object or a string containing a JSON object with runtime values to use for any GraphQL query variables.
|
||||
|
||||
* **operationName**: `string` (optional)
|
||||
|
||||
If the provided `query` contains multiple named operations, this specifies which operation should be executed.
|
||||
|
||||
* **raw**: `boolean` (Default: `false`)
|
||||
|
||||
Forces a JSON response even if *graphiql* is enabled and the request was made using a browser.
|
||||
|
||||
The POST request body can be provided as JSON or as query string using `application/x-www-form-urlencoded`. A request body passed as `application/graphql` will be interpreted as the `query` parameter.
|
|
@ -74,6 +74,7 @@
|
|||
* [Middleware](Foxx/Router/Middleware.md)
|
||||
* [Request](Foxx/Router/Request.md)
|
||||
* [Response](Foxx/Router/Response.md)
|
||||
* [Using GraphQL](Foxx/GraphQL.md)
|
||||
* [Sessions middleware](Foxx/Sessions/README.md)
|
||||
* [Session storages](Foxx/Sessions/Storages/README.md)
|
||||
* [Collection storage](Foxx/Sessions/Storages/Collection.md)
|
||||
|
|
|
@ -525,7 +525,7 @@ void Constituent::run() {
|
|||
} else if (_role == CANDIDATE) {
|
||||
callElection(); // Run for office
|
||||
} else {
|
||||
int32_t left = 100000.0 * config().minPing;
|
||||
int32_t left = static_cast<int32_t>(100000.0 * config().minPing);
|
||||
long rand_wait = static_cast<long>(left);
|
||||
{
|
||||
CONDITION_LOCKER(guardv, _cv);
|
||||
|
|
|
@ -2365,7 +2365,7 @@ void AstNode::stringify(arangodb::basics::StringBuffer* buffer, bool verbose,
|
|||
auto returnNode = getMember(4);
|
||||
if (returnNode != nullptr && returnNode != Ast::getNodeNop()) {
|
||||
buffer->appendText(TRI_CHAR_LENGTH_PAIR(" RETURN "));
|
||||
returnNode->getMember(0)->stringify(buffer, verbose, failIfLong);
|
||||
returnNode->stringify(buffer, verbose, failIfLong);
|
||||
}
|
||||
|
||||
buffer->appendChar(')');
|
||||
|
|
|
@ -254,13 +254,12 @@ bool SkiplistLookupBuilder::next() {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
||||
Transaction* trx,
|
||||
std::vector<std::vector<arangodb::aql::AstNode const*>>& ops,
|
||||
arangodb::aql::Variable const* var, bool reverse) : BaseSkiplistLookupBuilder(trx), _dataBuilder(trx) {
|
||||
arangodb::aql::Variable const* var, bool reverse) : BaseSkiplistLookupBuilder(trx), _dataBuilder(trx), _done(false) {
|
||||
TRI_ASSERT(!ops.empty()); // We certainly do not need IN here
|
||||
VPackBuilder tmp;
|
||||
TransactionBuilderLeaser tmp(trx);
|
||||
std::set<VPackSlice, arangodb::basics::VelocyPackHelper::VPackSorted<true>>
|
||||
unique_set(
|
||||
(arangodb::basics::VelocyPackHelper::VPackSorted<true>(reverse)));
|
||||
|
@ -293,10 +292,10 @@ SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
|||
} else {
|
||||
// Case: x.a IN value
|
||||
TRI_ASSERT(value->numMembers() > 0);
|
||||
tmp.clear();
|
||||
tmp->clear();
|
||||
unique_set.clear();
|
||||
value->toVelocyPackValue(tmp);
|
||||
for (auto const& it : VPackArrayIterator(tmp.slice())) {
|
||||
value->toVelocyPackValue(*(tmp.get()));
|
||||
for (auto const& it : VPackArrayIterator(tmp->slice())) {
|
||||
unique_set.emplace(it);
|
||||
}
|
||||
_inPositions.emplace_back(i, 0, unique_set.size());
|
||||
|
@ -366,10 +365,10 @@ SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
|||
TRI_ASSERT(upper == nullptr);
|
||||
TRI_ASSERT(lower == nullptr);
|
||||
TRI_ASSERT(value->numMembers() > 0);
|
||||
tmp.clear();
|
||||
tmp->clear();
|
||||
unique_set.clear();
|
||||
value->toVelocyPackValue(tmp);
|
||||
for (auto const& it : VPackArrayIterator(tmp.slice())) {
|
||||
value->toVelocyPackValue(*(tmp.get()));
|
||||
for (auto const& it : VPackArrayIterator(tmp->slice())) {
|
||||
unique_set.emplace(it);
|
||||
}
|
||||
_inPositions.emplace_back(ops.size() - 1, 0, unique_set.size());
|
||||
|
@ -380,6 +379,7 @@ SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
|||
_dataBuilder->close();
|
||||
_isEquality = true;
|
||||
_dataBuilder->close();
|
||||
|
||||
buildSearchValues();
|
||||
return;
|
||||
case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ:
|
||||
|
@ -388,6 +388,7 @@ SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
|||
value->toVelocyPackValue(*(_dataBuilder.get()));
|
||||
_isEquality = true;
|
||||
_dataBuilder->close();
|
||||
|
||||
buildSearchValues();
|
||||
return;
|
||||
default:
|
||||
|
@ -408,11 +409,12 @@ SkiplistInLookupBuilder::SkiplistInLookupBuilder(
|
|||
}
|
||||
_dataBuilder->close();
|
||||
_dataBuilder->close();
|
||||
|
||||
buildSearchValues();
|
||||
}
|
||||
|
||||
bool SkiplistInLookupBuilder::next() {
|
||||
if (!forwardInPosition()) {
|
||||
if (_done || !forwardInPosition()) {
|
||||
return false;
|
||||
}
|
||||
buildSearchValues();
|
||||
|
@ -423,14 +425,15 @@ bool SkiplistInLookupBuilder::forwardInPosition() {
|
|||
std::list<PosStruct>::reverse_iterator it = _inPositions.rbegin();
|
||||
while (it != _inPositions.rend()) {
|
||||
it->current++;
|
||||
TRI_ASSERT(it->max > 0);
|
||||
if (it->current < it->max) {
|
||||
TRI_ASSERT(it->_max > 0);
|
||||
if (it->current < it->_max) {
|
||||
return true;
|
||||
// Okay we increased this, next search value;
|
||||
}
|
||||
it->current = 0;
|
||||
it++;
|
||||
}
|
||||
_done = true;
|
||||
// If we get here all positions are reset to 0.
|
||||
// We are done, no further combination
|
||||
return false;
|
||||
|
@ -529,7 +532,6 @@ TRI_doc_mptr_t* SkiplistIterator::next() {
|
|||
return tmp->document()->document();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Checks if the interval is valid. It is declared invalid if
|
||||
/// one border is nullptr or the right is lower than left.
|
||||
|
@ -553,14 +555,12 @@ bool SkiplistIterator2::intervalValid(Node* left, Node* right) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Reset the cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkiplistIterator2::reset() {
|
||||
// If _interals is empty at this point
|
||||
// If _intervals is empty at this point
|
||||
// the cursor does not contain any
|
||||
// document at all. Reset is pointless
|
||||
if (!_intervals.empty()) {
|
||||
|
@ -686,7 +686,6 @@ void SkiplistIterator2::initNextInterval() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the skiplist index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -60,7 +60,7 @@ class BaseSkiplistLookupBuilder {
|
|||
arangodb::velocypack::Slice _upperSlice;
|
||||
|
||||
public:
|
||||
BaseSkiplistLookupBuilder(Transaction* trx) :
|
||||
explicit BaseSkiplistLookupBuilder(Transaction* trx) :
|
||||
_lowerBuilder(trx), _upperBuilder(trx)
|
||||
{
|
||||
_isEquality = true;
|
||||
|
@ -127,9 +127,9 @@ class SkiplistInLookupBuilder : public BaseSkiplistLookupBuilder {
|
|||
struct PosStruct {
|
||||
size_t field;
|
||||
size_t current;
|
||||
size_t max;
|
||||
size_t _max; // thanks, windows.h!
|
||||
|
||||
PosStruct(size_t f, size_t c, size_t m) : field(f), current(c), max(m) {}
|
||||
PosStruct(size_t f, size_t c, size_t m) : field(f), current(c), _max(m) {}
|
||||
};
|
||||
|
||||
TransactionBuilderLeaser _dataBuilder;
|
||||
|
@ -137,6 +137,8 @@ class SkiplistInLookupBuilder : public BaseSkiplistLookupBuilder {
|
|||
/// values. (field, inPosition, maxPosition)
|
||||
std::list<PosStruct> _inPositions;
|
||||
|
||||
bool _done;
|
||||
|
||||
public:
|
||||
SkiplistInLookupBuilder(
|
||||
Transaction* trx,
|
||||
|
|
|
@ -279,7 +279,7 @@ int TraditionalKeyGenerator::validate(std::string const& key, bool isRestore) {
|
|||
/// @brief track usage of a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TraditionalKeyGenerator::track(std::string const&) {}
|
||||
void TraditionalKeyGenerator::track(char const*, VPackValueLength) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a VPack representation of the generator
|
||||
|
@ -398,9 +398,9 @@ int AutoIncrementKeyGenerator::validate(std::string const& key,
|
|||
/// @brief track usage of a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AutoIncrementKeyGenerator::track(std::string const& key) {
|
||||
void AutoIncrementKeyGenerator::track(char const* p, VPackValueLength length) {
|
||||
// check the numeric key part
|
||||
uint64_t value = StringUtils::uint64(key);
|
||||
uint64_t value = StringUtils::uint64(p, length);
|
||||
|
||||
if (value > _lastValue) {
|
||||
// and update our last value
|
||||
|
|
|
@ -104,7 +104,7 @@ class KeyGenerator {
|
|||
/// @brief track usage of a key
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void track(std::string const&) = 0;
|
||||
virtual void track(char const*, VPackValueLength) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a VelocyPack representation of the generator
|
||||
|
@ -176,7 +176,7 @@ class TraditionalKeyGenerator : public KeyGenerator {
|
|||
/// @brief track usage of a key
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void track(std::string const&) override;
|
||||
void track(char const*, VPackValueLength) override final;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the generator name (must be lowercase)
|
||||
|
@ -229,7 +229,7 @@ class AutoIncrementKeyGenerator : public KeyGenerator {
|
|||
/// @brief track usage of a key
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void track(std::string const&) override;
|
||||
void track(char const*, VPackValueLength) override final;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the generator name (must be lowercase)
|
||||
|
|
|
@ -276,7 +276,7 @@ class Traverser {
|
|||
/// @brief Constructor. This is an abstract only class.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Traverser(TraverserOptions& opts)
|
||||
explicit Traverser(TraverserOptions& opts)
|
||||
: _readDocuments(0),
|
||||
_filteredPaths(0),
|
||||
_pruneNext(false),
|
||||
|
|
|
@ -794,7 +794,9 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
Transaction::extractKeyAndRevFromDocument(slice, keySlice, revisionId);
|
||||
|
||||
SetRevision(document, revisionId, false);
|
||||
document->_keyGenerator->track(keySlice.copyString());
|
||||
VPackValueLength length;
|
||||
char const* p = keySlice.getString(length);
|
||||
document->_keyGenerator->track(p, length);
|
||||
|
||||
++state->_documents;
|
||||
|
||||
|
@ -891,7 +893,9 @@ static int OpenIteratorHandleDeletionMarker(TRI_df_marker_t const* marker,
|
|||
Transaction::extractKeyAndRevFromDocument(slice, keySlice, revisionId);
|
||||
|
||||
document->setLastRevision(revisionId, false);
|
||||
document->_keyGenerator->track(keySlice.copyString());
|
||||
VPackValueLength length;
|
||||
char const* p = keySlice.getString(length);
|
||||
document->_keyGenerator->track(p, length);
|
||||
|
||||
++state->_deletions;
|
||||
|
||||
|
|
|
@ -486,6 +486,7 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data,
|
|||
options.recoveryMarker = envelope;
|
||||
options.isRestore = true;
|
||||
options.waitForSync = false;
|
||||
options.ignoreRevs = true;
|
||||
|
||||
// try an insert first
|
||||
TRI_ASSERT(VPackSlice(ptr).isObject());
|
||||
|
|
|
@ -22,14 +22,6 @@
|
|||
// / @author Alan Plum
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// * schema: Object the schema
|
||||
// * context: ?mixed graphql context
|
||||
// * rootValue: ?Object graphql rootValue
|
||||
// * pretty: ?boolean prettier output
|
||||
// * formatError: ?Function formatError for graphql errors
|
||||
// * validationRules: ?Array<any> additional validation rules???
|
||||
// * graphiql: ?boolean enable graphiql
|
||||
|
||||
const dd = require('dedent');
|
||||
const assert = require('assert');
|
||||
const joi = require('joi');
|
||||
|
|
|
@ -705,6 +705,45 @@ function arrayAccessTestSuite () {
|
|||
var expected = [ 4, 8, 12 ];
|
||||
var result = AQL_EXECUTE("RETURN @value[**** FILTER CURRENT % 2 == 0 LIMIT 3 RETURN CURRENT * 2]", { value : data }).json;
|
||||
assertEqual([ expected ], result);
|
||||
},
|
||||
|
||||
testCollapseWithData : function () {
|
||||
var data = [ {
|
||||
"last": "2016-07-12",
|
||||
"name": "a1",
|
||||
"st": [ {
|
||||
"last": "2016-07-12",
|
||||
"name": "a11",
|
||||
"id": "a2",
|
||||
"dx": [ {
|
||||
"last": "2016-07-12",
|
||||
"name": "a21",
|
||||
"id": "a3",
|
||||
"docs": []
|
||||
}, {
|
||||
"last": "2016-07-12",
|
||||
"name": "a22",
|
||||
"id": "a4",
|
||||
"docs": []
|
||||
} ]
|
||||
} ]
|
||||
} ];
|
||||
|
||||
var expected = [
|
||||
{
|
||||
"st" : [
|
||||
{ "id" : "a2", "date" : "2016-07-12" }
|
||||
],
|
||||
"dx" : [
|
||||
{ "id" : "a3", "date" : "2016-07-12" },
|
||||
{ "id" : "a4", "date" : "2016-07-12" }
|
||||
],
|
||||
"docs" : [ ]
|
||||
}
|
||||
];
|
||||
|
||||
var result = AQL_EXECUTE("FOR c IN @value COLLECT st = c.st[* RETURN { id: CURRENT.id, date: CURRENT.last }], dx = c.st[*].dx[* RETURN { id: CURRENT.id, date: CURRENT.last }][**], docs = c.st[*].dx[*][**].docs[* RETURN { id: CURRENT.id, date: CURRENT.last }][**] RETURN { st , dx, docs }", { value : data }).json;
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -993,23 +993,18 @@ bool TRI_fsync(int fd) {
|
|||
|
||||
char* TRI_SlurpFile(TRI_memory_zone_t* zone, char const* filename,
|
||||
size_t* length) {
|
||||
TRI_string_buffer_t result;
|
||||
int fd;
|
||||
|
||||
fd = TRI_OPEN(filename, O_RDONLY | TRI_O_CLOEXEC);
|
||||
int fd = TRI_OPEN(filename, O_RDONLY | TRI_O_CLOEXEC);
|
||||
|
||||
if (fd == -1) {
|
||||
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TRI_string_buffer_t result;
|
||||
TRI_InitStringBuffer(&result, zone);
|
||||
|
||||
while (true) {
|
||||
int res;
|
||||
ssize_t n;
|
||||
|
||||
res = TRI_ReserveStringBuffer(&result, READBUFFER_SIZE);
|
||||
int res = TRI_ReserveStringBuffer(&result, READBUFFER_SIZE);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_CLOSE(fd);
|
||||
|
@ -1019,7 +1014,7 @@ char* TRI_SlurpFile(TRI_memory_zone_t* zone, char const* filename,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
n = TRI_READ(fd, (void*)TRI_EndStringBuffer(&result), READBUFFER_SIZE);
|
||||
ssize_t n = TRI_READ(fd, (void*)TRI_EndStringBuffer(&result), READBUFFER_SIZE);
|
||||
|
||||
if (n == 0) {
|
||||
break;
|
||||
|
|
|
@ -205,7 +205,7 @@ void Logger::log(char const* function, char const* file, long int line,
|
|||
std::string const& message) {
|
||||
#ifdef _WIN32
|
||||
if (level == LogLevel::FATAL || level == LogLevel::ERR) {
|
||||
if (ArangoGlobalContext::CONTEXT->useEventLog()) {
|
||||
if (ArangoGlobalContext::CONTEXT != nullptr && ArangoGlobalContext::CONTEXT->useEventLog()) {
|
||||
TRI_LogWindowsEventlog(function, file, line, message);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue