]> git.proxmox.com Git - ceph.git/blame - ceph/doc/dev/encoding.rst
import quincy beta 17.1.0
[ceph.git] / ceph / doc / dev / encoding.rst
CommitLineData
11fdf7f2
TL
1
2Serialization (encode/decode)
3=============================
4
5When a structure is sent over the network or written to disk, it is
6encoded into a string of bytes. Serializable structures have
7``encode`` and ``decode`` methods that write and read from ``bufferlist``
8objects representing byte strings.
9
10Adding a field to a structure
11-----------------------------
12
13You can see examples of this all over the Ceph code, but here's an
14example:
15
20effc67 16.. code-block:: cpp
11fdf7f2
TL
17
18 class AcmeClass
19 {
20 int member1;
21 std::string member2;
22
23 void encode(bufferlist &bl)
24 {
25 ENCODE_START(1, 1, bl);
26 ::encode(member1, bl);
27 ::encode(member2, bl);
28 ENCODE_FINISH(bl);
29 }
30
31 void decode(bufferlist::iterator &bl)
32 {
33 DECODE_START(1, bl);
34 ::decode(member1, bl);
35 ::decode(member2, bl);
36 DECODE_FINISH(bl);
37 }
38 };
39
40The ``ENCODE_START`` macro writes a header that specifies a *version* and
41a *compat_version* (both initially 1). The message version is incremented
42whenever a change is made to the encoding. The compat_version is incremented
43only if the change will break existing decoders -- decoders are tolerant
44of trailing bytes, so changes that add fields at the end of the structure
45do not require incrementing compat_version.
46
47The ``DECODE_START`` macro takes an argument specifying the most recent
48message version that the code can handle. This is compared with the
49compat_version encoded in the message, and if the message is too new then
50an exception will be thrown. Because changes to compat_verison are rare,
51this isn't usually something to worry about when adding fields.
52
53In practice, changes to encoding usually involve simply adding the desired fields
54at the end of the ``encode`` and ``decode`` functions, and incrementing
55the versions in ``ENCODE_START`` and ``DECODE_START``. For example, here's how
56to add a third field to ``AcmeClass``:
57
20effc67 58.. code-block:: cpp
11fdf7f2
TL
59
60 class AcmeClass
61 {
62 int member1;
63 std::string member2;
64 std::vector<std::string> member3;
65
66 void encode(bufferlist &bl)
67 {
68 ENCODE_START(2, 1, bl);
69 ::encode(member1, bl);
70 ::encode(member2, bl);
71 ::encode(member3, bl);
72 ENCODE_FINISH(bl);
73 }
74
75 void decode(bufferlist::iterator &bl)
76 {
77 DECODE_START(2, bl);
78 ::decode(member1, bl);
79 ::decode(member2, bl);
80 if (struct_v >= 2) {
81 ::decode(member3, bl);
82 }
83 DECODE_FINISH(bl);
84 }
85 };
86
87Note that the compat_version did not change because the encoded message
88will still be decodable by versions of the code that only understand
89version 1 -- they will just ignore the trailing bytes where we encode ``member3``.
90
91In the ``decode`` function, decoding the new field is conditional: this is
92because we might still be passed older-versioned messages that do not
93have the field. The ``struct_v`` variable is a local set by the ``DECODE_START``
94macro.
95