1 /*****************************************************************************
2 
3 Copyright (c) 1997, 2021, Oracle and/or its affiliates.
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/read0types.h
29 Cursor read
30 
31 Created 2/16/1997 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef read0types_h
35 #define read0types_h
36 
37 #include <algorithm>
38 #include "dict0mem.h"
39 
40 #include "mem0mem.h"
41 #include "trx0types.h"
42 
43 // Friend declaration
44 class MVCC;
45 
46 /** Read view lists the trx ids of those transactions for which a consistent
47 read should not see the modifications to the database. */
48 
49 class ReadView {
50 	/** This is similar to a std::vector but it is not a drop
51 	in replacement. It is specific to ReadView. */
52 	class ids_t {
53 		typedef trx_ids_t::value_type value_type;
54 
55 		/**
56 		Constructor */
ids_t()57 		ids_t() : m_ptr(), m_size(), m_reserved() { }
58 
59 		/**
60 		Destructor */
~ids_t()61 		~ids_t() { UT_DELETE_ARRAY(m_ptr); }
62 
63 		/**
64 		Try and increase the size of the array. Old elements are
65 		copied across. It is a no-op if n is < current size.
66 
67 		@param n 		Make space for n elements */
68 		void reserve(ulint n);
69 
70 		/**
71 		Resize the array, sets the current element count.
72 		@param n		new size of the array, in elements */
resize(ulint n)73 		void resize(ulint n)
74 		{
75 			ut_ad(n <= capacity());
76 
77 			m_size = n;
78 		}
79 
80 		/**
81 		Reset the size to 0 */
clear()82 		void clear() { resize(0); }
83 
84 		/**
85 		@return the capacity of the array in elements */
capacity()86 		ulint capacity() const { return(m_reserved); }
87 
88 		/**
89 		Copy and overwrite the current array contents
90 
91 		@param start		Source array
92 		@param end		Pointer to end of array */
93 		void assign(const value_type* start, const value_type* end);
94 
95 		/**
96 		Insert the value in the correct slot, preserving the order.
97 		Doesn't check for duplicates. */
98 		void insert(value_type value);
99 
100 		/**
101 		@return the value of the first element in the array */
front()102 		value_type front() const
103 		{
104 			ut_ad(!empty());
105 
106 			return(m_ptr[0]);
107 		}
108 
109 		/**
110 		@return the value of the last element in the array */
back()111 		value_type back() const
112 		{
113 			ut_ad(!empty());
114 
115 			return(m_ptr[m_size - 1]);
116 		}
117 
118 		/**
119 		Append a value to the array.
120 		@param value		the value to append */
121 		void push_back(value_type value);
122 
123 		/**
124 		@return a pointer to the start of the array */
data()125 		trx_id_t* data() { return(m_ptr); };
126 
127 		/**
128 		@return a const pointer to the start of the array */
data()129 		const trx_id_t* data() const { return(m_ptr); };
130 
131 		/**
132 		@return the number of elements in the array */
size()133 		ulint size() const { return(m_size); }
134 
135 		/**
136 		@return true if size() == 0 */
empty()137 		bool empty() const { return(size() == 0); }
138 
139 	private:
140 		// Prevent copying
141 		ids_t(const ids_t&);
142 		ids_t& operator=(const ids_t&);
143 
144 	private:
145 		/** Memory for the array */
146 		value_type*	m_ptr;
147 
148 		/** Number of active elements in the array */
149 		ulint		m_size;
150 
151 		/** Size of m_ptr in elements */
152 		ulint		m_reserved;
153 
154 		friend class ReadView;
155 	};
156 public:
157 	ReadView();
158 	~ReadView();
159 	/** Check whether transaction id is valid.
160 	@param[in]	id		transaction id to check
161 	@param[in]	name		table name */
162 	static void check_trx_id_sanity(
163 		trx_id_t		id,
164 		const table_name_t&	name);
165 
166 	/** Check whether the changes by id are visible.
167 	@param[in]	id	transaction id to check against the view
168 	@param[in]	name	table name
169 	@return whether the view sees the modifications of id. */
changes_visible(trx_id_t id,const table_name_t & name)170 	bool changes_visible(
171 		trx_id_t		id,
172 		const table_name_t&	name) const
173 		MY_ATTRIBUTE((warn_unused_result))
174 	{
175 		ut_ad(id > 0);
176 
177 		if (id < m_up_limit_id || id == m_creator_trx_id) {
178 
179 			return(true);
180 		}
181 
182 		check_trx_id_sanity(id, name);
183 
184 		if (id >= m_low_limit_id) {
185 
186 			return(false);
187 
188 		} else if (m_ids.empty()) {
189 
190 			return(true);
191 		}
192 
193 		const ids_t::value_type*	p = m_ids.data();
194 
195 		return(!std::binary_search(p, p + m_ids.size(), id));
196 	}
197 
198 	/**
199 	@param id		transaction to check
200 	@return true if view sees transaction id */
sees(trx_id_t id)201 	bool sees(trx_id_t id) const
202 	{
203 		return(id < m_up_limit_id);
204 	}
205 
206 	/**
207 	Mark the view as closed */
close()208 	void close()
209 	{
210 		ut_ad(m_creator_trx_id != TRX_ID_MAX);
211 		m_creator_trx_id = TRX_ID_MAX;
212 		m_cloned = false;
213 	}
214 
215 	/**
216 	@return true if the view is closed */
is_closed()217 	bool is_closed() const
218 	{
219 		return(m_closed);
220 	}
221 
222 	/**
223 	Write the limits to the file.
224 	@param file		file to write to */
print_limits(FILE * file)225 	void print_limits(FILE* file) const
226 	{
227 		fprintf(file,
228 			"Trx read view will not see trx with"
229 			" id >= " TRX_ID_FMT ", sees < " TRX_ID_FMT "\n",
230 			m_low_limit_id, m_up_limit_id);
231 	}
232 
233 	/**
234 	@return the low limit no */
low_limit_no()235 	trx_id_t low_limit_no() const
236 	{
237 		return(m_low_limit_no);
238 	}
239 
240 	/**
241 	@return the low limit id */
low_limit_id()242 	trx_id_t low_limit_id() const
243 	{
244 		return(m_low_limit_id);
245 	}
246 
247 	/**
248 	@return true if there are no transaction ids in the snapshot */
empty()249 	bool empty() const
250 	{
251 		return(m_ids.empty());
252 	}
253 
254 	/**
255 	Clones a read view object. The resulting read view has identical change
256 	visibility as the donor read view
257 	@param	result	pointer to resulting read view. If NULL, a view will be
258 	allocated. If non-NULL, a view will overwrite a previously-existing
259 	in-use or released view.
260 	@param	from_trx	transation owning the donor read view. */
261 
262 	void clone(ReadView*& result, trx_t* from_trx) const;
263 
264 #ifdef UNIV_DEBUG
265 	/**
266 	@param rhs		view to compare with
267 	@return truen if this view is less than or equal rhs */
le(const ReadView * rhs)268 	bool le(const ReadView* rhs) const
269 	{
270 		return(m_low_limit_no <= rhs->m_low_limit_no);
271 	}
272 #endif /* UNIV_DEBUG */
273 
up_limit_id()274 	trx_id_t up_limit_id() const
275 	{
276 		return(m_up_limit_id);
277 	}
278 
print(FILE * file)279 	void print(FILE* file) const
280 	{
281 		fprintf(file, "Read view low limit trx n:o " TRX_ID_FMT "\n",
282 			low_limit_no());
283 		print_limits(file);
284 		fprintf(file, "Read view individually stored trx ids:\n");
285 		for (ulint i = 0; i < m_ids.size(); i++) {
286 			fprintf(file, "Read view trx id " TRX_ID_FMT "\n",
287 				m_ids.data()[i]);
288 		}
289 	}
290 
is_cloned()291 	bool is_cloned() const
292 	{
293 		return(m_cloned);
294 	}
295 
296 private:
297 	/**
298 	Copy the transaction ids from the source vector */
299 	inline void copy_trx_ids(const trx_ids_t& trx_ids);
300 
301 	/**
302 	Opens a read view where exactly the transactions serialized before this
303 	point in time are seen in the view.
304 	@param id		Creator transaction id */
305 	inline void prepare(trx_id_t id);
306 
307 	/**
308 	Complete the read view creation */
309 	inline void complete();
310 
311 	/**
312 	Copy state from another view. Must call copy_complete() to finish.
313 	@param other		view to copy from */
314 	inline void copy_prepare(const ReadView& other);
315 
316 	/**
317 	Complete the copy, insert the creator transaction id into the
318 	m_trx_ids too and adjust the m_up_limit_id *, if required */
319 	inline void copy_complete();
320 
321 	/**
322 	Set the creator transaction id, existing id must be 0 */
creator_trx_id(trx_id_t id)323 	void creator_trx_id(trx_id_t id)
324 	{
325 		ut_ad(m_creator_trx_id == 0);
326 		m_creator_trx_id = id;
327 	}
328 
329 	friend class MVCC;
330 
331 private:
332 	// Disable copying
333 	ReadView(const ReadView&);
334 	ReadView& operator=(const ReadView&);
335 
336 private:
337 	/** The read should not see any transaction with trx id >= this
338 	value. In other words, this is the "high water mark". */
339 	trx_id_t	m_low_limit_id;
340 
341 	/** The read should see all trx ids which are strictly
342 	smaller (<) than this value.  In other words, this is the
343 	low water mark". */
344 	trx_id_t	m_up_limit_id;
345 
346 	/** trx id of creating transaction, set to TRX_ID_MAX for free
347 	views. */
348 	trx_id_t	m_creator_trx_id;
349 
350 	/** Set of RW transactions that was active when this snapshot
351 	was taken */
352 	ids_t		m_ids;
353 
354 	/** The view does not need to see the undo logs for transactions
355 	whose transaction number is strictly smaller (<) than this value:
356 	they can be removed in purge if not needed by other views */
357 	trx_id_t	m_low_limit_no;
358 
359 	/** AC-NL-RO transaction view that has been "closed". */
360 	bool		m_closed;
361 
362 	/** This is a view cloned by clone but not by
363 	MVCC::clone_oldest_view. Used to make sure the cloned transaction does
364 	not see its own changes. */
365 	bool		m_cloned;
366 
367 	typedef UT_LIST_NODE_T(ReadView) node_t;
368 
369 	/** List of read views in trx_sys */
370 	byte		pad1[64 - sizeof(node_t)];
371 	node_t		m_view_list;
372 };
373 
374 #endif
375