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/*======
5This file is part of PerconaFT.
6
7
8Copyright (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#include "ft/node.h"
40#include "ft/ft-internal.h"
41#include "ft/serialize/ft_node-serialize.h"
42
43/*
44 * ft-node-deserialize.c -
45 * This file contains functions used by deserializtion
46 * code paths in and out of the engine. The functions can,
47 * essentially, be broken up into two types. Some of these
48 * functions return error codes based expected values inside
49 * the fractal tree node, others merely read the specific
50 * quantities of bytes out of the buffer. It is expeceted
51 * that these will be called in the correct order by users
52 * of these functions/this API.
53 *
54 */
55
56// Sets initial values for the given fractal tree node to be
57// deserialized
58void
59initialize_ftnode(FTNODE node, BLOCKNUM blocknum)
60{
61 node->fullhash = 0xDEADBEEF; // <CER> Is this 'spoof' ok?
62 node->blocknum = blocknum;
63 node->dirty = 0;
64 node->bp = NULL;
65 // <CER> Can we use this initialization as a correctness assert in
66 // a later function?
67 node->layout_version_read_from_disk = 0;
68}
69
70/************************
71 * TODO: In other deserialization code, we check the rb size member. We
72 * verify that it is greater than or equal to 24. Ignoring this magic
73 * number for a moment, should we put this check in its own function? *
74*************************/
75
76
77// Read and check the 'magic' bytes on disk. Returns an error if
78// the magic does not match.
79int
80read_and_check_magic(struct rbuf *rb)
81{
82 int r = 0;
83 const void *magic;
84 rbuf_literal_bytes(rb, &magic, 8);
85 if (memcmp(magic, "tokuleaf", 8)!=0 &&
86 memcmp(magic, "tokunode", 8)!=0) {
87 r = DB_BADFORMAT; // TODO: Return more meaningful error.
88 }
89
90 return r;
91}
92
93// Read the version number from the given buffer
94// and returns an error if the version is too old.
95int
96read_and_check_version(FTNODE node, struct rbuf *rb)
97{
98 int r = 0;
99 int version = rbuf_int(rb);
100 node->layout_version_read_from_disk = version;
101 if (version < FT_LAYOUT_MIN_SUPPORTED_VERSION) {
102 r = 1; // TODO: Better error reporting.
103 }
104
105 return r;
106}
107
108// Reads the basic version, build, and child info from
109// the given buffer.
110void
111read_node_info(FTNODE node, struct rbuf *rb, int version)
112{
113 node->layout_version = version;
114 node->layout_version_original = rbuf_int(rb);
115 node->build_id = rbuf_int(rb);
116 node->n_children = rbuf_int(rb);
117}
118
119// Allocates the partitions based on the given node's nubmer
120// of children. It then reads, out of the given buffer,
121// the start and size of each child partition.
122// TODO: Should these be two seperate functions?
123void
124allocate_and_read_partition_offsets(FTNODE node, struct rbuf *rb, FTNODE_DISK_DATA *ndd)
125{
126 XMALLOC_N(node->n_children, node->bp);
127 // TODO: Fix this to use xmalloc_n
128 XMALLOC_N(node->n_children, *ndd);
129 // Read the partition locations.
130 for (int i = 0; i < node->n_children; i++) {
131 BP_START(*ndd, i) = rbuf_int(rb);
132 BP_SIZE (*ndd, i) = rbuf_int(rb);
133 }
134}
135
136// Compares checksum of stored (in the given buffer) checksum
137// and the checksum of the buffer itself. If these are NOT
138// equal, this function returns an appropriate error code.
139int
140check_node_info_checksum(struct rbuf *rb)
141{
142 int r = 0;
143 // Verify checksum of header stored.
144 uint32_t checksum = toku_x1764_memory(rb->buf, rb->ndone);
145 uint32_t stored_checksum = rbuf_int(rb);
146
147 if (stored_checksum != checksum) {
148 // TODO: dump_bad_block(rb->buf, rb->size);
149 r = TOKUDB_BAD_CHECKSUM;
150 }
151
152 return r;
153}
154
155// Reads node info from older (13 and 14) fractal tree nodes
156// out of the given buffer.
157void
158read_legacy_node_info(FTNODE node, struct rbuf *rb, int version)
159{
160 (void)rbuf_int(rb); // 1. nodesize
161 node->flags = rbuf_int(rb); // 2. flags
162 node->height = rbuf_int(rb); // 3. height
163
164 // If the version is less than 14, there are two extra ints here.
165 // we would need to ignore them if they are there.
166 if (version == FT_LAYOUT_VERSION_13) {
167 (void) rbuf_int(rb); // 4. rand4
168 (void) rbuf_int(rb); // 5. local
169 }
170}
171
172// Assuming the given buffer is in the correct position,
173// this checks to see if the stored checksum matches the
174// checksum of the entire buffer.
175int
176check_legacy_end_checksum(struct rbuf *rb)
177{
178 int r = 0;
179 uint32_t expected_xsum = rbuf_int(rb);
180 uint32_t actual_xsum = toku_x1764_memory(rb->buf, rb->size - 4);
181 if (expected_xsum != actual_xsum) {
182 r = TOKUDB_BAD_CHECKSUM;
183 }
184
185 return r;
186}
187