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 lob0util_h
27 #define lob0util_h
28 
29 #include <stdint.h>
30 
31 #include "buf0buf.h"
32 #include "fil0fil.h"
33 #include "fut0lst.h"
34 
35 namespace lob {
36 
37 /** Number of times an LOB can be partially updated.  Once this limit is
38 reached, then the LOB will be fully updated. */
39 const uint32_t MAX_PARTIAL_UPDATE_LIMIT = 1000;
40 
41 struct basic_page_t {
basic_page_tbasic_page_t42   basic_page_t() : m_block(nullptr), m_mtr(nullptr), m_index(nullptr) {}
43 
basic_page_tbasic_page_t44   basic_page_t(buf_block_t *block, mtr_t *mtr)
45       : m_block(block), m_mtr(mtr), m_index(nullptr) {}
46 
basic_page_tbasic_page_t47   basic_page_t(buf_block_t *block, mtr_t *mtr, dict_index_t *index)
48       : m_block(block), m_mtr(mtr), m_index(index) {}
49 
50   /** Update the space identifier to given value without generating
51   any redo log records.
52   @param[in]	space_id	the space identifier. */
set_space_id_no_redobasic_page_t53   void set_space_id_no_redo(space_id_t space_id) {
54     mach_write_to_4(frame() + FIL_PAGE_SPACE_ID, space_id);
55   }
56 
57   /** Get page number of the current page.
58   @return the page number of the current page. */
get_page_nobasic_page_t59   page_no_t get_page_no() const {
60     ut_ad(m_block != nullptr);
61     return (m_block->page.id.page_no());
62   }
63 
64   /** Get the page id of the current page.
65   @return the page id of current page. */
get_page_idbasic_page_t66   page_id_t get_page_id() const {
67     ut_ad(m_block != nullptr);
68     return (m_block->page.id);
69   }
70 
71   /** Set the FIL_PAGE_NEXT to the given page number, using the given mini
72   transaction context.
73   @param[in]    page_no   The page number to set.
74   @param[in]    mtr       The mini transaction context. */
set_next_pagebasic_page_t75   void set_next_page(page_no_t page_no, mtr_t *mtr) {
76     mlog_write_ulint(frame() + FIL_PAGE_NEXT, page_no, MLOG_4BYTES, mtr);
77   }
78 
79   /** Set the FIL_PAGE_NEXT to the given page number.
80   @param[in]    page_no   The page number to set. */
set_next_pagebasic_page_t81   void set_next_page(page_no_t page_no) { set_next_page(page_no, m_mtr); }
82 
83   /** Set the FIL_PAGE_NEXT to FIL_NULL. */
set_next_page_nullbasic_page_t84   void set_next_page_null() {
85     ut_ad(m_mtr != nullptr);
86 
87     set_next_page(FIL_NULL);
88   }
89 
get_next_pagebasic_page_t90   page_no_t get_next_page() {
91     return (mach_read_from_4(frame() + FIL_PAGE_NEXT));
92   }
93 
get_page_typebasic_page_t94   page_type_t get_page_type() const {
95     return (mach_read_from_2(frame() + FIL_PAGE_TYPE));
96   }
97 
framebasic_page_t98   byte *frame() const { return (buf_block_get_frame(m_block)); }
99 
get_flst_nodebasic_page_t100   flst_node_t *get_flst_node(const fil_addr_t &addr) {
101     ut_ad(!addr.is_null());
102 
103     flst_node_t *node = nullptr;
104     if (addr.page == get_page_no()) {
105       node = frame() + addr.boffset;
106     }
107     return (node);
108   }
109 
110   static ulint payload();
111   ulint max_space_available();
112 
set_blockbasic_page_t113   void set_block(buf_block_t *block) {
114     ut_ad(mtr_memo_contains(m_mtr, block, MTR_MEMO_PAGE_X_FIX) ||
115           mtr_memo_contains(m_mtr, block, MTR_MEMO_PAGE_S_FIX));
116 
117     m_block = block;
118   }
119 
set_mtrbasic_page_t120   void set_mtr(mtr_t *mtr) { m_mtr = mtr; }
121 
122  protected:
123   buf_block_t *m_block;
124   mtr_t *m_mtr;
125   dict_index_t *m_index;
126 };
127 
128 /** Allocate one LOB page.
129 @param[in]	index	the index in which LOB exists.
130 @param[in]	lob_mtr	the mini-transaction context.
131 @param[in]	hint	the hint page number for allocation.
132 @param[in]	bulk	true if operation is OPCODE_INSERT_BULK,
133                         false otherwise.
134 @return the allocated block of the BLOB page. */
135 buf_block_t *alloc_lob_page(dict_index_t *index, mtr_t *lob_mtr, page_no_t hint,
136                             bool bulk);
137 
138 /** Check if the index entry is visible to the given transaction.
139 @param[in]	index		the index to which LOB belongs.
140 @param[in]	trx		the transaction reading the index entry.
141 @param[in]	entry_trx_id	the trx id in the index entry. */
142 bool entry_visible_to(dict_index_t *index, trx_t *trx, trx_id_t entry_trx_id);
143 
144 } /* namespace lob */
145 
146 #endif /* lob0util_h */
147