1 /*****************************************************************************
2 
3 Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2018, 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/lock0prdt.h
22 The predicate lock system
23 
24 Created 9/7/2013 Jimmy Yang
25 *******************************************************/
26 #ifndef lock0prdt_h
27 #define lock0prdt_h
28 
29 #include "lock0lock.h"
30 
31 /* Predicate lock data */
32 typedef struct lock_prdt {
33 	void*		data;		/* Predicate data */
34 	uint16		op;		/* Predicate operator */
35 } lock_prdt_t;
36 
37 /*********************************************************************//**
38 Acquire a predicate lock on a block
39 @return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
40 dberr_t
41 lock_prdt_lock(
42 /*===========*/
43 	buf_block_t*	block,	/*!< in/out: buffer block of rec */
44 	lock_prdt_t*	prdt,	/*!< in: Predicate for the lock */
45 	dict_index_t*	index,	/*!< in: secondary index */
46 	enum lock_mode	mode,	/*!< in: mode of the lock which
47 				the read cursor should set on
48 				records: LOCK_S or LOCK_X; the
49 				latter is possible in
50 				SELECT FOR UPDATE */
51 	ulint		type_mode,
52 				/*!< in: LOCK_PREDICATE or LOCK_PRDT_PAGE */
53 	que_thr_t*	thr);	/*!< in: query thread
54 				(can be NULL if BTR_NO_LOCKING_FLAG) */
55 
56 /*********************************************************************//**
57 Acquire a "Page" lock on a block
58 @return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
59 dberr_t
60 lock_place_prdt_page_lock(
61 /*======================*/
62 	ulint		space,	/*!< in: space for the page to lock */
63 	ulint		pageno,	/*!< in: page number */
64 	dict_index_t*	index,	/*!< in: secondary index */
65 	que_thr_t*	thr);	/*!< in: query thread */
66 
67 /*********************************************************************//**
68 Initiate a Predicate lock from a MBR */
69 void
70 lock_init_prdt_from_mbr(
71 /*====================*/
72 	lock_prdt_t*	prdt,	/*!< in/out: predicate to initialized */
73 	rtr_mbr_t*	mbr,	/*!< in: Minimum Bounding Rectangle */
74 	ulint		mode,	/*!< in: Search mode */
75 	mem_heap_t*	heap);	/*!< in: heap for allocating memory */
76 
77 /*********************************************************************//**
78 Get predicate lock's minimum bounding box
79 @return the minimum bounding box*/
80 lock_prdt_t*
81 lock_get_prdt_from_lock(
82 /*====================*/
83 	const lock_t*	lock);	/*!< in: the lock */
84 
85 /*********************************************************************//**
86 Checks if a predicate lock request for a new lock has to wait for
87 request lock2.
88 @return true if new lock has to wait for lock2 to be removed */
89 bool
90 lock_prdt_has_to_wait(
91 /*==================*/
92 	const trx_t*	trx,	/*!< in: trx of new lock */
93 	ulint		type_mode,/*!< in: precise mode of the new lock
94 				to set: LOCK_S or LOCK_X, possibly
95 				ORed to LOCK_PREDICATE or LOCK_PRDT_PAGE,
96 				LOCK_INSERT_INTENTION */
97 	lock_prdt_t*	prdt,	/*!< in: lock predicate to check */
98 	const lock_t*	lock2);	/*!< in: another record lock; NOTE that
99 				it is assumed that this has a lock bit
100 				set on the same record as in the new
101 				lock we are setting */
102 
103 /**************************************************************//**
104 Update predicate lock when page splits */
105 void
106 lock_prdt_update_split(
107 /*===================*/
108 	buf_block_t*	new_block,	/*!< in/out: the new half page */
109 	lock_prdt_t*	prdt,		/*!< in: MBR on the old page */
110 	lock_prdt_t*	new_prdt,	/*!< in: MBR on the new page */
111 	ulint		space,		/*!< in: space id */
112 	ulint		page_no);	/*!< in: page number */
113 
114 /**************************************************************//**
115 Ajust locks from an ancester page of Rtree on the appropriate level . */
116 void
117 lock_prdt_update_parent(
118 /*====================*/
119 	buf_block_t*	left_block,	/*!< in/out: page to be split */
120 	buf_block_t*	right_block,	/*!< in/out: the new half page */
121 	lock_prdt_t*	left_prdt,	/*!< in: MBR on the old page */
122 	lock_prdt_t*	right_prdt,	/*!< in: MBR on the new page */
123 	ulint		space,		/*!< in: space id */
124 	ulint		page_no);	/*!< in: page number */
125 
126 /*********************************************************************//**
127 Checks if locks of other transactions prevent an immediate insert of
128 a predicate record.
129 @return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
130 dberr_t
131 lock_prdt_insert_check_and_lock(
132 /*============================*/
133 	ulint		flags,	/*!< in: if BTR_NO_LOCKING_FLAG bit is
134 				set, does nothing */
135 	const rec_t*	rec,	/*!< in: record after which to insert */
136 	buf_block_t*	block,	/*!< in/out: buffer block of rec */
137 	dict_index_t*	index,	/*!< in: index */
138 	que_thr_t*	thr,	/*!< in: query thread */
139 	mtr_t*		mtr,	/*!< in/out: mini-transaction */
140 	lock_prdt_t*	prdt);	/*!< in: Minimum Bound Rectangle */
141 
142 /*********************************************************************//**
143 Append a predicate to the lock */
144 void
145 lock_prdt_set_prdt(
146 /*===============*/
147 	lock_t*			lock,	/*!< in: lock */
148 	const lock_prdt_t*	prdt);	/*!< in: Predicate */
149 
150 #if 0
151 
152 /*********************************************************************//**
153 Checks if a predicate lock request for a new lock has to wait for
154 request lock2.
155 @return true if new lock has to wait for lock2 to be removed */
156 UNIV_INLINE
157 bool
158 lock_prdt_has_to_wait(
159 /*==================*/
160 	const trx_t*	trx,	/*!< in: trx of new lock */
161 	ulint		type_mode,/*!< in: precise mode of the new lock
162 				to set: LOCK_S or LOCK_X, possibly
163 				ORed to LOCK_PREDICATE or LOCK_PRDT_PAGE,
164 				LOCK_INSERT_INTENTION */
165 	lock_prdt_t*	prdt,	/*!< in: lock predicate to check */
166 	const lock_t*	lock2);	/*!< in: another record lock; NOTE that
167 				it is assumed that this has a lock bit
168 				set on the same record as in the new
169 				lock we are setting */
170 
171 /*********************************************************************//**
172 Get predicate lock's minimum bounding box
173 @return the minimum bounding box*/
174 UNIV_INLINE
175 rtr_mbr_t*
176 prdt_get_mbr_from_prdt(
177 /*===================*/
178 	const lock_prdt_t*	prdt);	/*!< in: the lock predicate */
179 
180 
181 #endif
182 /*************************************************************//**
183 Moves the locks of a record to another record and resets the lock bits of
184 the donating record. */
185 void
186 lock_prdt_rec_move(
187 /*===============*/
188 	const buf_block_t*	receiver,	/*!< in: buffer block containing
189 						the receiving record */
190 	const buf_block_t*	donator);	/*!< in: buffer block containing
191 						the donating record */
192 
193 /** Check whether there are R-tree Page lock on a buffer page
194 @param[in]	trx	trx to test the lock
195 @param[in]	space	space id for the page
196 @param[in]	page_no	page number
197 @return true if there is none */
198 bool
199 lock_test_prdt_page_lock(
200 /*=====================*/
201 	const trx_t*	trx,
202 	ulint		space,
203 	ulint		page_no);
204 
205 /** Removes predicate lock objects set on an index page which is discarded.
206 @param[in]	block		page to be discarded
207 @param[in]	lock_hash	lock hash */
208 void
209 lock_prdt_page_free_from_discard(
210 /*=============================*/
211 	const buf_block_t*	block,
212 	hash_table_t*		lock_hash);
213 
214 #endif
215