1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2019, 2020, MariaDB Corporation.
5 
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
17 
18 *****************************************************************************/
19 
20 /**************************************************//**
21 @file include/page0types.h
22 Index page routines
23 
24 Created 2/2/1994 Heikki Tuuri
25 *******************************************************/
26 
27 #ifndef page0types_h
28 #define page0types_h
29 
30 #include "dict0types.h"
31 #include "mtr0types.h"
32 #include "rem0types.h"
33 
34 #include <map>
35 
36 /** Eliminates a name collision on HP-UX */
37 #define page_t	   ib_page_t
38 /** Type of the index page */
39 typedef	byte		page_t;
40 #ifndef UNIV_INNOCHECKSUM
41 /** Index page cursor */
42 struct page_cur_t;
43 /** Buffer pool block */
44 struct buf_block_t;
45 
46 /** Compressed index page */
47 typedef byte		page_zip_t;
48 
49 /* The following definitions would better belong to page0zip.h,
50 but we cannot include page0zip.h from rem0rec.ic, because
51 page0*.h includes rem0rec.h and may include rem0rec.ic. */
52 
53 /** Number of bits needed for representing different compressed page sizes */
54 #define PAGE_ZIP_SSIZE_BITS 3
55 
56 /** Maximum compressed page shift size */
57 #define PAGE_ZIP_SSIZE_MAX	\
58 	(UNIV_ZIP_SIZE_SHIFT_MAX - UNIV_ZIP_SIZE_SHIFT_MIN + 1)
59 
60 /* Make sure there are enough bits available to store the maximum zip
61 ssize, which is the number of shifts from 512. */
62 #if PAGE_ZIP_SSIZE_MAX >= (1 << PAGE_ZIP_SSIZE_BITS)
63 # error "PAGE_ZIP_SSIZE_MAX >= (1 << PAGE_ZIP_SSIZE_BITS)"
64 #endif
65 
66 /* Page cursor search modes; the values must be in this order! */
67 enum page_cur_mode_t {
68 	PAGE_CUR_UNSUPP	= 0,
69 	PAGE_CUR_G	= 1,
70 	PAGE_CUR_GE	= 2,
71 	PAGE_CUR_L	= 3,
72 	PAGE_CUR_LE	= 4,
73 
74 /*      PAGE_CUR_LE_OR_EXTENDS = 5,*/ /* This is a search mode used in
75 				 "column LIKE 'abc%' ORDER BY column DESC";
76 				 we have to find strings which are <= 'abc' or
77 				 which extend it */
78 
79 /* These search mode is for search R-tree index. */
80 	PAGE_CUR_CONTAIN		= 7,
81 	PAGE_CUR_INTERSECT		= 8,
82 	PAGE_CUR_WITHIN			= 9,
83 	PAGE_CUR_DISJOINT		= 10,
84 	PAGE_CUR_MBR_EQUAL		= 11,
85 	PAGE_CUR_RTREE_INSERT		= 12,
86 	PAGE_CUR_RTREE_LOCATE		= 13,
87 	PAGE_CUR_RTREE_GET_FATHER	= 14
88 };
89 
90 /** Compressed page descriptor */
91 struct page_zip_des_t
92 {
93 	page_zip_t*	data;		/*!< compressed page data */
94 
95 #ifdef UNIV_DEBUG
96 	unsigned	m_start:16;	/*!< start offset of modification log */
97 	bool		m_external;	/*!< Allocated externally, not from the
98 					buffer pool */
99 #endif /* UNIV_DEBUG */
100 	unsigned	m_end:16;	/*!< end offset of modification log */
101 	unsigned	m_nonempty:1;	/*!< TRUE if the modification log
102 					is not empty */
103 	unsigned	n_blobs:12;	/*!< number of externally stored
104 					columns on the page; the maximum
105 					is 744 on a 16 KiB page */
106 	unsigned	ssize:PAGE_ZIP_SSIZE_BITS;
107 					/*!< 0 or compressed page shift size;
108 					the size in bytes is
109 					(UNIV_ZIP_SIZE_MIN >> 1) << ssize. */
110 };
111 
112 /** Compression statistics for a given page size */
113 struct page_zip_stat_t {
114 	/** Number of page compressions */
115 	ulint		compressed;
116 	/** Number of successful page compressions */
117 	ulint		compressed_ok;
118 	/** Number of page decompressions */
119 	ulint		decompressed;
120 	/** Duration of page compressions in microseconds */
121 	ib_uint64_t	compressed_usec;
122 	/** Duration of page decompressions in microseconds */
123 	ib_uint64_t	decompressed_usec;
page_zip_stat_tpage_zip_stat_t124 	page_zip_stat_t() :
125 		/* Initialize members to 0 so that when we do
126 		stlmap[key].compressed++ and element with "key" does not
127 		exist it gets inserted with zeroed members. */
128 		compressed(0),
129 		compressed_ok(0),
130 		decompressed(0),
131 		compressed_usec(0),
132 		decompressed_usec(0)
133 	{ }
134 };
135 
136 /** Compression statistics types */
137 typedef std::map<
138 	index_id_t,
139 	page_zip_stat_t,
140 	std::less<index_id_t>,
141 	ut_allocator<std::pair<const index_id_t, page_zip_stat_t> > >
142 	page_zip_stat_per_index_t;
143 
144 /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
145 extern page_zip_stat_t			page_zip_stat[PAGE_ZIP_SSIZE_MAX];
146 /** Statistics on compression, indexed by dict_index_t::id */
147 extern page_zip_stat_per_index_t	page_zip_stat_per_index;
148 
149 /**********************************************************************//**
150 Write the "owned" flag of a record on a compressed page.  The n_owned field
151 must already have been written on the uncompressed page. */
152 void
153 page_zip_rec_set_owned(
154 /*===================*/
155 	buf_block_t*	block,	/*!< in/out: ROW_FORMAT=COMPRESSED page */
156 	const byte*	rec,	/*!< in: record on the uncompressed page */
157 	ulint		flag,	/*!< in: the owned flag (nonzero=TRUE) */
158 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
159 	MY_ATTRIBUTE((nonnull));
160 #endif /* !UNIV_INNOCHECKSUM */
161 #endif
162