Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix zone lost in backup #4319

Merged
merged 3 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/meta/processors/BaseProcessor-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,11 @@ bool BaseProcessor<RESP>::checkIndexExist(const std::vector<cpp2::IndexFieldDef>
}

template <typename RESP>
ErrorOr<nebula::cpp2::ErrorCode, ZoneID> BaseProcessor<RESP>::getZoneId(
const std::string& zoneName) {
auto indexKey = MetaKeyUtils::indexZoneKey(zoneName);
auto ret = doGet(std::move(indexKey));
nebula::cpp2::ErrorCode BaseProcessor<RESP>::zoneExist(const std::string& zoneName) {
auto zoneKey = MetaKeyUtils::zoneKey(zoneName);
auto ret = doGet(std::move(zoneKey));
if (nebula::ok(ret)) {
return *reinterpret_cast<const ZoneID*>(nebula::value(ret).c_str());
return nebula::cpp2::ErrorCode::SUCCEEDED;
}
auto retCode = nebula::error(ret);
if (retCode == nebula::cpp2::ErrorCode::E_KEY_NOT_FOUND) {
Expand Down
6 changes: 3 additions & 3 deletions src/meta/processors/BaseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,13 @@ class BaseProcessor {
bool checkIndexExist(const std::vector<cpp2::IndexFieldDef>& fields, const cpp2::IndexItem& item);

/**
* @brief Get zone id by zone name
* @brief Check if given zone exist.
*
* @tparam RESP
* @param zoneName
* @return ErrorOr<nebula::cpp2::ErrorCode, ZoneID>
* @return SUCCEEDED means exist, E_ZONE_NOT_FOUND means not, others means error.
*/
ErrorOr<nebula::cpp2::ErrorCode, ZoneID> getZoneId(const std::string& zoneName);
nebula::cpp2::ErrorCode zoneExist(const std::string& zoneName);

/**
* @brief Check if given space exist given type's listener.
Expand Down
59 changes: 49 additions & 10 deletions src/meta/processors/admin/RestoreProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,61 @@ nebula::cpp2::ErrorCode RestoreProcessor::replaceHostInZone(kvstore::WriteBatch*
}
auto iter = nebula::value(iterRet).get();

// Explicit use of the zone feature is disabled, and a zone can only have one host.
std::unordered_map<std::string, std::string> zoneNameMap;
std::vector<kvstore::KV> zonekv;
while (iter->valid()) {
bool needUpdate = false;
auto zoneName = MetaKeyUtils::parseZoneName(iter->key());
auto oldZoneKey = iter->key();
auto oldZoneName = MetaKeyUtils::parseZoneName(oldZoneKey);
auto hosts = MetaKeyUtils::parseZoneHosts(iter->val());
for (auto& host : hosts) {
if (hostMap.find(host) != hostMap.end()) {
host = hostMap[host];
needUpdate = true;
}
}
if (needUpdate) {
batch->put(iter->key(), MetaKeyUtils::zoneVal(hosts));

CHECK_EQ(1, hosts.size());
if (hostMap.find(hosts[0]) != hostMap.end()) {
auto host = hostMap[hosts[0]];
auto newZoneName = folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
batch->remove(oldZoneKey);
zonekv.emplace_back(
std::make_pair(MetaKeyUtils::zoneKey(newZoneName), MetaKeyUtils::zoneVal({host})));
zoneNameMap.emplace(oldZoneName, newZoneName);
}
iter->next();
}

for (auto& kv : zonekv) {
batch->put(kv.first, kv.second);
}

// Update the zonename of spaceDesc in space system table
std::map<GraphSpaceID, meta::cpp2::SpaceDesc> spaceMap;
std::string spacePrefix = MetaKeyUtils::spacePrefix();
auto spaceIterRet = doPrefix(spacePrefix, true);
if (!nebula::ok(spaceIterRet)) {
retCode = nebula::error(iterRet);
LOG(INFO) << "Space prefix failed, error: " << apache::thrift::util::enumNameSafe(retCode);
return retCode;
}

auto spaceIter = nebula::value(spaceIterRet).get();
while (spaceIter->valid()) {
spaceMap.emplace(MetaKeyUtils::spaceId(spaceIter->key()),
MetaKeyUtils::parseSpace(spaceIter->val()));
spaceIter->next();
}
for (auto& [spaceId, properties] : spaceMap) {
std::vector<std::string> curZones = properties.get_zone_names();
for (size_t i = 0; i < curZones.size(); i++) {
auto zoneName = curZones[i];
if (zoneNameMap.find(zoneName) != zoneNameMap.end()) {
curZones[i] = zoneNameMap[zoneName];
}
}
properties.zone_names_ref() = std::move(curZones);
}

for (auto& [spaceId, properties] : spaceMap) {
batch->put(MetaKeyUtils::spaceKey(spaceId), MetaKeyUtils::spaceVal(properties));
}

return retCode;
}

Expand Down
18 changes: 11 additions & 7 deletions src/meta/processors/zone/AddHostsProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ void AddHostsProcessor::process(const cpp2::AddHostsReq& req) {
onFinished();
return;
}

while (spaceIter->valid()) {
spaceMap.emplace(MetaKeyUtils::spaceId(spaceIter->key()),
MetaKeyUtils::parseSpace(spaceIter->val()));
Expand All @@ -59,10 +60,13 @@ void AddHostsProcessor::process(const cpp2::AddHostsReq& req) {

// Automatic generation zone
auto zoneName = folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
auto zoneIdRet = getZoneId(zoneName);
if (nebula::ok(zoneIdRet)) {
LOG(ERROR) << "Zone " << zoneName << " have existed";
code = nebula::error(zoneIdRet);
auto zoneRet = zoneExist(zoneName);
if (zoneRet != nebula::cpp2::ErrorCode::E_ZONE_NOT_FOUND) {
if (zoneRet == nebula::cpp2::ErrorCode::SUCCEEDED) {
LOG(ERROR) << "Zone " << zoneName << " have existed";
zoneRet = nebula::cpp2::ErrorCode::E_KEY_HAS_EXISTS;
}
code = zoneRet;
break;
}

Expand All @@ -78,16 +82,16 @@ void AddHostsProcessor::process(const cpp2::AddHostsReq& req) {
properties.zone_names_ref() = std::move(newZones);
}
}
for (auto& [spaceId, properties] : spaceMap) {
data.emplace_back(MetaKeyUtils::spaceKey(spaceId), MetaKeyUtils::spaceVal(properties));
}

if (code != nebula::cpp2::ErrorCode::SUCCEEDED) {
handleErrorCode(code);
onFinished();
return;
}

for (auto& [spaceId, properties] : spaceMap) {
data.emplace_back(MetaKeyUtils::spaceKey(spaceId), MetaKeyUtils::spaceVal(properties));
}
auto ret = doSyncPut(std::move(data));
handleErrorCode(ret);
onFinished();
Expand Down
62 changes: 36 additions & 26 deletions src/meta/test/RestoreProcessorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,11 @@ TEST(RestoreProcessorTest, RestoreTest) {
// mock an root user
data.emplace_back(MetaKeyUtils::userKey("root"), MetaKeyUtils::userVal("root"));

// mock an zone with {host1, host2, host3}
std::string zoneName = "test_zone";
std::vector<std::string> zoneNames = {zoneName};
auto zoneId = 1;
data.emplace_back(MetaKeyUtils::indexZoneKey(zoneName),
std::string(reinterpret_cast<const char*>(&zoneId), sizeof(ZoneID)));
data.emplace_back(MetaKeyUtils::zoneKey(zoneName), MetaKeyUtils::zoneVal(hosts));
// mock three zones, each zone each host
for (auto host : hosts) {
std::string zoneName = folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
data.emplace_back(MetaKeyUtils::zoneKey(zoneName), MetaKeyUtils::zoneVal({host}));
}

int32_t autoId = 666;
data.emplace_back(MetaKeyUtils::idKey(),
Expand Down Expand Up @@ -168,15 +166,20 @@ TEST(RestoreProcessorTest, RestoreTest) {
ASSERT_EQ(nebula::cpp2::ErrorCode::SUCCEEDED, result);
std::vector<cpp2::Zone> zones;
std::vector<HostAddr> restoredHosts = {host4, host5, host6};

std::unordered_map<std::string, HostAddr> restoreZoneNames;
// mock three zones, each zone each host
for (auto host : restoredHosts) {
std::string zoneName =
folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
restoreZoneNames.emplace(zoneName, host);
}
while (iter->valid()) {
auto zn = MetaKeyUtils::parseZoneName(iter->key());
auto zoneHosts = MetaKeyUtils::parseZoneHosts(iter->val());
cpp2::Zone zone;
ASSERT_EQ(zoneName, zn);
ASSERT_EQ(zoneHosts.size(), restoredHosts.size());
for (std::vector<nebula::HostAddr>::size_type i = 0; i < zoneHosts.size(); ++i) {
ASSERT_EQ(zoneHosts[i], restoredHosts[i]);
}
ASSERT_TRUE(restoreZoneNames.find(zn) != restoreZoneNames.end());
ASSERT_EQ(1, zoneHosts.size());
ASSERT_EQ(restoreZoneNames[zn], zoneHosts[0]);
iter->next();
}

Expand Down Expand Up @@ -273,14 +276,15 @@ TEST(RestoreProcessorTest, RestoreFullTest) {
data.emplace_back(MetaKeyUtils::partKey(id, partId), MetaKeyUtils::partVal(partHosts));
}

// mock an zone with {host1, host2, host3}
std::string zoneName = "test_zone";
std::vector<std::string> zoneNames = {zoneName};
// mock three zones, each zone each host
for (auto host : hosts) {
std::string zoneName = folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
data.emplace_back(MetaKeyUtils::zoneKey(zoneName), MetaKeyUtils::zoneVal({host}));
}

// mock an root user
data.emplace_back(MetaKeyUtils::userKey("root"), MetaKeyUtils::userVal("root"));
auto zoneId = 1;
data.emplace_back(MetaKeyUtils::indexZoneKey(zoneName),
std::string(reinterpret_cast<const char*>(&zoneId), sizeof(ZoneID)));
data.emplace_back(MetaKeyUtils::zoneKey(zoneName), MetaKeyUtils::zoneVal(hosts));

TestUtils::doPut(kv.get(), data);

// check part data
Expand Down Expand Up @@ -373,15 +377,21 @@ TEST(RestoreProcessorTest, RestoreFullTest) {
ASSERT_EQ(nebula::cpp2::ErrorCode::SUCCEEDED, result);
std::vector<cpp2::Zone> zones;
std::vector<HostAddr> restoredHosts = {host4, host5, host6};

std::unordered_map<std::string, HostAddr> restoreZoneNames;
// mock three zones, each zone each host
for (auto host : restoredHosts) {
std::string zoneName =
folly::stringPrintf("default_zone_%s_%d", host.host.c_str(), host.port);
restoreZoneNames.emplace(zoneName, host);
}

while (iter->valid()) {
auto zn = MetaKeyUtils::parseZoneName(iter->key());
auto zoneHosts = MetaKeyUtils::parseZoneHosts(iter->val());
cpp2::Zone zone;
ASSERT_EQ(zoneName, zn);
ASSERT_EQ(zoneHosts.size(), restoredHosts.size());
for (std::vector<nebula::HostAddr>::size_type i = 0; i < zoneHosts.size(); ++i) {
ASSERT_EQ(zoneHosts[i], restoredHosts[i]);
}
ASSERT_TRUE(restoreZoneNames.find(zn) != restoreZoneNames.end());
ASSERT_EQ(1, zoneHosts.size());
ASSERT_EQ(restoreZoneNames[zn], zoneHosts[0]);
iter->next();
}

Expand Down