1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
3 | #ident "$Id$" |
4 | /*====== |
5 | This file is part of PerconaFT. |
6 | |
7 | |
8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
9 | |
10 | PerconaFT is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU General Public License, version 2, |
12 | as published by the Free Software Foundation. |
13 | |
14 | PerconaFT 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 for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
21 | |
22 | ---------------------------------------- |
23 | |
24 | PerconaFT is free software: you can redistribute it and/or modify |
25 | it under the terms of the GNU Affero General Public License, version 3, |
26 | as published by the Free Software Foundation. |
27 | |
28 | PerconaFT is distributed in the hope that it will be useful, |
29 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | GNU Affero General Public License for more details. |
32 | |
33 | You should have received a copy of the GNU Affero General Public License |
34 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
35 | ======= */ |
36 | |
37 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
38 | |
39 | #pragma once |
40 | |
41 | #include <memory.h> |
42 | #include <string.h> |
43 | |
44 | #include "portability/toku_htonl.h" |
45 | |
46 | #include "util/bytestring.h" |
47 | #include "util/x1764.h" |
48 | |
49 | /* When serializing a value, write it into a buffer. */ |
50 | /* This code requires that the buffer be big enough to hold whatever you put into it. */ |
51 | /* This abstraction doesn't do a good job of hiding its internals. |
52 | * Why? The performance of this code is important, and we want to inline stuff */ |
53 | //Why is size here an int instead of DISKOFF like in the initializer? |
54 | struct wbuf { |
55 | unsigned char *buf; |
56 | unsigned int size; |
57 | unsigned int ndone; |
58 | struct x1764 checksum; // The checksum state |
59 | }; |
60 | |
61 | static inline void wbuf_nocrc_init (struct wbuf *w, void *buf, unsigned int size) { |
62 | w->buf = (unsigned char *) buf; |
63 | w->size = size; |
64 | w->ndone = 0; |
65 | } |
66 | |
67 | static inline void wbuf_init (struct wbuf *w, void *buf, unsigned int size) { |
68 | wbuf_nocrc_init(w, buf, size); |
69 | toku_x1764_init(&w->checksum); |
70 | } |
71 | |
72 | static inline size_t wbuf_get_woffset(struct wbuf *w) { |
73 | return w->ndone; |
74 | } |
75 | |
76 | /* Write a character. */ |
77 | static inline void wbuf_nocrc_char (struct wbuf *w, unsigned char ch) { |
78 | assert(w->ndone<w->size); |
79 | w->buf[w->ndone++]=ch; |
80 | } |
81 | |
82 | /* Write a character. */ |
83 | static inline void wbuf_nocrc_uint8_t (struct wbuf *w, uint8_t ch) { |
84 | assert(w->ndone<w->size); |
85 | w->buf[w->ndone++]=ch; |
86 | } |
87 | |
88 | static inline void wbuf_char (struct wbuf *w, unsigned char ch) { |
89 | wbuf_nocrc_char (w, ch); |
90 | toku_x1764_add(&w->checksum, &w->buf[w->ndone-1], 1); |
91 | } |
92 | |
93 | //Write an int that MUST be in network order regardless of disk order |
94 | static void wbuf_network_int (struct wbuf *w, int32_t i) __attribute__((__unused__)); |
95 | static void wbuf_network_int (struct wbuf *w, int32_t i) { |
96 | assert(w->ndone + 4 <= w->size); |
97 | *(uint32_t*)(&w->buf[w->ndone]) = toku_htonl(i); |
98 | toku_x1764_add(&w->checksum, &w->buf[w->ndone], 4); |
99 | w->ndone += 4; |
100 | } |
101 | |
102 | static inline void wbuf_nocrc_int (struct wbuf *w, int32_t i) { |
103 | #if 0 |
104 | wbuf_nocrc_char(w, i>>24); |
105 | wbuf_nocrc_char(w, i>>16); |
106 | wbuf_nocrc_char(w, i>>8); |
107 | wbuf_nocrc_char(w, i>>0); |
108 | #else |
109 | assert(w->ndone + 4 <= w->size); |
110 | #if 0 |
111 | w->buf[w->ndone+0] = i>>24; |
112 | w->buf[w->ndone+1] = i>>16; |
113 | w->buf[w->ndone+2] = i>>8; |
114 | w->buf[w->ndone+3] = i>>0; |
115 | #else |
116 | *(uint32_t*)(&w->buf[w->ndone]) = toku_htod32(i); |
117 | #endif |
118 | w->ndone += 4; |
119 | #endif |
120 | } |
121 | |
122 | static inline void wbuf_int (struct wbuf *w, int32_t i) { |
123 | wbuf_nocrc_int(w, i); |
124 | toku_x1764_add(&w->checksum, &w->buf[w->ndone-4], 4); |
125 | } |
126 | |
127 | static inline void wbuf_nocrc_uint (struct wbuf *w, uint32_t i) { |
128 | wbuf_nocrc_int(w, (int32_t)i); |
129 | } |
130 | |
131 | static inline void wbuf_uint (struct wbuf *w, uint32_t i) { |
132 | wbuf_int(w, (int32_t)i); |
133 | } |
134 | |
135 | static inline uint8_t* wbuf_nocrc_reserve_literal_bytes(struct wbuf *w, uint32_t nbytes) { |
136 | assert(w->ndone + nbytes <= w->size); |
137 | uint8_t * dest = w->buf + w->ndone; |
138 | w->ndone += nbytes; |
139 | return dest; |
140 | } |
141 | |
142 | static inline void wbuf_nocrc_literal_bytes(struct wbuf *w, const void *bytes_bv, uint32_t nbytes) { |
143 | const unsigned char *bytes = (const unsigned char *) bytes_bv; |
144 | #if 0 |
145 | { int i; for (i=0; i<nbytes; i++) wbuf_nocrc_char(w, bytes[i]); } |
146 | #else |
147 | assert(w->ndone + nbytes <= w->size); |
148 | memcpy(w->buf + w->ndone, bytes, (size_t)nbytes); |
149 | w->ndone += nbytes; |
150 | #endif |
151 | } |
152 | |
153 | static inline void wbuf_literal_bytes(struct wbuf *w, const void *bytes_bv, uint32_t nbytes) { |
154 | wbuf_nocrc_literal_bytes(w, bytes_bv, nbytes); |
155 | toku_x1764_add(&w->checksum, &w->buf[w->ndone-nbytes], nbytes); |
156 | } |
157 | |
158 | static void wbuf_nocrc_bytes (struct wbuf *w, const void *bytes_bv, uint32_t nbytes) { |
159 | wbuf_nocrc_uint(w, nbytes); |
160 | wbuf_nocrc_literal_bytes(w, bytes_bv, nbytes); |
161 | } |
162 | |
163 | static void wbuf_bytes (struct wbuf *w, const void *bytes_bv, uint32_t nbytes) { |
164 | wbuf_uint(w, nbytes); |
165 | wbuf_literal_bytes(w, bytes_bv, nbytes); |
166 | } |
167 | |
168 | static void wbuf_nocrc_ulonglong (struct wbuf *w, uint64_t ull) { |
169 | wbuf_nocrc_uint(w, (uint32_t)(ull>>32)); |
170 | wbuf_nocrc_uint(w, (uint32_t)(ull&0xFFFFFFFF)); |
171 | } |
172 | |
173 | static void wbuf_ulonglong (struct wbuf *w, uint64_t ull) { |
174 | wbuf_uint(w, (uint32_t)(ull>>32)); |
175 | wbuf_uint(w, (uint32_t)(ull&0xFFFFFFFF)); |
176 | } |
177 | |
178 | static inline void wbuf_nocrc_uint64_t(struct wbuf *w, uint64_t ull) { |
179 | wbuf_nocrc_ulonglong(w, ull); |
180 | } |
181 | |
182 | |
183 | static inline void wbuf_uint64_t(struct wbuf *w, uint64_t ull) { |
184 | wbuf_ulonglong(w, ull); |
185 | } |
186 | |
187 | static inline void wbuf_nocrc_bool (struct wbuf *w, bool b) { |
188 | wbuf_nocrc_uint8_t(w, (uint8_t)(b ? 1 : 0)); |
189 | } |
190 | |
191 | static inline void wbuf_nocrc_BYTESTRING (struct wbuf *w, BYTESTRING v) { |
192 | wbuf_nocrc_bytes(w, v.data, v.len); |
193 | } |
194 | |
195 | static inline void wbuf_BYTESTRING (struct wbuf *w, BYTESTRING v) { |
196 | wbuf_bytes(w, v.data, v.len); |
197 | } |
198 | |
199 | static inline void wbuf_uint8_t (struct wbuf *w, uint8_t v) { |
200 | wbuf_char(w, v); |
201 | } |
202 | |
203 | static inline void wbuf_nocrc_uint32_t (struct wbuf *w, uint32_t v) { |
204 | wbuf_nocrc_uint(w, v); |
205 | } |
206 | |
207 | static inline void wbuf_uint32_t (struct wbuf *w, uint32_t v) { |
208 | wbuf_uint(w, v); |
209 | } |
210 | |