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