1/*****************************************************************************
2
3Copyright (c) 1995, 2020, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24
25*****************************************************************************/
26
27/** @file include/mtr0log.ic
28 Mini-transaction logging routines
29
30 Created 12/7/1995 Heikki Tuuri
31 *******************************************************/
32
33#include "buf0dblwr.h"
34#include "fsp0types.h"
35#include "mach0data.h"
36#include "trx0types.h"
37
38#include "mysqld_error.h"
39
40UNIV_INLINE
41bool mlog_open(mtr_t *mtr, ulint size, byte *&buffer) {
42  mtr->set_modified();
43  return (mlog_open_metadata(mtr, size, buffer));
44}
45
46UNIV_INLINE
47bool mlog_open_metadata(mtr_t *mtr, ulint size, byte *&buffer) {
48  if (mtr_get_log_mode(mtr) == MTR_LOG_NONE ||
49      mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) {
50    buffer = nullptr;
51    return (false);
52  }
53
54  buffer = mtr->get_log()->open(size);
55  return (buffer != nullptr);
56}
57
58/** Closes a buffer opened to mlog. */
59UNIV_INLINE
60void mlog_close(mtr_t *mtr, /*!< in: mtr */
61                byte *ptr)  /*!< in: buffer space from ptr up was not used */
62{
63  ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE);
64  ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NO_REDO);
65
66  mtr->get_log()->close(ptr);
67}
68
69/** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */
70UNIV_INLINE
71void mlog_catenate_ulint(mtr_buf_t *mtr_buf, /*!< in/out: buffer to write */
72                         ulint val,          /*!< in: value to write */
73                         mlog_id_t type)     /*!< in: type of value to write */
74{
75  ut_ad(MLOG_1BYTE == 1);
76  ut_ad(MLOG_2BYTES == 2);
77  ut_ad(MLOG_4BYTES == 4);
78  ut_ad(MLOG_8BYTES == 8);
79
80  byte *ptr = mtr_buf->push<byte *>(type);
81
82  switch (type) {
83    case MLOG_4BYTES:
84      mach_write_to_4(ptr, val);
85      break;
86    case MLOG_2BYTES:
87      mach_write_to_2(ptr, val);
88      break;
89    case MLOG_1BYTE:
90      mach_write_to_1(ptr, val);
91      break;
92    default:
93      ut_error;
94  }
95}
96
97/** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */
98UNIV_INLINE
99void mlog_catenate_ulint(
100    mtr_t *mtr,     /*!< in/out: mtr */
101    ulint val,      /*!< in: value to write */
102    mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
103{
104  if (mtr_get_log_mode(mtr) == MTR_LOG_NONE ||
105      mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) {
106    return;
107  }
108
109  mlog_catenate_ulint(mtr->get_log(), val, type);
110}
111
112/** Catenates a compressed ulint to mlog. */
113UNIV_INLINE
114void mlog_catenate_ulint_compressed(mtr_t *mtr, /*!< in: mtr */
115                                    ulint val)  /*!< in: value to write */
116{
117  byte *log_ptr = nullptr;
118
119  /* If no logging is requested, we may return now */
120  if (!mlog_open(mtr, 10, log_ptr)) {
121    return;
122  }
123
124  log_ptr += mach_write_compressed(log_ptr, val);
125
126  mlog_close(mtr, log_ptr);
127}
128
129/** Catenates a compressed 64-bit integer to mlog. */
130UNIV_INLINE
131void mlog_catenate_ull_compressed(mtr_t *mtr,      /*!< in: mtr */
132                                  ib_uint64_t val) /*!< in: value to write */
133{
134  byte *log_ptr = nullptr;
135
136  /* If no logging is requested, we may return now */
137  if (!mlog_open(mtr, 15, log_ptr)) {
138    return;
139  }
140
141  log_ptr += mach_u64_write_compressed(log_ptr, val);
142
143  mlog_close(mtr, log_ptr);
144}
145
146UNIV_INLINE
147byte *mlog_write_initial_dict_log_record(mlog_id_t type, table_id_t id,
148                                         uint64_t version, byte *log_ptr,
149                                         mtr_t *mtr) {
150  ut_ad(type <= MLOG_BIGGEST_TYPE);
151  ut_ad(type == MLOG_TABLE_DYNAMIC_META);
152
153  mach_write_to_1(log_ptr, type);
154  log_ptr++;
155
156  log_ptr += mach_u64_write_much_compressed(log_ptr, id);
157  log_ptr += mach_u64_write_much_compressed(log_ptr, version);
158
159  mtr->added_rec();
160  return (log_ptr);
161}
162
163/** Writes a log record about an operation.
164@param[in]	type		redo log record type
165@param[in]	space_id	tablespace identifier
166@param[in]	page_no		page number
167@param[in,out]	log_ptr		current end of mini-transaction log
168@param[in,out]	mtr		mini-transaction
169@return	end of mini-transaction log */
170UNIV_INLINE
171byte *mlog_write_initial_log_record_low(mlog_id_t type, space_id_t space_id,
172                                        page_no_t page_no, byte *log_ptr,
173                                        mtr_t *mtr) {
174  ut_ad(type <= MLOG_BIGGEST_TYPE);
175
176  mach_write_to_1(log_ptr, type);
177  log_ptr++;
178
179  log_ptr += mach_write_compressed(log_ptr, space_id);
180  log_ptr += mach_write_compressed(log_ptr, page_no);
181
182  mtr->added_rec();
183  return (log_ptr);
184}
185
186#ifndef UNIV_HOTBACKUP
187/** Writes the initial part of a log record (3..11 bytes).
188 If the implementation of this function is changed, all
189 size parameters to mlog_open() should be adjusted accordingly!
190 @return new value of log_ptr */
191UNIV_INLINE
192byte *mlog_write_initial_log_record_fast(
193    const byte *ptr, /*!< in: pointer to (inside) a buffer
194                     frame holding the file page where
195                     modification is made */
196    mlog_id_t type,  /*!< in: log item type: MLOG_1BYTE, ... */
197    byte *log_ptr,   /*!< in: pointer to mtr log which has
198                     been opened */
199    mtr_t *mtr)      /*!< in/out: mtr */
200{
201  const byte *page;
202  space_id_t space;
203  page_no_t offset;
204
205  ut_ad(log_ptr);
206  ut_d(mtr->memo_modify_page(ptr));
207
208  page = (const byte *)ut_align_down(ptr, UNIV_PAGE_SIZE);
209  space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
210  offset = mach_read_from_4(page + FIL_PAGE_OFFSET);
211
212  /* check whether the page is in the doublewrite buffer;
213  the doublewrite buffer is located in pages
214  FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
215  system tablespace */
216
217  /* We don't redo log the double write buffer */
218  if (space == TRX_SYS_SPACE && offset >= FSP_EXTENT_SIZE &&
219      offset < 3 * FSP_EXTENT_SIZE) {
220    return (log_ptr);
221  }
222
223  return (mlog_write_initial_log_record_low(type, space, offset, log_ptr, mtr));
224}
225#endif /* !UNIV_HOTBACKUP */
226