8000 Merge branch 'devel' of github.com:arangodb/arangodb into feature/val… · arangodb/arangodb@9802a9c · GitHub
[go: up one dir, main page]

Skip to content

Commit 9802a9c

Browse files
committed
Merge branch 'devel' of github.com:arangodb/arangodb into feature/validation-web-ui
* 'devel' of github.com:arangodb/arangodb: Fix an agency supervision bug. (#11356) (mostly) restore pre-3.7 API behavior (#11364) validation: AQL functions (#11327) Check MSVC_VERSION instead of CMAKE_GENERATOR (#11351) added sleep time (lousy fix) Feature/aql interleave function (#11352) cheapify IN lookups on unsorted arrays (#11342) Bug fix/fix msvc2019 build (#11052)
2 parents 69d0140 + 485e14a commit 9802a9c

20 files changed

+1091
-608
lines changed

3rdParty/V8/v7.9.317/src/codegen/source-position.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,23 @@ class SourcePosition final {
146146

147147
// The two below are only used if IsExternal() is true.
148148
using ExternalLineField = BitField64<int, 1, 20>;
149-
#ifdef DEBUG
149+
//#ifdef DEBUG
150150
// looks like debug build uses more external files
151151
// so extend bits for this field, but play safe for release builds
152152
using ExternalFileIdField = BitField64<int, 21, 16>;
153-
#else
154-
using ExternalFileIdField = BitField64<int, 21, 10>;
155-
#endif
153+
//#else
154+
// using ExternalFileIdField = BitField64<int, 21, 10>;
155+
//#endif
156156
// ScriptOffsetField is only used if IsExternal() is false.
157157
using ScriptOffsetField = BitField64<int, 1, 30>;
158158

159159
// InliningId is in the high bits for better compression in
160160
// SourcePositionTable.
161-
#ifdef DEBUG // also shift this field for above change for ExternalFileIdField
161+
//#ifdef DEBUG // also shift this field for above change for ExternalFileIdField
162162
using InliningIdField = BitField64<int, 37, 16>;
163-
#else
164-
using InliningIdField = BitField64<int, 31, 16>;
165-
#endif
163+
//#else
164+
// using InliningIdField = BitField64<int, 31, 16>;
165+
//#endif
166166
// Leaving the highest bit untouched to allow for signed conversion.
167167
uint64_t value_;
168168
};

CHANGELOG

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
devel
22
-----
33

4+
* Fixed a bug in the agency supervision, which ignored the `failoverCandidates`
5+
field.
6+
7+
* Fixed a bug in the agency supervision, which could declare an already FAILED
8+
dbserver temporarily as GOOD again after an agency leader change.
9+
10+
* Added INTERLEAVE AQL function.
11+
412
* Upgraded bundled RocksDB library to version 6.8.0.
513

614
* Added AQL function `IN_RANGE`.
715

8-
* Added startup option `--ssl.prefer-http1-in-alpn` to optionally let the
16+
* Added startup option `--ssl.prefer-http1-in-alpn` to optionally let the
917
server prefer HTTP/1.1 over HTTP/2 in ALPN protocol negotiations.
1018

1119
* Compilation issues with wrong cv-qualifiers and unnecessary

VERSIONS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CXX_STANDARD "17"
22
STARTER_REV "0.14.14"
33
SYNCER_REV "0.7.3"
44
GCC_LINUX "9.2.0"
5-
MSVC_WINDOWS "2017"
5+
MSVC_WINDOWS "2019"
66
MACOS_MIN "10.14"
77
OPENSSL_LINUX "1.1.1d"
88
OPENSSL_MACOS "1.1.1d"

arangod/Agency/Job.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ std::string Job::findNonblockedCommonHealthyInSyncFollower( // Which is in "GOO
471471
auto sharedPath = db + "/" + clone.collection + "/";
472472
auto currentShardPath = curColPrefix + sharedPath + clone.shard + "/servers";
473473
auto currentFailoverCandidatesPath =
474-
curColPrefix + sharedPath + clone.shard + "/servers";
474+
curColPrefix + sharedPath + clone.shard + "/failoverCandidates";
475475
auto plannedShardPath = planColPrefix + sharedPath + "shards/" + clone.shard;
476476

477477
// start up race condition ... current might not have everything in plan

arangod/Agency/Supervision.cpp

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -588,30 +588,66 @@ std::vector<check_t> Supervision::check(std::string const& type) {
588588
HealthRecord persist(shortName, endpoint, hostId, engine, serverVersion, externalEndpoint);
589589

590590
// Get last health entries from transient and persistent key value stores
591+
bool transientHealthRecordFound = true;
591592
if (_transient.has(healthPrefix + serverID)) {
592593
transist = _transient.hasAsNode(healthPrefix + serverID).first;
594+
} else {
595+
// In this case this is the first time we look at this server during our
596+
// new leadership. So we do not touch the persisted health record and
597+
// only create a new transient health record.
598+
transientHealthRecordFound = false;
593599
}
594600
if (snapshot().has(healthPrefix + serverID)) {
595601
persist = snapshot().hasAsNode(healthPrefix + serverID).first;
596602
}
597603

604+
// Here is an important subtlety: We will derive the health status of this
605+
// server a bit further down by looking at the time when we saw the last
606+
// heartbeat. The heartbeat is stored in transient in `Sync/ServerStates`.
607+
// It has a timestamp, however, this was taken on the other server, so we
608+
// cannot trust this time stamp because of possible clock skew. Since we
609+
// do not actually know when this heartbeat came in, we have to proceed as
610+
// follows: We make a copy of the `syncTime` and store it into the health
611+
// record in transient `Supervision/Health`. If we detect a difference, it
612+
// is the first time we have seen the new heartbeat and we can then take
613+
// a reading of our local system clock and use that time. However, if we
614+
// do not yet have a previous reading in our transient health record,
615+
// we must not touch the persisted health record at all. This is what the
616+
// flag `transientHealthRecordFound` means.
617+
598618
// New health record (start with old add current information from sync)
599619
// Sync.time is copied to Health.syncTime
600620
// Sync.status is copied to Health.syncStatus
601-
std::string syncTime =
602-
_transient.has(syncPrefix + serverID)
603-
? _transient.hasAsString(syncPrefix + serverID + "/time").first
604-
: timepointToString(std::chrono::system_clock::time_point());
605-
std::string syncStatus =
606-
_transient.has(syncPrefix + serverID)
607-
? _transient.hasAsString(syncPrefix + serverID + "/status").first
608-
: "UNKNOWN";
609-
610-
// Last change registered in sync (transient != sync)
611-
// Either now or value in transient
612-
auto lastAckedTime = (syncTime != transist.syncTime)
613-
? startTimeLoop
614-
: stringToTimepoint(transist.lastAcked);
621+
std::string syncTime;
622+
std::string syncStatus;
623+
bool heartBeatVisible = _transient.has(syncPrefix + serverID);
624+
if (heartBeatVisible) {
625+
syncTime = _transient.hasAsString(syncPrefix + serverID + "/time").first;
626+
syncStatus = _transient.hasAsString(syncPrefix + serverID + "/status").first;
627+
} else {
628+
syncTime = timepointToString(std::chrono::system_clock::time_point()); // beginning of time
629+
syncStatus = "UNKNOWN";
630+
}
631+
632+
// Compute the time when we last discovered a new heartbeat from that server:
633+
std::chrono::system_clock::time_point lastAckedTime;
634+
if (heartBeatVisible) {
635+
if (transientHealthRecordFound) {
636+
lastAckedTime = (syncTime != transist.syncTime)
637+
? startTimeLoop
638+
: stringToTimepoint(transist.lastAcked);
639+
} else {
640+
// in this case we do no really know when this heartbeat came in,
641+
// however, it must have been after we became a leader, and since we
642+
// do not have a transient health record yet, we just assume that we
643+
// got it recently and set it to "now". Note that this will not make
644+
// a FAILED server "GOOD" again, since we do not touch the persisted
645+
// health record if we do not have a transient health record yet.
646+
lastAckedTime = startTimeLoop;
647+
}
648+
} else {
649+
lastAckedTime = std::chrono::system_clock::time_point();
650+
}
615651
transist.lastAcked = timepointToString(lastAckedTime);
616652
transist.syncTime = syncTime;
617653
transist.syncStatus = syncStatus;
@@ -623,34 +659,41 @@ std::vector<check_t> Supervision::check(std::string const& type) {
623659
transist.hostId = hostId;
624660
transist.endpoint = endpoint;
625661

626-
// Calculate elapsed since lastAcked
627-
auto elapsed = std::chrono::duration<double>(startTimeLoop - lastAckedTime);
662+
// We have now computed a new transient health record under all circumstances.
663+
664+
bool changed;
665+
if (transientHealthRecordFound) {
666+
// Calculate elapsed since lastAcked
667+
auto elapsed = std::chrono::duration<double>(startTimeLoop - lastAckedTime);
628668

629-
if (elapsed.count() <= _okThreshold) {
630-
transist.status = Supervision::HEALTH_STATUS_GOOD;
631-
} else if (elapsed.count() <= _gracePeriod) {
632-
transist.status = Supervision::HEALTH_STATUS_BAD;
669+
if (elapsed.count() <= _okThreshold) {
670+
transist.status = Supervision::HEALTH_STATUS_GOOD;
671+
} else if (elapsed.count() <= _gracePeriod) {
672+
transist.status = Supervision::HEALTH_STATUS_BAD;
673+
} else {
674+
transist.status = Supervision::HEALTH_STATUS_FAILED;
675+
}
676+
677+
// Status changed?
678+
changed = transist.statusDiff(persist);
633679
} else {
634-
transist.status = Supervision::HEALTH_STATUS_FAILED;
680+
transist.status = persist.status;
681+
changed = false;
635682
}
636683

637-
// Status changed?
638-
bool changed = transist.statusDiff(persist);
639-
640684
// Take necessary actions if any
641685
std::shared_ptr<VPackBuilder> envelope;
642686
if (changed) {
643687
LOG_TOPIC("bbbde", DEBUG, Logger::SUPERVISION)
644688
<< "Status of server " << serverID << " has changed from "
645689
<< persist.status << " to " << transist.status;
646690
handleOnStatus(_agent, snapshot(), persist, transist, serverID, _jobId, envelope);
691+
persist = transist; // Now copy Status, SyncStatus from transient to persited
647692
} else {
648693
LOG_TOPIC("44253", TRACE, Logger::SUPERVISION)
649694
<< "Health of server " << machine.first << " remains " << transist.status;
650695
}
651696

652-
persist = transist; // Now copy Status, SyncStatus from transient to persited
653-
654697
// Transient report
655698
std::shared_ptr<Builder> tReport = std::make_shared<Builder>();
656699
{

arangod/Aql/AqlFunctionFeature.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ void AqlFunctionFeature::addListFunctions() {
316316
add({"REMOVE_VALUES", ".,.", flags, &Functions::RemoveValues});
317317
add({"REMOVE_NTH", ".,.", flags, &Functions::RemoveNth});
318318
add({"REPLACE_NTH", ".,.,.|.", flags, &Functions::ReplaceNth});
319+
add({"INTERLEAVE", ".,.|+", flags, &Functions::Interleave});
319320

320321
// special flags:
321322
// CALL and APPLY will always run on the coordinator and are not deterministic
@@ -435,6 +436,10 @@ void AqlFunctionFeature::addMiscFunctions() {
435436
add({"DECODE_REV", ".", flags, &Functions::DecodeRev});
436437
add({"V8", ".", Function::makeFlags(FF::Deterministic, FF::Cacheable)}); // only function without a
437438
// C++ implementation
439+
//
440+
auto validationFlags = Function::makeFlags(FF::None);
441+
add({"SCHEMA_GET", ".", validationFlags, &Functions::SchemaGet});
442+
add({"SCHEMA_VALIDATE", ".,.", validationFlags, &Functions::SchemaValidate});
438443

439444
// special flags:
440445
add({"VERSION", "", Function::makeFlags(FF::Deterministic), &Functions::Version}); // deterministic, not cacheable. only on

arangod/Aql/AqlItemMatrix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ ShadowAqlItemRow AqlItemMatrix::popShadowRow() {
151151
TRI_ASSERT(blockPtr->size() >= _startIndexInFirstBlock);
152152
_size = blockPtr->size() - _startIndexInFirstBlock;
153153
}
154-
// Remove all but the last
154+
// Remove all but the last block
155155
_blocks.erase(_blocks.begin(), _blocks.end() - 1);
156156
TRI_ASSERT(_blocks.size() == 1);
157157
return shadowRow;

arangod/Aql/Expression.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "Basics/StringBuffer.h"
4444
#include "Basics/VPackStringBufferAdapter.h"
4545
#include "Basics/VelocyPackHelper.h"
46+
#include "Transaction/Context.h"
4647
#include "Transaction/Helpers.h"
4748
#include "Transaction/Methods.h"
4849
#include "V8/v8-globals.h"
@@ -261,18 +262,40 @@ bool Expression::findInArray(AqlValue const& left, AqlValue const& right,
261262
}
262263
// fall-through to linear search
263264
}
264-
265+
265266
// use linear search
266-
for (size_t i = 0; i < n; ++i) {
267-
bool mustDestroy;
268-
AqlValue a = right.at(i, mustDestroy, false);
269-
AqlValueGuard guard(a, mustDestroy);
270267

271-
int compareResult = AqlValue::Compare(trx, left, a, false);
268+
if (!right.isDocvec() && !right.isRange() &&
269+
!left.isDocvec() && !left.isRange()) {
270+
// optimization for the case in which rhs is a Velocypack array, and we
271+
// can simply use a VelocyPack iterator to walk through it. this will
272+
// be a lot more efficient than using right.at(i) in case the array is
273+
// of type Compact (without any index tables)
274+
VPackSlice const lhs(left.slice());
275+
276+
VPackOptions const* options = trx->transactionContextPtr()->getVPackOptions();
277+
VPackArrayIterator it(right.slice());
278+
while (it.valid()) {
279+
int compareResult = arangodb::basics::VelocyPackHelper::compare(lhs, it.value(), false, options);
280+
281+
if (compareResult == 0) {
282+
// item found in the list
283+
return true;
284+
}
285+
it.next();
286+
}
287+
} else {
288+
for (size_t i = 0; i < n; ++i) {
289+
bool mustDestroy;
290+
AqlValue a = right.at(i, mustDestroy, false);
291+
AqlValueGuard guard(a, mustDestroy);
292+
293+
int compareResult = AqlValue::Compare(trx, left, a, false);
272294

273-
if (compareResult == 0) {
274-
// item found in the list
275-
return true;
295+
if (compareResult == 0) {
296+
// item found in the list
297+
return true;
298+
}
276299
}
277300
}
278301

0 commit comments

Comments
 (0)
0