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