8000 Merge branch 'devel' of https://github.com/arangodb/arangodb into devel · saliormoon/arangodb@a2f0b0a · GitHub
[go: up one dir, main page]

Skip to content

Commit a2f0b0a

Browse files
committed
Merge branch 'devel' of https://github.com/arangodb/arangodb into devel
2 parents e03d550 + 3294708 commit a2f0b0a

File tree

10 files changed

+90
-34
lines changed

10 files changed

+90
-34
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ devel
4444

4545
* added module.context.createDocumentationRouter to replace module.context.apiDocumentation
4646

47+
* bug in RAFT implementation of reads. dethroned leader still answered
48+
requests in isolation
4749

4850
v3.0.6 (XXXX-XX-XX)
4951
-------------------

Documentation/DocuBlocks/Rest/Documents/REST_DOCUMENT_DELETE_MULTI.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ A JSON array of strings or documents.
1111
@RESTURLPARAM{collection,string,required}
1212
Collection from which documents are removed.
1313

14-
@RESTURLPARAMETERS
15-
1614
@RESTQUERYPARAMETERS
1715

1816
@RESTQUERYPARAM{waitForSync,boolean,optional}

README_maintainers.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@ you need to place hooks:
518518
is replaced in with its own evaluated content - so *@EXAMPLE_ARANGOSH_[OUTPUT | RUN]* sections are executed
519519
the same way as inside of source code documentation.
520520

