1 | /* Copyright (C) 2007 Michael Widenius |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
15 | |
16 | /* |
17 | Storage of records in block |
18 | */ |
19 | |
20 | #define LSN_SIZE 7 |
21 | #define DIR_COUNT_SIZE 1 /* Stores number of rows on page */ |
22 | #define DIR_FREE_SIZE 1 /* Pointer to first free dir entry */ |
23 | #define EMPTY_SPACE_SIZE 2 /* Stores empty space on page */ |
24 | #define PAGE_TYPE_SIZE 1 |
25 | #define PAGE_SUFFIX_SIZE 4 /* Bytes for checksum */ |
26 | #define (LSN_SIZE + DIR_COUNT_SIZE + DIR_FREE_SIZE + \ |
27 | EMPTY_SPACE_SIZE + PAGE_TYPE_SIZE) |
28 | |
29 | #define (share) (PAGE_HEADER_SIZE_RAW + \ |
30 | (share)->crypt_page_header_space) |
31 | |
32 | #define PAGE_OVERHEAD_SIZE_RAW (PAGE_HEADER_SIZE_RAW + DIR_ENTRY_SIZE + \ |
33 | PAGE_SUFFIX_SIZE) |
34 | #define PAGE_OVERHEAD_SIZE(share) (PAGE_OVERHEAD_SIZE_RAW + \ |
35 | (share)->crypt_page_header_space) |
36 | |
37 | #define BLOCK_RECORD_POINTER_SIZE 6 |
38 | |
39 | #define (share) (LSN_SIZE + PAGE_TYPE_SIZE + \ |
40 | (share)->crypt_page_header_space) |
41 | #define FULL_PAGE_SIZE(share) ((share)->block_size - \ |
42 | FULL_PAGE_HEADER_SIZE(share) - \ |
43 | PAGE_SUFFIX_SIZE) |
44 | |
45 | #define FULL_PAGE_SIZE2(block_size, crypt_size) \ |
46 | ((block_size) - (LSN_SIZE + PAGE_TYPE_SIZE + PAGE_SUFFIX_SIZE + (crypt_size))) |
47 | |
48 | #define ROW_EXTENT_PAGE_SIZE 5 |
49 | #define ROW_EXTENT_COUNT_SIZE 2 |
50 | #define SUB_RANGE_SIZE 2 |
51 | #define BLOCK_FILLER_SIZE 2 |
52 | #define ROW_EXTENT_SIZE (ROW_EXTENT_PAGE_SIZE + ROW_EXTENT_COUNT_SIZE) |
53 | #define TAIL_BIT 0x8000U /* Bit in page_count to signify tail */ |
54 | #define START_EXTENT_BIT 0x4000U /* Bit in page_count to signify start*/ |
55 | /* page_count set by bitmap code for tail pages */ |
56 | #define TAIL_PAGE_COUNT_MARKER 0xffff |
57 | /* Number of extents reserved MARIA_BITMAP_BLOCKS to store head part */ |
58 | #define ELEMENTS_RESERVED_FOR_MAIN_PART 4 |
59 | /* This is just used to prealloc a dynamic array */ |
60 | #define AVERAGE_BLOB_SIZE (1024L*1024L) |
61 | /* Number of pages to store continuous blob parts */ |
62 | #define BLOB_SEGMENT_MIN_SIZE 128 |
63 | |
64 | /* Fields before 'row->null_field_lengths' used by find_where_to_split_row */ |
65 | #define 3 |
66 | |
67 | /* Size for the different parts in the row header (and head page) */ |
68 | #define FLAG_SIZE 1 |
69 | #define VERPTR_SIZE 7 |
70 | #define DIR_ENTRY_SIZE 4 |
71 | #define FIELD_OFFSET_SIZE 2 /* size of pointers to field starts */ |
72 | |
73 | /* Minimum header size needed for a new row */ |
74 | #define FLAG_SIZE |
75 | |
76 | #define PAGE_TYPE_MASK 7 |
77 | enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_TYPE }; |
78 | #define PAGE_CAN_BE_COMPACTED 128U /* Bit in PAGE_TYPE */ |
79 | |
80 | #define PAGE_TYPE_OFFSET LSN_SIZE |
81 | #define DIR_COUNT_OFFSET (LSN_SIZE+PAGE_TYPE_SIZE) |
82 | #define DIR_FREE_OFFSET (DIR_COUNT_OFFSET+DIR_COUNT_SIZE) |
83 | #define EMPTY_SPACE_OFFSET (DIR_FREE_OFFSET+DIR_FREE_SIZE) |
84 | /* for encryption */ |
85 | #define KEY_VERSION_OFFSET (EMPTY_SPACE_OFFSET+EMPTY_SPACE_SIZE) |
86 | #define FULL_PAGE_KEY_VERSION_OFFSET (PAGE_TYPE_OFFSET + PAGE_TYPE_SIZE) |
87 | |
88 | /* Bits used for flag uchar (one byte, first in record) */ |
89 | #define ROW_FLAG_TRANSID 1U |
90 | #define ROW_FLAG_VER_PTR 2U |
91 | #define ROW_FLAG_DELETE_TRANSID 4U |
92 | #define ROW_FLAG_NULLS_EXTENDED 8U |
93 | #define ROW_FLAG_EXTENTS 128U |
94 | #define ROW_FLAG_ALL (1U+2U+4U+8U+128U) |
95 | |
96 | /* Size for buffer to hold information about bitmap */ |
97 | #define MAX_BITMAP_INFO_LENGTH ((MARIA_MAX_KEY_BLOCK_LENGTH*8/3)*(61*11/60)+10) |
98 | |
99 | |
100 | /******** Variables that affects how data pages are utilized ********/ |
101 | |
102 | /* Minimum size of tail segment */ |
103 | #define MIN_TAIL_SIZE 32U |
104 | |
105 | /* |
106 | Fixed length part of Max possible header size; See row data structure |
107 | table in ma_blockrec.c. |
108 | */ |
109 | #define (FLAG_SIZE + 3 + ROW_EXTENT_SIZE + 3) |
110 | #define (MAX_FIXED_HEADER_SIZE + \ |
111 | TRANSID_SIZE + VERPTR_SIZE + \ |
112 | TRANSID_SIZE) |
113 | |
114 | /* We use 1 uchar in record header to store number of directory entries */ |
115 | #define MAX_ROWS_PER_PAGE 255 |
116 | #define END_OF_DIR_FREE_LIST ((uchar) 255) |
117 | |
118 | /* Bits for MARIA_BITMAP_BLOCKS->used */ |
119 | /* We stored data on disk in the block */ |
120 | #define BLOCKUSED_USED 1 |
121 | /* Bitmap on disk is block->org_bitmap_value ; Happens only on update */ |
122 | #define BLOCKUSED_USE_ORG_BITMAP 2 |
123 | /* We stored tail data on disk for the block */ |
124 | #define BLOCKUSED_TAIL 4 |
125 | |
126 | /******* defines that affects allocation (density) of data *******/ |
127 | |
128 | /* |
129 | If the tail part (from the main block or a blob) would use more than 75 % of |
130 | the size of page, store the tail on a full page instead of a shared |
131 | tail page. |
132 | */ |
133 | #define MAX_TAIL_SIZE(block_size) ((block_size) *3 / 4) |
134 | |
135 | /* Don't allocate memory for too many row extents on the stack */ |
136 | #define ROW_EXTENTS_ON_STACK 32 |
137 | |
138 | /* Functions to convert MARIA_RECORD_POS to/from page:offset */ |
139 | |
140 | static inline MARIA_RECORD_POS ma_recordpos(pgcache_page_no_t page, |
141 | uint dir_entry) |
142 | { |
143 | DBUG_ASSERT(dir_entry <= 255); |
144 | DBUG_ASSERT(page > 0); /* page 0 is bitmap, not data page */ |
145 | return (MARIA_RECORD_POS) (((ulonglong) page << 8) | dir_entry); |
146 | } |
147 | |
148 | static inline pgcache_page_no_t ma_recordpos_to_page(MARIA_RECORD_POS record_pos) |
149 | { |
150 | return (pgcache_page_no_t) (record_pos >> 8); |
151 | } |
152 | |
153 | static inline uint ma_recordpos_to_dir_entry(MARIA_RECORD_POS record_pos) |
154 | { |
155 | return (uint) (record_pos & 255); |
156 | } |
157 | |
158 | static inline uchar *dir_entry_pos(uchar *buff, uint block_size, uint pos) |
159 | { |
160 | return (buff + block_size - DIR_ENTRY_SIZE * pos - PAGE_SUFFIX_SIZE - |
161 | DIR_ENTRY_SIZE); |
162 | } |
163 | |
164 | /* ma_blockrec.c */ |
165 | void _ma_init_block_record_data(void); |
166 | my_bool _ma_once_init_block_record(MARIA_SHARE *share, File dfile); |
167 | my_bool _ma_once_end_block_record(MARIA_SHARE *share); |
168 | my_bool _ma_init_block_record(MARIA_HA *info); |
169 | void _ma_end_block_record(MARIA_HA *info); |
170 | |
171 | my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS pos, |
172 | const uchar *oldrec, const uchar *newrec); |
173 | my_bool _ma_delete_block_record(MARIA_HA *info, const uchar *record); |
174 | int _ma_read_block_record(MARIA_HA *info, uchar *record, |
175 | MARIA_RECORD_POS record_pos); |
176 | int _ma_read_block_record2(MARIA_HA *info, uchar *record, |
177 | uchar *data, uchar *end_of_data); |
178 | int _ma_scan_block_record(MARIA_HA *info, uchar *record, |
179 | MARIA_RECORD_POS, my_bool); |
180 | my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, |
181 | const uchar *record, MARIA_RECORD_POS pos); |
182 | my_bool _ma_scan_init_block_record(MARIA_HA *info); |
183 | void _ma_scan_end_block_record(MARIA_HA *info); |
184 | int _ma_scan_remember_block_record(MARIA_HA *info, |
185 | MARIA_RECORD_POS *lastpos); |
186 | int _ma_scan_restore_block_record(MARIA_HA *info, |
187 | MARIA_RECORD_POS lastpos); |
188 | |
189 | MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, |
190 | const uchar *record); |
191 | my_bool _ma_write_block_record(MARIA_HA *info, const uchar *record); |
192 | my_bool _ma_write_abort_block_record(MARIA_HA *info); |
193 | my_bool _ma_compare_block_record(MARIA_HA *info, const uchar *record); |
194 | void _ma_compact_block_page(MARIA_SHARE *share, uchar *buff, uint rownr, |
195 | my_bool extend_block, TrID min_read_from, |
196 | uint min_row_length); |
197 | my_bool enough_free_entries_on_page(MARIA_SHARE *share, uchar *page_buff); |
198 | TRANSLOG_ADDRESS |
199 | maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr); |
200 | |
201 | /* ma_bitmap.c */ |
202 | extern const char *bits_to_txt[]; |
203 | |
204 | my_bool _ma_bitmap_init(MARIA_SHARE *share, File file, |
205 | pgcache_page_no_t *last_page); |
206 | my_bool _ma_bitmap_end(MARIA_SHARE *share); |
207 | my_bool _ma_bitmap_flush(MARIA_SHARE *share); |
208 | my_bool _ma_bitmap_flush_all(MARIA_SHARE *share); |
209 | void _ma_bitmap_reset_cache(MARIA_SHARE *share); |
210 | my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, |
211 | MARIA_BITMAP_BLOCKS *result_blocks); |
212 | my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks); |
213 | my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const uchar *extents, |
214 | uint count); |
215 | my_bool _ma_bitmap_set(MARIA_HA *info, pgcache_page_no_t pos, my_bool head, |
216 | uint empty_space); |
217 | my_bool _ma_bitmap_reset_full_page_bits(MARIA_HA *info, |
218 | MARIA_FILE_BITMAP *bitmap, |
219 | pgcache_page_no_t page, |
220 | uint page_count); |
221 | my_bool _ma_bitmap_set_full_page_bits(MARIA_HA *info, |
222 | MARIA_FILE_BITMAP *bitmap, |
223 | pgcache_page_no_t page, uint page_count); |
224 | uint _ma_free_size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size); |
225 | my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *new_row, |
226 | pgcache_page_no_t page, uint free_size, |
227 | MARIA_BITMAP_BLOCKS *result_blocks); |
228 | my_bool _ma_check_bitmap_data(MARIA_HA *info, |
229 | enum en_page_type page_type, |
230 | uint empty_space, uint bitmap_pattern); |
231 | my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info, |
232 | enum en_page_type page_type, |
233 | pgcache_page_no_t page, |
234 | uint *bitmap_pattern); |
235 | uint _ma_bitmap_get_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, |
236 | pgcache_page_no_t page); |
237 | void _ma_bitmap_delete_all(MARIA_SHARE *share); |
238 | int _ma_bitmap_create_first(MARIA_SHARE *share); |
239 | void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc); |
240 | void _ma_bitmap_lock(MARIA_SHARE *share); |
241 | void _ma_bitmap_unlock(MARIA_SHARE *share); |
242 | void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file, |
243 | MARIA_SHARE *share); |
244 | #ifndef DBUG_OFF |
245 | void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, |
246 | pgcache_page_no_t page); |
247 | #endif |
248 | void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, |
249 | uchar *bitmap_data, |
250 | pgcache_page_no_t page, |
251 | char *out); |
252 | |
253 | uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, |
254 | uint page_type, |
255 | my_bool new_page, |
256 | const uchar *, |
257 | const uchar *data, |
258 | size_t data_length); |
259 | uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, |
260 | uint page_type, |
261 | const uchar *); |
262 | uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn, LSN rec_lsn, |
263 | const uchar *); |
264 | uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, |
265 | const uchar *); |
266 | uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, LSN lsn, |
267 | const uchar *, LSN redo_lsn, |
268 | uint * const number_of_blobs, |
269 | uint * const number_of_ranges, |
270 | pgcache_page_no_t * const first_page, |
271 | pgcache_page_no_t * const last_page); |
272 | my_bool _ma_apply_redo_bitmap_new_page(MARIA_HA *info, LSN lsn, |
273 | const uchar *); |
274 | my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, |
275 | const uchar *); |
276 | my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, |
277 | const uchar *, size_t length); |
278 | my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, |
279 | const uchar *, size_t length); |
280 | my_bool _ma_apply_undo_bulk_insert(MARIA_HA *info, LSN undo_lsn); |
281 | |
282 | my_bool write_hook_for_redo(enum translog_record_type type, |
283 | TRN *trn, MARIA_HA *tbl_info, LSN *lsn, |
284 | void *hook_arg); |
285 | my_bool write_hook_for_undo(enum translog_record_type type, |
286 | TRN *trn, MARIA_HA *tbl_info, LSN *lsn, |
287 | void *hook_arg); |
288 | my_bool write_hook_for_redo_delete_all(enum translog_record_type type, |
289 | TRN *trn, MARIA_HA *tbl_info, |
290 | LSN *lsn, void *hook_arg); |
291 | my_bool write_hook_for_undo_row_insert(enum translog_record_type type, |
292 | TRN *trn, MARIA_HA *tbl_info, |
293 | LSN *lsn, void *hook_arg); |
294 | my_bool write_hook_for_undo_row_delete(enum translog_record_type type, |
295 | TRN *trn, MARIA_HA *tbl_info, |
296 | LSN *lsn, void *hook_arg); |
297 | my_bool write_hook_for_undo_row_update(enum translog_record_type type, |
298 | TRN *trn, MARIA_HA *tbl_info, |
299 | LSN *lsn, void *hook_arg); |
300 | my_bool write_hook_for_undo_bulk_insert(enum translog_record_type type, |
301 | TRN *trn, MARIA_HA *tbl_info, |
302 | LSN *lsn, void *hook_arg); |
303 | my_bool write_hook_for_file_id(enum translog_record_type type, |
304 | TRN *trn, MARIA_HA *tbl_info, LSN *lsn, |
305 | void *hook_arg); |
306 | my_bool write_hook_for_commit(enum translog_record_type type, |
307 | TRN *trn, MARIA_HA *tbl_info, LSN *lsn, |
308 | void *hook_arg); |
309 | void _ma_block_get_status(void *param, my_bool concurrent_insert); |
310 | my_bool _ma_block_start_trans(void* param); |
311 | my_bool _ma_block_start_trans_no_versioning(void *param); |
312 | void _ma_block_update_status(void *param); |
313 | void _ma_block_restore_status(void *param); |
314 | my_bool _ma_block_check_status(void *param); |
315 | |