/// Persist the globally commited truth bool State::persistReadDB(arangodb::consensus::index_t cind) { if (checkCollection("compact")) { Builder store; store.openObject(); store.add("readDB", VPackValue(VPackValueType::Array)); _agent->readDB().dumpToBuilder(store); store.close(); std::stringstream i_str; i_str << std::setw(20) << std::setfill('0') << cind; store.add("_key", VPackValue(i_str.str())); store.close(); TRI_ASSERT(_vocbase != nullptr); auto transactionContext = std::make_shared<StandaloneTransactionContext>(_vocbase); SingleCollectionTransaction trx(transactionContext, "compact", TRI_TRANSACTION_WRITE); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } auto result = trx.insert("compact", store.slice(), _options); res = trx.finish(result.code); return (res == TRI_ERROR_NO_ERROR); } LOG_TOPIC(ERR, Logger::AGENCY) << "Failed to persist read DB for compaction!"; return false; }
static void JS_WriteAgent(v8::FunctionCallbackInfo<v8::Value> const& args) { TRI_V8_TRY_CATCH_BEGIN(isolate); v8::HandleScope scope(isolate); Agent* agent = nullptr; try { AgencyFeature* feature = ApplicationServer::getEnabledFeature<AgencyFeature>("Agency"); agent = feature->agent(); } catch (std::exception const& e) { TRI_V8_THROW_EXCEPTION_MESSAGE( TRI_ERROR_INTERNAL, std::string("couldn't access agency feature: ") + e.what()); } query_t query = std::make_shared<Builder>(); int res = TRI_V8ToVPack(isolate, *query, args[0], false); if (res != TRI_ERROR_NO_ERROR) { TRI_V8_THROW_EXCEPTION(res); } write_ret_t ret = agent->write(query); if (ret.accepted) { // Leading size_t errors = 0; Builder body; body.openObject(); body.add("results", VPackValue(VPackValueType::Array)); for (auto const& index : ret.indices) { body.add(VPackValue(index)); if (index == 0) { errors++; } } body.close(); body.close(); // Wait for commit of highest except if it is 0? arangodb::consensus::index_t max_index = 0; try { max_index = *std::max_element(ret.indices.begin(), ret.indices.end()); } catch (std::exception const& e) { LOG_TOPIC(WARN, Logger::AGENCY) << e.what() << " " << __FILE__ << __LINE__; } if (max_index > 0) { agent->waitFor(max_index); } TRI_V8_RETURN(TRI_VPackToV8(isolate, body.slice())); } else { // Not leading TRI_V8_RETURN_FALSE(); } TRI_V8_TRY_CATCH_END }
// Upgrade agency, guarded by wakeUp void Supervision::upgradeAgency() { try { if (_snapshot(failedServersPrefix).slice().isArray()) { Builder builder; builder.openArray(); builder.openObject(); builder.add( _agencyPrefix + failedServersPrefix, VPackValue(VPackValueType::Object)); for (auto const& failed : VPackArrayIterator(_snapshot(failedServersPrefix).slice())) { builder.add(failed.copyString(), VPackValue(VPackValueType::Object)); builder.close(); } builder.close(); builder.close(); builder.close(); transact(_agent, builder); } } catch (std::exception const&) { Builder builder; builder.openArray(); builder.openObject(); builder.add( _agencyPrefix + failedServersPrefix, VPackValue(VPackValueType::Object)); builder.close(); builder.close(); builder.close(); transact(_agent, builder); } }
/// Persist one entry bool State::persist(arangodb::consensus::index_t index, term_t term, arangodb::velocypack::Slice const& entry) const { Builder body; body.add(VPackValue(VPackValueType::Object)); body.add("_key", Value(stringify(index))); body.add("term", Value(term)); body.add("request", entry); body.close(); TRI_ASSERT(_vocbase != nullptr); auto transactionContext = std::make_shared<StandaloneTransactionContext>(_vocbase); SingleCollectionTransaction trx(transactionContext, "log", TRI_TRANSACTION_WRITE); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } OperationResult result; try { result = trx.insert("log", body.slice(), _options); } catch (std::exception const& e) { LOG_TOPIC(ERR, Logger::AGENCY) << "Failed to persist log entry:" << e.what(); } res = trx.finish(result.code); return (res == TRI_ERROR_NO_ERROR); }
//----------- void CameraHead::init(int cameraID, const Payload& payload, Builder& gui) { this->init(cameraID, payload); this->gui = &gui; gui.add(this->camera, "Camera " + ofToString(this->getCameraID())); this->panelPinC = gui.add(this->getDecoder().getProjectorInCamera(), "Projector in Camera " + ofToString( this->getCameraID() )); this->panelCinP = gui.add(this->getDecoder().getCameraInProjector(), "Camera " + ofToString( this->getCameraID() ) + " in Projector"); gui.add( this->getDecoder().getCaptures() ); }
HttpHandler::status_t RestAgencyHandler::handleConfig() { Builder body; body.add(VPackValue(VPackValueType::Object)); body.add("term", Value(_agent->term())); body.add("leaderId", Value(_agent->leaderID())); body.add("configuration", _agent->config().toBuilder()->slice()); body.close(); generateResult(GeneralResponse::ResponseCode::OK, body.slice()); return HttpHandler::status_t(HANDLER_DONE); }
bool Node::handle<DECREMENT>(VPackSlice const& slice) { Builder tmp; tmp.openObject(); try { tmp.add("tmp", Value(this->slice().getInt() - 1)); } catch (std::exception const&) { tmp.add("tmp", Value(-1)); } tmp.close(); *this = tmp.slice().get("tmp"); return true; }
Builder Collection::values(Slice const& slice) { Builder b; b.add(Value(ValueType::Array)); ObjectIterator it(slice); while (it.valid()) { b.add(it.value()); it.next(); } b.close(); return b; }
Builder Collection::extract(Slice const& slice, int64_t from, int64_t to) { Builder b; b.openArray(); int64_t length = static_cast<int64_t>(slice.length()); int64_t skip = from; int64_t limit = to; if (limit < 0) { limit = length + limit - skip; } if (limit > 0) { ArrayIterator it(slice); while (it.valid()) { if (skip > 0) { --skip; } else { b.add(it.value()); if (--limit == 0) { break; } } it.next(); } } b.close(); return b; }
bool Node::handle<PREPEND>(VPackSlice const& slice) { if (!slice.hasKey("new")) { LOG_TOPIC(WARN, Logger::AGENCY) << "Operator prepend without new value: " << slice.toJson(); return false; } Builder tmp; tmp.openArray(); tmp.add(slice.get("new")); if (this->slice().isArray()) { for (auto const& old : VPackArrayIterator(this->slice())) tmp.add(old); } tmp.close(); *this = tmp.slice(); return true; }
HttpHandler::status_t RestAgencyHandler::handleStores() { if (_request->requestType() == GeneralRequest::RequestType::GET) { Builder body; body.openObject(); body.add("spearhead", VPackValue(VPackValueType::Array)); _agent->spearhead().dumpToBuilder(body); body.close(); body.add("read_db", VPackValue(VPackValueType::Array)); _agent->readDB().dumpToBuilder(body); body.close(); body.close(); generateResult(GeneralResponse::ResponseCode::OK, body.slice()); } else { generateError(GeneralResponse::ResponseCode::BAD, 400); } return HttpHandler::status_t(HANDLER_DONE); }
// fully append an array to the builder static void appendArray(Builder& builder, Slice const& slice) { ArrayIterator it(slice); while (it.valid()) { builder.add(it.value()); it.next(); } }
/// Update my term void Constituent::term(term_t t) { term_t tmp; { MUTEX_LOCKER(guard, _castLock); tmp = _term; _term = t; } if (tmp != t) { LOG_TOPIC(DEBUG, Logger::AGENCY) << _id << ": " << roleStr[_role] << " term " << t; Builder body; body.add(VPackValue(VPackValueType::Object)); std::ostringstream i_str; i_str << std::setw(20) << std::setfill('0') << t; body.add("_key", Value(i_str.str())); body.add("term", Value(t)); body.add("voted_for", Value((uint32_t)_votedFor)); body.close(); TRI_ASSERT(_vocbase != nullptr); auto transactionContext = std::make_shared<StandaloneTransactionContext>(_vocbase); SingleCollectionTransaction trx(transactionContext, "election", TRI_TRANSACTION_WRITE); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } OperationOptions options; options.waitForSync = waitForSync(); options.silent = true; OperationResult result = trx.insert("election", body.slice(), options); trx.finish(result.code); } }
void Node::toBuilder(Builder& builder) const { try { if (type() == NODE) { VPackObjectBuilder guard(&builder); for (auto const& child : _children) { builder.add(VPackValue(child.first)); child.second->toBuilder(builder); } } else { if (!slice().isNone()) { builder.add(slice()); } } } catch (std::exception const& e) { LOG_TOPIC(ERR, Logger::AGENCY) << e.what() << " " << __FILE__ << __LINE__; } }
Builder Collection::remove(Slice const& slice, std::unordered_set<std::string> const& keys) { Builder b; b.add(Value(ValueType::Object)); ObjectIterator it(slice); while (it.valid()) { auto key = it.key(true).copyString(); if (keys.find(key) == keys.end()) { b.add(key, it.value()); } it.next(); } b.close(); return b; }
/// Create collection by name bool State::createCollection(std::string const& name) { Builder body; body.add(VPackValue(VPackValueType::Object)); body.add("type", VPackValue(static_cast<int>(TRI_COL_TYPE_DOCUMENT))); body.add("name", VPackValue(name)); body.add("isSystem", VPackValue(LogicalCollection::IsSystemName(name))); body.close(); TRI_voc_cid_t cid = 0; arangodb::LogicalCollection const* collection = _vocbase->createCollection(body.slice(), cid, true); if (collection == nullptr) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_errno(), "cannot create collection"); } return true; }
Builder Collection::filter(Slice const& slice, Predicate const& predicate) { // construct a new Array Builder b; b.add(Value(ValueType::Array)); ArrayIterator it(slice); ValueLength index = 0; while (it.valid()) { Slice s = it.value(); if (predicate(s, index)) { b.add(s); } it.next(); ++index; } b.close(); return b; }
// Get bunch of cluster's unique ids from agency, guarded above void Supervision::getUniqueIds() { uint64_t latestId; // Run forever, supervision does not make sense before the agency data // is initialized by some other server... while (!this->isStopping()) { try { latestId = std::stoul(_agent->readDB() .get(_agencyPrefix + "/Sync/LatestID") .slice() .toJson()); } catch (...) { std::this_thread::sleep_for(std::chrono::seconds(1)); continue; } Builder uniq; uniq.openArray(); uniq.openObject(); uniq.add(_agencyPrefix + syncLatest, VPackValue(latestId + 100000)); // new uniq.close(); uniq.openObject(); uniq.add(_agencyPrefix + syncLatest, VPackValue(latestId)); // precond uniq.close(); uniq.close(); auto result = transact(_agent, uniq); if (!result.accepted || result.indices.empty()) { LOG_TOPIC(DEBUG, Logger::AGENCY) << "We have lost agency leadership. " "Stopping any supervision processing " << __FILE__ << __LINE__; return; } if (result.indices[0]) { _agent->waitFor(result.indices[0]); _jobId = latestId; _jobIdMax = latestId + 100000; return; } } }
void Node::rebuildVecBuf() const { if (_vecBufDirty) { // Dirty vector buffer Builder tmp; tmp.openArray(); for (auto const& i : _value) { tmp.add(Slice(i.data())); } tmp.close(); _vecBuf = *tmp.steal(); _vecBufDirty = false; } }
sk_sp<SkLights> SkLights::MakeFromBuffer(SkReadBuffer& buf) { Builder builder; SkColor3f ambColor; if (!buf.readScalarArray(&ambColor.fX, 3)) { return nullptr; } builder.setAmbientLightColor(ambColor); int numLights = buf.readInt(); for (int l = 0; l < numLights; ++l) { bool isPoint = buf.readBool(); SkColor3f color; if (!buf.readScalarArray(&color.fX, 3)) { return nullptr; } SkVector3 dirOrPos; if (!buf.readScalarArray(&dirOrPos.fX, 3)) { return nullptr; } if (isPoint) { SkScalar intensity; intensity = buf.readScalar(); Light light = Light::MakePoint(color, dirOrPos, intensity); builder.add(light); } else { Light light = Light::MakeDirectional(color, dirOrPos); builder.add(light); } } return builder.finish(); }
Builder Collection::remove(Slice const& slice, std::vector<std::string> const& keys) { // check if there are so many keys that we want to use the hash-based version // cut-off values are arbitrary... if (keys.size() >= 4 && slice.length() > 10) { return remove(slice, makeSet(keys)); } Builder b; b.add(Value(ValueType::Object)); ObjectIterator it(slice); while (it.valid()) { auto key = it.key(true).copyString(); if (std::find(keys.begin(), keys.end(), key) == keys.end()) { b.add(key, it.value()); } it.next(); } b.close(); return b; }
bool Node::handle<POP>(VPackSlice const& slice) { Builder tmp; tmp.openArray(); if (this->slice().isArray()) { VPackArrayIterator it(this->slice()); if (it.size() > 1) { size_t j = it.size() - 1; for (auto old : it) { tmp.add(old); if (--j == 0) break; } } } tmp.close(); *this = tmp.slice(); return true; }
int main(int, char* []) { // create an object with a few members Builder b; b(Value(ValueType::Object)); b.add("foo", Value(42)); b.add("bar", Value("some string value")); b.add("baz", Value(ValueType::Object)); b.add("qux", Value(true)); b.add("bart", Value("this is a string")); b.close(); b.add("quux", Value(12345)); b.close(); // a Slice is a lightweight accessor for a VPack value Slice s(b.start()); // now fetch the string in the object's "bar" attribute if (s.hasKey("bar")) { Slice bar(s.get("bar")); std::cout << "'bar' attribute value has type: " << bar.type() << std::endl; } // fetch non-existing attribute "quetzal" Slice quetzal(s.get("quetzal")); // note: this returns a slice of type None std::cout << "'quetzal' attribute value has type: " << quetzal.type() << std::endl; std::cout << "'quetzal' attribute is None: " << std::boolalpha << quetzal.isNone() << std::endl; // fetch subattribute "baz.qux" Slice qux(s.get(std::vector<std::string>({"baz", "qux"}))); std::cout << "'baz'.'qux' attribute has type: " << qux.type() << std::endl; std::cout << "'baz'.'qux' attribute has bool value: " << std::boolalpha << qux.getBoolean() << std::endl; std::cout << "Complete value of 'baz' is: " << s.get("baz").toJson() << std::endl; // fetch non-existing subattribute "bark.foobar" Slice foobar(s.get(std::vector<std::string>({"bark", "foobar"}))); std::cout << "'bark'.'foobar' attribute is None: " << std::boolalpha << foobar.isNone() << std::endl; // check if subattribute "baz"."bart" does exist if (s.hasKey(std::vector<std::string>({"baz", "bart"}))) { // access subattribute using operator syntax std::cout << "'baz'.'bart' attribute has type: " << s["baz"]["bart"].type() << std::endl; std::cout << "'baz'.'bart' attribute has value: '" << s["baz"]["bart"].copyString() << "'" << std::endl; } }
bool Node::handle<SHIFT>(VPackSlice const& slice) { Builder tmp; tmp.openArray(); if (this->slice().isArray()) { // If a VPackArrayIterator it(this->slice()); bool first = true; for (auto const& old : it) { if (first) { first = false; } else { tmp.add(old); } } } tmp.close(); *this = tmp.slice(); return true; }
HttpHandler::status_t RestAgencyHandler::handleState() { Builder body; body.add(VPackValue(VPackValueType::Array)); for (auto const& i : _agent->state().get()) { body.add(VPackValue(VPackValueType::Object)); body.add("index", VPackValue(i.index)); body.add("term", VPackValue(i.term)); body.add("leader", VPackValue(i.leaderId)); body.add("query", VPackSlice(i.entry->data())); body.close(); } body.close(); generateResult(GeneralResponse::ResponseCode::OK, body.slice()); return HttpHandler::status_t(HANDLER_DONE); }
Builder Collection::sort( Slice const& array, std::function<bool (Slice const&, Slice const&)> lessthan) { if (!array.isArray()) { throw Exception(Exception::InvalidValueType, "Expecting type Array"); } std::vector<Slice> subValues; ValueLength len = array.length(); subValues.reserve(checkOverflow(len)); for (ValueLength i = 0; i < len; i++) { subValues.push_back(array[i]); } std::sort(subValues.begin(), subValues.end(), lessthan); Builder b; b.openArray(); for (auto const&s : subValues) { b.add(s); } b.close(); return b; }
JOB_STATUS CleanOutServer::status () { auto status = exists(); if (status != NOTFOUND) { // Get job details from agency try { _server = _snapshot(pos[status] + _jobId + "/server").getString(); } catch (std::exception const& e) { std::stringstream err; err << "Failed to find job " << _jobId << " in agency: " << e.what(); LOG_TOPIC(ERR, Logger::AGENCY) << err.str(); finish("DBServers/" + _server, false, err.str()); return FAILED; } } if (status == PENDING) { Node::Children const todos = _snapshot(toDoPrefix).children(); Node::Children const pends = _snapshot(pendingPrefix).children(); size_t found = 0; for (auto const& subJob : todos) { if (!subJob.first.compare(0, _jobId.size()+1, _jobId + "-")) { found++; } } for (auto const& subJob : pends) { if (!subJob.first.compare(0, _jobId.size()+1, _jobId + "-")) { found++; } } if (found == 0) { // Put server in /Target/CleanedServers: Builder reportTrx; { VPackArrayBuilder guard(&reportTrx); { VPackObjectBuilder guard3(&reportTrx); reportTrx.add(VPackValue(_agencyPrefix + "/Target/CleanedServers")); { VPackObjectBuilder guard4(&reportTrx); reportTrx.add("op", VPackValue("push")); reportTrx.add("new", VPackValue(_server)); } } } // Transact to agency write_ret_t res = transact(_agent, reportTrx); if (res.accepted && res.indices.size() == 1 && res.indices[0] != 0) { LOG_TOPIC(INFO, Logger::AGENCY) << "Have reported " << _server << " in /Target/CleanedServers"; } else { LOG_TOPIC(ERR, Logger::AGENCY) << "Failed to report " << _server << " in /Target/CleanedServers"; } if (finish("DBServers/" + _server)) { return FINISHED; } } } return status; }
// Check all DB servers, guarded above doChecks std::vector<check_t> Supervision::checkDBServers() { std::vector<check_t> ret; Node::Children const& machinesPlanned = _snapshot(planDBServersPrefix).children(); Node::Children const serversRegistered = _snapshot(currentServersRegisteredPrefix).children(); std::vector<std::string> todelete; for (auto const& machine : _snapshot(healthPrefix).children()) { if (machine.first.substr(0, 2) == "DB") { todelete.push_back(machine.first); } } for (auto const& machine : machinesPlanned) { bool good = false; std::string lastHeartbeatTime, lastHeartbeatAcked, lastStatus, heartbeatTime, heartbeatStatus, serverID; serverID = machine.first; heartbeatTime = _snapshot(syncPrefix + serverID + "/time").toJson(); heartbeatStatus = _snapshot(syncPrefix + serverID + "/status").toJson(); todelete.erase(std::remove(todelete.begin(), todelete.end(), serverID), todelete.end()); try { // Existing lastHeartbeatTime = _snapshot(healthPrefix + serverID + "/LastHeartbeatSent").toJson(); lastHeartbeatAcked = _snapshot(healthPrefix + serverID + "/LastHeartbeatAcked").toJson(); lastStatus = _snapshot(healthPrefix + serverID + "/Status").toJson(); if (lastHeartbeatTime != heartbeatTime) { // Update good = true; } } catch (...) { // New server good = true; } query_t report = std::make_shared<Builder>(); report->openArray(); report->openArray(); report->openObject(); report->add(_agencyPrefix + healthPrefix + serverID, VPackValue(VPackValueType::Object)); report->add("LastHeartbeatSent", VPackValue(heartbeatTime)); report->add("LastHeartbeatStatus", VPackValue(heartbeatStatus)); report->add("Role", VPackValue("DBServer")); auto endpoint = serversRegistered.find(serverID); if (endpoint != serversRegistered.end()) { endpoint = endpoint->second->children().find("endpoint"); if (endpoint != endpoint->second->children().end()) { if (endpoint->second->children().size() == 0) { VPackSlice epString = endpoint->second->slice(); if (epString.isString()) { report->add("Endpoint", epString); } } } } if (good) { report->add( "LastHeartbeatAcked", VPackValue(timepointToString(std::chrono::system_clock::now()))); report->add("Status", VPackValue(Supervision::HEALTH_STATUS_GOOD)); std::string failedServerPath = failedServersPrefix + "/" + serverID; if (_snapshot.exists(failedServerPath).size() == 3) { Builder del; del.openArray(); del.openObject(); del.add(_agencyPrefix + failedServerPath, VPackValue(VPackValueType::Object)); del.add("op", VPackValue("delete")); del.close(); del.close(); del.close(); transact(_agent, del); } } else { std::chrono::seconds t{0}; t = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now() - stringToTimepoint(lastHeartbeatAcked)); if (t.count() > _gracePeriod) { // Failure if (lastStatus == "BAD") { report->add("Status", VPackValue("FAILED")); FailedServer fsj(_snapshot, _agent, std::to_string(_jobId++), "supervision", _agencyPrefix, serverID); } } else { report->add("Status", VPackValue("BAD")); } } report->close(); report->close(); report->close(); report->close(); if (!this->isStopping()) { _agent->write(report); } } if (!todelete.empty()) { query_t del = std::make_shared<Builder>(); del->openArray(); del->openArray(); del->openObject(); for (auto const& srv : todelete) { del->add(_agencyPrefix + healthPrefix + srv, VPackValue(VPackValueType::Object)); del->add("op", VPackValue("delete")); del->close(); } del->close(); del->close(); del->close(); _agent->write(del); } return ret; }
int main(int argc,char **argv) { int sockfd,n, count = 0; Builder bhj; bhj.add(Value("aaa")); ValueLength len; velocystream velocy_one, velocy_two; //srt_l velocy_one.length = 100; velocy_one.chunkx = 12334; velocy_one.messageId = 12345; velocy_one.messageLength = 1; velocy_one.vpacks = bhj; velocy_two.length = 100; velocy_two.chunkx = 12335; velocy_two.messageId = 12346; velocy_two.length = 1; velocy_two.vpacks = bhj; const char *b; const char *c; const char *d; const char *elf; velocystream *srt_l = (velocystream *)malloc(1000); char ex[sizeof(velocy_one)]; b = static_cast<char*>(static_cast<void*>(&st)); c = static_cast<char*>(static_cast<void*>(&velocy_one)); d = static_cast<char*>(static_cast<void*>(&velocy_two)); int sourceArray[ARRAY_LEN]; sourceArray[0] = 1; sourceArray[1] = 2; char sendline[100]; char recvline[100]; struct sockaddr_in servaddr; int arr[2] = {1, 2}; sockfd=socket(AF_INET,SOCK_STREAM,0); bzero(&servaddr,sizeof servaddr); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(22000); inet_pton(AF_INET,"127.0.0.1",&(servaddr.sin_addr)); connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); while(1) { count +=1; if(count < 100) write(sockfd, c, sizeof(c)+1); read(sockfd,recvline,100); printf("%s",recvline); } // write(sockfd, sourceArray, sizeof(int) * ARRAY_LEN); printf("sent!!!"); }
JOB_STATUS RemoveServer::status() { auto status = exists(); if (status != NOTFOUND) { // Get job details from agency try { _server = _snapshot(pos[status] + _jobId + "/server").getString(); } catch (std::exception const& e) { std::stringstream err; err << "Failed to find job " << _jobId << " in agency: " << e.what(); LOG_TOPIC(ERR, Logger::AGENCY) << err.str(); finish("DBServers/" + _server, false, err.str()); return FAILED; } } if (status == PENDING) { Node::Children const todos = _snapshot(toDoPrefix).children(); Node::Children const pends = _snapshot(pendingPrefix).children(); size_t found = 0; for (auto const& subJob : todos) { if (!subJob.first.compare(0, _jobId.size() + 1, _jobId + "-")) { found++; } } for (auto const& subJob : pends) { if (!subJob.first.compare(0, _jobId.size() + 1, _jobId + "-")) { found++; } } if (found > 0) { // mop: TODO check if the server has reappeared and abort shard moving if // server has reappeared return status; } // mop: all addfollower jobs have been finished. Forcefully remove the // server from everything Node::Children const& planDatabases = _snapshot("/Plan/Collections").children(); Builder desiredPlanState; Builder preconditions; desiredPlanState.openObject(); preconditions.openObject(); Builder trx; trx.openArray(); trx.openObject(); for (auto const& database : planDatabases) { for (auto const& collptr : database.second->children()) { Node const& collection = *(collptr.second); for (auto const& shard : collection("shards").children()) { VPackArrayIterator dbsit(shard.second->slice()); bool found = false; Builder desiredServers; desiredServers.openArray(); // Only shards, which are affected for (auto const& dbserver : dbsit) { std::string server = dbserver.copyString(); if (server != _server) { desiredServers.add(VPackValue(server)); } else { found = true; } } desiredServers.close(); if (found == false) { continue; } std::string const& key(_agencyPrefix + "/Plan/Collections/" + database.first + "/" + collptr.first + "/shards/" + shard.first); trx.add(key, desiredServers.slice()); preconditions.add(VPackValue(key)); preconditions.openObject(); preconditions.add("old", shard.second->slice()); preconditions.close(); } } } preconditions.close(); trx.add(VPackValue(_agencyPrefix + "/Target/CleanedServers")); trx.openObject(); trx.add("op", VPackValue("push")); trx.add("new", VPackValue(_server)); trx.close(); trx.add(VPackValue(_agencyPrefix + planVersion)); trx.openObject(); trx.add("op", VPackValue("increment")); trx.close(); trx.close(); trx.add(preconditions.slice()); trx.close(); // Transact to agency write_ret_t res = transact(_agent, trx); if (res.accepted && res.indices.size() == 1 && res.indices[0] != 0) { LOG_TOPIC(INFO, Logger::AGENCY) << "Have reported " << _server << " in /Target/CleanedServers"; if (finish("DBServers/" + _server)) { return FINISHED; } return status; } } return status; }