521+
Include ditaa diagrams
522+
----------------------
523+
We use the [beautifull ditaa (DIagrams Through Ascii Art)](http://ditaa.sourceforge.net/) to generate diagrams explaining flows etc.
524+
in our documentation.
525+
526+
We have i.e. `Manual/Graphs/graph_user_in_group.ditaa` which is transpiled by ditaa into a png file, thus you simply include
527+
a png file of the same name as image into the mardown: `![User in group example](graph_user_in_group.png)` to reference it.
528+
521529
Read / use the documentation
522530
----------------------------
523531
- `file:///Documentation/Books/books/Manual/index.html` contains the generated manual

arangod/Agency/Agent.cpp

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,6 @@ bool Agent::recvAppendEntriesRPC(
269269
return false;
270270
}
271271

272-
if (!_constituent.vote(term, leaderId, prevIndex, prevTerm, true)) {
273-
return false;
274-
}
275-
276272
size_t nqs = queries->slice().length();
277273

278274
if (nqs > 0) {
@@ -360,7 +356,7 @@ priv_rpc_ret_t Agent::sendAppendEntriesRPC(std::string const& follower_id) {
360356
std::make_shared<std::string>(builder.toJson()), headerFields,
361357
std::make_shared<AgentCallback>(this, follower_id, highest),
362358
0.1*_config.minPing(), true, 0.05*_config.minPing());
363-
359+
364360
_lastSent[follower_id] = std::chrono::system_clock::now();
365361
_lastHighest[follower_id] = highest;
366362

@@ -454,8 +450,23 @@ write_ret_t Agent::write(query_t const& query) {
454450
// Only leader else redirect
455451
if (!_constituent.leading()) {
456452
return write_ret_t(false, _constituent.leaderID());
453+
} else {
454+
// Still leading?
455+
size_t good = 0;
456+
for (auto const& i : _lastAcked) {
457+
std::chrono::duration<double> m =
458+
std::chrono::system_clock::now() - i.second;
459+
if(0.9*_config.minPing() > m.count()) {
460+
++good;
461+
}
462+
}
463+
if (good < size() / 2) {
464+
_constituent.candidate();
465+
return write_ret_t(false, NO_LEADER);
466+
}
457467
}
458468

469+
459470
// Apply to spearhead and get indices for log entries
460471
{
461472
MUTEX_LOCKER(mutexLocker, _ioLock);
@@ -484,22 +495,22 @@ read_ret_t Agent::read(query_t const& query) {
484495
// Only leader else redirect
485496
if (!_constituent.leading()) {
486497
return read_ret_t(false, _constituent.leaderID());
487-
}
488-
489-
// Still leading?
490-
size_t good = 0;
491-
for (auto const& i : _lastAcked) {
492-
std::chrono::duration<double> m =
493-
std::chrono::system_clock::now() - i.second;
494-
if(0.9*_config.minPing() > m.count()) {
495-
++good;
498+
} else {
499+
// Still leading?
500+
size_t good = 0;
501+
for (auto const& i : _lastAcked) {
502+
std::chrono::duration<double> m =
503+
std::chrono::system_clock::now() - i.second;
504+
if(0.9*_config.minPing() > m.count()) {
505+
++good;
506+
}
507+
}
508+
if (good < size() / 2) {
509+
_constituent.candidate();
510+
return read_ret_t(false, NO_LEADER);
496511
}
497512
}
498-
499-
if (good < size() / 2) {
500-
_constituent.candidate();
501-
}
502-
513+
503514
// Retrieve data from readDB
504515
auto result = std::make_shared<arangodb::velocypack::Builder>();
505516
std::vector<bool> success = _readDB.read(query, result);

arangod/Agency/Constituent.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ void Constituent::lead(std::map<std::string, bool> const& votes) {
214214
void Constituent::candidate() {
215215

216216
MUTEX_LOCKER(guard, _castLock);
217+
218+
_leaderID = NO_LEADER;
217219

218220
if (_role != CANDIDATE)
219221
LOG_TOPIC(DEBUG, Logger::AGENCY)

arangod/Agency/RestAgencyHandler.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,8 @@ RestHandler::status RestAgencyHandler::handleWrite() {
140140
}
141141

142142
auto s = std::chrono::system_clock::now(); // Leadership established?
143-
std::chrono::seconds timeout(1);
144-
while(_agent->size() > 1 && _agent->leaderID() == "") {
145-
std::this_thread::sleep_for(duration_t(100));
143+
std::chrono::duration<double> timeout(_agent->config().minPing());
144+
while(_agent->size() > 1 && _agent->leaderID() == NO_LEADER) {
146145
if ((std::chrono::system_clock::now()-s) > timeout) {
147146
Builder body;
148147
body.openObject();
@@ -153,12 +152,12 @@ RestHandler::status RestAgencyHandler::handleWrite() {
153152
LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is";
154153
return status::DONE;
155154
}
155+
std::this_thread::sleep_for(duration_t(100));
156156
}
157157

158158
write_ret_t ret = _agent->write(query);
159159

160160
if (ret.accepted) { // We're leading and handling the request
161-
162161
bool found;
163162
std::string call_mode = _request->header("x-arangodb-agency-mode", found);
164163
if (!found) {
@@ -206,7 +205,18 @@ RestHandler::status RestAgencyHandler::handleWrite() {
206205
generateResult(GeneralResponse::ResponseCode::OK, body.slice());
207206
}
208207
} else { // Redirect to leader
209-
redirectRequest(ret.redirect);
208+
if (_agent->leaderID() == NO_LEADER) {
209+
Builder body;
210+
body.openObject();
211+
body.add("message", VPackValue("No leader"));
212+
body.close();
213+
generateResult(GeneralResponse::ResponseCode::SERVICE_UNAVAILABLE,
214+
body.slice());
215+
LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is";
216+
return status::DONE;
217+
} else {
218+
redirectRequest(ret.redirect);
219+
}
210220
}
211221
} else { // Unknown method
212222
generateError(GeneralResponse::ResponseCode::METHOD_NOT_ALLOWED, 405);
@@ -227,9 +237,8 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
227237
}
228238

229239
auto s = std::chrono::system_clock::now(); // Leadership established?
230-
std::chrono::seconds timeout(1);
231-
while(_agent->size() > 1 && _agent->leaderID() == "") {
232-
std::this_thread::sleep_for(duration_t(100));
240+
std::chrono::duration<double> timeout(_agent->config().minPing());
241+
while(_agent->size() > 1 && _agent->leaderID() == NO_LEADER) {
233242
if ((std::chrono::system_clock::now()-s) > timeout) {
234243
Builder body;
235244
body.openObject();
@@ -240,6 +249,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
240249
LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is";
241250
return status::DONE;
242251
}
252+
std::this_thread::sleep_for(duration_t(100));
243253
}
244254

245255
read_ret_t ret = _agent->read(query);
@@ -252,7 +262,20 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
252262
generateResult(GeneralResponse::ResponseCode::OK, ret.result->slice());
253263
}
254264
} else { // Redirect to leader
255-
redirectRequest(ret.redirect);
265+
if (_agent->leaderID() == NO_LEADER) {
266+
267+
Builder body;
268+
body.openObject();
269+
body.add("message", VPackValue("No leader"));
270+
body.close();
271+
generateResult(GeneralResponse::ResponseCode::SERVICE_UNAVAILABLE,
272+
body.slice());
273+
LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is";
274+
return status::DONE;
275+
276+
} else {
277+
redirectRequest(ret.redirect);
278+
}
256279
return status::DONE;
257280
}
258281
} else {
@@ -263,6 +286,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
263286
}
264287

265288
RestHandler::status RestAgencyHandler::handleConfig() {
289+
266290
Builder body;
267291
body.add(VPackValue(VPackValueType::Object));
268292
body.add("term", Value(_agent->term()));

arangod/Scheduler/SchedulerLibev.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,11 @@ SchedulerLibev::~SchedulerLibev() {
267267
for (size_t i = 0; i < nrThreads; ++i) {
268268
threads[i]->beginShutdown();
269269
}
270-
271-
// force threads to shutdown
270+
272271
for (size_t i = 0; i < nrThreads; ++i) {
273-
threads[i]->beginShutdown();
272+
while (threads[i]->isRunning()) {
273+
usleep(1000);
274+
}
274275
}
275276

276277
for (size_t i = 0; i < 100 && isRunning(); ++i) {

arangod/Scheduler/SocketTask.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ SocketTask::SocketTask(TRI_socket_t socket, double keepAliveTimeout)
6464
////////////////////////////////////////////////////////////////////////////////
6565

6666
SocketTask::~SocketTask() {
67+
cleanup();
68+
6769
if (TRI_isvalidsocket(_commSocket)) {
6870
TRI_CLOSE_SOCKET(_commSocket);
6971
TRI_invalidatesocket(&_commSocket);
@@ -320,9 +322,11 @@ bool SocketTask::setup(Scheduler* scheduler, EventLoop loop) {
320322

321323
_tid = Thread::currentThreadId();
322324

325+
TRI_ASSERT(_writeWatcher == nullptr);
323326
_writeWatcher = _scheduler->installSocketEvent(loop, EVENT_SOCKET_WRITE, this,
324327
_commSocket);
325328

329+
TRI_ASSERT(_readWatcher == nullptr);
326330
_readWatcher = _scheduler->installSocketEvent(loop, EVENT_SOCKET_READ, this,
327331
_commSocket);
328332
return true;

js/client/tests/agency/agency-test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,13 @@ function agencyTestSuite () {
529529
var res = writeAgency([[{"/bumms":{"op":"set","new":"fallera"}, "/bummsfallera": {"op":"set","new":"lalalala"}}]]);
530530
assertEqual(res.statusCode, 200);
531531
assertEqual(readAndCheck([["/bumms", "/bummsfallera"]]), [{bumms:"fallera", bummsfallera: "lalalala"}]);
532+
},
533+
534+
testThousand: function() {
535+
var i;
536+
for (i = 0; i < 1000; i++) {
537+
writeAndCheck([[{x:12}]]);
538+
}
532539
}
533540
};
534541
}

lib/Basics/files.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,6 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
16471647

16481648
if (dir == nullptr) {
16491649
binaryPath = TRI_DuplicateString("");
1650-
TRI_FreeString(TRI_CORE_MEM_ZONE, dir);
16511650
}
16521651
else {
16531652
binaryPath = dir;

0 commit comments

Comments
 (0)
0