| 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 | |