]>
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 | ||
19 | static librados::ObjectWriteOperation *new_op() { | |
20 | return new librados::ObjectWriteOperation(); | |
21 | } | |
22 | ||
23 | static librados::ObjectReadOperation *new_rop() { | |
24 | return new librados::ObjectReadOperation(); | |
25 | } | |
26 | ||
27 | static void reset_rop(librados::ObjectReadOperation **pop) { | |
28 | delete *pop; | |
29 | *pop = new_rop(); | |
30 | } | |
31 | ||
32 | static int read_bl(bufferlist& bl, int *i) | |
33 | { | |
11fdf7f2 | 34 | auto iter = bl.cbegin(); |
7c673cae FG |
35 | |
36 | try { | |
11fdf7f2 | 37 | decode(*i, iter); |
7c673cae FG |
38 | } catch (buffer::error& err) { |
39 | std::cout << "failed to decode buffer" << std::endl; | |
40 | return -EIO; | |
41 | } | |
42 | ||
43 | return 0; | |
44 | } | |
45 | ||
46 | void add_log(librados::ObjectWriteOperation *op, utime_t& timestamp, string& section, string&name, int i) | |
47 | { | |
48 | bufferlist bl; | |
11fdf7f2 | 49 | encode(i, bl); |
7c673cae FG |
50 | |
51 | cls_log_add(*op, timestamp, section, name, bl); | |
52 | } | |
53 | ||
54 | ||
55 | string get_name(int i) | |
56 | { | |
57 | string name_prefix = "data-source"; | |
58 | ||
59 | char buf[16]; | |
60 | snprintf(buf, sizeof(buf), "%d", i); | |
61 | return name_prefix + buf; | |
62 | } | |
63 | ||
64 | void generate_log(librados::IoCtx& ioctx, string& oid, int max, utime_t& start_time, bool modify_time) | |
65 | { | |
66 | string section = "global"; | |
67 | ||
68 | librados::ObjectWriteOperation *op = new_op(); | |
69 | ||
70 | int i; | |
71 | ||
72 | for (i = 0; i < max; i++) { | |
73 | uint32_t secs = start_time.sec(); | |
74 | if (modify_time) | |
75 | secs += i; | |
76 | ||
77 | utime_t ts(secs, start_time.nsec()); | |
78 | string name = get_name(i); | |
79 | ||
80 | add_log(op, ts, section, name, i); | |
81 | } | |
82 | ||
83 | ASSERT_EQ(0, ioctx.operate(oid, op)); | |
84 | ||
85 | delete op; | |
86 | } | |
87 | ||
88 | utime_t get_time(utime_t& start_time, int i, bool modify_time) | |
89 | { | |
90 | uint32_t secs = start_time.sec(); | |
91 | if (modify_time) | |
92 | secs += i; | |
93 | return utime_t(secs, start_time.nsec()); | |
94 | } | |
95 | ||
96 | void check_entry(cls_log_entry& entry, utime_t& start_time, int i, bool modified_time) | |
97 | { | |
98 | string section = "global"; | |
99 | string name = get_name(i); | |
100 | utime_t ts = get_time(start_time, i, modified_time); | |
101 | ||
102 | ASSERT_EQ(section, entry.section); | |
103 | ASSERT_EQ(name, entry.name); | |
104 | ASSERT_EQ(ts, entry.timestamp); | |
105 | } | |
106 | ||
107 | ||
108 | TEST(cls_rgw, test_log_add_same_time) | |
109 | { | |
110 | librados::Rados rados; | |
111 | librados::IoCtx ioctx; | |
112 | string pool_name = get_temp_pool_name(); | |
113 | ||
114 | /* create pool */ | |
115 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
116 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
117 | ||
118 | /* add chains */ | |
119 | string oid = "obj"; | |
120 | ||
121 | /* create object */ | |
122 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
123 | ||
124 | /* generate log */ | |
125 | utime_t start_time = ceph_clock_now(); | |
126 | generate_log(ioctx, oid, 10, start_time, false); | |
127 | ||
128 | librados::ObjectReadOperation *rop = new_rop(); | |
129 | ||
130 | list<cls_log_entry> entries; | |
131 | bool truncated; | |
132 | ||
133 | /* check list */ | |
134 | ||
135 | utime_t to_time = get_time(start_time, 1, true); | |
136 | ||
137 | string marker; | |
138 | ||
139 | cls_log_list(*rop, start_time, to_time, marker, 0, entries, &marker, &truncated); | |
140 | ||
141 | bufferlist obl; | |
142 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
143 | ||
144 | ASSERT_EQ(10, (int)entries.size()); | |
145 | ASSERT_EQ(0, (int)truncated); | |
146 | ||
147 | list<cls_log_entry>::iterator iter; | |
148 | ||
149 | /* need to sort returned entries, all were using the same time as key */ | |
150 | map<int, cls_log_entry> check_ents; | |
151 | ||
152 | for (iter = entries.begin(); iter != entries.end(); ++iter) { | |
153 | cls_log_entry& entry = *iter; | |
154 | ||
155 | int num; | |
156 | ASSERT_EQ(0, read_bl(entry.data, &num)); | |
157 | ||
158 | check_ents[num] = entry; | |
159 | } | |
160 | ||
161 | ASSERT_EQ(10, (int)check_ents.size()); | |
162 | ||
163 | map<int, cls_log_entry>::iterator ei; | |
164 | ||
165 | /* verify entries are as expected */ | |
166 | ||
167 | int i; | |
168 | ||
169 | for (i = 0, ei = check_ents.begin(); i < 10; i++, ++ei) { | |
170 | cls_log_entry& entry = ei->second; | |
171 | ||
172 | ASSERT_EQ(i, ei->first); | |
173 | check_entry(entry, start_time, i, false); | |
174 | } | |
175 | ||
176 | reset_rop(&rop); | |
177 | ||
178 | /* check list again, now want to be truncated*/ | |
179 | ||
180 | marker.clear(); | |
181 | ||
182 | cls_log_list(*rop, start_time, to_time, marker, 1, entries, &marker, &truncated); | |
183 | ||
184 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
185 | ||
186 | ASSERT_EQ(1, (int)entries.size()); | |
187 | ASSERT_EQ(1, (int)truncated); | |
188 | ||
189 | delete rop; | |
190 | ||
191 | /* destroy pool */ | |
192 | ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); | |
193 | } | |
194 | ||
195 | TEST(cls_rgw, test_log_add_different_time) | |
196 | { | |
197 | librados::Rados rados; | |
198 | librados::IoCtx ioctx; | |
199 | string pool_name = get_temp_pool_name(); | |
200 | ||
201 | /* create pool */ | |
202 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
203 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
204 | ||
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 | ||
215 | librados::ObjectReadOperation *rop = new_rop(); | |
216 | ||
217 | list<cls_log_entry> entries; | |
218 | bool truncated; | |
219 | ||
220 | utime_t to_time = utime_t(start_time.sec() + 10, start_time.nsec()); | |
221 | ||
222 | string marker; | |
223 | ||
224 | /* check list */ | |
225 | cls_log_list(*rop, start_time, to_time, marker, 0, entries, &marker, &truncated); | |
226 | ||
227 | bufferlist obl; | |
228 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
229 | ||
230 | ASSERT_EQ(10, (int)entries.size()); | |
231 | ASSERT_EQ(0, (int)truncated); | |
232 | ||
233 | list<cls_log_entry>::iterator iter; | |
234 | ||
235 | /* returned entries should be sorted by time */ | |
236 | map<int, cls_log_entry> check_ents; | |
237 | ||
238 | int i; | |
239 | ||
240 | for (i = 0, iter = entries.begin(); iter != entries.end(); ++iter, ++i) { | |
241 | cls_log_entry& entry = *iter; | |
242 | ||
243 | int num; | |
244 | ||
245 | ASSERT_EQ(0, read_bl(entry.data, &num)); | |
246 | ||
247 | ASSERT_EQ(i, num); | |
248 | ||
249 | check_entry(entry, start_time, i, true); | |
250 | } | |
251 | ||
252 | reset_rop(&rop); | |
253 | ||
254 | /* check list again with shifted time */ | |
255 | utime_t next_time = get_time(start_time, 1, true); | |
256 | ||
257 | marker.clear(); | |
258 | ||
259 | cls_log_list(*rop, next_time, to_time, marker, 0, entries, &marker, &truncated); | |
260 | ||
261 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
262 | ||
263 | ASSERT_EQ(9, (int)entries.size()); | |
264 | ASSERT_EQ(0, (int)truncated); | |
265 | ||
266 | reset_rop(&rop); | |
267 | ||
268 | marker.clear(); | |
269 | ||
270 | i = 0; | |
271 | do { | |
272 | bufferlist obl; | |
273 | string old_marker = marker; | |
274 | cls_log_list(*rop, start_time, to_time, old_marker, 1, entries, &marker, &truncated); | |
275 | ||
276 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
277 | ASSERT_NE(old_marker, marker); | |
278 | ASSERT_EQ(1, (int)entries.size()); | |
279 | ||
280 | ++i; | |
281 | ASSERT_GE(10, i); | |
282 | } while (truncated); | |
283 | ||
284 | ASSERT_EQ(10, i); | |
285 | delete rop; | |
286 | ||
287 | /* destroy pool */ | |
288 | ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); | |
289 | } | |
290 | ||
291 | TEST(cls_rgw, test_log_trim) | |
292 | { | |
293 | librados::Rados rados; | |
294 | librados::IoCtx ioctx; | |
295 | string pool_name = get_temp_pool_name(); | |
296 | ||
297 | /* create pool */ | |
298 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
299 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
300 | ||
301 | /* add chains */ | |
302 | string oid = "obj"; | |
303 | ||
304 | /* create object */ | |
305 | ASSERT_EQ(0, ioctx.create(oid, true)); | |
306 | ||
307 | /* generate log */ | |
308 | utime_t start_time = ceph_clock_now(); | |
309 | generate_log(ioctx, oid, 10, start_time, true); | |
310 | ||
311 | librados::ObjectReadOperation *rop = new_rop(); | |
312 | ||
313 | list<cls_log_entry> entries; | |
314 | bool truncated; | |
315 | ||
316 | /* check list */ | |
317 | ||
318 | /* trim */ | |
319 | utime_t to_time = get_time(start_time, 10, true); | |
320 | ||
321 | for (int i = 0; i < 10; i++) { | |
322 | utime_t trim_time = get_time(start_time, i, true); | |
323 | ||
324 | utime_t zero_time; | |
325 | string start_marker, end_marker; | |
326 | ||
327 | ASSERT_EQ(0, cls_log_trim(ioctx, oid, zero_time, trim_time, start_marker, end_marker)); | |
328 | ||
329 | string marker; | |
330 | ||
331 | cls_log_list(*rop, start_time, to_time, marker, 0, entries, &marker, &truncated); | |
332 | ||
333 | bufferlist obl; | |
334 | ASSERT_EQ(0, ioctx.operate(oid, rop, &obl)); | |
335 | ||
336 | ASSERT_EQ(9 - i, (int)entries.size()); | |
337 | ASSERT_EQ(0, (int)truncated); | |
338 | } | |
339 | delete rop; | |
340 | ||
341 | /* destroy pool */ | |
342 | ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); | |
343 | } |