1 /*****************************************************************************
2 
3 Copyright (c) 2013, 2019, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8 
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 
25 *****************************************************************************/
26 
27 /** @file include/page0size.h
28  A class describing a page size.
29 
30  Created Nov 14, 2013 Vasil Dimov
31  *******************************************************/
32 
33 #ifndef page0size_t
34 #define page0size_t
35 
36 #include "fsp0types.h"
37 
38 constexpr size_t FIELD_REF_SIZE = 20;
39 
40 /** A BLOB field reference full of zero, for use in assertions and
41 tests.Initially, BLOB field references are set to zero, in
42 dtuple_convert_big_rec(). */
43 extern const byte field_ref_zero[FIELD_REF_SIZE];
44 
45 constexpr size_t PAGE_SIZE_T_SIZE_BITS = 17;
46 
47 /** Page size descriptor. Contains the physical and logical page size, as well
48 as whether the page is compressed or not. */
49 class page_size_t {
50  public:
51   /** Constructor from (physical, logical, is_compressed).
52   @param[in]	physical	physical (on-disk/zipped) page size
53   @param[in]	logical		logical (in-memory/unzipped) page size
54   @param[in]	is_compressed	whether the page is compressed */
page_size_t(uint32_t physical,uint32_t logical,bool is_compressed)55   page_size_t(uint32_t physical, uint32_t logical, bool is_compressed) {
56     if (physical == 0) {
57       physical = UNIV_PAGE_SIZE_ORIG;
58     }
59     if (logical == 0) {
60       logical = UNIV_PAGE_SIZE_ORIG;
61     }
62 
63     m_physical = static_cast<unsigned>(physical);
64     m_logical = static_cast<unsigned>(logical);
65     m_is_compressed = static_cast<unsigned>(is_compressed);
66 
67     ut_ad(physical <= (1 << PAGE_SIZE_T_SIZE_BITS));
68     ut_ad(logical <= (1 << PAGE_SIZE_T_SIZE_BITS));
69 
70     ut_ad(ut_is_2pow(physical));
71     ut_ad(ut_is_2pow(logical));
72 
73     ut_ad(logical <= UNIV_PAGE_SIZE_MAX);
74     ut_ad(logical >= physical);
75     ut_ad(!is_compressed || physical <= UNIV_ZIP_SIZE_MAX);
76   }
77 
78   /** Constructor from (fsp_flags).
79   @param[in]	fsp_flags	filespace flags */
page_size_t(uint32_t fsp_flags)80   explicit page_size_t(uint32_t fsp_flags) {
81     uint32_t ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
82 
83     /* If the logical page size is zero in fsp_flags, then use the
84     legacy 16k page size. */
85     ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize;
86 
87     /* Convert from a 'log2 minus 9' to a page size in bytes. */
88     const ulint size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
89 
90     ut_ad(size <= UNIV_PAGE_SIZE_MAX);
91     ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS));
92 
93     m_logical = size;
94 
95     ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
96 
97     /* If the fsp_flags have zero in the zip_ssize field, then
98     it means that the tablespace does not have compressed pages
99     and the physical page size is the same as the logical page
100     size. */
101     if (ssize == 0) {
102       m_is_compressed = false;
103       m_physical = m_logical;
104     } else {
105       m_is_compressed = true;
106 
107       /* Convert from a 'log2 minus 9' to a page size
108       in bytes. */
109       const ulint phy = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
110 
111       ut_ad(phy <= UNIV_ZIP_SIZE_MAX);
112       ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS));
113 
114       m_physical = phy;
115     }
116   }
117 
118   /** Retrieve the physical page size (on-disk).
119   @return physical page size in bytes */
physical()120   inline size_t physical() const {
121     ut_ad(m_physical > 0);
122 
123     return (m_physical);
124   }
125 
126   /** Retrieve the logical page size (in-memory).
127   @return logical page size in bytes */
logical()128   inline size_t logical() const {
129     ut_ad(m_logical > 0);
130     return (m_logical);
131   }
132 
extent_size()133   page_no_t extent_size() const {
134     page_no_t size = 0;
135     switch (m_physical) {
136       case 4096:
137         size = 256;
138         break;
139       case 8192:
140         size = 128;
141         break;
142       case 16384:
143       case 32768:
144       case 65536:
145         size = 64;
146         break;
147       default:
148         ut_ad(0);
149     }
150     return (size);
151   }
152 
extents_per_xdes()153   size_t extents_per_xdes() const { return (m_physical / extent_size()); }
154 
155   /** Check whether the page is compressed on disk.
156   @return true if compressed */
is_compressed()157   inline bool is_compressed() const { return (m_is_compressed); }
158 
159   /** Copy the values from a given page_size_t object.
160   @param[in]	src	page size object whose values to fetch */
copy_from(const page_size_t & src)161   inline void copy_from(const page_size_t &src) {
162     m_physical = src.physical();
163     m_logical = src.logical();
164     m_is_compressed = src.is_compressed();
165   }
166 
167   /** Check if a given page_size_t object is equal to the current one.
168   @param[in]	a	page_size_t object to compare
169   @return true if equal */
equals_to(const page_size_t & a)170   inline bool equals_to(const page_size_t &a) const {
171     return (a.physical() == m_physical && a.logical() == m_logical &&
172             a.is_compressed() == m_is_compressed);
173   }
174 
set_flag(uint32_t fsp_flags)175   inline void set_flag(uint32_t fsp_flags) {
176     uint32_t ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
177 
178     /* If the logical page size is zero in fsp_flags, then
179     use the legacy 16k page size. */
180     ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize;
181 
182     /* Convert from a 'log2 minus 9' to a page size in bytes. */
183     const uint32_t size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
184 
185     ut_ad(size <= UNIV_PAGE_SIZE_MAX);
186     ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS));
187 
188     m_logical = size;
189 
190     ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
191 
192     /* If the fsp_flags have zero in the zip_ssize field,
193     then it means that the tablespace does not have
194     compressed pages and the physical page size is the same
195     as the logical page size. */
196     if (ssize == 0) {
197       m_is_compressed = false;
198       m_physical = m_logical;
199     } else {
200       m_is_compressed = true;
201 
202       /* Convert from a 'log2 minus 9' to a page size
203       in bytes. */
204       const ulint phy = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
205 
206       ut_ad(phy <= UNIV_ZIP_SIZE_MAX);
207       ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS));
208 
209       m_physical = phy;
210     }
211   }
212 
213   /* Disable implicit copying. */
214   void operator=(const page_size_t &) = delete;
215 
216   page_size_t(const page_size_t &) = default;
217 
218  private:
219   /* For non compressed tablespaces, physical page size is equal to
220   the logical page size and the data is stored in buf_page_t::frame
221   (and is also always equal to univ_page_size (--innodb-page-size=)).
222 
223   For compressed tablespaces, physical page size is the compressed
224   page size as stored on disk and in buf_page_t::zip::data. The logical
225   page size is the uncompressed page size in memory - the size of
226   buf_page_t::frame (currently also always equal to univ_page_size
227   (--innodb-page-size=)). */
228 
229   /** Physical page size. */
230   unsigned m_physical : PAGE_SIZE_T_SIZE_BITS;
231 
232   /** Logical page size. */
233   unsigned m_logical : PAGE_SIZE_T_SIZE_BITS;
234 
235   /** Flag designating whether the physical page is compressed, which is
236   true IFF the whole tablespace where the page belongs is compressed. */
237   unsigned m_is_compressed : 1;
238 };
239 
240 /* Overloading the global output operator to conveniently print an object
241 of type the page_size_t.
242 @param[in,out]	out	the output stream
243 @param[in]	obj	an object of type page_size_t to be printed
244 @retval	the output stream */
245 inline std::ostream &operator<<(std::ostream &out, const page_size_t &obj) {
246   out << "[page size: physical=" << obj.physical()
247       << ", logical=" << obj.logical() << ", compressed=" << obj.is_compressed()
248       << "]";
249   return (out);
250 }
251 
252 extern page_size_t univ_page_size;
253 
254 #endif /* page0size_t */
255