Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / journal / test_Entries.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librbd/test_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "librbd/internal.h"
7 #include "librbd/Journal.h"
8 #include "librbd/io/AioCompletion.h"
9 #include "librbd/io/ImageRequestWQ.h"
10 #include "librbd/journal/Types.h"
11 #include "journal/Journaler.h"
12 #include "journal/ReplayEntry.h"
13 #include "journal/ReplayHandler.h"
14 #include "journal/Settings.h"
15 #include <list>
16 #include <boost/variant.hpp>
17
18 void register_test_journal_entries() {
19 }
20
21 class TestJournalEntries : public TestFixture {
22 public:
23   typedef std::list<journal::Journaler *> Journalers;
24
25   struct ReplayHandler : public journal::ReplayHandler {
26     Mutex lock;
27     Cond cond;
28     bool entries_available;
29     bool complete;
30
31     ReplayHandler()
32       : lock("ReplayHandler::lock"), entries_available(false), complete(false) {
33     }
34
35     void get() override {
36     }
37     void put() override {
38     }
39
40     void handle_entries_available() override  {
41       Mutex::Locker locker(lock);
42       entries_available = true;
43       cond.Signal();
44     }
45
46     void handle_complete(int r) override {
47       Mutex::Locker locker(lock);
48       complete = true;
49       cond.Signal();
50     }
51   };
52
53   ReplayHandler m_replay_handler;
54   Journalers m_journalers;
55
56   void TearDown() override {
57     for (Journalers::iterator it = m_journalers.begin();
58          it != m_journalers.end(); ++it) {
59       journal::Journaler *journaler = *it;
60       journaler->stop_replay();
61       journaler->shut_down();
62       delete journaler;
63     }
64
65     TestFixture::TearDown();
66   }
67
68   journal::Journaler *create_journaler(librbd::ImageCtx *ictx) {
69     journal::Journaler *journaler = new journal::Journaler(
70       ictx->md_ctx, ictx->id, "dummy client", {});
71
72     int r = journaler->register_client(bufferlist());
73     if (r < 0) {
74       ADD_FAILURE() << "failed to register journal client";
75       delete journaler;
76       return NULL;
77     }
78
79     C_SaferCond cond;
80     journaler->init(&cond);
81     r = cond.wait();
82     if (r < 0) {
83       ADD_FAILURE() << "failed to initialize journal client";
84       delete journaler;
85       return NULL;
86     }
87
88     journaler->start_live_replay(&m_replay_handler, 0.1);
89     m_journalers.push_back(journaler);
90     return journaler;
91   }
92
93   bool wait_for_entries_available(librbd::ImageCtx *ictx) {
94     Mutex::Locker locker(m_replay_handler.lock);
95     while (!m_replay_handler.entries_available) {
96       if (m_replay_handler.cond.WaitInterval(m_replay_handler.lock,
97                                              utime_t(10, 0)) != 0) {
98         return false;
99       }
100     }
101     m_replay_handler.entries_available = false;
102     return true;
103   }
104
105   bool get_event_entry(const journal::ReplayEntry &replay_entry,
106                        librbd::journal::EventEntry *event_entry) {
107     try {
108       bufferlist data_bl = replay_entry.get_data();
109       bufferlist::iterator it = data_bl.begin();
110       ::decode(*event_entry, it);
111     } catch (const buffer::error &err) {
112       return false;
113     }
114     return true;
115   }
116
117 };
118
119 TEST_F(TestJournalEntries, AioWrite) {
120   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
121
122   librbd::ImageCtx *ictx;
123   ASSERT_EQ(0, open_image(m_image_name, &ictx));
124
125   journal::Journaler *journaler = create_journaler(ictx);
126   ASSERT_TRUE(journaler != NULL);
127
128   std::string buffer(512, '1');
129   bufferlist write_bl;
130   write_bl.append(buffer);
131
132   C_SaferCond cond_ctx;
133   auto c = librbd::io::AioCompletion::create(&cond_ctx);
134   c->get();
135   ictx->io_work_queue->aio_write(c, 123, buffer.size(), std::move(write_bl), 0);
136   ASSERT_EQ(0, c->wait_for_complete());
137   c->put();
138
139   ASSERT_TRUE(wait_for_entries_available(ictx));
140
141   journal::ReplayEntry replay_entry;
142   ASSERT_TRUE(journaler->try_pop_front(&replay_entry));
143
144   librbd::journal::EventEntry event_entry;
145   ASSERT_TRUE(get_event_entry(replay_entry, &event_entry));
146
147   ASSERT_EQ(librbd::journal::EVENT_TYPE_AIO_WRITE,
148             event_entry.get_event_type());
149
150   librbd::journal::AioWriteEvent aio_write_event =
151     boost::get<librbd::journal::AioWriteEvent>(event_entry.event);
152   ASSERT_EQ(123U, aio_write_event.offset);
153   ASSERT_EQ(buffer.size(), aio_write_event.length);
154
155   bufferlist buffer_bl;
156   buffer_bl.append(buffer);
157   ASSERT_TRUE(aio_write_event.data.contents_equal(buffer_bl));
158
159   ASSERT_EQ(librbd::journal::AioWriteEvent::get_fixed_size() +
160               aio_write_event.data.length(), replay_entry.get_data().length());
161 }
162
163 TEST_F(TestJournalEntries, AioDiscard) {
164   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
165
166   CephContext* cct = reinterpret_cast<CephContext*>(_rados.cct());
167   REQUIRE(!cct->_conf->get_val<bool>("rbd_skip_partial_discard"));
168
169   librbd::ImageCtx *ictx;
170   ASSERT_EQ(0, open_image(m_image_name, &ictx));
171
172   journal::Journaler *journaler = create_journaler(ictx);
173   ASSERT_TRUE(journaler != NULL);
174
175   C_SaferCond cond_ctx;
176   auto c = librbd::io::AioCompletion::create(&cond_ctx);
177   c->get();
178   ictx->io_work_queue->aio_discard(c, 123, 234, ictx->skip_partial_discard);
179   ASSERT_EQ(0, c->wait_for_complete());
180   c->put();
181
182   ASSERT_TRUE(wait_for_entries_available(ictx));
183
184   journal::ReplayEntry replay_entry;
185   ASSERT_TRUE(journaler->try_pop_front(&replay_entry));
186
187   librbd::journal::EventEntry event_entry;
188   ASSERT_TRUE(get_event_entry(replay_entry, &event_entry));
189
190   ASSERT_EQ(librbd::journal::EVENT_TYPE_AIO_DISCARD,
191             event_entry.get_event_type());
192
193   librbd::journal::AioDiscardEvent aio_discard_event =
194     boost::get<librbd::journal::AioDiscardEvent>(event_entry.event);
195   ASSERT_EQ(123U, aio_discard_event.offset);
196   ASSERT_EQ(234U, aio_discard_event.length);
197 }
198
199 TEST_F(TestJournalEntries, AioFlush) {
200   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
201
202   librbd::ImageCtx *ictx;
203   ASSERT_EQ(0, open_image(m_image_name, &ictx));
204
205   journal::Journaler *journaler = create_journaler(ictx);
206   ASSERT_TRUE(journaler != NULL);
207
208   C_SaferCond cond_ctx;
209   auto c = librbd::io::AioCompletion::create(&cond_ctx);
210   c->get();
211   ictx->io_work_queue->aio_flush(c);
212   ASSERT_EQ(0, c->wait_for_complete());
213   c->put();
214
215   ASSERT_TRUE(wait_for_entries_available(ictx));
216
217   journal::ReplayEntry replay_entry;
218   ASSERT_TRUE(journaler->try_pop_front(&replay_entry));
219
220   librbd::journal::EventEntry event_entry;
221   ASSERT_TRUE(get_event_entry(replay_entry, &event_entry));
222
223   ASSERT_EQ(librbd::journal::EVENT_TYPE_AIO_FLUSH,
224             event_entry.get_event_type());
225 }