1 /*****************************************************************************
2 
3 Copyright (c) 2013, 2016, 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 as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************//**
20 @file include/fsp0sysspace.h
21 Multi file, shared, system tablespace implementation.
22 
23 Created 2013-7-26 by Kevin Lewis
24 *******************************************************/
25 
26 #ifndef fsp0sysspace_h
27 #define fsp0sysspace_h
28 
29 #include "fsp0space.h"
30 
31 /** If the last data file is auto-extended, we add this many pages to it
32 at a time. We have to make this public because it is a config variable. */
33 extern uint sys_tablespace_auto_extend_increment;
34 
35 /** Data structure that contains the information about shared tablespaces.
36 Currently this can be the system tablespace or a temporary table tablespace */
37 class SysTablespace : public Tablespace
38 {
39 public:
40 
SysTablespace()41 	SysTablespace()
42 		:
43 		m_auto_extend_last_file(),
44 		m_last_file_size_max(),
45 		m_created_new_raw(),
46 		m_is_tablespace_full(false),
47 		m_sanity_checks_done(false)
48 	{
49 		/* No op */
50 	}
51 
~SysTablespace()52 	~SysTablespace() override
53 	{
54 		shutdown();
55 	}
56 
57 	/** Set tablespace full status
58 	@param[in]	is_full		true if full */
set_tablespace_full_status(bool is_full)59 	void set_tablespace_full_status(bool is_full)
60 	{
61 		m_is_tablespace_full = is_full;
62 	}
63 
64 	/** Get tablespace full status
65 	@return true if table is full */
get_tablespace_full_status()66 	bool get_tablespace_full_status()
67 	{
68 		return(m_is_tablespace_full);
69 	}
70 
71 	/** Set sanity check status
72 	@param[in]	status	true if sanity checks are done */
set_sanity_check_status(bool status)73 	void set_sanity_check_status(bool status)
74 	{
75 		m_sanity_checks_done = status;
76 	}
77 
78 	/** Get sanity check status
79 	@return true if sanity checks are done */
get_sanity_check_status()80 	bool get_sanity_check_status()
81 	{
82 		return(m_sanity_checks_done);
83 	}
84 
85 	/** Parse the input params and populate member variables.
86 	@param	filepath	path to data files
87 	@param	supports_raw	true if it supports raw devices
88 	@return true on success parse */
89 	bool parse_params(const char* filepath, bool supports_raw);
90 
91 	/** Check the data file specification.
92 	@param[out]	create_new_db		true if a new database
93 	is to be created
94 	@param[in]	min_expected_size	expected tablespace
95 	size in bytes
96 	@return DB_SUCCESS if all OK else error code */
97 	dberr_t check_file_spec(
98 		bool*	create_new_db,
99 		ulint	min_expected_tablespace_size);
100 
101 	/** Free the memory allocated by parse() */
102 	void shutdown();
103 
104 	/** Normalize the file size, convert to extents. */
105 	void normalize_size();
106 
107 	/**
108 	@return true if a new raw device was created. */
created_new_raw()109 	bool created_new_raw() const
110 	{
111 		return(m_created_new_raw);
112 	}
113 
114 	/**
115 	@return auto_extend value setting */
can_auto_extend_last_file()116 	ulint can_auto_extend_last_file() const
117 	{
118 		return(m_auto_extend_last_file);
119 	}
120 
121 	/** Set the last file size.
122 	@param[in]	size	the size to set */
set_last_file_size(uint32_t size)123 	void set_last_file_size(uint32_t size)
124 	{
125 		ut_ad(!m_files.empty());
126 		m_files.back().m_size = size;
127 	}
128 
129 	/** Get the size of the last data file in the tablespace
130 	@return the size of the last data file in the array */
last_file_size()131 	uint32_t last_file_size() const
132 	{
133 		ut_ad(!m_files.empty());
134 		return(m_files.back().m_size);
135 	}
136 
137 	/**
138 	@return the autoextend increment in pages. */
get_autoextend_increment()139 	uint32_t get_autoextend_increment() const
140 	{
141 		return sys_tablespace_auto_extend_increment
142 			<< (20 - srv_page_size_shift);
143 	}
144 
145 	/**
146 	@return next increment size */
147 	uint32_t get_increment() const;
148 
149 	/** Open or create the data files
150 	@param[in]  is_temp		whether this is a temporary tablespace
151 	@param[in]  create_new_db	whether we are creating a new database
152 	@param[out] sum_new_sizes	sum of sizes of the new files added
153 	@param[out] flush_lsn		FIL_PAGE_FILE_FLUSH_LSN of first file
154 	@return DB_SUCCESS or error code */
155 	dberr_t open_or_create(
156 		bool	is_temp,
157 		bool	create_new_db,
158 		ulint*	sum_new_sizes,
159 		lsn_t*	flush_lsn)
160 		MY_ATTRIBUTE((warn_unused_result));
161 
162 private:
163 	/** Check the tablespace header for this tablespace.
164 	@param[out]	flushed_lsn	the value of FIL_PAGE_FILE_FLUSH_LSN
165 	@return DB_SUCCESS or error code */
166 	dberr_t read_lsn_and_check_flags(lsn_t* flushed_lsn);
167 
168 	/**
169 	@return true if the last file size is valid. */
is_valid_size()170 	bool is_valid_size() const
171 	{
172 		return(m_last_file_size_max >= last_file_size());
173 	}
174 
175 	/**
176 	@return true if configured to use raw devices */
177 	bool has_raw_device();
178 
179 	/** Note that the data file was not found.
180 	@param[in]	file		data file object
181 	@param[out]	create_new_db	true if a new instance to be created
182 	@return DB_SUCESS or error code */
183 	dberr_t file_not_found(Datafile& file, bool* create_new_db);
184 
185 	/** Note that the data file was found.
186 	@param[in,out]	file	data file object
187 	@return true if a new instance to be created */
188 	bool file_found(Datafile& file);
189 
190 	/** Create a data file.
191 	@param[in,out]	file	data file object
192 	@return DB_SUCCESS or error code */
193 	dberr_t create(Datafile& file);
194 
195 	/** Create a data file.
196 	@param[in,out]	file	data file object
197 	@return DB_SUCCESS or error code */
198 	dberr_t create_file(Datafile& file);
199 
200 	/** Open a data file.
201 	@param[in,out]	file	data file object
202 	@return DB_SUCCESS or error code */
203 	dberr_t open_file(Datafile& file);
204 
205 	/** Set the size of the file.
206 	@param[in,out]	file	data file object
207 	@return DB_SUCCESS or error code */
208 	dberr_t set_size(Datafile& file);
209 
210 	/** Convert a numeric string that optionally ends in G or M, to a
211 	number containing megabytes.
212 	@param[in]	ptr	string with a quantity in bytes
213 	@param[out]	megs	the number in megabytes
214 	@return next character in string */
215 	static char* parse_units(char* ptr, ulint* megs);
216 
217 private:
218 	enum file_status_t {
219 		FILE_STATUS_VOID = 0,		/** status not set */
220 		FILE_STATUS_RW_PERMISSION_ERROR,/** permission error */
221 		FILE_STATUS_READ_WRITE_ERROR,	/** not readable/writable */
222 		FILE_STATUS_NOT_REGULAR_FILE_ERROR /** not a regular file */
223 	};
224 
225 	/** Verify the size of the physical file
226 	@param[in]	file	data file object
227 	@return DB_SUCCESS if OK else error code. */
228 	dberr_t check_size(Datafile& file);
229 
230 	/** Check if a file can be opened in the correct mode.
231 	@param[in,out]	file	data file object
232 	@param[out]	reason	exact reason if file_status check failed.
233 	@return DB_SUCCESS or error code. */
234 	dberr_t check_file_status(
235 		const Datafile& 	file,
236 		file_status_t& 		reason);
237 
238 	/* DATA MEMBERS */
239 
240 	/** if true, then we auto-extend the last data file */
241 	bool		m_auto_extend_last_file;
242 
243 	/** maximum size of the last data file (0=unlimited) */
244 	ulint		m_last_file_size_max;
245 
246 	/** If the following is true we do not allow
247 	inserts etc. This protects the user from forgetting
248 	the 'newraw' keyword to my.cnf */
249 	bool		m_created_new_raw;
250 
251 	/** Tablespace full status */
252 	bool		m_is_tablespace_full;
253 
254 	/** if false, then sanity checks are still pending */
255 	bool		m_sanity_checks_done;
256 };
257 
258 /* GLOBAL OBJECTS */
259 
260 /** The control info of the system tablespace. */
261 extern SysTablespace srv_sys_space;
262 
263 /** The control info of a temporary table shared tablespace. */
264 extern SysTablespace srv_tmp_space;
265 
266 /** Check if the space_id is for a system-tablespace (shared + temp).
267 @param[in]	id	Space ID to check
268 @return true if id is a system tablespace, false if not. */
269 UNIV_INLINE
270 bool
is_system_tablespace(ulint id)271 is_system_tablespace(ulint	id)
272 {
273 	return(id == TRX_SYS_SPACE || id == SRV_TMP_SPACE_ID);
274 }
275 
276 /** Check if predefined shared tablespace.
277 @return true if predefined shared tablespace */
278 UNIV_INLINE
279 bool
is_predefined_tablespace(ulint id)280 is_predefined_tablespace(
281 	ulint   id)
282 {
283 	ut_ad(srv_sys_space.space_id() == TRX_SYS_SPACE);
284 	ut_ad(TRX_SYS_SPACE == 0);
285 	return(id == TRX_SYS_SPACE
286 	       || id == SRV_TMP_SPACE_ID
287 	       || srv_is_undo_tablespace(id));
288 }
289 #endif /* fsp0sysspace_h */
290