]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "include/types.h" | |
5 | #include "cls/log/cls_log_types.h" | |
6 | #include "cls/log/cls_log_client.h" | |
7 | ||
8 | #include "include/utime.h" | |
9 | #include "common/Clock.h" | |
10 | #include "global/global_context.h" | |
11 | ||
12 | #include "gtest/gtest.h" | |
11fdf7f2 | 13 | #include "test/librados/test_cxx.h" |
7c673cae FG |
14 | |
15 | #include <errno.h> | |
16 | #include <string> | |
17 | #include <vector> | |
18 | ||
9f95a23c TL |
19 | /// creates a temporary pool and initializes an IoCtx for each test |
20 | class cls_log : public ::testing::Test { | |
21 | librados::Rados rados; | |
22 | std::string pool_name; | |
23 | protected: | |
24 | librados::IoCtx ioctx; | |
7c673cae | 25 | |
9f95a23c TL |
26 | void SetUp() { |
27 | pool_name = get_temp_pool_name(); | |
28 | /* create pool */ | |
29 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
30 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
31 | } | |
32 | void TearDown() { | |
33 | /* remove pool */ | |
34 | ioctx.close(); | |
35 | ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); | |
36 | } | |
37 | }; | |
7c673cae FG |
38 | |
39 | static int read_bl(bufferlist& bl, int *i) | |
40 | { | |
11fdf7f2 | 41 | auto iter = bl.cbegin(); |
7c673cae FG |
42 | |
43 | try { | |
11fdf7f2 | 44 | decode(*i, iter); |
7c673cae FG |
45 | } catch (buffer::error& err) { |
46 | std::cout << "failed to decode buffer" << std::endl; | |
47 | return -EIO; | |
48 | } | |
49 | ||
50 | return 0; | |
51 | } | |
52 | ||
53 | void add_log(librados::ObjectWriteOperation *op, utime_t& timestamp, string& section, string&name, int i) | |
54 | { | |
55 | bufferlist bl; | |
11fdf7f2 | 56 | encode(i, bl); |
7c673cae FG |
57 | |
58 | cls_log_add(*op, timestamp, section, name, bl); | |
59 | } | |
60 | ||
61 | ||
62 | string get_name(int i) | |
63 | { | |
64 | string name_prefix = "data-source"; | |
65 | ||
66 | char buf[16]; | |
67 | snprintf(buf, sizeof(buf), "%d", i); | |
68 | return name_prefix + buf; | |
69 | } | |
70 | ||
71 | void generate_log(librados::IoCtx& ioctx, string& oid, int max, utime_t& start_time, bool modify_time) | |
72 | { | |
73 | string section = "global"; | |
74 | ||
9f95a23c | 75 | librados::ObjectWriteOperation op; |
7c673cae FG |
76 | |
77 | int i; | |
78 | ||
79 | for (i = 0; i < max; i++) { | |
80 | uint32_t secs = start_time.sec(); | |
81 | if (modify_time) | |
82 | secs += i; | |
83 | ||
84 | utime_t ts(secs, start_time.nsec()); | |
85 | string name = get_name(i); | |
86 | ||
9f95a23c | 87 | add_log(&op, ts, section, name, i); |
7c673cae FG |
88 | } |
89 | ||
9f95a23c | 90 | ASSERT_EQ(0, ioctx.operate(oid, &op)); |
7c673cae FG |
91 | } |
92 | ||
93 | utime_t get_time(utime_t& start_time, int i, bool modify_time) | |
94 | { | |
95 | uint32_t secs = start_time.sec(); | |
96 | if (modify_time) | |
97 | secs += i; | |
98 | return utime_t(secs, start_time.nsec()); | |
99 | } | |
100 | ||
101 | void check_entry(cls_log_entry& entry, utime_t& start_time, int i, bool modified_time) | |
102 | { | |
103 | string section = "global"; | |
104 | string name = get_name(i); | |
105 | utime_t ts = get_time(start_time, i, modified_time); | |
106 | ||
107 | ASSERT_EQ(section, entry.section); | |
108 | ASSERT_EQ(name, entry.name); | |
109 | ASSERT_EQ(ts, entry.timestamp); | |
110 | } | |
111 | ||
9f95a23c TL |
112 | static int log_list(librados::IoCtx& ioctx, const std::string& oid, |
113 | utime_t& from, utime_t& to, | |
114 | const string& in_marker, int max_entries, | |
115 | list<cls_log_entry>& entries, | |
116 | string *out_marker, bool *truncated) | |
117 | { | |
118 | librados::ObjectReadOperation rop; | |
119 | cls_log_list(rop, from, to, in_marker, max_entries, | |
120 | entries, out_marker, truncated); | |
121 | bufferlist obl; | |
122 | return ioctx.operate(oid, &rop, &obl); | |
123 | } | |
7c673cae | 124 | |
9f95a23c TL |
125 | static int log_list(librados::IoCtx& ioctx, const std::string& oid, |
126 | utime_t& from, utime_t& to, int max_entries, | |
127 | list<cls_log_entry>& entries, bool *truncated) | |
7c673cae | 128 | { |
9f95a23c TL |
129 | std::string marker; |
130 | return log_list(ioctx, oid, from, to, marker, max_entries, | |
131 | entries, &marker, truncated); | |
132 | } | |
7c673cae | 133 | |
9f95a23c TL |
134 | static int log_list(librados::IoCtx& ioctx, const std::string& oid, |
135 | list<cls_log_entry>& entries) | |
136 | { | |
137 | utime_t from, to; | |
138 | bool truncated{false}; | |
139 | return log_list(ioctx, oid, from, to, 0, entries, &truncated); | |
140 | } | |
7c673cae | 141 | |
9f95a23c TL |
142 | TEST_F(cls_log, test_log_add_same_time) |
143 | { | |
7c673cae FG |
144 | /* add chains */ |
145 | string oid = "obj"; | |
146 | ||
147 | /* create object */ | |
148 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
149 | ||
150 | /* generate log */ | |
151 | utime_t start_time = ceph_clock_now(); | |
9f95a23c | 152 | utime_t to_time = get_time(start_time, 1, true); |
7c673cae FG |
153 | generate_log(ioctx, oid, 10, start_time, false); |
154 | ||
7c673cae FG |
155 | list<cls_log_entry> entries; |
156 | bool truncated; | |
157 | ||
158 | /* check list */ | |
9f95a23c TL |
159 | { |
160 | ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0, | |
161 | entries, &truncated)); | |
162 | ASSERT_EQ(10, (int)entries.size()); | |
163 | ASSERT_EQ(0, (int)truncated); | |
164 | } | |
7c673cae FG |
165 | list<cls_log_entry>::iterator iter; |
166 | ||
167 | /* need to sort returned entries, all were using the same time as key */ | |
168 | map<int, cls_log_entry> check_ents; | |
169 | ||
170 | for (iter = entries.begin(); iter != entries.end(); ++iter) { | |
171 | cls_log_entry& entry = *iter; | |
172 | ||
173 | int num; | |
174 | ASSERT_EQ(0, read_bl(entry.data, &num)); | |
175 | ||
176 | check_ents[num] = entry; | |
177 | } | |
178 | ||
179 | ASSERT_EQ(10, (int)check_ents.size()); | |
180 | ||
181 | map<int, cls_log_entry>::iterator ei; | |
182 | ||
183 | /* verify entries are as expected */ | |
184 | ||
185 | int i; | |
186 | ||
187 | for (i = 0, ei = check_ents.begin(); i < 10; i++, ++ei) { | |
188 | cls_log_entry& entry = ei->second; | |
189 | ||
190 | ASSERT_EQ(i, ei->first); | |
191 | check_entry(entry, start_time, i, false); | |
192 | } | |
193 | ||
7c673cae | 194 | /* check list again, now want to be truncated*/ |
9f95a23c TL |
195 | { |
196 | ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 1, | |
197 | entries, &truncated)); | |
198 | ASSERT_EQ(1, (int)entries.size()); | |
199 | ASSERT_EQ(1, (int)truncated); | |
200 | } | |
7c673cae FG |
201 | } |
202 | ||
9f95a23c | 203 | TEST_F(cls_log, test_log_add_different_time) |
7c673cae | 204 | { |
7c673cae FG |
205 | /* add chains */ |
206 | string oid = "obj"; | |
207 | ||
208 | /* create object */ | |
209 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
210 | ||
211 | /* generate log */ | |
212 | utime_t start_time = ceph_clock_now(); | |
213 | generate_log(ioctx, oid, 10, start_time, true); | |
214 | ||
7c673cae FG |
215 | list<cls_log_entry> entries; |
216 | bool truncated; | |
217 | ||
218 | utime_t to_time = utime_t(start_time.sec() + 10, start_time.nsec()); | |
219 | ||
9f95a23c TL |
220 | { |
221 | /* check list */ | |
222 | ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0, | |
223 | entries, &truncated)); | |
224 | ASSERT_EQ(10, (int)entries.size()); | |
225 | ASSERT_EQ(0, (int)truncated); | |
226 | } | |
7c673cae FG |
227 | |
228 | list<cls_log_entry>::iterator iter; | |
229 | ||
230 | /* returned entries should be sorted by time */ | |
231 | map<int, cls_log_entry> check_ents; | |
232 | ||
233 | int i; | |
234 | ||
235 | for (i = 0, iter = entries.begin(); iter != entries.end(); ++iter, ++i) { | |
236 | cls_log_entry& entry = *iter; | |
237 | ||
238 | int num; | |
239 | ||
240 | ASSERT_EQ(0, read_bl(entry.data, &num)); | |
241 | ||
242 | ASSERT_EQ(i, num); | |
243 | ||
244 | check_entry(entry, start_time, i, true); | |
245 | } | |
246 | ||
7c673cae | 247 | /* check list again with shifted time */ |
9f95a23c TL |
248 | { |
249 | utime_t next_time = get_time(start_time, 1, true); | |
250 | ASSERT_EQ(0, log_list(ioctx, oid, next_time, to_time, 0, | |
251 | entries, &truncated)); | |
252 | ASSERT_EQ(9u, entries.size()); | |
253 | ASSERT_FALSE(truncated); | |
254 | } | |
7c673cae | 255 | |
9f95a23c | 256 | string marker; |
7c673cae FG |
257 | i = 0; |
258 | do { | |
9f95a23c TL |
259 | string old_marker = std::move(marker); |
260 | ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, old_marker, 1, | |
261 | entries, &marker, &truncated)); | |
7c673cae FG |
262 | ASSERT_NE(old_marker, marker); |
263 | ASSERT_EQ(1, (int)entries.size()); | |
264 | ||
265 | ++i; | |
266 | ASSERT_GE(10, i); | |
267 | } while (truncated); | |
268 | ||
269 | ASSERT_EQ(10, i); | |
7c673cae FG |
270 | } |
271 | ||
9f95a23c TL |
272 | int do_log_trim(librados::IoCtx& ioctx, const std::string& oid, |
273 | const std::string& from_marker, const std::string& to_marker) | |
7c673cae | 274 | { |
9f95a23c TL |
275 | librados::ObjectWriteOperation op; |
276 | cls_log_trim(op, {}, {}, from_marker, to_marker); | |
277 | return ioctx.operate(oid, &op); | |
278 | } | |
7c673cae | 279 | |
9f95a23c TL |
280 | int do_log_trim(librados::IoCtx& ioctx, const std::string& oid, |
281 | const utime_t& from_time, const utime_t& to_time) | |
282 | { | |
283 | librados::ObjectWriteOperation op; | |
284 | cls_log_trim(op, from_time, to_time, "", ""); | |
285 | return ioctx.operate(oid, &op); | |
286 | } | |
7c673cae | 287 | |
9f95a23c TL |
288 | TEST_F(cls_log, trim_by_time) |
289 | { | |
7c673cae FG |
290 | /* add chains */ |
291 | string oid = "obj"; | |
292 | ||
293 | /* create object */ | |
294 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
295 | ||
296 | /* generate log */ | |
297 | utime_t start_time = ceph_clock_now(); | |
298 | generate_log(ioctx, oid, 10, start_time, true); | |
299 | ||
7c673cae FG |
300 | list<cls_log_entry> entries; |
301 | bool truncated; | |
302 | ||
303 | /* check list */ | |
304 | ||
305 | /* trim */ | |
306 | utime_t to_time = get_time(start_time, 10, true); | |
307 | ||
308 | for (int i = 0; i < 10; i++) { | |
309 | utime_t trim_time = get_time(start_time, i, true); | |
310 | ||
311 | utime_t zero_time; | |
7c673cae | 312 | |
9f95a23c TL |
313 | ASSERT_EQ(0, do_log_trim(ioctx, oid, zero_time, trim_time)); |
314 | ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, zero_time, trim_time)); | |
7c673cae | 315 | |
9f95a23c TL |
316 | ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0, |
317 | entries, &truncated)); | |
318 | ASSERT_EQ(9u - i, entries.size()); | |
319 | ASSERT_FALSE(truncated); | |
320 | } | |
321 | } | |
7c673cae | 322 | |
9f95a23c TL |
323 | TEST_F(cls_log, trim_by_marker) |
324 | { | |
325 | string oid = "obj"; | |
326 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
7c673cae | 327 | |
9f95a23c TL |
328 | utime_t start_time = ceph_clock_now(); |
329 | generate_log(ioctx, oid, 10, start_time, true); | |
7c673cae | 330 | |
9f95a23c TL |
331 | utime_t zero_time; |
332 | std::vector<cls_log_entry> log1; | |
333 | { | |
334 | list<cls_log_entry> entries; | |
335 | ASSERT_EQ(0, log_list(ioctx, oid, entries)); | |
336 | ASSERT_EQ(10u, entries.size()); | |
7c673cae | 337 | |
9f95a23c TL |
338 | log1.assign(std::make_move_iterator(entries.begin()), |
339 | std::make_move_iterator(entries.end())); | |
340 | } | |
341 | // trim front of log | |
342 | { | |
343 | const std::string from = ""; | |
344 | const std::string to = log1[0].id; | |
345 | ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to)); | |
346 | list<cls_log_entry> entries; | |
347 | ASSERT_EQ(0, log_list(ioctx, oid, entries)); | |
348 | ASSERT_EQ(9u, entries.size()); | |
349 | EXPECT_EQ(log1[1].id, entries.begin()->id); | |
350 | ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to)); | |
351 | } | |
352 | // trim back of log | |
353 | { | |
354 | const std::string from = log1[8].id; | |
355 | const std::string to = "9"; | |
356 | ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to)); | |
357 | list<cls_log_entry> entries; | |
358 | ASSERT_EQ(0, log_list(ioctx, oid, entries)); | |
359 | ASSERT_EQ(8u, entries.size()); | |
360 | EXPECT_EQ(log1[8].id, entries.rbegin()->id); | |
361 | ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to)); | |
362 | } | |
363 | // trim a key from the middle | |
364 | { | |
365 | const std::string from = log1[3].id; | |
366 | const std::string to = log1[4].id; | |
367 | ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to)); | |
368 | list<cls_log_entry> entries; | |
369 | ASSERT_EQ(0, log_list(ioctx, oid, entries)); | |
370 | ASSERT_EQ(7u, entries.size()); | |
371 | ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to)); | |
372 | } | |
373 | // trim full log | |
374 | { | |
375 | const std::string from = ""; | |
376 | const std::string to = "9"; | |
377 | ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to)); | |
378 | list<cls_log_entry> entries; | |
379 | ASSERT_EQ(0, log_list(ioctx, oid, entries)); | |
380 | ASSERT_EQ(0u, entries.size()); | |
381 | ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to)); | |
382 | } | |
7c673cae | 383 | } |