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