1 /*
2    Portions Copyright (c) 2016-Present, Facebook, Inc.
3    Portions Copyright (c) 2012,2013 Monty Program Ab
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; version 2 of the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
17 #pragma once
18 
19 #include <algorithm>
20 #include <string>
21 #include <vector>
22 
23 /* MySQL header files */
24 #include "my_global.h"
25 
26 /* MyRocks header files */
27 #include "./rdb_global.h"
28 #include "./rdb_utils.h"
29 
30 /* RocksDB header files */
31 #include "rocksdb/slice.h"
32 #include "rocksdb/status.h"
33 
34 namespace myrocks {
35 
36 /*
37   Basic composition functions for a network buffer presented as a MySQL String
38   ("netstr") which stores data in Network Byte Order (Big Endian).
39 */
40 
rdb_netstr_append_uint64(my_core::String * const out_netstr,const uint64 val)41 inline void rdb_netstr_append_uint64(my_core::String *const out_netstr,
42                                      const uint64 val) {
43   assert(out_netstr != nullptr);
44 
45   // Convert from host machine byte order (usually Little Endian) to network
46   // byte order (Big Endian).
47   uint64 net_val = htobe64(val);
48   out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
49 }
50 
rdb_netstr_append_uint32(my_core::String * const out_netstr,const uint32 val)51 inline void rdb_netstr_append_uint32(my_core::String *const out_netstr,
52                                      const uint32 val) {
53   assert(out_netstr != nullptr);
54 
55   // Convert from host machine byte order (usually Little Endian) to network
56   // byte order (Big Endian).
57   uint32 net_val = htobe32(val);
58   out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
59 }
60 
rdb_netstr_append_uint16(my_core::String * const out_netstr,const uint16 val)61 inline void rdb_netstr_append_uint16(my_core::String *const out_netstr,
62                                      const uint16 val) {
63   assert(out_netstr != nullptr);
64 
65   // Convert from host machine byte order (usually Little Endian) to network
66   // byte order (Big Endian).
67   uint16 net_val = htobe16(val);
68   out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
69 }
70 
71 /*
72   Basic network buffer ("netbuf") write helper functions.
73 */
74 
rdb_netbuf_store_uint64(uchar * const dst_netbuf,const uint64 n)75 inline void rdb_netbuf_store_uint64(uchar *const dst_netbuf, const uint64 n) {
76   assert(dst_netbuf != nullptr);
77 
78   // Convert from host byte order (usually Little Endian) to network byte order
79   // (Big Endian).
80   uint64 net_val = htobe64(n);
81   memcpy(dst_netbuf, &net_val, sizeof(net_val));
82 }
83 
rdb_netbuf_store_uint32(uchar * const dst_netbuf,const uint32 n)84 inline void rdb_netbuf_store_uint32(uchar *const dst_netbuf, const uint32 n) {
85   assert(dst_netbuf != nullptr);
86 
87   // Convert from host byte order (usually Little Endian) to network byte order
88   // (Big Endian).
89   uint32 net_val = htobe32(n);
90   memcpy(dst_netbuf, &net_val, sizeof(net_val));
91 }
92 
rdb_netbuf_store_uint16(uchar * const dst_netbuf,const uint16 n)93 inline void rdb_netbuf_store_uint16(uchar *const dst_netbuf, const uint16 n) {
94   assert(dst_netbuf != nullptr);
95 
96   // Convert from host byte order (usually Little Endian) to network byte order
97   // (Big Endian).
98   uint16 net_val = htobe16(n);
99   memcpy(dst_netbuf, &net_val, sizeof(net_val));
100 }
101 
rdb_netbuf_store_byte(uchar * const dst_netbuf,const uchar c)102 inline void rdb_netbuf_store_byte(uchar *const dst_netbuf, const uchar c) {
103   assert(dst_netbuf != nullptr);
104 
105   *dst_netbuf = c;
106 }
107 
rdb_netbuf_store_index(uchar * const dst_netbuf,const uint32 number)108 inline void rdb_netbuf_store_index(uchar *const dst_netbuf,
109                                    const uint32 number) {
110   assert(dst_netbuf != nullptr);
111 
112   rdb_netbuf_store_uint32(dst_netbuf, number);
113 }
114 
115 /*
116   Basic conversion helper functions from network byte order (Big Endian) to host
117   machine byte order (usually Little Endian).
118 */
119 
rdb_netbuf_to_uint64(const uchar * const netbuf)120 inline uint64 rdb_netbuf_to_uint64(const uchar *const netbuf) {
121   assert(netbuf != nullptr);
122 
123   uint64 net_val;
124   memcpy(&net_val, netbuf, sizeof(net_val));
125 
126   // Convert from network byte order (Big Endian) to host machine byte order
127   // (usually Little Endian).
128   return be64toh(net_val);
129 }
130 
rdb_netbuf_to_uint32(const uchar * const netbuf)131 inline uint32 rdb_netbuf_to_uint32(const uchar *const netbuf) {
132   assert(netbuf != nullptr);
133 
134   uint32 net_val;
135   memcpy(&net_val, netbuf, sizeof(net_val));
136 
137   // Convert from network byte order (Big Endian) to host machine byte order
138   // (usually Little Endian).
139   return be32toh(net_val);
140 }
141 
rdb_netbuf_to_uint16(const uchar * const netbuf)142 inline uint16 rdb_netbuf_to_uint16(const uchar *const netbuf) {
143   assert(netbuf != nullptr);
144 
145   uint16 net_val;
146   memcpy(&net_val, netbuf, sizeof(net_val));
147 
148   // Convert from network byte order (Big Endian) to host machine byte order
149   // (usually Little Endian).
150   return be16toh(net_val);
151 }
152 
rdb_netbuf_to_byte(const uchar * const netbuf)153 inline uchar rdb_netbuf_to_byte(const uchar *const netbuf) {
154   assert(netbuf != nullptr);
155 
156   return (uchar)netbuf[0];
157 }
158 
159 /*
160   Basic network buffer ("netbuf") read helper functions.
161   Network buffer stores data in Network Byte Order (Big Endian).
162   NB: The netbuf is passed as an input/output param, hence after reading,
163       the netbuf pointer gets advanced to the following byte.
164 */
165 
rdb_netbuf_read_uint64(const uchar ** netbuf_ptr)166 inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr) {
167   assert(netbuf_ptr != nullptr);
168 
169   // Convert from network byte order (Big Endian) to host machine byte order
170   // (usually Little Endian).
171   const uint64 host_val = rdb_netbuf_to_uint64(*netbuf_ptr);
172 
173   // Advance pointer.
174   *netbuf_ptr += sizeof(host_val);
175 
176   return host_val;
177 }
178 
rdb_netbuf_read_uint32(const uchar ** netbuf_ptr)179 inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr) {
180   assert(netbuf_ptr != nullptr);
181 
182   // Convert from network byte order (Big Endian) to host machine byte order
183   // (usually Little Endian).
184   const uint32 host_val = rdb_netbuf_to_uint32(*netbuf_ptr);
185 
186   // Advance pointer.
187   *netbuf_ptr += sizeof(host_val);
188 
189   return host_val;
190 }
191 
rdb_netbuf_read_uint16(const uchar ** netbuf_ptr)192 inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr) {
193   assert(netbuf_ptr != nullptr);
194 
195   // Convert from network byte order (Big Endian) to host machine byte order
196   // (usually Little Endian).
197   const uint16 host_val = rdb_netbuf_to_uint16(*netbuf_ptr);
198 
199   // Advance pointer.
200   *netbuf_ptr += sizeof(host_val);
201 
202   return host_val;
203 }
204 
rdb_netbuf_read_gl_index(const uchar ** netbuf_ptr,GL_INDEX_ID * const gl_index_id)205 inline void rdb_netbuf_read_gl_index(const uchar **netbuf_ptr,
206                                      GL_INDEX_ID *const gl_index_id) {
207   assert(gl_index_id != nullptr);
208   assert(netbuf_ptr != nullptr);
209 
210   gl_index_id->cf_id = rdb_netbuf_read_uint32(netbuf_ptr);
211   gl_index_id->index_id = rdb_netbuf_read_uint32(netbuf_ptr);
212 }
213 
214 /*
215   A simple string reader:
216   - it keeps position within the string that we read from
217   - it prevents one from reading beyond the end of the string.
218 */
219 
220 class Rdb_string_reader {
221   const char *m_ptr;
222   uint m_len;
223 
224  private:
225   Rdb_string_reader &operator=(const Rdb_string_reader &) = default;
226 
227  public:
228   Rdb_string_reader(const Rdb_string_reader &) = default;
229   /* named constructor */
read_or_empty(const rocksdb::Slice * const slice)230   static Rdb_string_reader read_or_empty(const rocksdb::Slice *const slice) {
231     if (!slice) {
232       return Rdb_string_reader("");
233     } else {
234       return Rdb_string_reader(slice);
235     }
236   }
237 
Rdb_string_reader(const std::string & str)238   explicit Rdb_string_reader(const std::string &str) {
239     m_len = str.length();
240     if (m_len) {
241       m_ptr = &str.at(0);
242     } else {
243       /*
244         One can a create a Rdb_string_reader for reading from an empty string
245         (although attempts to read anything will fail).
246         We must not access str.at(0), since len==0, we can set ptr to any
247         value.
248       */
249       m_ptr = nullptr;
250     }
251   }
252 
Rdb_string_reader(const rocksdb::Slice * const slice)253   explicit Rdb_string_reader(const rocksdb::Slice *const slice) {
254     m_ptr = slice->data();
255     m_len = slice->size();
256   }
257 
258   /*
259     Read the next @param size bytes. Returns pointer to the bytes read, or
260     nullptr if the remaining string doesn't have that many bytes.
261   */
read(const uint size)262   const char *read(const uint size) {
263     const char *res;
264     if (m_len < size) {
265       res = nullptr;
266     } else {
267       res = m_ptr;
268       m_ptr += size;
269       m_len -= size;
270     }
271     return res;
272   }
273 
read_uint8(uint * const res)274   bool read_uint8(uint *const res) {
275     const uchar *p;
276     if (!(p = reinterpret_cast<const uchar *>(read(1)))) {
277       return true;  // error
278     } else {
279       *res = *p;
280       return false;  // Ok
281     }
282   }
283 
read_uint16(uint * const res)284   bool read_uint16(uint *const res) {
285     const uchar *p;
286     if (!(p = reinterpret_cast<const uchar *>(read(2)))) {
287       return true;  // error
288     } else {
289       *res = rdb_netbuf_to_uint16(p);
290       return false;  // Ok
291     }
292   }
293 
read_uint64(uint64 * const res)294   bool read_uint64(uint64 *const res) {
295     const uchar *p;
296     if (!(p = reinterpret_cast<const uchar *>(read(sizeof(uint64))))) {
297       return true;  // error
298     } else {
299       *res = rdb_netbuf_to_uint64(p);
300       return false;  // Ok
301     }
302   }
303 
remaining_bytes()304   uint remaining_bytes() const { return m_len; }
305 
306   /*
307     Return pointer to data that will be read by next read() call (if there is
308     nothing left to read, returns pointer to beyond the end of previous read()
309     call)
310   */
get_current_ptr()311   const char *get_current_ptr() const { return m_ptr; }
312 };
313 
314 /*
315   @brief
316   A buffer one can write the data to.
317 
318   @detail
319   Suggested usage pattern:
320 
321     writer->clear();
322     writer->write_XXX(...);
323     ...
324     // Ok, writer->ptr() points to the data written so far,
325     // and writer->get_current_pos() is the length of the data
326 
327 */
328 
329 class Rdb_string_writer {
330   std::vector<uchar> m_data;
331 
332  public:
333   Rdb_string_writer(const Rdb_string_writer &) = delete;
334   Rdb_string_writer &operator=(const Rdb_string_writer &) = delete;
335   Rdb_string_writer() = default;
336 
clear()337   void clear() { m_data.clear(); }
write_uint8(const uint val)338   void write_uint8(const uint val) {
339     m_data.push_back(static_cast<uchar>(val));
340   }
341 
write_uint16(const uint val)342   void write_uint16(const uint val) {
343     const auto size = m_data.size();
344     m_data.resize(size + 2);
345     rdb_netbuf_store_uint16(m_data.data() + size, val);
346   }
347 
write_uint32(const uint val)348   void write_uint32(const uint val) {
349     const auto size = m_data.size();
350     m_data.resize(size + 4);
351     rdb_netbuf_store_uint32(m_data.data() + size, val);
352   }
353 
write(const uchar * const new_data,const size_t len)354   void write(const uchar *const new_data, const size_t len) {
355     assert(new_data != nullptr);
356     m_data.insert(m_data.end(), new_data, new_data + len);
357   }
358 
ptr()359   uchar *ptr() { return m_data.data(); }
get_current_pos()360   size_t get_current_pos() const { return m_data.size(); }
361 
write_uint8_at(const size_t pos,const uint new_val)362   void write_uint8_at(const size_t pos, const uint new_val) {
363     // This function will only overwrite what was written
364     assert(pos < get_current_pos());
365     m_data.data()[pos] = new_val;
366   }
367 
write_uint16_at(const size_t pos,const uint new_val)368   void write_uint16_at(const size_t pos, const uint new_val) {
369     // This function will only overwrite what was written
370     assert(pos < get_current_pos());
371     assert((pos + 1) < get_current_pos());
372     rdb_netbuf_store_uint16(m_data.data() + pos, new_val);
373   }
374 
truncate(const size_t pos)375   void truncate(const size_t pos) {
376     assert(pos < m_data.size());
377     m_data.resize(pos);
378   }
379 
380   void allocate(const size_t len, const uchar val = 0) {
381     assert(len > 0);
382     m_data.resize(m_data.size() + len, val);
383   }
384 
385   /*
386     An awful hack to deallocate the buffer without relying on the deconstructor.
387     This is needed to suppress valgrind errors in rocksdb.partition
388   */
free()389   void free() { std::vector<uchar>().swap(m_data); }
390 };
391 
392 /*
393    A helper class for writing bits into Rdb_string_writer.
394 
395    The class assumes (but doesn't check) that nobody tries to write
396    anything to the Rdb_string_writer that it is writing to.
397 */
398 class Rdb_bit_writer {
399   Rdb_string_writer *m_writer;
400   uchar m_offset;
401 
402  public:
403   Rdb_bit_writer(const Rdb_bit_writer &) = delete;
404   Rdb_bit_writer &operator=(const Rdb_bit_writer &) = delete;
405 
Rdb_bit_writer(Rdb_string_writer * writer_arg)406   explicit Rdb_bit_writer(Rdb_string_writer *writer_arg)
407       : m_writer(writer_arg), m_offset(0) {}
408 
write(uint size,const uint value)409   void write(uint size, const uint value) {
410     assert((value & ((1 << size) - 1)) == value);
411 
412     while (size > 0) {
413       if (m_offset == 0) {
414         m_writer->write_uint8(0);
415       }
416       // number of bits to put in this byte
417       const uint bits = std::min(size, (uint)(8 - m_offset));
418       uchar *const last_byte =
419           m_writer->ptr() + m_writer->get_current_pos() - 1;
420       *last_byte |= (uchar)((value >> (size - bits)) & ((1 << bits) - 1))
421                     << m_offset;
422       size -= bits;
423       m_offset = (m_offset + bits) & 0x7;
424     }
425   }
426 };
427 
428 class Rdb_bit_reader {
429   const uchar *m_cur;
430   uchar m_offset;
431   uint m_ret;
432   Rdb_string_reader *const m_reader;
433 
434  public:
435   Rdb_bit_reader(const Rdb_bit_reader &) = delete;
436   Rdb_bit_reader &operator=(const Rdb_bit_reader &) = delete;
437 
Rdb_bit_reader(Rdb_string_reader * const reader)438   explicit Rdb_bit_reader(Rdb_string_reader *const reader)
439       : m_cur(nullptr), m_offset(0), m_reader(reader) {}
440 
441   // Returns a pointer to an uint containing the bits read. On subsequent
442   // reads, the value being pointed to will be overwritten.  Returns nullptr
443   // on failure.
read(uint size)444   uint *read(uint size) {
445     m_ret = 0;
446     assert(size <= 32);
447 
448     while (size > 0) {
449       if (m_offset == 0) {
450         m_cur = (const uchar *)m_reader->read(1);
451         if (m_cur == nullptr) {
452           return nullptr;
453         }
454       }
455       // how many bits from the current byte?
456       const uint bits = std::min((uint)(8 - m_offset), size);
457       m_ret <<= bits;
458       m_ret |= (*m_cur >> m_offset) & ((1 << bits) - 1);
459       size -= bits;
460       m_offset = (m_offset + bits) & 0x7;
461     }
462 
463     return &m_ret;
464   }
465 };
466 
467 template <size_t buf_length>
468 class Rdb_buf_writer {
469  public:
470   Rdb_buf_writer(const Rdb_buf_writer &) = delete;
471   Rdb_buf_writer &operator=(const Rdb_buf_writer &) = delete;
Rdb_buf_writer()472   Rdb_buf_writer() { reset(); }
473 
write_uint32(const uint32 n)474   void write_uint32(const uint32 n) {
475     assert(m_ptr + sizeof(n) <= m_buf.data() + buf_length);
476     rdb_netbuf_store_uint32(m_ptr, n);
477     m_ptr += sizeof(n);
478   }
479 
write_uint64(const uint64 n)480   void write_uint64(const uint64 n) {
481     assert(m_ptr + sizeof(n) <= m_buf.data() + buf_length);
482     rdb_netbuf_store_uint64(m_ptr, n);
483     m_ptr += sizeof(n);
484   }
485 
write_uint16(const uint16 n)486   void write_uint16(const uint16 n) {
487     assert(m_ptr + sizeof(n) <= m_buf.data() + buf_length);
488     rdb_netbuf_store_uint16(m_ptr, n);
489     m_ptr += sizeof(n);
490   }
491 
write_byte(const uchar c)492   void write_byte(const uchar c) {
493     assert(m_ptr + sizeof(c) <= m_buf.data() + buf_length);
494     rdb_netbuf_store_byte(m_ptr, c);
495     m_ptr += sizeof(c);
496   }
497 
write_index(const uint32 n)498   void write_index(const uint32 n) { write_uint32(n); }
499 
write(const char * buf,const size_t size)500   void write(const char *buf, const size_t size) {
501     assert(m_ptr + size <= m_buf.data() + buf_length);
502     memcpy(m_ptr, buf, size);
503     m_ptr += size;
504   }
505 
write(const uchar * buf,const size_t size)506   void write(const uchar *buf, const size_t size) {
507     assert(m_ptr + size <= m_buf.data() + buf_length);
508     memcpy(m_ptr, buf, size);
509     m_ptr += size;
510   }
511 
reset()512   void reset() { m_ptr = m_buf.data(); }
513 
data()514   const char *data() const {
515     return reinterpret_cast<const char *>(m_buf.data());
516   }
517 
capacity()518   size_t capacity() { return buf_length; }
519 
520   /** Returns actual size of the buffer that has data */
size()521   size_t size() { return m_ptr - m_buf.data(); }
522 
to_slice()523   rocksdb::Slice to_slice() { return rocksdb::Slice(data(), size()); }
524 
525  private:
526   std::array<uchar, buf_length> m_buf;
527   uchar *m_ptr;
528 };
529 
530 }  // namespace myrocks
531