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