diff options
Diffstat (limited to 'src/test/journal/test_JournalMetadata.cc')
-rw-r--r-- | src/test/journal/test_JournalMetadata.cc | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/test/journal/test_JournalMetadata.cc b/src/test/journal/test_JournalMetadata.cc new file mode 100644 index 000000000..4108d4da3 --- /dev/null +++ b/src/test/journal/test_JournalMetadata.cc @@ -0,0 +1,210 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "journal/JournalMetadata.h" +#include "test/journal/RadosTestFixture.h" +#include "common/Cond.h" +#include <map> + +class TestJournalMetadata : public RadosTestFixture { +public: + void TearDown() override { + for (MetadataList::iterator it = m_metadata_list.begin(); + it != m_metadata_list.end(); ++it) { + (*it)->remove_listener(&m_listener); + } + m_metadata_list.clear(); + + RadosTestFixture::TearDown(); + } + + auto create_metadata(const std::string &oid, + const std::string &client_id, + double commit_interval = 0.1, + int max_concurrent_object_sets = 0) { + auto metadata = RadosTestFixture::create_metadata( + oid, client_id, commit_interval, max_concurrent_object_sets); + m_metadata_list.push_back(metadata); + metadata->add_listener(&m_listener); + return metadata; + } + + typedef std::list<ceph::ref_t<journal::JournalMetadata>> MetadataList; + MetadataList m_metadata_list; +}; + +TEST_F(TestJournalMetadata, JournalDNE) { + std::string oid = get_temp_oid(); + + auto metadata1 = create_metadata(oid, "client1"); + ASSERT_EQ(-ENOENT, init_metadata(metadata1)); +} + +TEST_F(TestJournalMetadata, ClientDNE) { + std::string oid = get_temp_oid(); + + ASSERT_EQ(0, create(oid, 14, 2)); + ASSERT_EQ(0, client_register(oid, "client1", "")); + + auto metadata1 = create_metadata(oid, "client1"); + ASSERT_EQ(0, init_metadata(metadata1)); + + auto metadata2 = create_metadata(oid, "client2"); + ASSERT_EQ(-ENOENT, init_metadata(metadata2)); +} + +TEST_F(TestJournalMetadata, Committed) { + std::string oid = get_temp_oid(); + + ASSERT_EQ(0, create(oid, 14, 2)); + ASSERT_EQ(0, client_register(oid, "client1", "")); + + auto metadata1 = create_metadata(oid, "client1", 600); + ASSERT_EQ(0, init_metadata(metadata1)); + + auto metadata2 = create_metadata(oid, "client1"); + ASSERT_EQ(0, init_metadata(metadata2)); + ASSERT_TRUE(wait_for_update(metadata2)); + + journal::JournalMetadata::ObjectSetPosition expect_commit_position; + journal::JournalMetadata::ObjectSetPosition read_commit_position; + metadata1->get_commit_position(&read_commit_position); + ASSERT_EQ(expect_commit_position, read_commit_position); + + uint64_t commit_tid1 = metadata1->allocate_commit_tid(0, 0, 0); + uint64_t commit_tid2 = metadata1->allocate_commit_tid(0, 1, 0); + uint64_t commit_tid3 = metadata1->allocate_commit_tid(1, 0, 1); + uint64_t commit_tid4 = metadata1->allocate_commit_tid(0, 0, 2); + + // cannot commit until tid1 + 2 committed + metadata1->committed(commit_tid2, []() { return nullptr; }); + metadata1->committed(commit_tid3, []() { return nullptr; }); + + C_SaferCond cond1; + metadata1->committed(commit_tid1, [&cond1]() { return &cond1; }); + + // given our 10 minute commit internal, this should override the + // in-flight commit + C_SaferCond cond2; + metadata1->committed(commit_tid4, [&cond2]() { return &cond2; }); + + ASSERT_EQ(-ESTALE, cond1.wait()); + metadata1->flush_commit_position(); + ASSERT_EQ(0, cond2.wait()); + + ASSERT_TRUE(wait_for_update(metadata2)); + metadata2->get_commit_position(&read_commit_position); + expect_commit_position = {{{0, 0, 2}, {1, 0, 1}}}; + ASSERT_EQ(expect_commit_position, read_commit_position); +} + +TEST_F(TestJournalMetadata, UpdateActiveObject) { + std::string oid = get_temp_oid(); + + ASSERT_EQ(0, create(oid, 14, 2)); + ASSERT_EQ(0, client_register(oid, "client1", "")); + + auto metadata1 = create_metadata(oid, "client1"); + ASSERT_EQ(0, init_metadata(metadata1)); + ASSERT_TRUE(wait_for_update(metadata1)); + + ASSERT_EQ(0U, metadata1->get_active_set()); + + ASSERT_EQ(0, metadata1->set_active_set(123)); + ASSERT_TRUE(wait_for_update(metadata1)); + + ASSERT_EQ(123U, metadata1->get_active_set()); +} + +TEST_F(TestJournalMetadata, DisconnectLaggyClient) { + std::string oid = get_temp_oid(); + + ASSERT_EQ(0, create(oid)); + ASSERT_EQ(0, client_register(oid, "client1", "")); + ASSERT_EQ(0, client_register(oid, "client2", "laggy")); + + int max_concurrent_object_sets = 100; + auto metadata = + create_metadata(oid, "client1", 0.1, max_concurrent_object_sets); + ASSERT_EQ(0, init_metadata(metadata)); + ASSERT_TRUE(wait_for_update(metadata)); + + ASSERT_EQ(0U, metadata->get_active_set()); + + journal::JournalMetadata::RegisteredClients clients; + +#define ASSERT_CLIENT_STATES(s1, s2) \ + ASSERT_EQ(2U, clients.size()); \ + for (auto &c : clients) { \ + if (c.id == "client1") { \ + ASSERT_EQ(c.state, s1); \ + } else if (c.id == "client2") { \ + ASSERT_EQ(c.state, s2); \ + } else { \ + ASSERT_TRUE(false); \ + } \ + } + + metadata->get_registered_clients(&clients); + ASSERT_CLIENT_STATES(cls::journal::CLIENT_STATE_CONNECTED, + cls::journal::CLIENT_STATE_CONNECTED); + + // client2 is connected when active set <= max_concurrent_object_sets + ASSERT_EQ(0, metadata->set_active_set(max_concurrent_object_sets)); + ASSERT_TRUE(wait_for_update(metadata)); + uint64_t commit_tid = metadata->allocate_commit_tid(0, 0, 0); + C_SaferCond cond1; + metadata->committed(commit_tid, [&cond1]() { return &cond1; }); + ASSERT_EQ(0, cond1.wait()); + metadata->flush_commit_position(); + ASSERT_TRUE(wait_for_update(metadata)); + ASSERT_EQ(100U, metadata->get_active_set()); + clients.clear(); + metadata->get_registered_clients(&clients); + ASSERT_CLIENT_STATES(cls::journal::CLIENT_STATE_CONNECTED, + cls::journal::CLIENT_STATE_CONNECTED); + + // client2 is disconnected when active set > max_concurrent_object_sets + ASSERT_EQ(0, metadata->set_active_set(max_concurrent_object_sets + 1)); + ASSERT_TRUE(wait_for_update(metadata)); + commit_tid = metadata->allocate_commit_tid(0, 0, 1); + C_SaferCond cond2; + metadata->committed(commit_tid, [&cond2]() { return &cond2; }); + ASSERT_EQ(0, cond2.wait()); + metadata->flush_commit_position(); + ASSERT_TRUE(wait_for_update(metadata)); + ASSERT_EQ(101U, metadata->get_active_set()); + clients.clear(); + metadata->get_registered_clients(&clients); + ASSERT_CLIENT_STATES(cls::journal::CLIENT_STATE_CONNECTED, + cls::journal::CLIENT_STATE_DISCONNECTED); +} + +TEST_F(TestJournalMetadata, AssertActiveTag) { + std::string oid = get_temp_oid(); + + ASSERT_EQ(0, create(oid)); + ASSERT_EQ(0, client_register(oid, "client1", "")); + + auto metadata = create_metadata(oid, "client1"); + ASSERT_EQ(0, init_metadata(metadata)); + ASSERT_TRUE(wait_for_update(metadata)); + + C_SaferCond ctx1; + cls::journal::Tag tag1; + metadata->allocate_tag(cls::journal::Tag::TAG_CLASS_NEW, {}, &tag1, &ctx1); + ASSERT_EQ(0, ctx1.wait()); + + C_SaferCond ctx2; + metadata->assert_active_tag(tag1.tid, &ctx2); + ASSERT_EQ(0, ctx2.wait()); + + C_SaferCond ctx3; + cls::journal::Tag tag2; + metadata->allocate_tag(tag1.tag_class, {}, &tag2, &ctx3); + ASSERT_EQ(0, ctx3.wait()); + + C_SaferCond ctx4; + metadata->assert_active_tag(tag1.tid, &ctx4); + ASSERT_EQ(-ESTALE, ctx4.wait()); +} |