bool api::isVolumeSyncedUpTo(const vd::VolumeId& vol_id, const vd::TLogId& tlog_id) { SharedVolumePtr v = VolManager::get()->findVolume_(vol_id); return v->isSyncedToBackendUpTo(tlog_id); }
TEST_P(OwnerTagTest, constant_tag) { auto ns(make_random_namespace()); SharedVolumePtr v = newVolume(*ns); const VolumeConfig cfg = v->get_config(); destroyVolume(v, DeleteLocalData::F, RemoveVolumeCompletely::F); v = localRestart(ns->ns()); EXPECT_EQ(cfg.owner_tag_, v->get_config().owner_tag_); destroyVolume(v, DeleteLocalData::T, RemoveVolumeCompletely::F); restartVolume(cfg); v = getVolume(cfg.id_); EXPECT_EQ(cfg.owner_tag_, v->get_config().owner_tag_); }
void api::setFOCTimeout(const vd::VolumeId& volName, const boost::chrono::seconds timeout) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); v->setFOCTimeout(timeout); }
TEST_P(OwnerTagTest, changing_tag) { auto ns(make_random_namespace()); SharedVolumePtr v = newVolume(*ns); const VolumeConfig cfg = v->get_config(); destroyVolume(v, DeleteLocalData::T, RemoveVolumeCompletely::F); const OwnerTag new_tag(new_owner_tag()); EXPECT_NE(cfg.owner_tag_, new_tag); { fungi::ScopedLock l(VolManager::get()->mgmtMutex_); VolManager::get()->backend_restart(cfg.getNS(), new_tag, PrefetchVolumeData::F, IgnoreFOCIfUnreachable::F); } v = getVolume(cfg.id_); EXPECT_EQ(new_tag, v->get_config().owner_tag_); }
void api::setFailOverCacheConfig(const vd::VolumeId& volName, const boost::optional<vd::FailOverCacheConfig>& maybe_foc_config) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); v->setFailOverCacheConfig(maybe_foc_config); }
bool api::isVolumeSynced(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->isSyncedToBackend(); }
bool api::isVolumeSyncedUpTo(const vd::VolumeId& volName, const vd::SnapshotName& snapshotName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->isSyncedToBackendUpTo(snapshotName); }
TEST_P(DtlCheckerTest, auto_recovery) { auto ns_ptr = make_random_namespace(); const backend::Namespace& ns = ns_ptr->ns(); SharedVolumePtr v = newVolume("vol1", ns); const auto port = get_next_foc_port(); ASSERT_THROW(v->setFailOverCacheConfig(FailOverCacheConfig(FailOverCacheTestSetup::host(), port, GetParam().foc_mode())), fungi::IOException); ASSERT_EQ(VolumeFailOverState::DEGRADED, v->getVolumeFailOverState()); auto foc_ctx(start_one_foc()); ASSERT_EQ(port, foc_ctx->port()); boost::this_thread::sleep_for(2 * dtl_check_interval_); ASSERT_EQ(VolumeFailOverState::OK_SYNC, v->getVolumeFailOverState()); }
uint64_t api::getSnapshotBackendSize(const vd::VolumeId& volName, const vd::SnapshotName& snapName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getSnapshotBackendSize(snapName); }
void api::showSnapshots(const VolumeId& volName, std::list<vd::SnapshotName>& l) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); v->listSnapshots(l); }
TEST_P(BigReadWriteTest, bigReadsOnFull) { auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns()); SCOPED_BLOCK_BACKEND(*v); size_t csz = v->getClusterSize(); size_t lba_size = v->getLBASize(); const std::string pattern(csz,'a'); size_t scoMul = v->getSCOMultiplier(); for(size_t i = 0;i < 50*scoMul; ++i) { writeToVolume(*v, i* csz / lba_size, csz, pattern); } // Stop here to manually delete sco's to check error handling for(size_t i = 0; i < scoMul; ++i) { checkVolume(*v,0, csz*scoMul, pattern); } }
uint64_t api::getSnapshotSCOCount(const vd::VolumeId& volName, const vd::SnapshotName& snapid) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getSnapshotSCOCount(snapid); }
boost::optional<be::Garbage> api::applyScrubbingWork(const vd::VolumeId& volName, const scrubbing::ScrubReply& scrub_reply, const vd::ScrubbingCleanup cleanup) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->applyScrubbingWork(scrub_reply, cleanup); }
TEST_P(SnapshotRestoreTest, snapshot_restoration_on_a_clone) { const auto wrns_parent(make_random_namespace()); const std::string parent_name(wrns_parent->ns().str()); SharedVolumePtr parent = newVolume(VolumeId(parent_name), be::Namespace(parent_name)); const std::string pattern1("before-parent-snapshot"); writeToVolume(*parent, 0, parent->getClusterSize(), pattern1); const SnapshotName parent_snap("parent-snapshot"); parent->createSnapshot(parent_snap); waitForThisBackendWrite(*parent); const auto wrns_clone(make_random_namespace()); const std::string clone_name(wrns_clone->ns().str()); SharedVolumePtr clone = createClone(clone_name, be::Namespace(clone_name), be::Namespace(parent_name), parent_snap); const std::string pattern2("before-clone-snapshot"); writeToVolume(*clone, 0, clone->getClusterSize(), pattern2); const SnapshotName clone_snap("clone-snapshot"); clone->createSnapshot(clone_snap); waitForThisBackendWrite(*clone); const std::string pattern3("after-clone-snapshot"); writeToVolume(*clone, 0, clone->getClusterSize(), pattern3); checkVolume(*clone, 0, clone->getClusterSize(), pattern3); restoreSnapshot(*clone, clone_snap); checkVolume(*clone, 0, clone->getClusterSize(), pattern2); }
TEST_P(SnapshotRestoreTest, TestFailOver) { auto foc_ctx(start_one_foc()); auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns(), VolumeSize((1 << 18) * 512), SCOMultiplier(1)); v->setFailOverCacheConfig(foc_ctx->config(GetParam().foc_mode())); VolumeConfig cfg = v->get_config(); v->createSnapshot(SnapshotName("snap0")); for(int i = 0; i < 5; ++i) { writeToVolume(*v, 0, 4096, "a"); } waitForThisBackendWrite(*v); v->restoreSnapshot(SnapshotName("snap0")); for(int i = 0; i < 7; ++i) { writeToVolume(*v, 8, 4096, "d"); } flushFailOverCache(*v); destroyVolume(v, DeleteLocalData::T, RemoveVolumeCompletely::F); SharedVolumePtr v1 = 0; v1 = getVolume(VolumeId("volume1")); ASSERT_FALSE(v1); restartVolume(cfg); v1 = getVolume(VolumeId("volume1")); ASSERT_TRUE(v1 != nullptr); checkVolume(*v1,0,4096, "\0"); checkVolume(*v1,8,4096, "d"); checkCurrentBackendSize(*v1); }
TEST_P(BigReadWriteTest, bigReadsOnEmpty) { auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns()); size_t csz = v->getClusterSize(); const std::string pattern(csz,'\0'); size_t scoMul = v->getSCOMultiplier(); for(size_t i = 0; i < scoMul; ++i) { checkVolume(*v,0, csz*scoMul, pattern); } }
TEST_P(BigReadWriteTest, OneBigWriteOneBigRead) { auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns()); SCOPED_BLOCK_BACKEND(*v); size_t csz = v->getClusterSize(); const std::string pattern(csz,'a'); size_t scoMul = v->getSCOMultiplier(); writeToVolume(*v, 0, csz * scoMul, pattern); // Stop here to manually delete sco's to check error handling checkVolume(*v,0, csz*scoMul, pattern); }
TEST_P(SnapshotRestoreTest, RestoreAndWriteAgain1) { auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns(), VolumeSize(1 << 26), SCOMultiplier(1)); const std::string pattern("e-manual"); v->createSnapshot(SnapshotName("snap1")); waitForThisBackendWrite(*v); writeToVolume(*v, 0, 5 * 4096, pattern); waitForThisBackendWrite(*v); restoreSnapshot(*v,"snap1"); writeToVolume(*v, 0, 4*4096, pattern); waitForThisBackendWrite(*v); checkCurrentBackendSize(*v); }
TEST_P(SnapshotRestoreTest, HaltOnError) { auto ns_ptr = make_random_namespace(); SharedVolumePtr v = newVolume(VolumeId("volume1"), ns_ptr->ns()); const std::string pattern1("blah"); const TLogId tlog_id(v->getSnapshotManagement().getCurrentTLogId()); writeToVolume(*v, 0, 4096, pattern1); v->createSnapshot(SnapshotName("snap1")); waitForThisBackendWrite(*v); EXPECT_THROW(restoreSnapshot(*v, "snap42"), std::exception); EXPECT_FALSE(v->is_halted()); v->getBackendInterface()->remove(boost::lexical_cast<std::string>(tlog_id)); EXPECT_THROW(restoreSnapshot(*v, "snap1"), std::exception); EXPECT_TRUE(v->is_halted()); }
uint64_t api::getTLogUsed(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getTLogUsed(); }
void test_after_tlog(bool failover) { const auto wrns(make_random_namespace()); SharedVolumePtr v = make_volume(*wrns); const std::string pattern1("Hairdresser On Fire"); { SCOPED_BLOCK_BACKEND(*v); writeToVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern1); } v->scheduleBackendSync(); waitForThisBackendWrite(*v); const std::string pattern2("Such A Little Thing Makes Such A Big Difference"); writeToVolume(*v, 2 * v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern2); const auto ncfgs(node_configs()); if (failover) { mds_manager_->stop_one(ncfgs[0]); checkVolume(*v, 0, v->getClusterSize(), ""); } else { const std::vector<MDSNodeConfig> ncfgs2{ ncfgs[1], ncfgs[0] }; v->updateMetaDataBackendConfig(MDSMetaDataBackendConfig(ncfgs2, ApplyRelocationsToSlaves::T)); } check_config(*v, ncfgs, true); checkVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern1); checkVolume(*v, 2 * v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern2); destroyVolume(v, DeleteLocalData::F, RemoveVolumeCompletely::F); v = localRestart(wrns->ns()); check_config(*v, ncfgs, true); checkVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern1); checkVolume(*v, 2 * v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern2); }
void api::startPrefetching(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); v->startPrefetch(); }
uint64_t api::getCurrentBackendSize(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getCurrentBackendSize(); }
vd::TLogId api::scheduleBackendSync(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->scheduleBackendSync(); }
bool api::checkVolumeConsistency(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->checkConsistency(); }
uint64_t api::getCurrentSCOCount(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getSnapshotSCOCount(); }
void test_before_tlog(bool failover) { const auto wrns(make_random_namespace()); SharedVolumePtr v = make_volume(*wrns); const auto ncfgs(node_configs()); const std::string pattern("King Leer"); { SCOPED_BLOCK_BACKEND(*v); writeToVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern); if (failover) { mds_manager_->stop_one(ncfgs[0]); checkVolume(*v, 0, v->getClusterSize(), ""); } else { const std::vector<MDSNodeConfig> ncfgs2{ ncfgs[1], ncfgs[0] }; v->updateMetaDataBackendConfig(MDSMetaDataBackendConfig(ncfgs2, ApplyRelocationsToSlaves::T)); } check_config(*v, ncfgs, true); checkVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern); } destroyVolume(v, DeleteLocalData::F, RemoveVolumeCompletely::F); v = localRestart(wrns->ns()); check_config(*v, ncfgs, true); checkVolume(*v, v->getClusterMultiplier() * CachePage::capacity(), v->getClusterSize(), pattern); }
vd::VolumeFailOverState api::getFailOverMode(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getVolumeFailOverState(); }
TEST_P(SimpleBackupRestoreTest, rollback_to_previous_snap_if_snapshot_didnt_make_it) { auto ns_ptr = make_random_namespace(); const backend::Namespace& nspace = ns_ptr->ns(); // const Namespace nspace; const VolumeId vid("backup"); auto wov = newWriteOnlyVolume(vid, nspace, BackupRole::WanBackupBase); ASSERT_TRUE(wov); const auto cfg(wov->get_config()); const std::string pattern("a mysteriously returning message"); const size_t size = 1024 * 1024; writeToVolume(*wov, 0, size, pattern); const SnapshotName snap("snap"); wov->createSnapshot(snap); waitForThisBackendWrite(*wov); const std::string pattern2("a mysteriously disappearing message"); writeToVolume(*wov, 0, size, pattern2); wov->scheduleBackendSync(); waitForThisBackendWrite(*wov); { SCOPED_DESTROY_WRITE_ONLY_VOLUME_UNBLOCK_BACKEND_FOR_BACKEND_RESTART(wov, 3); wov->createSnapshot(SnapshotName("snap2")); const SnapshotPersistor& sp = wov->getSnapshotManagement().getSnapshotPersistor(); SnapshotManagement::writeSnapshotPersistor(sp, cm_->newBackendInterface(nspace)); } const fs::path cfg_file(make_config_file(nspace, MaybeString(), MaybeString(), MaybeBackupRole(BackupRole::WanBackupNormal))); bu::Restore(cfg_file, false, youtils::GracePeriod(boost::posix_time::seconds(2)))(); { fungi::ScopedLock l(api::getManagementMutex()); api::backend_restart(nspace, new_owner_tag(), PrefetchVolumeData::T, IgnoreFOCIfUnreachable::T); } SharedVolumePtr v = getVolume(vid); checkVolume(*v, 0, size, pattern); std::list<SnapshotName> snaps; v->listSnapshots(snaps); EXPECT_EQ(1U, snaps.size()); EXPECT_EQ(snap, snaps.front()); }
boost::optional<vd::FailOverCacheConfig> api::getFailOverCacheConfig(const vd::VolumeId& volName) { SharedVolumePtr v = VolManager::get()->findVolume_(volName); return v->getFailOverCacheConfig(); }