Merge PR #56755 into main
[ceph.git] / src / os / Transaction.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 "os/Transaction.h"
5 #include "common/Formatter.h"
6
7 using std::list;
8 using std::map;
9 using std::ostream;
10 using std::set;
11 using std::string;
12
13 using ceph::bufferlist;
14 using ceph::decode;
15 using ceph::encode;
16
17 void decode_str_str_map_to_bl(bufferlist::const_iterator& p,
18                               bufferlist *out)
19 {
20   auto start = p;
21   __u32 n;
22   decode(n, p);
23   unsigned len = 4;
24   while (n--) {
25     __u32 l;
26     decode(l, p);
27     p += l;
28     len += 4 + l;
29     decode(l, p);
30     p += l;
31     len += 4 + l;
32   }
33   start.copy(len, *out);
34 }
35
36 void decode_str_set_to_bl(bufferlist::const_iterator& p,
37                           bufferlist *out)
38 {
39   auto start = p;
40   __u32 n;
41   decode(n, p);
42   unsigned len = 4;
43   while (n--) {
44     __u32 l;
45     decode(l, p);
46     p += l;
47     len += 4 + l;
48   }
49   start.copy(len, *out);
50 }
51
52 namespace ceph::os {
53
54 void Transaction::dump(ceph::Formatter *f)
55 {
56   f->open_array_section("ops");
57   iterator i = begin();
58   int op_num = 0;
59   bool stop_looping = false;
60   while (i.have_op() && !stop_looping) {
61     Transaction::Op *op = i.decode_op();
62     f->open_object_section("op");
63     f->dump_int("op_num", op_num);
64
65     switch (op->op) {
66     case Transaction::OP_NOP:
67       f->dump_string("op_name", "nop");
68       break;
69     case Transaction::OP_CREATE:
70       {
71         coll_t cid = i.get_cid(op->cid);
72         ghobject_t oid = i.get_oid(op->oid);
73         f->dump_string("op_name", "create");
74         f->dump_stream("collection") << cid;
75         f->dump_stream("oid") << oid;
76       }
77       break;
78
79     case Transaction::OP_TOUCH:
80       {
81         coll_t cid = i.get_cid(op->cid);
82         ghobject_t oid = i.get_oid(op->oid);
83         f->dump_string("op_name", "touch");
84         f->dump_stream("collection") << cid;
85         f->dump_stream("oid") << oid;
86       }
87       break;
88       
89     case Transaction::OP_WRITE:
90       {
91         coll_t cid = i.get_cid(op->cid);
92         ghobject_t oid = i.get_oid(op->oid);
93         uint64_t off = op->off;
94         uint64_t len = op->len;
95         bufferlist bl;
96         i.decode_bl(bl);
97         f->dump_string("op_name", "write");
98         f->dump_stream("collection") << cid;
99         f->dump_stream("oid") << oid;
100         f->dump_unsigned("length", len);
101         f->dump_unsigned("offset", off);
102         f->dump_unsigned("bufferlist length", bl.length());
103       }
104       break;
105       
106     case Transaction::OP_ZERO:
107       {
108         coll_t cid = i.get_cid(op->cid);
109         ghobject_t oid = i.get_oid(op->oid);
110         uint64_t off = op->off;
111         uint64_t len = op->len;
112         f->dump_string("op_name", "zero");
113         f->dump_stream("collection") << cid;
114         f->dump_stream("oid") << oid;
115         f->dump_unsigned("offset", off);
116         f->dump_unsigned("length", len);
117       }
118       break;
119       
120     case Transaction::OP_TRIMCACHE:
121       {
122         // deprecated, no-op
123         f->dump_string("op_name", "trim_cache");
124       }
125       break;
126       
127     case Transaction::OP_TRUNCATE:
128       {
129         coll_t cid = i.get_cid(op->cid);
130         ghobject_t oid = i.get_oid(op->oid);
131         uint64_t off = op->off;
132         f->dump_string("op_name", "truncate");
133         f->dump_stream("collection") << cid;
134         f->dump_stream("oid") << oid;
135         f->dump_unsigned("offset", off);
136       }
137       break;
138       
139     case Transaction::OP_REMOVE:
140       {
141         coll_t cid = i.get_cid(op->cid);
142         ghobject_t oid = i.get_oid(op->oid);
143         f->dump_string("op_name", "remove");
144         f->dump_stream("collection") << cid;
145         f->dump_stream("oid") << oid;
146       }
147       break;
148       
149     case Transaction::OP_SETATTR:
150       {
151         coll_t cid = i.get_cid(op->cid);
152         ghobject_t oid = i.get_oid(op->oid);
153         string name = i.decode_string();
154         bufferlist bl;
155         i.decode_bl(bl);
156         f->dump_string("op_name", "setattr");
157         f->dump_stream("collection") << cid;
158         f->dump_stream("oid") << oid;
159         f->dump_string("name", name);
160         f->dump_unsigned("length", bl.length());
161       }
162       break;
163       
164     case Transaction::OP_SETATTRS:
165       {
166         coll_t cid = i.get_cid(op->cid);
167         ghobject_t oid = i.get_oid(op->oid);
168         map<string, bufferptr> aset;
169         i.decode_attrset(aset);
170         f->dump_string("op_name", "setattrs");
171         f->dump_stream("collection") << cid;
172         f->dump_stream("oid") << oid;
173         f->open_object_section("attr_lens");
174         for (map<string,bufferptr>::iterator p = aset.begin();
175             p != aset.end(); ++p) {
176           f->dump_unsigned(p->first.c_str(), p->second.length());
177         }
178         f->close_section();
179       }
180       break;
181
182     case Transaction::OP_RMATTR:
183       {
184         coll_t cid = i.get_cid(op->cid);
185         ghobject_t oid = i.get_oid(op->oid);
186         string name = i.decode_string();
187         f->dump_string("op_name", "rmattr");
188         f->dump_stream("collection") << cid;
189         f->dump_stream("oid") << oid;
190         f->dump_string("name", name);
191       }
192       break;
193
194     case Transaction::OP_RMATTRS:
195       {
196         coll_t cid = i.get_cid(op->cid);
197         ghobject_t oid = i.get_oid(op->oid);
198         f->dump_string("op_name", "rmattrs");
199         f->dump_stream("collection") << cid;
200         f->dump_stream("oid") << oid;
201       }
202       break;
203       
204     case Transaction::OP_CLONE:
205       {
206         coll_t cid = i.get_cid(op->cid);
207         ghobject_t oid = i.get_oid(op->oid);
208         ghobject_t noid = i.get_oid(op->dest_oid);
209         f->dump_string("op_name", "clone");
210         f->dump_stream("collection") << cid;
211         f->dump_stream("src_oid") << oid;
212         f->dump_stream("dst_oid") << noid;
213       }
214       break;
215
216     case Transaction::OP_CLONERANGE:
217       {
218         coll_t cid = i.get_cid(op->cid);
219         ghobject_t oid = i.get_oid(op->oid);
220         ghobject_t noid = i.get_oid(op->dest_oid);
221         uint64_t off = op->off;
222         uint64_t len = op->len;
223         f->dump_string("op_name", "clonerange");
224         f->dump_stream("collection") << cid;
225         f->dump_stream("src_oid") << oid;
226         f->dump_stream("dst_oid") << noid;
227         f->dump_unsigned("offset", off);
228         f->dump_unsigned("len", len);
229       }
230       break;
231
232     case Transaction::OP_CLONERANGE2:
233       {
234         coll_t cid = i.get_cid(op->cid);
235         ghobject_t oid = i.get_oid(op->oid);
236         ghobject_t noid = i.get_oid(op->dest_oid);
237         uint64_t srcoff = op->off;
238         uint64_t len = op->len;
239         uint64_t dstoff = op->dest_off;
240         f->dump_string("op_name", "clonerange2");
241         f->dump_stream("collection") << cid;
242         f->dump_stream("src_oid") << oid;
243         f->dump_stream("dst_oid") << noid;
244         f->dump_unsigned("src_offset", srcoff);
245         f->dump_unsigned("len", len);
246         f->dump_unsigned("dst_offset", dstoff);
247       }
248       break;
249
250     case Transaction::OP_MKCOLL:
251       {
252         coll_t cid = i.get_cid(op->cid);
253         f->dump_string("op_name", "mkcoll");
254         f->dump_stream("collection") << cid;
255       }
256       break;
257
258     case Transaction::OP_COLL_HINT:
259       {
260         using ceph::decode;
261         coll_t cid = i.get_cid(op->cid);
262         uint32_t type = op->hint;
263         f->dump_string("op_name", "coll_hint");
264         f->dump_stream("collection") << cid;
265         f->dump_unsigned("type", type);
266         bufferlist hint;
267         i.decode_bl(hint);
268         auto hiter = hint.cbegin();
269         if (type == Transaction::COLL_HINT_EXPECTED_NUM_OBJECTS) {
270           uint32_t pg_num;
271           uint64_t num_objs;
272           decode(pg_num, hiter);
273           decode(num_objs, hiter);
274           f->dump_unsigned("pg_num", pg_num);
275           f->dump_unsigned("expected_num_objects", num_objs);
276         }
277       }
278       break;
279
280     case Transaction::OP_COLL_SET_BITS:
281       {
282         coll_t cid = i.get_cid(op->cid);
283         f->dump_string("op_name", "coll_set_bits");
284         f->dump_stream("collection") << cid;
285         f->dump_unsigned("bits", op->split_bits);
286       }
287       break;
288
289     case Transaction::OP_RMCOLL:
290       {
291         coll_t cid = i.get_cid(op->cid);
292         f->dump_string("op_name", "rmcoll");
293         f->dump_stream("collection") << cid;
294       }
295       break;
296
297     case Transaction::OP_COLL_ADD:
298       {
299         coll_t ocid = i.get_cid(op->cid);
300         coll_t ncid = i.get_cid(op->dest_cid);
301         ghobject_t oid = i.get_oid(op->oid);
302         f->dump_string("op_name", "collection_add");
303         f->dump_stream("src_collection") << ocid;
304         f->dump_stream("dst_collection") << ncid;
305         f->dump_stream("oid") << oid;
306       }
307       break;
308
309     case Transaction::OP_COLL_REMOVE:
310        {
311         coll_t cid = i.get_cid(op->cid);
312         ghobject_t oid = i.get_oid(op->oid);
313         f->dump_string("op_name", "collection_remove");
314         f->dump_stream("collection") << cid;
315         f->dump_stream("oid") << oid;
316        }
317       break;
318
319     case Transaction::OP_COLL_MOVE:
320        {
321         coll_t ocid = i.get_cid(op->cid);
322         coll_t ncid = i.get_cid(op->dest_cid);
323         ghobject_t oid = i.get_oid(op->oid);
324         f->open_object_section("collection_move");
325         f->dump_stream("src_collection") << ocid;
326         f->dump_stream("dst_collection") << ncid;
327         f->dump_stream("oid") << oid;
328         f->close_section();
329        }
330       break;
331
332     case Transaction::OP_COLL_SETATTR:
333       {
334         coll_t cid = i.get_cid(op->cid);
335         string name = i.decode_string();
336         bufferlist bl;
337         i.decode_bl(bl);
338         f->dump_string("op_name", "collection_setattr");
339         f->dump_stream("collection") << cid;
340         f->dump_string("name", name);
341         f->dump_unsigned("length", bl.length());
342       }
343       break;
344
345     case Transaction::OP_COLL_RMATTR:
346       {
347         coll_t cid = i.get_cid(op->cid);
348         string name = i.decode_string();
349         f->dump_string("op_name", "collection_rmattr");
350         f->dump_stream("collection") << cid;
351         f->dump_string("name", name);
352       }
353       break;
354
355     case Transaction::OP_COLL_RENAME:
356       {
357         f->dump_string("op_name", "collection_rename");
358       }
359       break;
360
361     case Transaction::OP_OMAP_CLEAR:
362       {
363         coll_t cid = i.get_cid(op->cid);
364         ghobject_t oid = i.get_oid(op->oid);
365         f->dump_string("op_name", "omap_clear");
366         f->dump_stream("collection") << cid;
367         f->dump_stream("oid") << oid;
368       }
369       break;
370
371     case Transaction::OP_OMAP_SETKEYS:
372       {
373         coll_t cid = i.get_cid(op->cid);
374         ghobject_t oid = i.get_oid(op->oid);
375         map<string, bufferlist> aset;
376         i.decode_attrset(aset);
377         f->dump_string("op_name", "omap_setkeys");
378         f->dump_stream("collection") << cid;
379         f->dump_stream("oid") << oid;
380         f->open_object_section("attr_lens");
381         for (map<string, bufferlist>::iterator p = aset.begin();
382             p != aset.end(); ++p) {
383           f->dump_unsigned(p->first.c_str(), p->second.length());
384         }
385         f->close_section();
386       }
387       break;
388
389     case Transaction::OP_OMAP_RMKEYS:
390       {
391         coll_t cid = i.get_cid(op->cid);
392         ghobject_t oid = i.get_oid(op->oid);
393         set<string> keys;
394         i.decode_keyset(keys);
395         f->dump_string("op_name", "omap_rmkeys");
396         f->dump_stream("collection") << cid;
397         f->dump_stream("oid") << oid;
398         f->open_array_section("attrs");
399         for (auto& k : keys) {
400           f->dump_string("", k.c_str());
401         }
402         f->close_section();
403       }
404       break;
405
406     case Transaction::OP_OMAP_SETHEADER:
407       {
408         coll_t cid = i.get_cid(op->cid);
409         ghobject_t oid = i.get_oid(op->oid);
410         bufferlist bl;
411         i.decode_bl(bl);
412         f->dump_string("op_name", "omap_setheader");
413         f->dump_stream("collection") << cid;
414         f->dump_stream("oid") << oid;
415         f->dump_stream("header_length") << bl.length();
416       }
417       break;
418
419     case Transaction::OP_SPLIT_COLLECTION:
420       {
421         coll_t cid = i.get_cid(op->cid);
422         uint32_t bits = op->split_bits;
423         uint32_t rem = op->split_rem;
424         coll_t dest = i.get_cid(op->dest_cid);
425         f->dump_string("op_name", "op_split_collection_create");
426         f->dump_stream("collection") << cid;
427         f->dump_stream("bits") << bits;
428         f->dump_stream("rem") << rem;
429         f->dump_stream("dest") << dest;
430       }
431       break;
432
433     case Transaction::OP_SPLIT_COLLECTION2:
434       {
435         coll_t cid = i.get_cid(op->cid);
436         uint32_t bits = op->split_bits;
437         uint32_t rem = op->split_rem;
438         coll_t dest = i.get_cid(op->dest_cid);
439         f->dump_string("op_name", "op_split_collection");
440         f->dump_stream("collection") << cid;
441         f->dump_stream("bits") << bits;
442         f->dump_stream("rem") << rem;
443         f->dump_stream("dest") << dest;
444       }
445       break;
446
447     case Transaction::OP_MERGE_COLLECTION:
448       {
449         coll_t cid = i.get_cid(op->cid);
450         uint32_t bits = op->split_bits;
451         coll_t dest = i.get_cid(op->dest_cid);
452         f->dump_string("op_name", "op_merge_collection");
453         f->dump_stream("collection") << cid;
454         f->dump_stream("dest") << dest;
455         f->dump_stream("bits") << bits;
456       }
457       break;
458
459     case Transaction::OP_OMAP_RMKEYRANGE:
460       {
461         coll_t cid = i.get_cid(op->cid);
462         ghobject_t oid = i.get_oid(op->oid);
463         string first, last;
464         first = i.decode_string();
465         last = i.decode_string();
466         f->dump_string("op_name", "op_omap_rmkeyrange");
467         f->dump_stream("collection") << cid;
468         f->dump_stream("oid") << oid;
469         f->dump_string("first", first);
470         f->dump_string("last", last);
471       }
472       break;
473
474     case Transaction::OP_COLL_MOVE_RENAME:
475       {
476         coll_t old_cid = i.get_cid(op->cid);
477         ghobject_t old_oid = i.get_oid(op->oid);
478         coll_t new_cid = i.get_cid(op->dest_cid);
479         ghobject_t new_oid = i.get_oid(op->dest_oid);
480         f->dump_string("op_name", "op_coll_move_rename");
481         f->dump_stream("old_collection") << old_cid;
482         f->dump_stream("old_oid") << old_oid;
483         f->dump_stream("new_collection") << new_cid;
484         f->dump_stream("new_oid") << new_oid;
485       }
486       break;
487
488     case Transaction::OP_TRY_RENAME:
489       {
490         coll_t cid = i.get_cid(op->cid);
491         ghobject_t old_oid = i.get_oid(op->oid);
492         ghobject_t new_oid = i.get_oid(op->dest_oid);
493         f->dump_string("op_name", "op_coll_move_rename");
494         f->dump_stream("collection") << cid;
495         f->dump_stream("old_oid") << old_oid;
496         f->dump_stream("new_oid") << new_oid;
497       }
498       break;
499         
500     case Transaction::OP_SETALLOCHINT:
501       {
502         coll_t cid = i.get_cid(op->cid);
503         ghobject_t oid = i.get_oid(op->oid);
504         uint64_t expected_object_size = op->expected_object_size;
505         uint64_t expected_write_size = op->expected_write_size;
506         uint32_t alloc_hint_flags = op->hint;
507         f->dump_string("op_name", "op_setallochint");
508         f->dump_stream("collection") << cid;
509         f->dump_stream("oid") << oid;
510         f->dump_stream("expected_object_size") << expected_object_size;
511         f->dump_stream("expected_write_size") << expected_write_size;
512         f->dump_string("alloc_hint_flags", ceph_osd_alloc_hint_flag_string(alloc_hint_flags));
513       }
514       break;
515
516     default:
517       f->dump_string("op_name", "unknown");
518       f->dump_unsigned("op_code", op->op);
519       stop_looping = true;
520       break;
521     }
522     f->close_section();
523     op_num++;
524   }
525   f->close_section();
526 }
527
528 #pragma GCC diagnostic ignored "-Wpragmas"
529 #pragma GCC diagnostic push
530 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
531
532 void Transaction::generate_test_instances(list<Transaction*>& o)
533 {
534   o.push_back(new Transaction);
535
536   Transaction *t = new Transaction;
537   t->nop();
538   o.push_back(t);
539   
540   t = new Transaction;
541   coll_t c(spg_t(pg_t(1,2), shard_id_t::NO_SHARD));
542   coll_t c2(spg_t(pg_t(4,5), shard_id_t::NO_SHARD));
543   ghobject_t o1(hobject_t("obj", "", 123, 456, -1, ""));
544   ghobject_t o2(hobject_t("obj2", "", 123, 456, -1, ""));
545   ghobject_t o3(hobject_t("obj3", "", 123, 456, -1, ""));
546   t->touch(c, o1);
547   bufferlist bl;
548   bl.append("some data");
549   t->write(c, o1, 1, bl.length(), bl);
550   t->zero(c, o1, 22, 33);
551   t->truncate(c, o1, 99);
552   t->remove(c, o1);
553   o.push_back(t);
554
555   t = new Transaction;
556   t->setattr(c, o1, "key", bl);
557   map<string,bufferptr> m;
558   m["a"] = buffer::copy("this", 4);
559   m["b"] = buffer::copy("that", 4);
560   t->setattrs(c, o1, m);
561   t->rmattr(c, o1, "b");
562   t->rmattrs(c, o1);
563
564   t->clone(c, o1, o2);
565   t->clone(c, o1, o3);
566   t->clone_range(c, o1, o2, 1, 12, 99);
567
568   t->create_collection(c, 12);
569   t->collection_move_rename(c, o2, c2, o3);
570   t->remove_collection(c);
571   o.push_back(t);  
572 }
573
574 ostream& operator<<(ostream& out, const Transaction& tx) {
575
576   return out << "Transaction(" << &tx << ")";
577 }
578
579 #pragma GCC diagnostic pop
580 #pragma GCC diagnostic warning "-Wpragmas"
581
582 }