]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/cls_log/test_cls_log.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / cls_log / test_cls_log.cc
CommitLineData
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
20class 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
39static 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
53void 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
62string 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
71void 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
93utime_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
101void 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
112static 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
125static 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
134static 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
142TEST_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 203TEST_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
272int 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
280int 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
288TEST_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
323TEST_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}