/* * MockDDTrackerShardEvaluator.actor.cpp * * This source file is part of the FoundationDB open source project * * Copyright 2013-2022 Apple Inc. and the FoundationDB project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "fdbserver/workloads/MockDDTest.h" #include "flow/actorcompiler.h" // This must be the last #include. class MockDDTrackerShardEvaluatorWorkload : public MockDDTestWorkload { public: static constexpr auto NAME = "MockDDTrackerShardEvaluator"; DDSharedContext ddcx; Reference mock; PromiseStream output; PromiseStream getShardMetrics; PromiseStream getTopKMetrics; PromiseStream getShardMetricsList; PromiseStream> getAverageShardBytes; PromiseStream triggerStorageQueueRebalance; PromiseStream triggerShardBulkLoading; KeyRangeMap shards; ActorCollection actors; std::map rsReasonCounts; Reference shardTracker; // --- test configs --- // check threshold int checkMinShardCount = 1; int checkMinSizeSplit = 0; int checkMinWriteSplit = 0; MockDDTrackerShardEvaluatorWorkload(WorkloadContext const& wcx) : MockDDTestWorkload(wcx), ddcx(deterministicRandom()->randomUniqueID()) { checkMinShardCount = getOption(options, "checkMinShardCount"_sr, checkMinShardCount); checkMinSizeSplit = getOption(options, "checkMinSizeSplit"_sr, checkMinSizeSplit); checkMinWriteSplit = getOption(options, "checkMinWriteSplit"_sr, checkMinWriteSplit); } Future setup(Database const& cx) override { if (!enabled) return Void(); MockDDTestWorkload::setup(cx); // populate sharedMgs before run tracker populateMgs(); mock = makeReference(sharedMgs); return Void(); } ACTOR static Future relocateShardReporter(MockDDTrackerShardEvaluatorWorkload* self, FutureStream input) { loop { try { choose { when(RelocateShard rs = waitNext(input)) { ++self->rsReasonCounts[rs.reason]; } } } catch (Error& e) { if (e.code() != error_code_wrong_shard_server) throw e; wait(delay(CLIENT_KNOBS->WRONG_SHARD_SERVER_DELAY)); } } } Future start(Database const& cx) override { if (!enabled) return Void(); // start mock servers actors.add(waitForAll(sharedMgs->runAllMockServers())); // start tracker Reference initData = mock->getInitialDataDistribution(ddcx.id(), ddcx.lock, {}, ddcx.ddEnabledState.get(), SkipDDModeCheck::True) .get(); Reference physicalShardCollection = makeReference(); Reference bulkLoadTaskCollection = makeReference(ddcx.id(), SERVER_KNOBS->DD_BULKLOAD_PARALLELISM); Reference> zeroHealthyTeams = makeReference>(false); shardTracker = makeReference( DataDistributionTrackerInitParams{ .db = mock, .distributorId = ddcx.id(), .readyToStart = Promise(), .output = output, .shardsAffectedByTeamFailure = ddcx.shardsAffectedByTeamFailure, .physicalShardCollection = physicalShardCollection, .bulkLoadTaskCollection = bulkLoadTaskCollection, .anyZeroHealthyTeams = zeroHealthyTeams, .shards = &shards, .trackerCancelled = &ddcx.trackerCancelled, .ddTenantCache = {} }); actors.add(DataDistributionTracker::run(shardTracker, initData, getShardMetrics.getFuture(), getTopKMetrics.getFuture(), getShardMetricsList.getFuture(), getAverageShardBytes.getFuture(), triggerStorageQueueRebalance.getFuture(), triggerShardBulkLoading.getFuture())); actors.add(relocateShardReporter(this, output.getFuture())); return timeout(reportErrors(actors.getResult(), "MockDDTrackerShardEvaluatorWorkload"), testDuration, Void()); } Future check(Database const& cx) override { if (!enabled) return true; fmt::print("Check phase shards count: {}\n", shards.size()); ASSERT_GE(shards.size(), checkMinShardCount); for (auto& [r, c] : rsReasonCounts) { fmt::print("{}: {}\n", r.toString(), c); } ASSERT_GE(rsReasonCounts[RelocateReason::SIZE_SPLIT], checkMinSizeSplit); ASSERT_GE(rsReasonCounts[RelocateReason::WRITE_SPLIT], checkMinWriteSplit); actors.clear(true); return true; } void getMetrics(std::vector& m) override { for (const auto& [reason, count] : rsReasonCounts) { m.push_back(PerfMetric(RelocateReason(reason).toString(), count, Averaged::False)); } } }; WorkloadFactory MockDDTrackerShardEvaluatorWorkload;