Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / include / encoding.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software 
11  * Foundation.  See file COPYING.
12  * 
13  */
14 #ifndef CEPH_ENCODING_H
15 #define CEPH_ENCODING_H
16
17 #include "include/int_types.h"
18
19 #include "include/memory.h"
20
21 #include "byteorder.h"
22 #include "buffer.h"
23
24 // pull in the new-style encoding so that we get the denc_traits<> definition.
25 #include "denc.h"
26
27 #include "assert.h"
28
29 using namespace ceph;
30
31 /*
32  * Notes on feature encoding:
33  *
34  * - The default encode() methods have a features argument with a default parameter
35  *   (which goes to zero).
36  * - Normal classes will use WRITE_CLASS_ENCODER, with that features=0 default.
37  * - Classes that _require_ features will use WRITE_CLASS_ENCODER_FEATURES, which
38  *   does not define the default.  Any caller must explicitly pass it in.
39  * - STL container macros have two encode variants: one with a features arg, and one
40  *   without.
41  *
42  * The result:
43  * - A feature encode() method will fail to compile if a value is not
44  *   passed in.
45  * - The feature varianet of the STL templates will be used when the feature arg is
46  *   provided.  It will be passed through to any template arg types, but it will be
47  *   ignored when not needed.
48  */
49
50 // --------------------------------------
51 // base types
52
53 template<class T>
54 inline void encode_raw(const T& t, bufferlist& bl)
55 {
56   bl.append((char*)&t, sizeof(t));
57 }
58 template<class T>
59 inline void decode_raw(T& t, bufferlist::iterator &p)
60 {
61   p.copy(sizeof(t), (char*)&t);
62 }
63
64 #define WRITE_RAW_ENCODER(type)                                         \
65   inline void encode(const type &v, bufferlist& bl, uint64_t features=0) { encode_raw(v, bl); } \
66   inline void decode(type &v, bufferlist::iterator& p) { __ASSERT_FUNCTION decode_raw(v, p); }
67
68 WRITE_RAW_ENCODER(__u8)
69 #ifndef _CHAR_IS_SIGNED
70 WRITE_RAW_ENCODER(__s8)
71 #endif
72 WRITE_RAW_ENCODER(char)
73 WRITE_RAW_ENCODER(ceph_le64)
74 WRITE_RAW_ENCODER(ceph_le32)
75 WRITE_RAW_ENCODER(ceph_le16)
76
77 // FIXME: we need to choose some portable floating point encoding here
78 WRITE_RAW_ENCODER(float)
79 WRITE_RAW_ENCODER(double)
80
81 inline void encode(const bool &v, bufferlist& bl) {
82   __u8 vv = v;
83   encode_raw(vv, bl);
84 }
85 inline void decode(bool &v, bufferlist::iterator& p) {
86   __u8 vv;
87   decode_raw(vv, p);
88   v = vv;
89 }
90
91
92 // -----------------------------------
93 // int types
94
95 #define WRITE_INTTYPE_ENCODER(type, etype)                              \
96   inline void encode(type v, bufferlist& bl, uint64_t features=0) {     \
97     ceph_##etype e;                                                     \
98     e = v;                                                              \
99     encode_raw(e, bl);                                                  \
100   }                                                                     \
101   inline void decode(type &v, bufferlist::iterator& p) {                \
102     ceph_##etype e;                                                     \
103     decode_raw(e, p);                                                   \
104     v = e;                                                              \
105   }
106
107 WRITE_INTTYPE_ENCODER(uint64_t, le64)
108 WRITE_INTTYPE_ENCODER(int64_t, le64)
109 WRITE_INTTYPE_ENCODER(uint32_t, le32)
110 WRITE_INTTYPE_ENCODER(int32_t, le32)
111 WRITE_INTTYPE_ENCODER(uint16_t, le16)
112 WRITE_INTTYPE_ENCODER(int16_t, le16)
113
114 // see denc.h for ENCODE_DUMP_PATH discussion and definition.
115 #ifdef ENCODE_DUMP_PATH
116 # define ENCODE_DUMP_PRE()                      \
117   unsigned pre_off = bl.length()
118 # define ENCODE_DUMP_POST(cl)                                           \
119   do {                                                                  \
120     static int i = 0;                                                   \
121     i++;                                                                \
122     int bits = 0;                                                       \
123     for (unsigned t = i; t; bits++)                                     \
124       t &= t - 1;                                                       \
125     if (bits > 2)                                                       \
126       break;                                                            \
127     char fn[PATH_MAX];                                                  \
128     snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \
129     int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644);                \
130     if (fd >= 0) {                                                      \
131       bufferlist sub;                                                   \
132       sub.substr_of(bl, pre_off, bl.length() - pre_off);                \
133       sub.write_fd(fd);                                                 \
134       ::close(fd);                                                      \
135     }                                                                   \
136   } while (0)
137 #else
138 # define ENCODE_DUMP_PRE()
139 # define ENCODE_DUMP_POST(cl)
140 #endif
141
142
143 #define WRITE_CLASS_ENCODER(cl)                                         \
144   inline void encode(const cl &c, bufferlist &bl, uint64_t features=0) { \
145     ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); }            \
146   inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); }
147
148 #define WRITE_CLASS_MEMBER_ENCODER(cl)                                  \
149   inline void encode(const cl &c, bufferlist &bl) const {               \
150     ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); }            \
151   inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); }
152
153 #define WRITE_CLASS_ENCODER_FEATURES(cl)                                \
154   inline void encode(const cl &c, bufferlist &bl, uint64_t features) {  \
155     ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); }  \
156   inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); }
157
158 #define WRITE_CLASS_ENCODER_OPTIONAL_FEATURES(cl)                               \
159   inline void encode(const cl &c, bufferlist &bl, uint64_t features = 0) {      \
160     ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); }  \
161   inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); }
162
163
164 // string
165 inline void encode(const std::string& s, bufferlist& bl, uint64_t features=0)
166 {
167   __u32 len = s.length();
168   encode(len, bl);
169   if (len)
170     bl.append(s.data(), len);
171 }
172 inline void decode(std::string& s, bufferlist::iterator& p)
173 {
174   __u32 len;
175   decode(len, p);
176   s.clear();
177   p.copy(len, s);
178 }
179
180 inline void encode_nohead(const std::string& s, bufferlist& bl)
181 {
182   bl.append(s.data(), s.length());
183 }
184 inline void decode_nohead(int len, std::string& s, bufferlist::iterator& p)
185 {
186   s.clear();
187   p.copy(len, s);
188 }
189
190 // const char* (encode only, string compatible)
191 inline void encode(const char *s, bufferlist& bl) 
192 {
193   __u32 len = strlen(s);
194   encode(len, bl);
195   if (len)
196     bl.append(s, len);
197 }
198
199
200 // -----------------------------
201 // buffers
202
203 // bufferptr (encapsulated)
204 inline void encode(const buffer::ptr& bp, bufferlist& bl) 
205 {
206   __u32 len = bp.length();
207   encode(len, bl);
208   if (len)
209     bl.append(bp);
210 }
211 inline void decode(buffer::ptr& bp, bufferlist::iterator& p)
212 {
213   __u32 len;
214   decode(len, p);
215
216   bufferlist s;
217   p.copy(len, s);
218
219   if (len) {
220     if (s.get_num_buffers() == 1)
221       bp = s.front();
222     else
223       bp = buffer::copy(s.c_str(), s.length());
224   }
225 }
226
227 // bufferlist (encapsulated)
228 inline void encode(const bufferlist& s, bufferlist& bl) 
229 {
230   __u32 len = s.length();
231   encode(len, bl);
232   bl.append(s);
233 }
234 inline void encode_destructively(bufferlist& s, bufferlist& bl) 
235 {
236   __u32 len = s.length();
237   encode(len, bl);
238   bl.claim_append(s);
239 }
240 inline void decode(bufferlist& s, bufferlist::iterator& p)
241 {
242   __u32 len;
243   decode(len, p);
244   s.clear();
245   p.copy(len, s);
246 }
247
248 inline void encode_nohead(const bufferlist& s, bufferlist& bl) 
249 {
250   bl.append(s);
251 }
252 inline void decode_nohead(int len, bufferlist& s, bufferlist::iterator& p)
253 {
254   s.clear();
255   p.copy(len, s);
256 }
257
258
259 // full bl decoder
260 template<class T>
261 inline void decode(T &o, bufferlist& bl)
262 {
263   bufferlist::iterator p = bl.begin();
264   decode(o, p);
265   assert(p.end());
266 }
267
268
269 // -----------------------------
270 // STL container types
271
272 #include <set>
273 #include <map>
274 #include <deque>
275 #include <vector>
276 #include <string>
277 #include <boost/optional/optional_io.hpp>
278 #include <boost/tuple/tuple.hpp>
279
280 #ifndef _BACKWARD_BACKWARD_WARNING_H
281 #define _BACKWARD_BACKWARD_WARNING_H   // make gcc 4.3 shut up about hash_*
282 #endif
283 #include "include/unordered_map.h"
284 #include "include/unordered_set.h"
285
286
287 // boost optional
288 template<typename T>
289 inline void encode(const boost::optional<T> &p, bufferlist &bl)
290 {
291   __u8 present = static_cast<bool>(p);
292   ::encode(present, bl);
293   if (p)
294     encode(p.get(), bl);
295 }
296
297 #pragma GCC diagnostic ignored "-Wpragmas"
298 #pragma GCC diagnostic push
299 #pragma GCC diagnostic ignored "-Wuninitialized"
300 template<typename T>
301 inline void decode(boost::optional<T> &p, bufferlist::iterator &bp)
302 {
303   __u8 present;
304   ::decode(present, bp);
305   if (present) {
306     p = T{};
307     decode(p.get(), bp);
308   } else {
309     p = boost::none;
310   }
311 }
312 #pragma GCC diagnostic pop
313 #pragma GCC diagnostic warning "-Wpragmas"
314
315 //triple tuple
316 template<class A, class B, class C>
317 inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl)
318 {
319   encode(boost::get<0>(t), bl);
320   encode(boost::get<1>(t), bl);
321   encode(boost::get<2>(t), bl);
322 }
323 template<class A, class B, class C>
324 inline void decode(boost::tuple<A, B, C> &t, bufferlist::iterator &bp)
325 {
326   decode(boost::get<0>(t), bp);
327   decode(boost::get<1>(t), bp);
328   decode(boost::get<2>(t), bp);
329 }
330
331 // std::pair<A,B>
332 template<class A, class B,
333          typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
334 inline typename std::enable_if<!a_traits::supported ||
335                                !b_traits::supported>::type
336   encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features)
337 {
338   encode(p.first, bl, features);
339   encode(p.second, bl, features);
340 }
341 template<class A, class B,
342          typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
343 inline typename std::enable_if<!a_traits::supported ||
344                                !b_traits::supported>::type
345   encode(const std::pair<A,B> &p, bufferlist &bl)
346 {
347   encode(p.first, bl);
348   encode(p.second, bl);
349 }
350 template<class A, class B,
351          typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
352 inline typename std::enable_if<!a_traits::supported ||
353                                !b_traits::supported>::type
354   decode(std::pair<A,B> &pa, bufferlist::iterator &p)
355 {
356   decode(pa.first, p);
357   decode(pa.second, p);
358 }
359
360 // std::list<T>
361 template<class T, class Alloc, typename traits=denc_traits<T>>
362 inline typename std::enable_if<!traits::supported>::type
363   encode(const std::list<T, Alloc>& ls, bufferlist& bl)
364 {
365   __u32 n = (__u32)(ls.size());  // c++11 std::list::size() is O(1)
366   encode(n, bl);
367   for (auto p = ls.begin(); p != ls.end(); ++p)
368     encode(*p, bl);
369 }
370 template<class T, class Alloc, typename traits=denc_traits<T>>
371 inline typename std::enable_if<!traits::supported>::type
372   encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features)
373 {
374   // should i pre- or post- count?
375   if (!ls.empty()) {
376     unsigned pos = bl.length();
377     unsigned n = 0;
378     encode(n, bl);
379     for (auto p = ls.begin(); p != ls.end(); ++p) {
380       n++;
381       encode(*p, bl, features);
382     }
383     ceph_le32 en;
384     en = n;
385     bl.copy_in(pos, sizeof(en), (char*)&en);
386   } else {
387     __u32 n = (__u32)(ls.size());    // FIXME: this is slow on a list.
388     encode(n, bl);
389     for (auto p = ls.begin(); p != ls.end(); ++p)
390       encode(*p, bl, features);
391   }
392 }
393 template<class T, class Alloc, typename traits=denc_traits<T>>
394 inline typename std::enable_if<!traits::supported>::type
395   decode(std::list<T,Alloc>& ls, bufferlist::iterator& p)
396 {
397   __u32 n;
398   decode(n, p);
399   ls.clear();
400   while (n--) {
401     T v;
402     decode(v, p);
403     ls.push_back(v);
404   }
405 }
406
407 // std::list<ceph::shared_ptr<T>>
408 template<class T, class Alloc>
409 inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls,
410                    bufferlist& bl)
411 {
412   __u32 n = (__u32)(ls.size());  // c++11 std::list::size() is O(1)
413   encode(n, bl);
414   for (auto p = ls.begin(); p != ls.end(); ++p)
415     encode(**p, bl);
416 }
417 template<class T, class Alloc>
418 inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls,
419                    bufferlist& bl, uint64_t features)
420 {
421   __u32 n = (__u32)(ls.size());  // c++11 std::list::size() is O(1)
422   encode(n, bl);
423   for (auto p = ls.begin(); p != ls.end(); ++p)
424     encode(**p, bl, features);
425 }
426 template<class T, class Alloc>
427 inline void decode(std::list<ceph::shared_ptr<T>, Alloc>& ls,
428                    bufferlist::iterator& p)
429 {
430   __u32 n;
431   decode(n, p);
432   ls.clear();
433   while (n--) {
434     ceph::shared_ptr<T> v(std::make_shared<T>());
435     decode(*v, p);
436     ls.push_back(v);
437   }
438 }
439
440 // std::set<T>
441 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
442 inline typename std::enable_if<!traits::supported>::type
443   encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl)
444 {
445   __u32 n = (__u32)(s.size());
446   encode(n, bl);
447   for (auto p = s.begin(); p != s.end(); ++p)
448     encode(*p, bl);
449 }
450 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
451 inline typename std::enable_if<!traits::supported>::type
452   decode(std::set<T,Comp,Alloc>& s, bufferlist::iterator& p)
453 {
454   __u32 n;
455   decode(n, p);
456   s.clear();
457   while (n--) {
458     T v;
459     decode(v, p);
460     s.insert(v);
461   }
462 }
463
464 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
465 inline typename std::enable_if<!traits::supported>::type
466   encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl)
467 {
468   for (auto p = s.begin(); p != s.end(); ++p)
469     encode(*p, bl);
470 }
471 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
472 inline typename std::enable_if<!traits::supported>::type
473   decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::iterator& p)
474 {
475   for (int i=0; i<len; i++) {
476     T v;
477     decode(v, p);
478     s.insert(v);
479   }
480 }
481
482 // boost::container::flat_set<T>
483 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
484 inline typename std::enable_if<!traits::supported>::type
485 encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl)
486 {
487   __u32 n = (__u32)(s.size());
488   encode(n, bl);
489   for (const auto& e : s)
490     encode(e, bl);
491 }
492 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
493 inline typename std::enable_if<!traits::supported>::type
494 decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::iterator& p)
495 {
496   __u32 n;
497   decode(n, p);
498   s.clear();
499   s.reserve(n);
500   while (n--) {
501     T v;
502     decode(v, p);
503     s.insert(v);
504   }
505 }
506
507 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
508 inline typename std::enable_if<!traits::supported>::type
509 encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s,
510               bufferlist& bl)
511 {
512   for (const auto& e : s)
513     encode(e, bl);
514 }
515 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
516 inline typename std::enable_if<!traits::supported>::type
517 decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s,
518               bufferlist::iterator& p)
519 {
520   s.reserve(len);
521   for (int i=0; i<len; i++) {
522     T v;
523     decode(v, p);
524     s.insert(v);
525   }
526 }
527
528 // multiset
529 template<class T, class Comp, class Alloc>
530 inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl)
531 {
532   __u32 n = (__u32)(s.size());
533   encode(n, bl);
534   for (auto p = s.begin(); p != s.end(); ++p)
535     encode(*p, bl);
536 }
537 template<class T, class Comp, class Alloc>
538 inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::iterator& p)
539 {
540   __u32 n;
541   decode(n, p);
542   s.clear();
543   while (n--) {
544     T v;
545     decode(v, p);
546     s.insert(v);
547   }
548 }
549
550 // vector (pointers)
551 /*template<class T>
552 inline void encode(const std::vector<T*>& v, bufferlist& bl)
553 {
554   __u32 n = v.size();
555   encode(n, bl);
556   for (typename std::vector<T*>::const_iterator p = v.begin(); p != v.end(); ++p)
557     encode(**p, bl);
558 }
559 template<class T>
560 inline void decode(std::vector<T*>& v, bufferlist::iterator& p)
561 {
562   __u32 n;
563   decode(n, p);
564   v.resize(n);
565   for (__u32 i=0; i<n; i++) 
566     v[i] = new T(p);
567 }
568 */
569 // std::vector<T>
570 template<class T, class Alloc, typename traits=denc_traits<T>>
571 inline typename std::enable_if<!traits::supported>::type
572   encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features)
573 {
574   __u32 n = (__u32)(v.size());
575   encode(n, bl);
576   for (auto p = v.begin(); p != v.end(); ++p)
577     encode(*p, bl, features);
578 }
579 template<class T, class Alloc, typename traits=denc_traits<T>>
580 inline typename std::enable_if<!traits::supported>::type
581   encode(const std::vector<T,Alloc>& v, bufferlist& bl)
582 {
583   __u32 n = (__u32)(v.size());
584   encode(n, bl);
585   for (auto p = v.begin(); p != v.end(); ++p)
586     encode(*p, bl);
587 }
588 template<class T, class Alloc, typename traits=denc_traits<T>>
589 inline typename std::enable_if<!traits::supported>::type
590   decode(std::vector<T,Alloc>& v, bufferlist::iterator& p)
591 {
592   __u32 n;
593   decode(n, p);
594   v.resize(n);
595   for (__u32 i=0; i<n; i++) 
596     decode(v[i], p);
597 }
598
599 template<class T, class Alloc, typename traits=denc_traits<T>>
600 inline typename std::enable_if<!traits::supported>::type
601   encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl)
602 {
603   for (auto p = v.begin(); p != v.end(); ++p)
604     encode(*p, bl);
605 }
606 template<class T, class Alloc, typename traits=denc_traits<T>>
607 inline typename std::enable_if<!traits::supported>::type
608   decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::iterator& p)
609 {
610   v.resize(len);
611   for (__u32 i=0; i<v.size(); i++) 
612     decode(v[i], p);
613 }
614
615 // vector (shared_ptr)
616 template<class T,class Alloc>
617 inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v,
618                    bufferlist& bl,
619                    uint64_t features)
620 {
621   __u32 n = (__u32)(v.size());
622   encode(n, bl);
623   for (auto p = v.begin(); p != v.end(); ++p)
624     if (*p)
625       encode(**p, bl, features);
626     else
627       encode(T(), bl, features);
628 }
629 template<class T, class Alloc>
630 inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v,
631                    bufferlist& bl)
632 {
633   __u32 n = (__u32)(v.size());
634   encode(n, bl);
635   for (auto p = v.begin(); p != v.end(); ++p)
636     if (*p)
637       encode(**p, bl);
638     else
639       encode(T(), bl);
640 }
641 template<class T, class Alloc>
642 inline void decode(std::vector<ceph::shared_ptr<T>,Alloc>& v,
643                    bufferlist::iterator& p)
644 {
645   __u32 n;
646   decode(n, p);
647   v.resize(n);
648   for (__u32 i=0; i<n; i++) {
649     v[i] = std::make_shared<T>();
650     decode(*v[i], p);
651   }
652 }
653
654 // map (pointers)
655 /*
656 template<class T, class U>
657 inline void encode(const std::map<T,U*>& m, bufferlist& bl)
658 {
659   __u32 n = m.size();
660   encode(n, bl);
661   for (typename std::map<T,U*>::const_iterator p = m.begin(); p != m.end(); ++p) {
662     encode(p->first, bl);
663     encode(*p->second, bl);
664   }
665 }
666 template<class T, class U>
667 inline void decode(std::map<T,U*>& m, bufferlist::iterator& p)
668 {
669   __u32 n;
670   decode(n, p);
671   m.clear();
672   while (n--) {
673     T k;
674     decode(k, p);
675     m[k] = new U(p);
676   }
677   }*/
678
679 // map
680 template<class T, class U, class Comp, class Alloc,
681          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
682 inline typename std::enable_if<!t_traits::supported ||
683                                  !u_traits::supported>::type
684   encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl)
685 {
686   __u32 n = (__u32)(m.size());
687   encode(n, bl);
688   for (auto p = m.begin(); p != m.end(); ++p) {
689     encode(p->first, bl);
690     encode(p->second, bl);
691   }
692 }
693 template<class T, class U, class Comp, class Alloc,
694          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
695 inline typename std::enable_if<!t_traits::supported ||
696                                  !u_traits::supported>::type
697   encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features)
698 {
699   __u32 n = (__u32)(m.size());
700   encode(n, bl);
701   for (auto p = m.begin(); p != m.end(); ++p) {
702     encode(p->first, bl, features);
703     encode(p->second, bl, features);
704   }
705 }
706 template<class T, class U, class Comp, class Alloc,
707          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
708 inline typename std::enable_if<!t_traits::supported ||
709                                  !u_traits::supported>::type
710   decode(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
711 {
712   __u32 n;
713   decode(n, p);
714   m.clear();
715   while (n--) {
716     T k;
717     decode(k, p);
718     decode(m[k], p);
719   }
720 }
721 template<class T, class U, class Comp, class Alloc>
722 inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
723 {
724   __u32 n;
725   decode(n, p);
726   while (n--) {
727     T k;
728     decode(k, p);
729     decode(m[k], p);
730   }
731 }
732 template<class T, class U, class Comp, class Alloc,
733          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
734 inline typename std::enable_if<!t_traits::supported ||
735                                  !u_traits::supported>::type
736   encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl)
737 {
738   for (auto p = m.begin(); p != m.end(); ++p) {
739     encode(p->first, bl);
740     encode(p->second, bl);
741   }
742 }
743 template<class T, class U, class Comp, class Alloc,
744          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
745 inline typename std::enable_if<!t_traits::supported ||
746                                  !u_traits::supported>::type
747   encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features)
748 {
749   for (auto p = m.begin(); p != m.end(); ++p) {
750     encode(p->first, bl, features);
751     encode(p->second, bl, features);
752   }
753 }
754 template<class T, class U, class Comp, class Alloc,
755          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
756 inline typename std::enable_if<!t_traits::supported ||
757                                  !u_traits::supported>::type
758   decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
759 {
760   m.clear();
761   while (n--) {
762     T k;
763     decode(k, p);
764     decode(m[k], p);
765   }
766 }
767
768 // boost::container::flat-map
769 template<class T, class U, class Comp, class Alloc,
770          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
771   inline typename std::enable_if<!t_traits::supported ||
772                                  !u_traits::supported>::type
773   encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl)
774 {
775   __u32 n = (__u32)(m.size());
776   encode(n, bl);
777   for (typename boost::container::flat_map<T,U,Comp>::const_iterator p
778          = m.begin(); p != m.end(); ++p) {
779     encode(p->first, bl);
780     encode(p->second, bl);
781   }
782 }
783 template<class T, class U, class Comp, class Alloc,
784          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
785   inline typename std::enable_if<!t_traits::supported ||
786                                  !u_traits::supported>::type
787   encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl,
788          uint64_t features)
789 {
790   __u32 n = (__u32)(m.size());
791   encode(n, bl);
792   for (auto p = m.begin(); p != m.end(); ++p) {
793     encode(p->first, bl, features);
794     encode(p->second, bl, features);
795   }
796 }
797 template<class T, class U, class Comp, class Alloc,
798          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
799   inline typename std::enable_if<!t_traits::supported ||
800                                  !u_traits::supported>::type
801   decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
802 {
803   __u32 n;
804   decode(n, p);
805   m.clear();
806   m.reserve(n);
807   while (n--) {
808     T k;
809     decode(k, p);
810     decode(m[k], p);
811   }
812 }
813 template<class T, class U, class Comp, class Alloc>
814 inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m,
815                            bufferlist::iterator& p)
816 {
817   __u32 n;
818   decode(n, p);
819   m.reserve(m.size() + n);
820   while (n--) {
821     T k;
822     decode(k, p);
823     decode(m[k], p);
824   }
825 }
826 template<class T, class U, class Comp, class Alloc,
827          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
828   inline typename std::enable_if<!t_traits::supported ||
829                                  !u_traits::supported>::type
830   encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m,
831                 bufferlist& bl)
832 {
833   for (auto p = m.begin(); p != m.end(); ++p) {
834     encode(p->first, bl);
835     encode(p->second, bl);
836   }
837 }
838 template<class T, class U, class Comp, class Alloc,
839          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
840   inline typename std::enable_if<!t_traits::supported ||
841                                  !u_traits::supported>::type
842   encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m,
843                 bufferlist& bl, uint64_t features)
844 {
845   for (auto p = m.begin(); p != m.end(); ++p) {
846     encode(p->first, bl, features);
847     encode(p->second, bl, features);
848   }
849 }
850 template<class T, class U, class Comp, class Alloc,
851          typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
852 inline typename std::enable_if<!t_traits::supported ||
853                                  !u_traits::supported>::type
854   decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m,
855                 bufferlist::iterator& p)
856 {
857   m.clear();
858   while (n--) {
859     T k;
860     decode(k, p);
861     decode(m[k], p);
862   }
863 }
864
865 // multimap
866 template<class T, class U, class Comp, class Alloc>
867 inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl)
868 {
869   __u32 n = (__u32)(m.size());
870   encode(n, bl);
871   for (auto p = m.begin(); p != m.end(); ++p) {
872     encode(p->first, bl);
873     encode(p->second, bl);
874   }
875 }
876 template<class T, class U, class Comp, class Alloc>
877 inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
878 {
879   __u32 n;
880   decode(n, p);
881   m.clear();
882   while (n--) {
883     typename std::pair<T,U> tu = std::pair<T,U>();
884     decode(tu.first, p);
885     typename std::multimap<T,U,Comp,Alloc>::iterator it = m.insert(tu);
886     decode(it->second, p);
887   }
888 }
889
890 // ceph::unordered_map
891 template<class T, class U, class Hash, class Pred, class Alloc>
892 inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl,
893                    uint64_t features)
894 {
895   __u32 n = (__u32)(m.size());
896   encode(n, bl);
897   for (auto p = m.begin(); p != m.end(); ++p) {
898     encode(p->first, bl, features);
899     encode(p->second, bl, features);
900   }
901 }
902 template<class T, class U, class Hash, class Pred, class Alloc>
903 inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl)
904 {
905   __u32 n = (__u32)(m.size());
906   encode(n, bl);
907   for (auto p = m.begin(); p != m.end(); ++p) {
908     encode(p->first, bl);
909     encode(p->second, bl);
910   }
911 }
912 template<class T, class U, class Hash, class Pred, class Alloc>
913 inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::iterator& p)
914 {
915   __u32 n;
916   decode(n, p);
917   m.clear();
918   while (n--) {
919     T k;
920     decode(k, p);
921     decode(m[k], p);
922   }
923 }
924
925 // ceph::unordered_set
926 template<class T, class Hash, class Pred, class Alloc>
927 inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl)
928 {
929   __u32 n = (__u32)(m.size());
930   encode(n, bl);
931   for (auto p = m.begin(); p != m.end(); ++p)
932     encode(*p, bl);
933 }
934 template<class T, class Hash, class Pred, class Alloc>
935 inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::iterator& p)
936 {
937   __u32 n;
938   decode(n, p);
939   m.clear();
940   while (n--) {
941     T k;
942     decode(k, p);
943     m.insert(k);
944   }
945 }
946
947 // deque
948 template<class T, class Alloc>
949 inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features)
950 {
951   __u32 n = ls.size();
952   encode(n, bl);
953   for (auto p = ls.begin(); p != ls.end(); ++p)
954     encode(*p, bl, features);
955 }
956 template<class T, class Alloc>
957 inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl)
958 {
959   __u32 n = ls.size();
960   encode(n, bl);
961   for (auto p = ls.begin(); p != ls.end(); ++p)
962     encode(*p, bl);
963 }
964 template<class T, class Alloc>
965 inline void decode(std::deque<T,Alloc>& ls, bufferlist::iterator& p)
966 {
967   __u32 n;
968   decode(n, p);
969   ls.clear();
970   while (n--) {
971     T v;
972     decode(v, p);
973     ls.push_back(v);
974   }
975 }
976
977 // std::array<T, N>
978 template<class T, size_t N, typename traits = denc_traits<T>>
979 inline typename std::enable_if<!traits::supported>::type
980 encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features)
981 {
982   for (const auto& e : v)
983     encode(e, bl, features);
984 }
985 template<class T, size_t N, typename traits = denc_traits<T>>
986 inline typename std::enable_if<!traits::supported>::type
987 encode(const std::array<T, N>& v, bufferlist& bl)
988 {
989   for (const auto& e : v)
990     encode(e, bl);
991 }
992 template<class T, size_t N, typename traits = denc_traits<T>>
993 inline typename std::enable_if<!traits::supported>::type
994 decode(std::array<T, N>& v, bufferlist::iterator& p)
995 {
996   for (auto& e : v)
997     decode(e, p);
998 }
999
1000
1001 /*
1002  * guards
1003  */
1004
1005 /**
1006  * start encoding block
1007  *
1008  * @param v current (code) version of the encoding
1009  * @param compat oldest code version that can decode it
1010  * @param bl bufferlist to encode to
1011  */
1012 #define ENCODE_START(v, compat, bl)                          \
1013   __u8 struct_v = v, struct_compat = compat;                 \
1014   ::encode(struct_v, (bl));                                  \
1015   ::encode(struct_compat, (bl));                             \
1016   buffer::list::iterator struct_compat_it = (bl).end();      \
1017   struct_compat_it.advance(-1);                              \
1018   ceph_le32 struct_len;                                      \
1019   struct_len = 0;                                            \
1020   ::encode(struct_len, (bl));                                \
1021   buffer::list::iterator struct_len_it = (bl).end();         \
1022   struct_len_it.advance(-4);                                 \
1023   do {
1024
1025 /**
1026  * finish encoding block
1027  *
1028  * @param bl bufferlist we were encoding to
1029  * @param new_struct_compat struct-compat value to use
1030  */
1031 #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat)                 \
1032   } while (false);                                                      \
1033   struct_len = (bl).length() - struct_len_it.get_off() - sizeof(struct_len); \
1034   struct_len_it.copy_in(4, (char *)&struct_len);                        \
1035   if (new_struct_compat) {                                              \
1036     struct_compat = new_struct_compat;                                  \
1037     struct_compat_it.copy_in(1, (char *)&struct_compat);                \
1038   }
1039
1040 #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0)
1041
1042 #define DECODE_ERR_OLDVERSION(func, v, compatv)                                 \
1043   (std::string(func) + " no longer understand old encoding version " #v " < " #compatv)
1044
1045 #define DECODE_ERR_PAST(func) \
1046   (std::string(func) + " decode past end of struct encoding")
1047
1048 /**
1049  * check for very old encoding
1050  *
1051  * If the encoded data is older than oldestv, raise an exception.
1052  *
1053  * @param oldestv oldest version of the code we can successfully decode.
1054  */
1055 #define DECODE_OLDEST(oldestv)                                          \
1056   if (struct_v < oldestv)                                               \
1057     throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv)); 
1058
1059 /**
1060  * start a decoding block
1061  *
1062  * @param v current version of the encoding that the code supports/encodes
1063  * @param bl bufferlist::iterator for the encoded data
1064  */
1065 #define DECODE_START(v, bl)                                             \
1066   __u8 struct_v, struct_compat;                                         \
1067   ::decode(struct_v, bl);                                               \
1068   ::decode(struct_compat, bl);                                          \
1069   if (v < struct_compat)                                                \
1070     throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1071   __u32 struct_len;                                                     \
1072   ::decode(struct_len, bl);                                             \
1073   if (struct_len > bl.get_remaining())                                  \
1074     throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1075   unsigned struct_end = bl.get_off() + struct_len;                      \
1076   do {
1077
1078 #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl)  \
1079   __u8 struct_v;                                                        \
1080   ::decode(struct_v, bl);                                               \
1081   if (struct_v >= compatv) {                                            \
1082     __u8 struct_compat;                                                 \
1083     ::decode(struct_compat, bl);                                        \
1084     if (v < struct_compat)                                              \
1085       throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1086   } else if (skip_v) {                                                  \
1087     if ((int)bl.get_remaining() < skip_v)                               \
1088       throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1089     bl.advance(skip_v);                                                 \
1090   }                                                                     \
1091   unsigned struct_end = 0;                                              \
1092   if (struct_v >= lenv) {                                               \
1093     __u32 struct_len;                                                   \
1094     ::decode(struct_len, bl);                                           \
1095     if (struct_len > bl.get_remaining())                                \
1096       throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1097     struct_end = bl.get_off() + struct_len;                             \
1098   }                                                                     \
1099   do {
1100
1101 /**
1102  * start a decoding block with legacy support for older encoding schemes
1103  *
1104  * The old encoding schemes has a __u8 struct_v only, or lacked either
1105  * the compat version or length.  Skip those fields conditionally.
1106  *
1107  * Most of the time, v, compatv, and lenv will all match the version
1108  * where the structure was switched over to the new macros.
1109  *
1110  * @param v current version of the encoding that the code supports/encodes
1111  * @param compatv oldest version that includes a __u8 compat version field
1112  * @param lenv oldest version that includes a __u32 length wrapper
1113  * @param bl bufferlist::iterator containing the encoded data
1114  */
1115 #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl)            \
1116   __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 0, bl)
1117
1118 /**
1119  * start a decoding block with legacy support for older encoding schemes
1120  *
1121  * This version of the macro assumes the legacy encoding had a 32 bit
1122  * version
1123  *
1124  * The old encoding schemes has a __u8 struct_v only, or lacked either
1125  * the compat version or length.  Skip those fields conditionally.
1126  *
1127  * Most of the time, v, compatv, and lenv will all match the version
1128  * where the structure was switched over to the new macros.
1129  *
1130  * @param v current version of the encoding that the code supports/encodes
1131  * @param compatv oldest version that includes a __u8 compat version field
1132  * @param lenv oldest version that includes a __u32 length wrapper
1133  * @param bl bufferlist::iterator containing the encoded data
1134  */
1135 #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl)         \
1136   __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3, bl)
1137
1138 #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl)         \
1139   __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1, bl)
1140
1141 /**
1142  * finish decode block
1143  *
1144  * @param bl bufferlist::iterator we were decoding from
1145  */
1146 #define DECODE_FINISH(bl)                                               \
1147   } while (false);                                                      \
1148   if (struct_end) {                                                     \
1149     if (bl.get_off() > struct_end)                                      \
1150       throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1151     if (bl.get_off() < struct_end)                                      \
1152       bl.advance(struct_end - bl.get_off());                            \
1153   }
1154
1155 /*
1156  * Encoders/decoders to read from current offset in a file handle and
1157  * encode/decode the data according to argument types.
1158  */
1159 inline ssize_t decode_file(int fd, std::string &str)
1160 {
1161   bufferlist bl;
1162   __u32 len = 0;
1163   bl.read_fd(fd, sizeof(len));
1164   decode(len, bl);                                                                                                  
1165   bl.read_fd(fd, len);
1166   decode(str, bl);                                                                                                  
1167   return bl.length();
1168 }
1169
1170 inline ssize_t decode_file(int fd, bufferptr &bp)
1171 {
1172   bufferlist bl;
1173   __u32 len = 0;
1174   bl.read_fd(fd, sizeof(len));
1175   decode(len, bl);                                                                                                  
1176   bl.read_fd(fd, len);
1177   bufferlist::iterator bli = bl.begin();
1178
1179   decode(bp, bli);                                                                                                  
1180   return bl.length();
1181 }
1182
1183 #endif