1 /***************************************************************************** 2 3 Copyright (c) 2016, 2018, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License, version 2.0, as published by the 7 Free Software Foundation. 8 9 This program is also distributed with certain software (including but not 10 limited to OpenSSL) that is licensed under separate terms, as designated in a 11 particular file or component or in included license documentation. The authors 12 of MySQL hereby grant you an additional permission to link the program and 13 your derivative works with the separately licensed software that they have 14 included with MySQL. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19 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 St, Fifth Floor, Boston, MA 02110-1301 USA 24 25 *****************************************************************************/ 26 #ifndef lob0pages_h 27 #define lob0pages_h 28 29 #include "lob0first.h" 30 31 namespace lob { 32 33 /** The LOB data page carrying the user data. */ 34 struct data_page_t : public basic_page_t { 35 static const ulint OFFSET_VERSION = FIL_PAGE_DATA; 36 static const ulint OFFSET_DATA_LEN = OFFSET_VERSION + 1; 37 static const ulint OFFSET_TRX_ID = OFFSET_DATA_LEN + 4; 38 static const ulint LOB_PAGE_DATA = OFFSET_TRX_ID + 6; 39 data_page_tdata_page_t40 data_page_t() {} 41 42 /** Contructor. */ data_page_tdata_page_t43 data_page_t(buf_block_t *block, mtr_t *mtr) : basic_page_t(block, mtr) { 44 page_type_t type = get_page_type(); 45 ut_a(type == FIL_PAGE_TYPE_LOB_DATA); 46 } 47 data_page_tdata_page_t48 data_page_t(buf_block_t *block, mtr_t *mtr, dict_index_t *index) 49 : basic_page_t(block, mtr, index) {} 50 data_page_tdata_page_t51 data_page_t(mtr_t *mtr, dict_index_t *index) 52 : basic_page_t(nullptr, mtr, index) {} 53 54 /** Constructor. 55 @param[in] block the buffer block.*/ data_page_tdata_page_t56 data_page_t(buf_block_t *block) : basic_page_t(block, nullptr, nullptr) {} 57 58 /** Allocate an LOB data page. 59 * @param[in] alloc_mtr the mini transaction to be used for 60 * allocation of LOB page. 61 * @param[in] is_bulk true if bulk operation. 62 * @return allocated buffer block or nullptr */ 63 buf_block_t *alloc(mtr_t *alloc_mtr, bool is_bulk); 64 65 buf_block_t *load_x(page_no_t page_no); 66 set_version_0data_page_t67 void set_version_0() { 68 mlog_write_ulint(frame() + OFFSET_VERSION, 0, MLOG_1BYTE, m_mtr); 69 } 70 deallocdata_page_t71 void dealloc() { 72 btr_page_free_low(m_index, m_block, ULINT_UNDEFINED, m_mtr); 73 m_block = nullptr; 74 } 75 set_page_typedata_page_t76 void set_page_type() { 77 ut_ad(m_mtr != nullptr); 78 79 mlog_write_ulint(frame() + FIL_PAGE_TYPE, FIL_PAGE_TYPE_LOB_DATA, 80 MLOG_2BYTES, m_mtr); 81 } 82 set_trx_iddata_page_t83 void set_trx_id(trx_id_t id) { 84 byte *ptr = frame() + OFFSET_TRX_ID; 85 mach_write_to_6(ptr, id); 86 mlog_log_string(ptr, 6, m_mtr); 87 } 88 89 /** Write the trx identifier to the header, without 90 generating redo log. 91 @param[in] id the transaction identifier.*/ set_trx_id_no_redodata_page_t92 void set_trx_id_no_redo(trx_id_t id) { 93 byte *ptr = frame() + OFFSET_TRX_ID; 94 mach_write_to_6(ptr, id); 95 } 96 payloaddata_page_t97 static ulint payload() { 98 return (UNIV_PAGE_SIZE - LOB_PAGE_DATA - FIL_PAGE_DATA_END); 99 } 100 data_begindata_page_t101 byte *data_begin() const { return (frame() + LOB_PAGE_DATA); } 102 103 /** Create a new data page and replace some or all parts of the old data 104 with data. 105 @param[in] trx the current transaction. 106 @param[in] offset the offset where replace begins. 107 @param[in,out] ptr pointer to new data. 108 @param[in] want amount of data the caller wants to replace. 109 @param[in] mtr the mini transaction context. 110 @return the buffer block of the new data page. */ 111 buf_block_t *replace(trx_t *trx, ulint offset, const byte *&ptr, ulint &want, 112 mtr_t *mtr); 113 114 /** Replace some or all parts of the data inline. 115 @param[in] trx the current transaction. 116 @param[in] offset the offset where replace begins. 117 @param[in,out] ptr pointer to new data. 118 @param[in] want amount of data the caller wants to replace. 119 @param[in] mtr the mini transaction context. */ 120 void replace_inline(trx_t *trx, ulint offset, const byte *&ptr, ulint &want, 121 mtr_t *mtr); 122 get_data_lendata_page_t123 ulint get_data_len() const { 124 return (mach_read_from_4(frame() + OFFSET_DATA_LEN)); 125 } 126 set_data_lendata_page_t127 void set_data_len(ulint len) { 128 ut_ad(m_mtr != nullptr); 129 130 mlog_write_ulint(frame() + OFFSET_DATA_LEN, len, MLOG_4BYTES, m_mtr); 131 } 132 133 /** Read data from the data page. 134 @param[in] offset read begins at this offset. 135 @param[out] ptr the output buffer. 136 @param[in] want bytes to read 137 @return bytes actually read. */ 138 ulint read(ulint offset, byte *ptr, ulint want); 139 140 /** Write data into a data page. 141 @param[in] trxid the transaction identifier of the session 142 writing data. 143 @param[in,out] data the data to be written. it will be updated 144 to point to the byte not yet written. 145 @param[in,out] len length of data to be written. 146 @return amount of data actually written into the page. */ 147 ulint write(trx_id_t trxid, const byte *&data, ulint &len); 148 149 /** Append given data in data page. 150 @param[in] trxid transaction doing append. 151 @param[in,out] data data to be appended. 152 @param[in,out] len length of data. 153 @return number of bytes appended. */ 154 ulint append(trx_id_t trxid, byte *&data, ulint &len); 155 156 std::pair<ulint, byte *> insert_middle(trx_t *trx, ulint offset, byte *&data, 157 ulint &len, buf_block_t *&new_block); 158 159 buf_block_t *remove_middle(trx_t *trx, ulint offset, ulint &len); 160 max_space_availabledata_page_t161 ulint max_space_available() const { return (payload()); } 162 163 ulint space_left() const; 164 }; 165 166 } /* namespace lob */ 167 168 #endif /* lob0pages_h */ 169