1 /*
2 Copyright (c) 2005, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef __NDB_DISKPAGE_HPP
26 #define __NDB_DISKPAGE_HPP
27
28 #include <ndb_types.h>
29 #include <NdbOut.hpp>
30
31 #define JAM_FILE_ID 436
32
33
34 struct File_formats
35 {
36 STATIC_CONST( NDB_PAGE_SIZE = 32768 );
37 STATIC_CONST( NDB_PAGE_SIZE_WORDS = NDB_PAGE_SIZE >> 2);
38
39 enum File_type
40 {
41 FT_Datafile = 0x1,
42 FT_Undofile = 0x2
43 };
44
45 struct Page_header
46 {
47 Uint32 m_page_lsn_hi;
48 Uint32 m_page_lsn_lo;
49 Uint32 m_page_type;
50 };
51
52 enum Page_type
53 {
54 PT_Unallocated = 0x0,
55 PT_Extent_page = 0x1,
56 PT_Tup_fixsize_page = 0x2,
57 PT_Tup_varsize_page = 0x3,
58 PT_Undopage = 0x4
59 };
60
61 struct Zero_page_header
62 {
63 char m_magic[8];
64 Uint32 m_byte_order;
65 Uint32 m_page_size;
66 Uint32 m_ndb_version;
67 Uint32 m_node_id;
68 Uint32 m_file_type;
69 Uint32 m_time; // time(0)
Zero_page_headerFile_formats::Zero_page_header70 Zero_page_header() {}
71 void init(File_type ft, Uint32 node_id, Uint32 version, Uint32 now);
72 int validate(File_type ft, Uint32 node_id, Uint32 version, Uint32 now);
73 };
74
75 STATIC_CONST( NDB_PAGE_HEADER_WORDS = sizeof(Page_header) >> 2);
76
77 struct Datafile
78 {
79 struct Zero_page
80 {
81 struct Zero_page_header m_page_header;
82 Uint32 m_file_no; // Local_key
83 Uint32 m_file_id; // DICT id
84 Uint32 m_tablespace_id;
85 Uint32 m_tablespace_version;
86 Uint32 m_data_pages;
87 Uint32 m_extent_pages;
88 Uint32 m_extent_size;
89 Uint32 m_extent_count;
90 Uint32 m_extent_headers_per_page;
91 Uint32 m_extent_header_words;
92 Uint32 m_extent_header_bits_per_page;
93 };
94
95 struct Extent_header
96 {
97 Uint32 m_table;
98 union
99 {
100 Uint32 m_fragment_id;
101 Uint32 m_next_free_extent;
102 };
Extent_headerFile_formats::Datafile::Extent_header103 Extent_header() {}
104 Uint32 m_page_bitmask[1]; // (BitsPerPage*ExtentSize)/(32*PageSize)
105 Uint32 get_free_bits(Uint32 page) const;
106 Uint32 get_free_word_offset(Uint32 page) const;
107 void update_free_bits(Uint32 page, Uint32 bit);
108 bool check_free(Uint32 extent_size) const ;
109 };
110
111 STATIC_CONST( EXTENT_HEADER_BITMASK_BITS_PER_PAGE = 4 );
112 STATIC_CONST( EXTENT_HEADER_FIXED_WORDS = (sizeof(Extent_header)>>2) - 1);
113 static Uint32 extent_header_words(Uint32 extent_size_in_pages);
114
115 struct Extent_page
116 {
117 struct Page_header m_page_header;
118 Extent_header m_extents[1];
119
Extent_pageFile_formats::Datafile::Extent_page120 Extent_page() {}
121 Extent_header* get_header(Uint32 extent_no, Uint32 extent_size);
122 };
123
124 STATIC_CONST( EXTENT_PAGE_WORDS = NDB_PAGE_SIZE_WORDS - NDB_PAGE_HEADER_WORDS );
125
126 struct Data_page
127 {
128 struct Page_header m_page_header;
129 };
130 };
131
132 struct Undofile
133 {
134 struct Zero_page
135 {
136 struct Zero_page_header m_page_header;
137 Uint32 m_file_id;
138 Uint32 m_logfile_group_id;
139 Uint32 m_logfile_group_version;
140 Uint32 m_undo_pages;
141 };
142 struct Undo_page
143 {
144 struct Page_header m_page_header;
145 Uint32 m_words_used;
146 Uint32 m_data[1];
147 };
148
149 struct Undo_entry
150 {
151 Uint32 m_file_no;
152 Uint32 m_page_no;
153 struct
154 {
155 Uint32 m_len_offset;
156 Uint32 m_data[1];
157 } m_changes[1];
158 Uint32 m_length; // [ 16-bit type | 16 bit length of entry ]
159 };
160
161 enum Undo_type {
162 UNDO_LCP_FIRST = 1 // First LCP record with specific lcp id
163 ,UNDO_LCP = 2 // LCP Start
164
165 /**
166 * TUP Undo record
167 */
168 ,UNDO_TUP_ALLOC = 3
169 ,UNDO_TUP_UPDATE = 4
170 ,UNDO_TUP_FREE = 5
171 ,UNDO_TUP_CREATE = 6
172 ,UNDO_TUP_DROP = 7
173 ,UNDO_TUP_ALLOC_EXTENT = 8
174 ,UNDO_TUP_FREE_EXTENT = 9
175
176 ,UNDO_END = 0x7FFF
177 ,UNDO_NEXT_LSN = 0x8000
178 };
179
180 struct Undo_lcp
181 {
182 Uint32 m_lcp_id;
183 Uint32 m_type_length; // 16 bit type, 16 bit length
184 };
185 };
186 STATIC_CONST( UNDO_PAGE_WORDS = NDB_PAGE_SIZE_WORDS - NDB_PAGE_HEADER_WORDS - 1);
187 };
188
189
190 /**
191 * Compute size of extent header in words
192 */
193 inline Uint32
extent_header_words(Uint32 extent_size_in_pages)194 File_formats::Datafile::extent_header_words(Uint32 extent_size_in_pages)
195 {
196 return EXTENT_HEADER_FIXED_WORDS +
197 ((extent_size_in_pages * EXTENT_HEADER_BITMASK_BITS_PER_PAGE + 31) >> 5);
198 }
199
200 inline
201 File_formats::Datafile::Extent_header*
get_header(Uint32 no,Uint32 extent_size)202 File_formats::Datafile::Extent_page::get_header(Uint32 no, Uint32 extent_size)
203 {
204 Uint32 * tmp = (Uint32*)m_extents;
205 tmp += no*File_formats::Datafile::extent_header_words(extent_size);
206 return (Extent_header*)tmp;
207 }
208
209 inline
210 Uint32
get_free_bits(Uint32 page) const211 File_formats::Datafile::Extent_header::get_free_bits(Uint32 page) const
212 {
213 return ((m_page_bitmask[page >> 3] >> ((page & 7) << 2))) & 15;
214 }
215
216 inline
217 Uint32
get_free_word_offset(Uint32 page) const218 File_formats::Datafile::Extent_header::get_free_word_offset(Uint32 page) const
219 {
220 return page >> 3;
221 }
222
223 inline
224 void
update_free_bits(Uint32 page,Uint32 bit)225 File_formats::Datafile::Extent_header::update_free_bits(Uint32 page,
226 Uint32 bit)
227 {
228 Uint32 shift = (page & 7) << 2;
229 Uint32 mask = (15 << shift);
230 Uint32 org = m_page_bitmask[page >> 3];
231 m_page_bitmask[page >> 3] = (org & ~mask) | (bit << shift);
232 }
233
234 inline
235 bool
check_free(Uint32 extent_size) const236 File_formats::Datafile::Extent_header::check_free(Uint32 extent_size) const
237 {
238 Uint32 words = (extent_size * EXTENT_HEADER_BITMASK_BITS_PER_PAGE + 31) >> 5;
239 Uint32 sum = 0;
240 for(; words; words--)
241 sum |= m_page_bitmask[words-1];
242
243 if(sum & 0x3333)
244 return false;
245
246 return true;
247 }
248
249 NdbOut& operator<<(NdbOut& out, const File_formats::Zero_page_header&);
250 NdbOut& operator<<(NdbOut& out, const File_formats::Datafile::Zero_page&);
251 NdbOut& operator<<(NdbOut& out, const File_formats::Undofile::Zero_page&);
252
253
254 #undef JAM_FILE_ID
255
256 #endif
257