1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, 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 Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/page0types.h
29 Index page routines
30 
31 Created 2/2/1994 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef page0types_h
35 #define page0types_h
36 
37 using namespace std;
38 
39 #include <map>
40 
41 #include "univ.i"
42 #include "dict0types.h"
43 #include "mtr0types.h"
44 
45 /** Eliminates a name collision on HP-UX */
46 #define page_t	   ib_page_t
47 /** Type of the index page */
48 typedef	byte		page_t;
49 /** Index page cursor */
50 struct page_cur_t;
51 
52 /** Compressed index page */
53 typedef byte		page_zip_t;
54 
55 /* The following definitions would better belong to page0zip.h,
56 but we cannot include page0zip.h from rem0rec.ic, because
57 page0*.h includes rem0rec.h and may include rem0rec.ic. */
58 
59 /** Number of bits needed for representing different compressed page sizes */
60 #define PAGE_ZIP_SSIZE_BITS 3
61 
62 /** Maximum compressed page shift size */
63 #define PAGE_ZIP_SSIZE_MAX	\
64 	(UNIV_ZIP_SIZE_SHIFT_MAX - UNIV_ZIP_SIZE_SHIFT_MIN + 1)
65 
66 /* Make sure there are enough bits available to store the maximum zip
67 ssize, which is the number of shifts from 512. */
68 #if PAGE_ZIP_SSIZE_MAX >= (1 << PAGE_ZIP_SSIZE_BITS)
69 # error "PAGE_ZIP_SSIZE_MAX >= (1 << PAGE_ZIP_SSIZE_BITS)"
70 #endif
71 
72 /** Compressed page descriptor */
73 struct page_zip_des_t
74 {
75 	page_zip_t*	data;		/*!< compressed page data */
76 
77 #ifdef UNIV_DEBUG
78 	unsigned	m_start:16;	/*!< start offset of modification log */
79 	bool		m_external;	/*!< Allocated externally, not from the
80 					buffer pool */
81 #endif /* UNIV_DEBUG */
82 	unsigned	m_end:16;	/*!< end offset of modification log */
83 	unsigned	m_nonempty:1;	/*!< TRUE if the modification log
84 					is not empty */
85 	unsigned	n_blobs:12;	/*!< number of externally stored
86 					columns on the page; the maximum
87 					is 744 on a 16 KiB page */
88 	unsigned	ssize:PAGE_ZIP_SSIZE_BITS;
89 					/*!< 0 or compressed page shift size;
90 					the size in bytes is
91 					(UNIV_ZIP_SIZE_MIN >> 1) << ssize. */
92 };
93 
94 /** Compression statistics for a given page size */
95 struct page_zip_stat_t {
96 	/** Number of page compressions */
97 	ulint		compressed;
98 	/** Number of successful page compressions */
99 	ulint		compressed_ok;
100 	/** Number of page decompressions */
101 	ulint		decompressed;
102 	/** Duration of page compressions in microseconds */
103 	ib_uint64_t	compressed_usec;
104 	/** Duration of page decompressions in microseconds */
105 	ib_uint64_t	decompressed_usec;
page_zip_stat_tpage_zip_stat_t106 	page_zip_stat_t() :
107 		/* Initialize members to 0 so that when we do
108 		stlmap[key].compressed++ and element with "key" does not
109 		exist it gets inserted with zeroed members. */
110 		compressed(0),
111 		compressed_ok(0),
112 		decompressed(0),
113 		compressed_usec(0),
114 		decompressed_usec(0)
115 	{ }
116 };
117 
118 #ifndef UNIV_INNOCHECKSUM
119 
120 /** Compression statistics types */
121 typedef map<index_id_t, page_zip_stat_t>	page_zip_stat_per_index_t;
122 
123 /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
124 extern page_zip_stat_t				page_zip_stat[PAGE_ZIP_SSIZE_MAX];
125 /** Statistics on compression, indexed by dict_index_t::id */
126 extern page_zip_stat_per_index_t		page_zip_stat_per_index;
127 extern ib_mutex_t				page_zip_stat_per_index_mutex;
128 #ifdef HAVE_PSI_INTERFACE
129 extern mysql_pfs_key_t				page_zip_stat_per_index_mutex_key;
130 #endif /* HAVE_PSI_INTERFACE */
131 
132 #endif /* !UNIV_INNOCHECKSUM */
133 
134 /**********************************************************************//**
135 Write the "deleted" flag of a record on a compressed page.  The flag must
136 already have been written on the uncompressed page. */
137 UNIV_INTERN
138 void
139 page_zip_rec_set_deleted(
140 /*=====================*/
141 	page_zip_des_t*	page_zip,/*!< in/out: compressed page */
142 	const byte*	rec,	/*!< in: record on the uncompressed page */
143 	ulint		flag)	/*!< in: the deleted flag (nonzero=TRUE) */
144 	MY_ATTRIBUTE((nonnull));
145 
146 /**********************************************************************//**
147 Write the "owned" flag of a record on a compressed page.  The n_owned field
148 must already have been written on the uncompressed page. */
149 UNIV_INTERN
150 void
151 page_zip_rec_set_owned(
152 /*===================*/
153 	page_zip_des_t*	page_zip,/*!< in/out: compressed page */
154 	const byte*	rec,	/*!< in: record on the uncompressed page */
155 	ulint		flag)	/*!< in: the owned flag (nonzero=TRUE) */
156 	MY_ATTRIBUTE((nonnull));
157 
158 /**********************************************************************//**
159 Shift the dense page directory when a record is deleted. */
160 UNIV_INTERN
161 void
162 page_zip_dir_delete(
163 /*================*/
164 	page_zip_des_t*	page_zip,/*!< in/out: compressed page */
165 	byte*		rec,	/*!< in: deleted record */
166 	dict_index_t*	index,	/*!< in: index of rec */
167 	const ulint*	offsets,/*!< in: rec_get_offsets(rec) */
168 	const byte*	free)	/*!< in: previous start of the free list */
169 	MY_ATTRIBUTE((nonnull(1,2,3,4)));
170 
171 /**********************************************************************//**
172 Add a slot to the dense page directory. */
173 UNIV_INTERN
174 void
175 page_zip_dir_add_slot(
176 /*==================*/
177 	page_zip_des_t*	page_zip,	/*!< in/out: compressed page */
178 	ulint		is_clustered)	/*!< in: nonzero for clustered index,
179 					zero for others */
180 	MY_ATTRIBUTE((nonnull));
181 #endif
182