1/******************************************************
2XtraBackup: hot backup tool for InnoDB
3(c) 2009-2012 Percona Inc.
4Originally Created 3/3/2009 Yasufumi Kinoshita
5Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; version 2 of the License.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20
21*******************************************************/
22
23/* Data file read filter implementation */
24
25#include "read_filt.h"
26#include "common.h"
27#include "fil_cur.h"
28#include "xtrabackup.h"
29
30/****************************************************************//**
31Perform read filter context initialization that is common to all read
32filters. */
33static
34void
35common_init(
36/*========*/
37 xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter context */
38 const xb_fil_cur_t* cursor) /*!<in: file cursor */
39{
40 ctxt->offset = 0;
41 ctxt->data_file_size = cursor->statinfo.st_size;
42 ctxt->buffer_capacity = cursor->buf_size;
43 ctxt->page_size = cursor->page_size;
44}
45
46/****************************************************************//**
47Initialize the pass-through read filter. */
48static
49void
50rf_pass_through_init(
51/*=================*/
52 xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter context */
53 const xb_fil_cur_t* cursor, /*!<in: file cursor */
54 ulint space_id __attribute__((unused)))
55 /*!<in: space id we are reading */
56{
57 common_init(ctxt, cursor);
58}
59
60/****************************************************************//**
61Get the next batch of pages for the pass-through read filter. */
62static
63void
64rf_pass_through_get_next_batch(
65/*===========================*/
66 xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
67 context */
68 ib_int64_t* read_batch_start, /*!<out: starting read
69 offset in bytes for the
70 next batch of pages */
71 ib_int64_t* read_batch_len) /*!<out: length in
72 bytes of the next batch
73 of pages */
74{
75 *read_batch_start = ctxt->offset;
76 *read_batch_len = ctxt->data_file_size - ctxt->offset;
77
78 if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) {
79 *read_batch_len = ctxt->buffer_capacity;
80 }
81
82 ctxt->offset += *read_batch_len;
83}
84
85/****************************************************************//**
86Deinitialize the pass-through read filter. */
87static
88void
89rf_pass_through_deinit(
90/*===================*/
91 xb_read_filt_ctxt_t* ctxt __attribute__((unused)))
92 /*!<in: read filter context */
93{
94}
95
96/****************************************************************//**
97Initialize the changed page bitmap-based read filter. Assumes that
98the bitmap is already set up in changed_page_bitmap. */
99static
100void
101rf_bitmap_init(
102/*===========*/
103 xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
104 context */
105 const xb_fil_cur_t* cursor, /*!<in: read cursor */
106 ulint space_id) /*!<in: space id */
107{
108 common_init(ctxt, cursor);
109 ctxt->bitmap_range = xb_page_bitmap_range_init(changed_page_bitmap,
110 space_id);
111 ctxt->filter_batch_end = 0;
112}
113
114/****************************************************************//**
115Get the next batch of pages for the bitmap read filter. */
116static
117void
118rf_bitmap_get_next_batch(
119/*=====================*/
120 xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
121 context */
122 ib_int64_t* read_batch_start, /*!<out: starting read
123 offset in bytes for the
124 next batch of pages */
125 ib_int64_t* read_batch_len) /*!<out: length in
126 bytes of the next batch
127 of pages */
128{
129 ulint start_page_id;
130 const ulint page_size = ctxt->page_size.physical();
131
132 start_page_id = (ulint)(ctxt->offset / page_size);
133
134 xb_a (ctxt->offset % page_size == 0);
135
136 if (start_page_id == ctxt->filter_batch_end) {
137
138 /* Used up all the previous bitmap range, get some more */
139 ulint next_page_id;
140
141 /* Find the next changed page using the bitmap */
142 next_page_id = xb_page_bitmap_range_get_next_bit
143 (ctxt->bitmap_range, TRUE);
144
145 if (next_page_id == ULINT_UNDEFINED) {
146 *read_batch_len = 0;
147 return;
148 }
149
150 ctxt->offset = next_page_id * page_size;
151
152 /* Find the end of the current changed page block by searching
153 for the next cleared bitmap bit */
154 ctxt->filter_batch_end
155 = xb_page_bitmap_range_get_next_bit(ctxt->bitmap_range,
156 FALSE);
157 xb_a(next_page_id < ctxt->filter_batch_end);
158 }
159
160 *read_batch_start = ctxt->offset;
161 if (ctxt->filter_batch_end == ULINT_UNDEFINED) {
162 /* No more cleared bits in the bitmap, need to copy all the
163 remaining pages. */
164 *read_batch_len = ctxt->data_file_size - ctxt->offset;
165 } else {
166 *read_batch_len = ctxt->filter_batch_end * page_size
167 - ctxt->offset;
168 }
169
170 /* If the page block is larger than the buffer capacity, limit it to
171 buffer capacity. The subsequent invocations will continue returning
172 the current block in buffer-sized pieces until ctxt->filter_batch_end
173 is reached, trigerring the next bitmap query. */
174 if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) {
175 *read_batch_len = ctxt->buffer_capacity;
176 }
177
178 ctxt->offset += *read_batch_len;
179 xb_a (ctxt->offset % page_size == 0);
180 xb_a (*read_batch_start % page_size == 0);
181 xb_a (*read_batch_len % page_size == 0);
182}
183
184/****************************************************************//**
185Deinitialize the changed page bitmap-based read filter. */
186static
187void
188rf_bitmap_deinit(
189/*=============*/
190 xb_read_filt_ctxt_t* ctxt) /*!<in/out: read filter context */
191{
192 xb_page_bitmap_range_deinit(ctxt->bitmap_range);
193}
194
195/* The pass-through read filter */
196xb_read_filt_t rf_pass_through = {
197 &rf_pass_through_init,
198 &rf_pass_through_get_next_batch,
199 &rf_pass_through_deinit
200};
201
202/* The changed page bitmap-based read filter */
203xb_read_filt_t rf_bitmap = {
204 &rf_bitmap_init,
205 &rf_bitmap_get_next_batch,
206 &rf_bitmap_deinit
207};
208