1 /***************************************************************************** 2 3 Copyright (c) 2016, 2019, 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 lob0ins_h 27 #define lob0ins_h 28 29 #include "lob0lob.h" 30 31 namespace lob { 32 33 /** This struct can hold BLOB routines/functions, and state variables, 34 that are common for compressed and uncompressed BLOB. */ 35 struct BaseInserter { 36 /** Constructor. 37 @param[in] ctx blob operation context. */ BaseInserterBaseInserter38 BaseInserter(InsertContext *ctx) 39 : m_ctx(ctx), 40 m_err(DB_SUCCESS), 41 m_prev_page_no(ctx->get_page_no()), 42 m_cur_blob_block(nullptr), 43 m_cur_blob_page_no(FIL_NULL) {} 44 45 /** Start the BLOB mtr. 46 @return pointer to the BLOB mtr. */ start_blob_mtrBaseInserter47 mtr_t *start_blob_mtr() { 48 mtr_start(&m_blob_mtr); 49 m_blob_mtr.set_log_mode(m_ctx->get_log_mode()); 50 m_blob_mtr.set_flush_observer(m_ctx->get_flush_observer()); 51 return (&m_blob_mtr); 52 } 53 54 /** Allocate one BLOB page. 55 @return the allocated block of the BLOB page. */ 56 buf_block_t *alloc_blob_page(); 57 58 /** Get the previous BLOB page frame. This will return a BLOB page. 59 It should not be called for the first BLOB page, because it will not 60 have a previous BLOB page. 61 @return the previous BLOB page frame. */ 62 page_t *get_previous_blob_page(); 63 64 /** Get the previous BLOB page block. This will return a BLOB block. 65 It should not be called for the first BLOB page, because it will not 66 have a previous BLOB page. 67 @return the previous BLOB block. */ 68 buf_block_t *get_previous_blob_block(); 69 70 /** Check if the index is SDI index 71 @return true if index is SDI index else false */ is_index_sdiBaseInserter72 bool is_index_sdi() { return (dict_index_is_sdi(m_ctx->index())); } 73 74 /** Get the current BLOB page frame. 75 @return the current BLOB page frame. */ cur_pageBaseInserter76 page_t *cur_page() const { return (buf_block_get_frame(m_cur_blob_block)); } 77 78 protected: 79 /** The BLOB operation context */ 80 InsertContext *m_ctx; 81 82 /** Success or failure status of the operation so far. */ 83 dberr_t m_err; 84 85 /** The mini trx used to write into blob pages */ 86 mtr_t m_blob_mtr; 87 88 /** The previous BLOB page number. This is needed to maintain 89 the linked list of BLOB pages. */ 90 page_no_t m_prev_page_no; 91 92 /** The current BLOB buf_block_t object. */ 93 buf_block_t *m_cur_blob_block; 94 95 /** The current BLOB page number. */ 96 page_no_t m_cur_blob_page_no; 97 }; 98 99 /** Insert or write an uncompressed BLOB */ 100 class Inserter : private BaseInserter { 101 public: 102 /** Constructor. 103 @param[in] ctx blob operation context. */ Inserter(InsertContext * ctx)104 Inserter(InsertContext *ctx) : BaseInserter(ctx) {} 105 106 /** Destructor. */ ~Inserter()107 ~Inserter() {} 108 109 /** Write all the BLOBs of the clustered index record. 110 @return DB_SUCCESS on success, error code on failure. */ 111 dberr_t write(); 112 113 /** Write one blob field data. 114 @param[in] blob_j the blob field number 115 @return DB_SUCCESS on success, error code on failure. */ 116 dberr_t write_one_blob(size_t blob_j); 117 118 /** Write one blob field data. 119 @param[in] blob_j the blob field number 120 @return DB_SUCCESS on success, error code on failure. */ 121 dberr_t write_one_small_blob(size_t blob_j); 122 123 /** Write one blob page. This function will be repeatedly called 124 with an increasing nth_blob_page to completely write a BLOB. 125 @param[in] blob_j the jth blob object of the record. 126 @param[in] field the big record field. 127 @param[in] nth_blob_page count of the BLOB page (starting from 1). 128 @return DB_SUCCESS or DB_FAIL. */ 129 dberr_t write_single_blob_page(size_t blob_j, big_rec_field_t &field, 130 ulint nth_blob_page); 131 132 /** Check if the BLOB operation has reported any errors. 133 @return true if BLOB operation is successful, false otherwise. */ is_ok()134 bool is_ok() const { return (m_err == DB_SUCCESS); } 135 136 /** Make the current page as next page of previous page. In other 137 words, make the page m_cur_blob_page_no as the next page of page 138 m_prev_page_no. */ 139 void set_page_next(); 140 141 /** Write the page type of the current BLOB page and also generate the 142 redo log record. */ log_page_type()143 void log_page_type() { 144 page_type_t page_type; 145 page_t *blob_page = cur_page(); 146 147 if (is_index_sdi()) { 148 page_type = FIL_PAGE_SDI_BLOB; 149 } else { 150 page_type = FIL_PAGE_TYPE_BLOB; 151 } 152 153 mlog_write_ulint(blob_page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES, 154 &m_blob_mtr); 155 } 156 157 /** Calculate the payload size of the BLOB page. 158 @return payload size in bytes. */ payload()159 ulint payload() const { 160 const page_size_t page_size = m_ctx->page_size(); 161 const ulint payload_size = 162 page_size.physical() - FIL_PAGE_DATA - LOB_HDR_SIZE - FIL_PAGE_DATA_END; 163 return (payload_size); 164 } 165 166 /** Write contents into a single BLOB page. 167 @param[in] field the big record field. */ 168 void write_into_single_page(big_rec_field_t &field); 169 170 /** Write first blob page. 171 @param[in] blob_j the jth blob object of the record. 172 @param[in] field the big record field. 173 @return DB_SUCCESS on success. */ 174 dberr_t write_first_page(size_t blob_j, big_rec_field_t &field); 175 176 private: 177 /** The BLOB directory information. */ 178 blob_dir_t m_dir; 179 180 /** Data remaining to be written. */ 181 ulint m_remaining; 182 }; 183 184 } // namespace lob 185 186 #endif /* lob0ins_h */ 187