MySQL  8.0.22
Source Code Documentation
gcs_internal_message_headers.h
Go to the documentation of this file.
1 /* Copyright (c) 2016, 2020, Oracle and/or its affiliates.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation. The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef GCS_MSG_HEADERS_H
24 #define GCS_MSG_HEADERS_H
25 
26 #include <limits>
27 #include <memory>
28 #include <sstream>
29 #include <type_traits>
31 
32 /**
33  The different stages that are currently available.
34 
35  Any time a new stage is created, the old stages must be added to this
36  enumeration class as new stages as follows. Let us assume that these
37  are the current stages:
38 
39  enum class Stage_code : unsigned int {
40  ST_UNKNOWN = 0,
41 
42  ST_LZ4_V1 = 1,
43 
44  ST_LZ4_V2 = 2,
45 
46  ST_SPLIT_V2 = 3,
47 
48  ST_MAX_STAGES = 4
49  };
50 
51  If a new stage is added meaning that the protocol has changed, the
52  enumeration class should be changed as follows:
53 
54  enum class Stage_code : unsigned int {
55  ST_UNKNOWN = 0,
56 
57  ST_LZ4_V1 = 1,
58 
59  ST_LZ4_V2 = 2,
60 
61  ST_SPLIT_V2 = 3,
62 
63  ST_LZ4_V3 = 4,
64 
65  ST_SPLIT_V3 = 5,
66 
67  ST_NEW_V3 = 6,
68 
69  ST_MAX_STAGES = 7
70  };
71  */
72 enum class Stage_code : unsigned int {
73  /*
74  This type should not be used anywhere.
75  */
76  ST_UNKNOWN = 0,
77 
78  /*
79  This type represents the compression stage v1.
80  */
81  ST_LZ4_V1 = 1,
82 
83  /*
84  This type represents the compression stage v2.
85  */
86  ST_LZ4_V2 = 2,
87 
88  /*
89  This type represents the split stage v2.
90  */
91  ST_SPLIT_V2 = 3,
92 
93  /*
94  No valid state codes can appear after this one. If a stage code is to
95  be added, this value needs to be incremented and the lowest type code
96  available be assigned to the new stage.
97  */
98  ST_MAX_STAGES = 4
99 };
100 
101 /**
102  The different cargo type codes.
103 */
104 enum class Cargo_type : unsigned short {
105  /*
106  This type should not be used anywhere.
107  */
108  CT_UNKNOWN = 0,
109 
110  /*
111  This cargo type is used for internal messaging related to stage
112  exchanges.
113  */
115 
116  /*
117  This cargo type is used for messages from the application.
118  */
119  CT_USER_DATA = 2,
120 
121  /*
122  No valid type codes can appear after this one. If a type code is to
123  be added, this value needs to be incremented and the lowest type code
124  available be assigned to the new type.
125  */
126  CT_MAX = 3
127 };
128 
129 /**
130  This header is internal to the MySQL GCS library and contains metadata
131  information about the message content.
132 
133  The on-the-wire representation of the fixed header is:
134 
135  +------------------+-----------+------------------------------------------+
136  | field | wire size | description |
137  +==================+===========+==========================================+
138  | used_version | 2 bytes | protocol version in use by sender |
139  | max_version | 2 bytes | max protocol version supported by sender |
140  | fixed_hdr_len | 2 bytes | length of the fixed header |
141  | message_len | 8 bytes | length of the message |
142  | dyn_hdr_len | 4 bytes | length of the dynamic headers |
143  | cargo_type | 2 bytes | the cargo type in the payload |
144  +------------------+-----------+------------------------------------------+
145 
146  Be aware that previously there was a single 4-byte version field.
147  Its semantics were the same of the used_version field.
148 
149  Older nodes will continue to send messages that, from their point of view,
150  contain the single version field.
151  Older nodes only know protocol version 1.
152  Messages sent by older nodes will be encoded as follows:
153 
154  used_version = 1 and max_version = 0
155 
156  This is due to two factors:
157 
158  1. The combined size of {used,max}_version is 4 bytes, which is the same
159  size of the old version field.
160  2. The fixed header is encoded in little endian. Therefore, the used_version
161  (max_version) field will contain the least (most) significant 2 bytes of
162  the old version field.
163 
164  This class takes care of messages from old nodes by decoding such messages as:
165 
166  used_version = 1 and max_version = 1
167 */
169  public:
170  /**
171  The used protocol version number length field.
172  */
173  static constexpr unsigned short WIRE_USED_VERSION_SIZE = 2;
174 
175  /**
176  The maximum protocol version number length field.
177  */
178  static constexpr unsigned short WIRE_MAX_VERSION_SIZE = 2;
179 
180  /**
181  The length of the combined version fields.
182  */
183  static constexpr unsigned short WIRE_VERSION_SIZE = 4;
184  static_assert(WIRE_VERSION_SIZE ==
185  WIRE_USED_VERSION_SIZE + WIRE_MAX_VERSION_SIZE,
186  "The two version fields must have a combined size of 4 bytes");
187 
188  /**
189  On-the-wire size of the fixed header length field.
190  */
191  static constexpr unsigned short WIRE_HD_LEN_SIZE = 2;
192 
193  /**
194  On-the-wire size of the message size field.
195  */
196  static constexpr unsigned short WIRE_TOTAL_LEN_SIZE = 8;
197 
198  /**
199  On-the-wire size of the cargo type field.
200  */
201  static constexpr unsigned short WIRE_CARGO_TYPE_SIZE = 2;
202 
203  /**
204  On-the-wire size of the dynamic headers length field.
205  */
206  static constexpr unsigned short WIRE_DYNAMIC_HDRS_LEN_SIZE = 4;
207 
208  /**
209  On-the-wire offset of the dynamic headers length field.
210  */
211  static constexpr unsigned short WIRE_DYNAMIC_HDRS_LEN_OFFSET =
212  WIRE_VERSION_SIZE + WIRE_HD_LEN_SIZE + WIRE_TOTAL_LEN_SIZE;
213 
214  /**
215  On-the-wire offset of the message length field.
216  */
217  static constexpr unsigned short WIRE_MSG_LEN_OFFSET =
218  WIRE_VERSION_SIZE + WIRE_HD_LEN_SIZE;
219 
220  /**
221  On-the-wire size of the fixed header.
222  */
223  static constexpr unsigned short WIRE_TOTAL_FIXED_HEADER_SIZE =
224  WIRE_VERSION_SIZE + WIRE_HD_LEN_SIZE + WIRE_TOTAL_LEN_SIZE +
225  WIRE_DYNAMIC_HDRS_LEN_SIZE + WIRE_CARGO_TYPE_SIZE;
226 
227  private:
228  /**
229  The header instance used protocol version.
230  */
232  static_assert(sizeof(decltype(m_used_version)) == WIRE_USED_VERSION_SIZE,
233  "The m_used_version size does not match the storage capacity");
234 
235  /**
236  The header instance maximum protocol version.
237  */
239  static_assert(sizeof(decltype(m_max_version)) == WIRE_MAX_VERSION_SIZE,
240  "The m_max_version size does not match the storage capacity");
241 
242  static_assert(
243  sizeof(decltype(m_max_version)) + sizeof(decltype(m_used_version)) ==
244  WIRE_VERSION_SIZE,
245  "The m_{max,used}_version sizes does not match the storage capacity");
246 
247  /**
248  The header instance length.
249  */
250  unsigned short m_fixed_header_len{WIRE_TOTAL_FIXED_HEADER_SIZE};
251  static_assert(
252  sizeof(decltype(m_fixed_header_len)) == WIRE_HD_LEN_SIZE,
253  "The m_fixed_header_len size does not match the storage capacity");
254 
255  /**
256  The payload length field.
257 
258  Note that we keep track of the total length indirectly and the storage
259  capacity is determined by the payload length which is the dominant factor.
260  */
261  unsigned long long m_payload_len{0};
262  static_assert(sizeof(decltype(m_payload_len)) <= WIRE_TOTAL_LEN_SIZE,
263  "The m_payload_len size does not match the storage capacity");
264 
265  /**
266  The length of the dynamic headers.
267  */
268  unsigned int m_dynamic_headers_len{0};
269  static_assert(
270  sizeof(decltype(m_dynamic_headers_len)) == WIRE_DYNAMIC_HDRS_LEN_SIZE,
271  "The m_dynamic_headers_len size does not match the storage capacity");
272 
273  /**
274  The cargo type code.
275  */
277  static_assert(sizeof(decltype(m_cargo_type)) == WIRE_CARGO_TYPE_SIZE,
278  "The m_cargo_type size does not match the storage capacity");
279 
280  public:
281  /**
282  Default constructor which is the only one provided.
283  */
284  explicit Gcs_internal_message_header() noexcept = default;
285 
286  /**
287  These constructors are to be used when move semantics may be needed.
288  */
290  default;
291  Gcs_internal_message_header &operator=(
292  Gcs_internal_message_header &&) noexcept = default;
293 
294  /**
295  These constructors are to be used when copy semantics may be needed.
296  */
298  default;
299  Gcs_internal_message_header &operator=(
300  const Gcs_internal_message_header &) noexcept = default;
301 
302  /**
303  @return the value of the maximum protocol version field.
304  */
305  Gcs_protocol_version get_maximum_version() const;
306 
307  /**
308  @return the value of the used protocol version field.
309  */
310  Gcs_protocol_version get_used_version() const;
311 
312  /**
313  Set the maximum protocol version.
314 
315  @param version Maximum protocol version.
316  */
317  void set_maximum_version(Gcs_protocol_version version);
318 
319  /**
320  Set the current protocol version.
321 
322  @param version Current protocol version.
323  */
324  void set_used_version(Gcs_protocol_version version);
325 
326  /**
327  @return the value of the header length field value.
328  */
329  constexpr unsigned short get_fixed_header_length() const {
330  return m_fixed_header_len;
331  }
332 
333  /**
334  @return the cargo type.
335  */
336  Cargo_type get_cargo_type() const;
337 
338  /**
339  Set the cargo type field value.
340 
341  @param type Cargo type to set.
342  */
343  void set_cargo_type(Cargo_type type);
344 
345  /**
346  @return The dynamic headers length field value.
347  */
348  unsigned int get_dynamic_headers_length() const;
349 
350  /**
351  Set the dynamic headers length field value.
352 
353  @param length The dynamic headers value.
354  */
355  void set_dynamic_headers_length(unsigned int length);
356 
357  /**
358  Set the message length attribute value according to the payload length and
359  the header length. Only the payload information is provided because the
360  header length is fixed.
361 
362  @param length Payload length.
363  */
364  void set_payload_length(unsigned long long length);
365 
366  /**
367  @return The message total length field value.
368  */
369  unsigned long long get_total_length() const;
370 
371  /**
372  Decode the contents of the buffer and sets the field values according to
373  the values decoded. The buffer MUST be encoded in little endian format.
374 
375  @param buffer The buffer to decode from.
376  @return Length of decoded information in bytes.
377  */
378  unsigned long long decode(const unsigned char *buffer);
379 
380  /**
381  Encode the contents of this instance into the buffer. The encoding SHALL
382  be done in little endian format.
383 
384  @param buffer The buffer to encode to.
385  @return Length of encoded information in bytes.
386  */
387  unsigned long long encode(unsigned char *buffer) const;
388 
389  /**
390  Create a string representation of the fixed header to be logged.
391 
392  @param output Reference to the output stream where the string will be
393  created.
394  */
395  void dump(std::ostringstream &output) const;
396 
397  static constexpr unsigned short calculate_length() {
398  return WIRE_TOTAL_FIXED_HEADER_SIZE;
399  }
400 };
401 
402 /**
403  This is a default header created per stage and contains information to
404  decode it.
405 
406  The on-the-wire-layout representation of a dynamic header is:
407 
408  +------------------+-----------+--------------------------------------+
409  | field | wire size | description |
410  +==================+===========+======================================+
411  | dyn_hdr_len | 2 bytes | length of the dynamic header |
412  | stage_code | 4 bytes | stage code |
413  | old_payload_len | 8 bytes | length of the previous stage payload |
414  +------------------+-----------+--------------------------------------+
415 */
417  private:
418  /**
419  Dynamic header length.
420  */
421  unsigned short m_dynamic_header_length{0};
422 
423  /**
424  Stage that created the dynamic header.
425  */
427 
428  /**
429  Payload length when the packet went through the stage.
430  */
431  unsigned long long m_payload_length{0};
432 
433  public:
434  /**
435  The offset of the header length within the stage header.
436  */
437  static constexpr unsigned short WIRE_HD_LEN_OFFSET = 0;
438 
439  /**
440  On-the-wire field size for the stage type code.
441  */
442  static constexpr unsigned short WIRE_HD_LEN_SIZE = 2;
443 
444  /**
445  The offset of the stage type code within the stage header.
446  */
447  static constexpr unsigned short WIRE_HD_TYPE_OFFSET = WIRE_HD_LEN_SIZE;
448 
449  /**
450  On-the-wire field size for the stage type code.
451  */
452  static constexpr unsigned short WIRE_HD_TYPE_SIZE = 4;
453 
454  /**
455  The offset of the payload length within the stage header.
456  */
457  static constexpr unsigned short WIRE_HD_PAYLOAD_LEN_OFFSET =
458  WIRE_HD_TYPE_OFFSET + WIRE_HD_TYPE_SIZE;
459 
460  /**
461  On-the-wire field size for the stage payload length.
462  */
463  static constexpr unsigned short WIRE_HD_PAYLOAD_LEN_SIZE = 8;
464 
465  /**
466  Constructor for the dynamic header.
467 
468  @param stage_code Stage code.
469  @param payload_length Payload length while the packet is in the stage.
470  */
471  explicit Gcs_dynamic_header(Stage_code stage_code,
472  unsigned long long payload_length) noexcept;
473 
474  /**
475  Default constructor is to be used when creating an empty dynamic header.
476  */
477  explicit Gcs_dynamic_header() noexcept = default;
478 
479  /**
480  These constructors are to be used when move semantics may be needed.
481  */
482  Gcs_dynamic_header(Gcs_dynamic_header &&) noexcept = default;
483  Gcs_dynamic_header &operator=(Gcs_dynamic_header &&) noexcept = default;
484 
485  /**
486  These constructors are to be used when copy semantics may be needed.
487  */
488  Gcs_dynamic_header(const Gcs_dynamic_header &) noexcept = default;
489  Gcs_dynamic_header &operator=(const Gcs_dynamic_header &) noexcept = default;
490 
491  /**
492  Return the dynamic header length.
493  */
494  unsigned short get_dynamic_header_length() const;
495 
496  /**
497  Return the stage code.
498  */
499  Stage_code get_stage_code() const;
500 
501  /**
502  Return the payload length the packet had before this stage was applied.
503  */
504  unsigned long long get_payload_length() const;
505 
506  /**
507  Set the payload length the packet had before this stage was applied.
508 
509  @param new_length payload length before this stage
510  */
511  void set_payload_length(unsigned long long new_length);
512 
513  /**
514  Decode the contents of the buffer and sets the field values according to
515  the values decoded. The buffer MUST be encoded in little endian format.
516 
517  @param buffer The buffer to decode from.
518  @return Length of decoded information in bytes.
519  */
520  unsigned long long decode(const unsigned char *buffer);
521 
522  /**
523  Encode the contents of this instance into the buffer. The encoding SHALL
524  be done in little endian format.
525 
526  @param buffer The buffer to encode to.
527  @return Length of encoded information in bytes.
528  */
529  unsigned long long encode(unsigned char *buffer) const;
530 
531  /**
532  Return length of dynamic header.
533  */
534  static constexpr unsigned long long calculate_length() {
535  return WIRE_HD_LEN_SIZE + WIRE_HD_TYPE_SIZE + WIRE_HD_PAYLOAD_LEN_SIZE;
536  }
537 
538  /**
539  Create a string representation of the dynamic header to be logged.
540 
541  @param output Reference to the output stream where the string will be
542  created.
543  */
544  void dump(std::ostringstream &output) const;
545 };
546 
547 /**
548  Abstract class that defines specific metadata associated to a stage if it
549  decides to extend it.
550  */
552  public:
553  Gcs_stage_metadata() = default;
554 
555  virtual ~Gcs_stage_metadata();
556 
557  Gcs_stage_metadata(const Gcs_stage_metadata &) = default;
558  Gcs_stage_metadata &operator=(const Gcs_stage_metadata &) = default;
559 
561  Gcs_stage_metadata &operator=(Gcs_stage_metadata &&) = default;
562 
563  /**
564  Creates a deep copy of this object.
565 
566  @returns a deep copy of this object.
567  */
568  virtual std::unique_ptr<Gcs_stage_metadata> clone() = 0;
569 
570  /**
571  Calculate the length required to encode this object.
572  */
573  virtual unsigned long long calculate_encode_length() const = 0;
574 
575  /**
576  Encode the contents of this instance into the buffer. The encoding SHALL
577  be done in little endian format.
578 
579  @param buffer The buffer to encode to.
580  @return Length of the encoded information.
581  */
582  virtual unsigned long long encode(unsigned char *buffer) const = 0;
583 
584  /**
585  Decode the contents of the buffer and sets the field values according to
586  the values decoded. The buffer MUST be encoded in little endian format.
587 
588  @param buffer The buffer to decode from.
589  @return Encoded size.
590  */
591  virtual unsigned long long decode(const unsigned char *buffer) = 0;
592 
593  /**
594  Create a string representation of the header to be logged.
595 
596  @param output Reference to the output stream where the string will be created
597  */
598  virtual void dump(std::ostringstream &output) const = 0;
599 };
600 
601 /**
602  Empty metadata for stages that do not require any metadata.
603  */
605  public:
606  Gcs_empty_stage_metadata() = default;
607 
608  std::unique_ptr<Gcs_stage_metadata> clone() final;
609 
610  unsigned long long calculate_encode_length() const final;
611 
612  unsigned long long encode(unsigned char *) const final;
613 
614  unsigned long long decode(unsigned char const *) final;
615 
616  void dump(std::ostringstream &) const final;
617 
619  Gcs_empty_stage_metadata &operator=(Gcs_empty_stage_metadata &&) = default;
620 
623  default;
624 };
625 
626 #endif // GCS_MSG_HEADERS_H
This header is internal to the MySQL GCS library and contains metadata information about the message ...
Definition: gcs_internal_message_headers.h:168
char buffer[STRING_BUFFER]
Definition: test_sql_9_sessions.cc:57
static constexpr unsigned short calculate_length()
Definition: gcs_internal_message_headers.h:397
Gcs_protocol_version
The GCS protocol versions.
Definition: gcs_types.h:127
Stage_code
The different stages that are currently available.
Definition: gcs_internal_message_headers.h:72
Cargo_type
The different cargo type codes.
Definition: gcs_internal_message_headers.h:104
static ORDER * clone(THD *thd, ORDER *order)
Shallow clone the list of ORDER objects using mem_root and return the cloned list.
Definition: window.cc:80
Empty metadata for stages that do not require any metadata.
Definition: gcs_internal_message_headers.h:604
constexpr unsigned short get_fixed_header_length() const
Definition: gcs_internal_message_headers.h:329
#define final(a, b, c)
Definition: hash.c:109
Abstract class that defines specific metadata associated to a stage if it decides to extend it...
Definition: gcs_internal_message_headers.h:551
const string version("\ersion\)
static int dump
Definition: myisam_ftdump.cc:42
std::basic_ostringstream< char, std::char_traits< char >, ut_allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut_allocator.
Definition: ut0new.h:1302
This is a default header created per stage and contains information to decode it. ...
Definition: gcs_internal_message_headers.h:416
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:75