1
/*****************************************************************************
3
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/******************************************************************//**
1
/**********************************************************************
21
2
File space management
23
6
Created 11/29/1995 Heikki Tuuri
24
7
***********************************************************************/
230
209
/* Offset of the descriptor array on a descriptor page */
231
210
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
233
#ifndef UNIV_HOTBACKUP
234
/* Flag to indicate if we have printed the tablespace full error. */
235
static ibool fsp_tbs_full_error_printed = FALSE;
237
/**********************************************************************//**
212
/**************************************************************************
238
213
Returns an extent to the free list of a space. */
243
ulint space, /*!< in: space id */
244
ulint zip_size,/*!< in: compressed page size in bytes
218
ulint space, /* in: space id */
219
ulint zip_size,/* in: compressed page size in bytes
245
220
or 0 for uncompressed pages */
246
ulint page, /*!< in: page offset in the extent */
247
mtr_t* mtr); /*!< in: mtr */
248
/**********************************************************************//**
221
ulint page, /* in: page offset in the extent */
222
mtr_t* mtr); /* in: mtr */
223
/**************************************************************************
249
224
Frees an extent of a segment to the space free list. */
252
227
fseg_free_extent(
253
228
/*=============*/
254
fseg_inode_t* seg_inode, /*!< in: segment inode */
255
ulint space, /*!< in: space id */
256
ulint zip_size,/*!< in: compressed page size in bytes
229
fseg_inode_t* seg_inode, /* in: segment inode */
230
ulint space, /* in: space id */
231
ulint zip_size,/* in: compressed page size in bytes
257
232
or 0 for uncompressed pages */
258
ulint page, /*!< in: page offset in the extent */
259
mtr_t* mtr); /*!< in: mtr handle */
260
/**********************************************************************//**
233
ulint page, /* in: page offset in the extent */
234
mtr_t* mtr); /* in: mtr handle */
235
/**************************************************************************
261
236
Calculates the number of pages reserved by a segment, and how
262
many pages are currently used.
263
@return number of reserved pages */
237
many pages are currently used. */
266
240
fseg_n_reserved_pages_low(
267
241
/*======================*/
268
fseg_inode_t* header, /*!< in: segment inode */
269
ulint* used, /*!< out: number of pages used (not
270
more than reserved) */
271
mtr_t* mtr); /*!< in: mtr handle */
272
/********************************************************************//**
242
/* out: number of reserved pages */
243
fseg_inode_t* header, /* in: segment inode */
244
ulint* used, /* out: number of pages used (<= reserved) */
245
mtr_t* mtr); /* in: mtr handle */
246
/************************************************************************
273
247
Marks a page used. The page must reside within the extents of the given
277
251
fseg_mark_page_used(
278
252
/*================*/
279
fseg_inode_t* seg_inode,/*!< in: segment inode */
280
ulint space, /*!< in: space id */
281
ulint zip_size,/*!< in: compressed page size in bytes
253
fseg_inode_t* seg_inode,/* in: segment inode */
254
ulint space, /* in: space id */
255
ulint zip_size,/* in: compressed page size in bytes
282
256
or 0 for uncompressed pages */
283
ulint page, /*!< in: page offset */
284
mtr_t* mtr); /*!< in: mtr */
285
/**********************************************************************//**
257
ulint page, /* in: page offset */
258
mtr_t* mtr); /* in: mtr */
259
/**************************************************************************
286
260
Returns the first extent descriptor for a segment. We think of the extent
287
261
lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
289
@return the first extent descriptor, or NULL if none */
292
265
fseg_get_first_extent(
293
266
/*==================*/
294
fseg_inode_t* inode, /*!< in: segment inode */
295
ulint space, /*!< in: space id */
296
ulint zip_size,/*!< in: compressed page size in bytes
267
/* out: the first extent descriptor, or NULL if
269
fseg_inode_t* inode, /* in: segment inode */
270
ulint space, /* in: space id */
271
ulint zip_size,/* in: compressed page size in bytes
297
272
or 0 for uncompressed pages */
298
mtr_t* mtr); /*!< in: mtr */
299
/**********************************************************************//**
273
mtr_t* mtr); /* in: mtr */
274
/**************************************************************************
300
275
Puts new extents to the free list if
301
276
there are free extents above the free limit. If an extent happens
302
277
to contain an extent descriptor page, the extent is put to
306
281
fsp_fill_free_list(
307
282
/*===============*/
308
ibool init_space, /*!< in: TRUE if this is a single-table
283
ibool init_space, /* in: TRUE if this is a single-table
309
284
tablespace and we are only initing
310
285
the tablespace's first extent
311
286
descriptor page and ibuf bitmap page;
312
287
then we do not allocate more extents */
313
ulint space, /*!< in: space */
314
fsp_header_t* header, /*!< in: space header */
315
mtr_t* mtr); /*!< in: mtr */
316
/**********************************************************************//**
288
ulint space, /* in: space */
289
fsp_header_t* header, /* in: space header */
290
mtr_t* mtr); /* in: mtr */
291
/**************************************************************************
317
292
Allocates a single free page from a segment. This function implements
318
293
the intelligent allocation strategy which tries to minimize file space
320
@return the allocated page number, FIL_NULL if no page could be allocated */
323
297
fseg_alloc_free_page_low(
324
298
/*=====================*/
325
ulint space, /*!< in: space */
326
ulint zip_size,/*!< in: compressed page size in bytes
299
/* out: the allocated page number, FIL_NULL
300
if no page could be allocated */
301
ulint space, /* in: space */
302
ulint zip_size,/* in: compressed page size in bytes
327
303
or 0 for uncompressed pages */
328
fseg_inode_t* seg_inode, /*!< in: segment inode */
329
ulint hint, /*!< in: hint of which page would be desirable */
330
byte direction, /*!< in: if the new page is needed because
304
fseg_inode_t* seg_inode, /* in: segment inode */
305
ulint hint, /* in: hint of which page would be desirable */
306
byte direction, /* in: if the new page is needed because
331
307
of an index page split, and records are
332
308
inserted there in order, into which
333
309
direction they go alphabetically: FSP_DOWN,
334
310
FSP_UP, FSP_NO_DIR */
335
mtr_t* mtr); /*!< in: mtr handle */
336
#endif /* !UNIV_HOTBACKUP */
338
/**********************************************************************//**
339
Reads the file space size stored in the header page.
340
@return tablespace size stored in the space header */
311
mtr_t* mtr); /* in: mtr handle */
314
/**************************************************************************
315
Reads the file space size stored in the header page. */
343
318
fsp_get_size_low(
344
319
/*=============*/
345
page_t* page) /*!< in: header page (page 0 in the tablespace) */
320
/* out: tablespace size stored in the space header */
321
page_t* page) /* in: header page (page 0 in the tablespace) */
347
323
return(mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SIZE));
350
#ifndef UNIV_HOTBACKUP
351
/**********************************************************************//**
352
Gets a pointer to the space header and x-locks its page.
353
@return pointer to the space header, page x-locked */
326
/**************************************************************************
327
Gets a pointer to the space header and x-locks its page. */
356
330
fsp_get_space_header(
357
331
/*=================*/
358
ulint id, /*!< in: space id */
359
ulint zip_size,/*!< in: compressed page size in bytes
332
/* out: pointer to the space header, page x-locked */
333
ulint id, /* in: space id */
334
ulint zip_size,/* in: compressed page size in bytes
360
335
or 0 for uncompressed pages */
361
mtr_t* mtr) /*!< in: mtr */
336
mtr_t* mtr) /* in: mtr */
363
338
buf_block_t* block;
364
339
fsp_header_t* header;
381
/**********************************************************************//**
382
Gets a descriptor bit of a page.
383
@return TRUE if free */
356
/**************************************************************************
357
Gets a descriptor bit of a page. */
388
const xdes_t* descr, /*!< in: descriptor */
389
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
390
ulint offset, /*!< in: page offset within extent:
391
0 ... FSP_EXTENT_SIZE - 1 */
392
mtr_t* mtr) /*!< in: mtr */
362
/* out: TRUE if free */
363
xdes_t* descr, /* in: descriptor */
364
ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */
365
ulint offset, /* in: page offset within extent:
366
0 ... FSP_EXTENT_SIZE - 1 */
367
mtr_t* mtr) /* in: mtr */
395
370
ulint byte_index;
412
/**********************************************************************//**
387
/**************************************************************************
413
388
Sets a descriptor bit of a page. */
418
xdes_t* descr, /*!< in: descriptor */
419
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
420
ulint offset, /*!< in: page offset within extent:
393
xdes_t* descr, /* in: descriptor */
394
ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */
395
ulint offset, /* in: page offset within extent:
421
396
0 ... FSP_EXTENT_SIZE - 1 */
422
ibool val, /*!< in: bit value */
423
mtr_t* mtr) /*!< in: mtr */
397
ibool val, /* in: bit value */
398
mtr_t* mtr) /* in: mtr */
426
401
ulint byte_index;
444
419
MLOG_1BYTE, mtr);
447
/**********************************************************************//**
422
/**************************************************************************
448
423
Looks for a descriptor bit having the desired value. Starts from hint
449
424
and scans upward; at the end of the extent the search is wrapped to
450
the start of the extent.
451
@return bit index of the bit, ULINT_UNDEFINED if not found */
425
the start of the extent. */
456
xdes_t* descr, /*!< in: descriptor */
457
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
458
ibool val, /*!< in: desired bit value */
459
ulint hint, /*!< in: hint of which bit position would be desirable */
460
mtr_t* mtr) /*!< in: mtr */
430
/* out: bit index of the bit, ULINT_UNDEFINED if not
432
xdes_t* descr, /* in: descriptor */
433
ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */
434
ibool val, /* in: desired bit value */
435
ulint hint, /* in: hint of which bit position would be desirable */
436
mtr_t* mtr) /* in: mtr */
482
458
return(ULINT_UNDEFINED);
485
/**********************************************************************//**
461
/**************************************************************************
486
462
Looks for a descriptor bit having the desired value. Scans the extent in
487
a direction opposite to xdes_find_bit.
488
@return bit index of the bit, ULINT_UNDEFINED if not found */
463
a direction opposite to xdes_find_bit. */
491
466
xdes_find_bit_downward(
492
467
/*===================*/
493
xdes_t* descr, /*!< in: descriptor */
494
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
495
ibool val, /*!< in: desired bit value */
496
ulint hint, /*!< in: hint of which bit position would be desirable */
497
mtr_t* mtr) /*!< in: mtr */
468
/* out: bit index of the bit, ULINT_UNDEFINED if not
470
xdes_t* descr, /* in: descriptor */
471
ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */
472
ibool val, /* in: desired bit value */
473
ulint hint, /* in: hint of which bit position would be desirable */
474
mtr_t* mtr) /* in: mtr */
639
616
xdes_set_state(descr, XDES_FREE, mtr);
642
/********************************************************************//**
643
Calculates the page where the descriptor of a page resides.
644
@return descriptor page offset */
619
/************************************************************************
620
Calculates the page where the descriptor of a page resides. */
647
623
xdes_calc_descriptor_page(
648
624
/*======================*/
649
ulint zip_size, /*!< in: compressed page size in bytes;
625
/* out: descriptor page offset */
626
ulint zip_size, /* in: compressed page size in bytes;
650
627
0 for uncompressed pages */
651
ulint offset) /*!< in: page offset */
628
ulint offset) /* in: page offset */
653
#ifndef DOXYGEN /* Doxygen gets confused of these */
654
# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
630
#if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
655
631
+ (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
658
# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
634
#if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
659
635
+ (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
662
#endif /* !DOXYGEN */
663
638
ut_ad(ut_is_2pow(zip_size));
695
/********************************************************************//**
670
/************************************************************************
696
671
Gets pointer to a the extent descriptor of a page. The page where the extent
697
672
descriptor resides is x-locked. If the page offset is equal to the free limit
698
673
of the space, adds new extents from above the free limit to the space free
699
674
list, if not free limit == space size. This adding is necessary to make the
700
descriptor defined, as they are uninitialized above the free limit.
701
@return pointer to the extent descriptor, NULL if the page does not
702
exist in the space or if the offset exceeds the free limit */
675
descriptor defined, as they are uninitialized above the free limit. */
705
678
xdes_get_descriptor_with_space_hdr(
706
679
/*===============================*/
707
fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
708
ulint space, /*!< in: space id */
709
ulint offset, /*!< in: page offset;
680
/* out: pointer to the extent descriptor,
681
NULL if the page does not exist in the
682
space or if offset > free limit */
683
fsp_header_t* sp_header,/* in: space header, x-latched */
684
ulint space, /* in: space id */
685
ulint offset, /* in: page offset;
710
686
if equal to the free limit,
711
687
we try to add new extents to
712
688
the space free list */
713
mtr_t* mtr) /*!< in: mtr handle */
689
mtr_t* mtr) /* in: mtr handle */
763
739
+ XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
766
/********************************************************************//**
742
/************************************************************************
767
743
Gets pointer to a the extent descriptor of a page. The page where the
768
744
extent descriptor resides is x-locked. If the page offset is equal to
769
745
the free limit of the space, adds new extents from above the free limit
770
746
to the space free list, if not free limit == space size. This adding
771
747
is necessary to make the descriptor defined, as they are uninitialized
772
above the free limit.
773
@return pointer to the extent descriptor, NULL if the page does not
774
exist in the space or if the offset exceeds the free limit */
748
above the free limit. */
777
751
xdes_get_descriptor(
778
752
/*================*/
779
ulint space, /*!< in: space id */
780
ulint zip_size,/*!< in: compressed page size in bytes
753
/* out: pointer to the extent descriptor, NULL if the
754
page does not exist in the space or if offset > free
756
ulint space, /* in: space id */
757
ulint zip_size,/* in: compressed page size in bytes
781
758
or 0 for uncompressed pages */
782
ulint offset, /*!< in: page offset; if equal to the free limit,
759
ulint offset, /* in: page offset; if equal to the free limit,
783
760
we try to add new extents to the space free list */
784
mtr_t* mtr) /*!< in: mtr handle */
761
mtr_t* mtr) /* in: mtr handle */
786
763
buf_block_t* block;
787
764
fsp_header_t* sp_header;
797
/********************************************************************//**
774
/************************************************************************
798
775
Gets pointer to a the extent descriptor if the file address
799
776
of the descriptor list node is known. The page where the
800
extent descriptor resides is x-locked.
801
@return pointer to the extent descriptor */
777
extent descriptor resides is x-locked. */
804
780
xdes_lst_get_descriptor(
805
781
/*====================*/
806
ulint space, /*!< in: space id */
807
ulint zip_size,/*!< in: compressed page size in bytes
782
/* out: pointer to the extent descriptor */
783
ulint space, /* in: space id */
784
ulint zip_size,/* in: compressed page size in bytes
808
785
or 0 for uncompressed pages */
809
fil_addr_t lst_node,/*!< in: file address of the list node
786
fil_addr_t lst_node,/* in: file address of the list node
810
787
contained in the descriptor */
811
mtr_t* mtr) /*!< in: mtr handle */
788
mtr_t* mtr) /* in: mtr handle */
871
memset(page, 0, UNIV_PAGE_SIZE);
845
#ifdef UNIV_BASIC_LOG_DEBUG
846
memset(page, 0xff, UNIV_PAGE_SIZE);
872
848
mach_write_to_4(page + FIL_PAGE_OFFSET, buf_block_get_page_no(block));
849
memset(page + FIL_PAGE_LSN, 0, 8);
873
850
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
874
851
buf_block_get_space(block));
852
memset(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, 0, 8);
877
#ifndef UNIV_HOTBACKUP
878
/***********************************************************//**
855
/***************************************************************
879
856
Inits a file page whose prior contents should be ignored. */
882
859
fsp_init_file_page(
883
860
/*===============*/
884
buf_block_t* block, /*!< in: pointer to a page */
885
mtr_t* mtr) /*!< in: mtr */
861
buf_block_t* block, /* in: pointer to a page */
862
mtr_t* mtr) /* in: mtr */
887
864
fsp_init_file_page_low(block);
889
866
mlog_write_initial_log_record(buf_block_get_frame(block),
890
867
MLOG_INIT_FILE_PAGE, mtr);
892
#endif /* !UNIV_HOTBACKUP */
894
/***********************************************************//**
895
Parses a redo log record of a file page init.
896
@return end of log record or NULL */
870
/***************************************************************
871
Parses a redo log record of a file page init. */
899
874
fsp_parse_init_file_page(
900
875
/*=====================*/
901
byte* ptr, /*!< in: buffer */
902
byte* end_ptr __attribute__((unused)), /*!< in: buffer end */
903
buf_block_t* block) /*!< in: block or NULL */
876
/* out: end of log record or NULL */
877
byte* ptr, /* in: buffer */
878
byte* end_ptr __attribute__((unused)), /* in: buffer end */
879
buf_block_t* block) /* in: block or NULL */
905
881
ut_ad(ptr && end_ptr);
998
973
flst_init(header + FSP_SEG_INODES_FULL, mtr);
999
974
flst_init(header + FSP_SEG_INODES_FREE, mtr);
1001
mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
976
mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
1002
977
if (space == 0) {
1003
978
fsp_fill_free_list(FALSE, space, header, mtr);
1004
979
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
1005
0, 0, DICT_IBUF_ID_MIN + space,
1006
dict_ind_redundant, mtr);
980
0, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
981
srv_sys->dummy_ind1, mtr);
1008
983
fsp_fill_free_list(TRUE, space, header, mtr);
1011
#endif /* !UNIV_HOTBACKUP */
1013
/**********************************************************************//**
1014
Reads the space id from the first page of a tablespace.
1015
@return space id, ULINT UNDEFINED if error */
987
/**************************************************************************
988
Reads the space id from the first page of a tablespace. */
1018
991
fsp_header_get_space_id(
1019
992
/*====================*/
1020
const page_t* page) /*!< in: first page of a tablespace */
993
/* out: space id, ULINT UNDEFINED if error */
994
const page_t* page) /* in: first page of a tablespace */
1041
/**********************************************************************//**
1042
Reads the space flags from the first page of a tablespace.
1015
/**************************************************************************
1016
Reads the space flags from the first page of a tablespace. */
1046
1019
fsp_header_get_flags(
1047
1020
/*=================*/
1048
const page_t* page) /*!< in: first page of a tablespace */
1022
const page_t* page) /* in: first page of a tablespace */
1050
1024
ut_ad(!page_offset(page));
1052
1026
return(mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page));
1055
/**********************************************************************//**
1056
Reads the compressed page size from the first page of a tablespace.
1057
@return compressed page size in bytes, or 0 if uncompressed */
1029
/**************************************************************************
1030
Reads the compressed page size from the first page of a tablespace. */
1060
1033
fsp_header_get_zip_size(
1061
1034
/*====================*/
1062
const page_t* page) /*!< in: first page of a tablespace */
1035
/* out: compressed page size in bytes,
1036
or 0 if uncompressed */
1037
const page_t* page) /* in: first page of a tablespace */
1064
1039
ulint flags = fsp_header_get_flags(page);
1066
1041
return(dict_table_flags_to_zip_size(flags));
1069
#ifndef UNIV_HOTBACKUP
1070
/**********************************************************************//**
1044
/**************************************************************************
1071
1045
Increases the space size field of a space. */
1074
1048
fsp_header_inc_size(
1075
1049
/*================*/
1076
ulint space, /*!< in: space id */
1077
ulint size_inc,/*!< in: size increment in pages */
1078
mtr_t* mtr) /*!< in: mini-transaction handle */
1050
ulint space, /* in: space id */
1051
ulint size_inc,/* in: size increment in pages */
1052
mtr_t* mtr) /* in: mini-transaction handle */
1080
1054
fsp_header_t* header;
1158
/***********************************************************************//**
1132
/***************************************************************************
1159
1133
Tries to extend a single-table tablespace so that a page would fit in the
1161
@return TRUE if success */
1164
1137
fsp_try_extend_data_file_with_pages(
1165
1138
/*================================*/
1166
ulint space, /*!< in: space */
1167
ulint page_no, /*!< in: page number */
1168
fsp_header_t* header, /*!< in: space header */
1169
mtr_t* mtr) /*!< in: mtr */
1139
/* out: TRUE if success */
1140
ulint space, /* in: space */
1141
ulint page_no, /* in: page number */
1142
fsp_header_t* header, /* in: space header */
1143
mtr_t* mtr) /* in: mtr */
1172
1146
ulint actual_size;
1188
1162
return(success);
1191
/***********************************************************************//**
1192
Tries to extend the last data file of a tablespace if it is auto-extending.
1193
@return FALSE if not auto-extending */
1165
/***************************************************************************
1166
Tries to extend the last data file of a tablespace if it is auto-extending. */
1196
1169
fsp_try_extend_data_file(
1197
1170
/*=====================*/
1198
ulint* actual_increase,/*!< out: actual increase in pages, where
1171
/* out: FALSE if not auto-extending */
1172
ulint* actual_increase,/* out: actual increase in pages, where
1199
1173
we measure the tablespace size from
1200
1174
what the header field says; it may be
1201
1175
the actual file size rounded down to
1203
ulint space, /*!< in: space */
1204
fsp_header_t* header, /*!< in: space header */
1205
mtr_t* mtr) /*!< in: mtr */
1177
ulint space, /* in: space */
1178
fsp_header_t* header, /* in: space header */
1179
mtr_t* mtr) /* in: mtr */
1208
1182
ulint zip_size;
1489
/**********************************************************************//**
1490
Allocates a new free extent.
1491
@return extent descriptor, NULL if cannot be allocated */
1450
/**************************************************************************
1451
Allocates a new free extent. */
1494
1454
fsp_alloc_free_extent(
1495
1455
/*==================*/
1496
ulint space, /*!< in: space id */
1497
ulint zip_size,/*!< in: compressed page size in bytes
1456
/* out: extent descriptor, NULL if cannot be
1458
ulint space, /* in: space id */
1459
ulint zip_size,/* in: compressed page size in bytes
1498
1460
or 0 for uncompressed pages */
1499
ulint hint, /*!< in: hint of which extent would be desirable: any
1461
ulint hint, /* in: hint of which extent would be desirable: any
1500
1462
page offset in the extent goes; the hint must not
1501
1463
be > FSP_FREE_LIMIT */
1502
mtr_t* mtr) /*!< in: mtr */
1464
mtr_t* mtr) /* in: mtr */
1504
1466
fsp_header_t* header;
1505
1467
fil_addr_t first;
1539
/**********************************************************************//**
1540
Allocates a single free page from a space. The page is marked as used.
1541
@return the page offset, FIL_NULL if no page could be allocated */
1501
/**************************************************************************
1502
Allocates a single free page from a space. The page is marked as used. */
1544
1505
fsp_alloc_free_page(
1545
1506
/*================*/
1546
ulint space, /*!< in: space id */
1547
ulint zip_size,/*!< in: compressed page size in bytes
1507
/* out: the page offset, FIL_NULL if no page could
1509
ulint space, /* in: space id */
1510
ulint zip_size,/* in: compressed page size in bytes
1548
1511
or 0 for uncompressed pages */
1549
ulint hint, /*!< in: hint of which page would be desirable */
1550
mtr_t* mtr) /*!< in: mtr handle */
1512
ulint hint, /* in: hint of which page would be desirable */
1513
mtr_t* mtr) /* in: mtr handle */
1552
1515
fsp_header_t* header;
1553
1516
fil_addr_t first;
1801
1764
flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
1804
/**********************************************************************//**
1805
Returns the nth inode slot on an inode page.
1806
@return segment inode */
1767
/**************************************************************************
1768
Returns the nth inode slot on an inode page. */
1809
1771
fsp_seg_inode_page_get_nth_inode(
1810
1772
/*=============================*/
1811
page_t* page, /*!< in: segment inode page */
1812
ulint i, /*!< in: inode index on page */
1773
/* out: segment inode */
1774
page_t* page, /* in: segment inode page */
1775
ulint i, /* in: inode index on page */
1813
1776
ulint zip_size __attribute__((unused)),
1814
/*!< in: compressed page size, or 0 */
1777
/* in: compressed page size, or 0 */
1815
1778
mtr_t* mtr __attribute__((unused)))
1816
/*!< in: mini-transaction handle */
1779
/* in: mini-transaction handle */
1818
1781
ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
1819
1782
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
1821
1784
return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
1824
/**********************************************************************//**
1825
Looks for a used segment inode on a segment inode page.
1826
@return segment inode index, or ULINT_UNDEFINED if not found */
1787
/**************************************************************************
1788
Looks for a used segment inode on a segment inode page. */
1829
1791
fsp_seg_inode_page_find_used(
1830
1792
/*=========================*/
1831
page_t* page, /*!< in: segment inode page */
1832
ulint zip_size,/*!< in: compressed page size, or 0 */
1833
mtr_t* mtr) /*!< in: mini-transaction handle */
1793
/* out: segment inode index, or ULINT_UNDEFINED
1795
page_t* page, /* in: segment inode page */
1796
ulint zip_size,/* in: compressed page size, or 0 */
1797
mtr_t* mtr) /* in: mini-transaction handle */
1836
1800
fseg_inode_t* inode;
1852
1814
return(ULINT_UNDEFINED);
1855
/**********************************************************************//**
1856
Looks for an unused segment inode on a segment inode page.
1857
@return segment inode index, or ULINT_UNDEFINED if not found */
1817
/**************************************************************************
1818
Looks for an unused segment inode on a segment inode page. */
1860
1821
fsp_seg_inode_page_find_free(
1861
1822
/*=========================*/
1862
page_t* page, /*!< in: segment inode page */
1863
ulint i, /*!< in: search forward starting from this index */
1864
ulint zip_size,/*!< in: compressed page size, or 0 */
1865
mtr_t* mtr) /*!< in: mini-transaction handle */
1823
/* out: segment inode index, or ULINT_UNDEFINED
1825
page_t* page, /* in: segment inode page */
1826
ulint i, /* in: search forward starting from this index */
1827
ulint zip_size,/* in: compressed page size, or 0 */
1828
mtr_t* mtr) /* in: mini-transaction handle */
1867
1830
fseg_inode_t* inode;
1871
1834
inode = fsp_seg_inode_page_get_nth_inode(
1872
1835
page, i, zip_size, mtr);
1874
if (!mach_read_from_8(inode + FSEG_ID)) {
1837
if (ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID))) {
1875
1838
/* This is unused */
1880
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
1881
== FSEG_MAGIC_N_VALUE);
1884
1844
return(ULINT_UNDEFINED);
1887
/**********************************************************************//**
1888
Allocates a new file segment inode page.
1889
@return TRUE if could be allocated */
1847
/**************************************************************************
1848
Allocates a new file segment inode page. */
1892
1851
fsp_alloc_seg_inode_page(
1893
1852
/*=====================*/
1894
fsp_header_t* space_header, /*!< in: space header */
1895
mtr_t* mtr) /*!< in: mini-transaction handle */
1853
/* out: TRUE if could be allocated */
1854
fsp_header_t* space_header, /* in: space header */
1855
mtr_t* mtr) /* in: mini-transaction handle */
1897
1857
fseg_inode_t* inode;
1898
1858
buf_block_t* block;
1997
1958
page + FSEG_INODE_PAGE_NODE, mtr);
2000
ut_ad(!mach_read_from_8(inode + FSEG_ID)
2001
|| mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2005
/**********************************************************************//**
1964
/**************************************************************************
2006
1965
Frees a file segment inode. */
2009
1968
fsp_free_seg_inode(
2010
1969
/*===============*/
2011
ulint space, /*!< in: space id */
2012
ulint zip_size,/*!< in: compressed page size in bytes
1970
ulint space, /* in: space id */
1971
ulint zip_size,/* in: compressed page size in bytes
2013
1972
or 0 for uncompressed pages */
2014
fseg_inode_t* inode, /*!< in: segment inode */
2015
mtr_t* mtr) /*!< in: mini-transaction handle */
1973
fseg_inode_t* inode, /* in: segment inode */
1974
mtr_t* mtr) /* in: mini-transaction handle */
2018
1977
fsp_header_t* space_header;
2053
/**********************************************************************//**
2054
Returns the file segment inode, page x-latched.
2055
@return segment inode, page x-latched; NULL if the inode is free */
2012
/**************************************************************************
2013
Returns the file segment inode, page x-latched. */
2060
fseg_header_t* header, /*!< in: segment header */
2061
ulint space, /*!< in: space id */
2062
ulint zip_size,/*!< in: compressed page size in bytes
2018
/* out: segment inode, page x-latched */
2019
fseg_header_t* header, /* in: segment header */
2020
ulint space, /* in: space id */
2021
ulint zip_size,/* in: compressed page size in bytes
2063
2022
or 0 for uncompressed pages */
2064
mtr_t* mtr) /*!< in: mtr handle */
2023
mtr_t* mtr) /* in: mtr handle */
2066
2025
fil_addr_t inode_addr;
2067
2026
fseg_inode_t* inode;
2073
2032
inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
2075
if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
2079
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
2080
== FSEG_MAGIC_N_VALUE);
2086
/**********************************************************************//**
2087
Returns the file segment inode, page x-latched.
2088
@return segment inode, page x-latched */
2093
fseg_header_t* header, /*!< in: segment header */
2094
ulint space, /*!< in: space id */
2095
ulint zip_size,/*!< in: compressed page size in bytes
2096
or 0 for uncompressed pages */
2097
mtr_t* mtr) /*!< in: mtr handle */
2100
= fseg_inode_try_get(header, space, zip_size, mtr);
2105
/**********************************************************************//**
2106
Gets the page number from the nth fragment page slot.
2107
@return page number, FIL_NULL if not in use */
2034
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2039
/**************************************************************************
2040
Gets the page number from the nth fragment page slot. */
2110
2043
fseg_get_nth_frag_page_no(
2111
2044
/*======================*/
2112
fseg_inode_t* inode, /*!< in: segment inode */
2113
ulint n, /*!< in: slot index */
2114
mtr_t* mtr __attribute__((unused))) /*!< in: mtr handle */
2045
/* out: page number, FIL_NULL if not in use */
2046
fseg_inode_t* inode, /* in: segment inode */
2047
ulint n, /* in: slot index */
2048
mtr_t* mtr __attribute__((unused))) /* in: mtr handle */
2116
2050
ut_ad(inode && mtr);
2117
2051
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
2118
2052
ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
2119
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2120
2053
return(mach_read_from_4(inode + FSEG_FRAG_ARR
2121
2054
+ n * FSEG_FRAG_SLOT_SIZE));
2124
/**********************************************************************//**
2057
/**************************************************************************
2125
2058
Sets the page number in the nth fragment page slot. */
2128
2061
fseg_set_nth_frag_page_no(
2129
2062
/*======================*/
2130
fseg_inode_t* inode, /*!< in: segment inode */
2131
ulint n, /*!< in: slot index */
2132
ulint page_no,/*!< in: page number to set */
2133
mtr_t* mtr) /*!< in: mtr handle */
2063
fseg_inode_t* inode, /* in: segment inode */
2064
ulint n, /* in: slot index */
2065
ulint page_no,/* in: page number to set */
2066
mtr_t* mtr) /* in: mtr handle */
2135
2068
ut_ad(inode && mtr);
2136
2069
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
2137
2070
ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
2138
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2140
2072
mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
2141
2073
page_no, MLOG_4BYTES, mtr);
2144
/**********************************************************************//**
2145
Finds a fragment page slot which is free.
2146
@return slot index; ULINT_UNDEFINED if none found */
2076
/**************************************************************************
2077
Finds a fragment page slot which is free. */
2149
2080
fseg_find_free_frag_page_slot(
2150
2081
/*==========================*/
2151
fseg_inode_t* inode, /*!< in: segment inode */
2152
mtr_t* mtr) /*!< in: mtr handle */
2082
/* out: slot index; ULINT_UNDEFINED if none
2084
fseg_inode_t* inode, /* in: segment inode */
2085
mtr_t* mtr) /* in: mtr handle */
2223
/**********************************************************************//**
2224
Creates a new segment.
2225
@return the block where the segment header is placed, x-latched, NULL
2226
if could not create segment because of lack of space */
2157
/**************************************************************************
2158
Creates a new segment. */
2229
2161
fseg_create_general(
2230
2162
/*================*/
2231
ulint space, /*!< in: space id */
2232
ulint page, /*!< in: page where the segment header is placed: if
2163
/* out: the block where the segment header is placed,
2164
x-latched, NULL if could not create segment
2165
because of lack of space */
2166
ulint space, /* in: space id */
2167
ulint page, /* in: page where the segment header is placed: if
2233
2168
this is != 0, the page must belong to another segment,
2234
2169
if this is 0, a new page will be allocated and it
2235
2170
will belong to the created segment */
2236
ulint byte_offset, /*!< in: byte offset of the created segment header
2171
ulint byte_offset, /* in: byte offset of the created segment header
2238
ibool has_done_reservation, /*!< in: TRUE if the caller has already
2173
ibool has_done_reservation, /* in: TRUE if the caller has already
2239
2174
done the reservation for the pages with
2240
2175
fsp_reserve_free_extents (at least 2 extents: one for
2241
2176
the inode and the other for the segment) then there is
2242
2177
no need to do the check for this individual
2244
mtr_t* mtr) /*!< in: mtr */
2179
mtr_t* mtr) /* in: mtr */
2247
2182
ulint zip_size;
2248
2183
fsp_header_t* space_header;
2249
2184
fseg_inode_t* inode;
2251
2186
buf_block_t* block = 0; /* remove warning */
2252
2187
fseg_header_t* header = 0; /* remove warning */
2253
2188
rw_lock_t* latch;
2356
/**********************************************************************//**
2357
Creates a new segment.
2358
@return the block where the segment header is placed, x-latched, NULL
2359
if could not create segment because of lack of space */
2292
/**************************************************************************
2293
Creates a new segment. */
2364
ulint space, /*!< in: space id */
2365
ulint page, /*!< in: page where the segment header is placed: if
2298
/* out: the block where the segment header is placed,
2299
x-latched, NULL if could not create segment
2300
because of lack of space */
2301
ulint space, /* in: space id */
2302
ulint page, /* in: page where the segment header is placed: if
2366
2303
this is != 0, the page must belong to another segment,
2367
2304
if this is 0, a new page will be allocated and it
2368
2305
will belong to the created segment */
2369
ulint byte_offset, /*!< in: byte offset of the created segment header
2306
ulint byte_offset, /* in: byte offset of the created segment header
2371
mtr_t* mtr) /*!< in: mtr */
2308
mtr_t* mtr) /* in: mtr */
2373
2310
return(fseg_create_general(space, page, byte_offset, FALSE, mtr));
2376
/**********************************************************************//**
2313
/**************************************************************************
2377
2314
Calculates the number of pages reserved by a segment, and how many pages are
2379
@return number of reserved pages */
2382
2318
fseg_n_reserved_pages_low(
2383
2319
/*======================*/
2384
fseg_inode_t* inode, /*!< in: segment inode */
2385
ulint* used, /*!< out: number of pages used (not
2386
more than reserved) */
2387
mtr_t* mtr) /*!< in: mtr handle */
2320
/* out: number of reserved pages */
2321
fseg_inode_t* inode, /* in: segment inode */
2322
ulint* used, /* out: number of pages used (<= reserved) */
2323
mtr_t* mtr) /* in: mtr handle */
2495
2431
xdes_set_state(descr, XDES_FSEG, mtr);
2497
seg_id = mach_read_from_8(inode + FSEG_ID);
2498
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
2499
== FSEG_MAGIC_N_VALUE);
2500
mlog_write_ull(descr + XDES_ID, seg_id, mtr);
2433
seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
2434
mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
2502
2436
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2503
2437
hint += FSP_EXTENT_SIZE;
2507
/*********************************************************************//**
2441
/*************************************************************************
2508
2442
Allocates a free extent for the segment: looks first in the free list of the
2509
2443
segment, then tries to allocate from the space free list. NOTE that the extent
2510
returned still resides in the segment free list, it is not yet taken off it!
2511
@return allocated extent, still placed in the segment free list, NULL
2512
if could not be allocated */
2444
returned still resides in the segment free list, it is not yet taken off it! */
2515
2447
fseg_alloc_free_extent(
2516
2448
/*===================*/
2517
fseg_inode_t* inode, /*!< in: segment inode */
2518
ulint space, /*!< in: space id */
2519
ulint zip_size,/*!< in: compressed page size in bytes
2449
/* out: allocated extent, still placed in the
2450
segment free list, NULL if could
2452
fseg_inode_t* inode, /* in: segment inode */
2453
ulint space, /* in: space id */
2454
ulint zip_size,/* in: compressed page size in bytes
2520
2455
or 0 for uncompressed pages */
2521
mtr_t* mtr) /*!< in: mtr */
2456
mtr_t* mtr) /* in: mtr */
2525
2460
fil_addr_t first;
2527
2462
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
2528
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2530
2464
if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
2531
2465
/* Segment free list is not empty, allocate from it */
2560
/**********************************************************************//**
2494
/**************************************************************************
2561
2495
Allocates a single free page from a segment. This function implements
2562
2496
the intelligent allocation strategy which tries to minimize file space
2564
@return the allocated page number, FIL_NULL if no page could be allocated */
2567
2500
fseg_alloc_free_page_low(
2568
2501
/*=====================*/
2569
ulint space, /*!< in: space */
2570
ulint zip_size,/*!< in: compressed page size in bytes
2502
/* out: the allocated page number, FIL_NULL
2503
if no page could be allocated */
2504
ulint space, /* in: space */
2505
ulint zip_size,/* in: compressed page size in bytes
2571
2506
or 0 for uncompressed pages */
2572
fseg_inode_t* seg_inode, /*!< in: segment inode */
2573
ulint hint, /*!< in: hint of which page would be desirable */
2574
byte direction, /*!< in: if the new page is needed because
2507
fseg_inode_t* seg_inode, /* in: segment inode */
2508
ulint hint, /* in: hint of which page would be desirable */
2509
byte direction, /* in: if the new page is needed because
2575
2510
of an index page split, and records are
2576
2511
inserted there in order, into which
2577
2512
direction they go alphabetically: FSP_DOWN,
2578
2513
FSP_UP, FSP_NO_DIR */
2579
mtr_t* mtr) /*!< in: mtr handle */
2514
mtr_t* mtr) /* in: mtr handle */
2581
2516
fsp_header_t* space_header;
2582
2517
ulint space_size;
2585
2520
ulint reserved;
2586
xdes_t* descr; /*!< extent of the hinted page */
2587
ulint ret_page; /*!< the allocated page offset, FIL_NULL
2521
xdes_t* descr; /* extent of the hinted page */
2522
ulint ret_page; /* the allocated page offset, FIL_NULL
2588
2523
if could not be allocated */
2589
xdes_t* ret_descr; /*!< the extent of the allocated page */
2524
xdes_t* ret_descr; /* the extent of the allocated page */
2590
2525
ibool frag_page_allocated = FALSE;
2803
2740
return(ret_page);
2806
/**********************************************************************//**
2743
/**************************************************************************
2807
2744
Allocates a single free page from a segment. This function implements
2808
2745
the intelligent allocation strategy which tries to minimize file space
2810
@return allocated page offset, FIL_NULL if no page could be allocated */
2813
2749
fseg_alloc_free_page_general(
2814
2750
/*=========================*/
2815
fseg_header_t* seg_header,/*!< in: segment header */
2816
ulint hint, /*!< in: hint of which page would be desirable */
2817
byte direction,/*!< in: if the new page is needed because
2751
/* out: allocated page offset, FIL_NULL if no
2752
page could be allocated */
2753
fseg_header_t* seg_header,/* in: segment header */
2754
ulint hint, /* in: hint of which page would be desirable */
2755
byte direction,/* in: if the new page is needed because
2818
2756
of an index page split, and records are
2819
2757
inserted there in order, into which
2820
2758
direction they go alphabetically: FSP_DOWN,
2821
2759
FSP_UP, FSP_NO_DIR */
2822
ibool has_done_reservation, /*!< in: TRUE if the caller has
2760
ibool has_done_reservation, /* in: TRUE if the caller has
2823
2761
already done the reservation for the page
2824
2762
with fsp_reserve_free_extents, then there
2825
2763
is no need to do the check for this individual
2827
mtr_t* mtr) /*!< in: mtr handle */
2765
mtr_t* mtr) /* in: mtr handle */
2829
2767
fseg_inode_t* inode;
2874
2812
return(page_no);
2877
/**********************************************************************//**
2815
/**************************************************************************
2878
2816
Allocates a single free page from a segment. This function implements
2879
2817
the intelligent allocation strategy which tries to minimize file space
2881
@return allocated page offset, FIL_NULL if no page could be allocated */
2884
2821
fseg_alloc_free_page(
2885
2822
/*=================*/
2886
fseg_header_t* seg_header,/*!< in: segment header */
2887
ulint hint, /*!< in: hint of which page would be desirable */
2888
byte direction,/*!< in: if the new page is needed because
2823
/* out: allocated page offset, FIL_NULL if no
2824
page could be allocated */
2825
fseg_header_t* seg_header,/* in: segment header */
2826
ulint hint, /* in: hint of which page would be desirable */
2827
byte direction,/* in: if the new page is needed because
2889
2828
of an index page split, and records are
2890
2829
inserted there in order, into which
2891
2830
direction they go alphabetically: FSP_DOWN,
2892
2831
FSP_UP, FSP_NO_DIR */
2893
mtr_t* mtr) /*!< in: mtr handle */
2832
mtr_t* mtr) /* in: mtr handle */
2895
2834
return(fseg_alloc_free_page_general(seg_header, hint, direction,
2899
/**********************************************************************//**
2838
/**************************************************************************
2900
2839
Checks that we have at least 2 frag pages free in the first extent of a
2901
2840
single-table tablespace, and they are also physically initialized to the data
2902
2841
file. That is we have already extended the data file so that those pages are
2903
2842
inside the data file. If not, this function extends the tablespace with
2905
@return TRUE if there were >= 3 free pages, or we were able to extend */
2908
2846
fsp_reserve_free_pages(
2909
2847
/*===================*/
2910
ulint space, /*!< in: space id, must be != 0 */
2911
fsp_header_t* space_header, /*!< in: header of that space,
2848
/* out: TRUE if there were >= 3 free
2849
pages, or we were able to extend */
2850
ulint space, /* in: space id, must be != 0 */
2851
fsp_header_t* space_header, /* in: header of that space,
2913
ulint size, /*!< in: size of the tablespace in pages,
2853
ulint size, /* in: size of the tablespace in pages,
2914
2854
must be < FSP_EXTENT_SIZE / 2 */
2915
mtr_t* mtr) /*!< in: mtr */
2855
mtr_t* mtr) /* in: mtr */
2959
2899
function we would liberally reserve several 64 page extents for every page
2960
2900
split or merge in a B-tree. But we do not want to waste disk space if the table
2961
2901
only occupies < 32 pages. That is why we apply different rules in that special
2962
case, just ensuring that there are 3 free pages available.
2963
@return TRUE if we were able to make the reservation */
2902
case, just ensuring that there are 3 free pages available. */
2966
2905
fsp_reserve_free_extents(
2967
2906
/*=====================*/
2968
ulint* n_reserved,/*!< out: number of extents actually reserved; if we
2907
/* out: TRUE if we were able to make the reservation */
2908
ulint* n_reserved,/* out: number of extents actually reserved; if we
2969
2909
return TRUE and the tablespace size is < 64 pages,
2970
2910
then this can be 0, otherwise it is n_ext */
2971
ulint space, /*!< in: space id */
2972
ulint n_ext, /*!< in: number of extents to reserve */
2973
ulint alloc_type,/*!< in: FSP_NORMAL, FSP_UNDO, or FSP_CLEANING */
2974
mtr_t* mtr) /*!< in: mtr */
2911
ulint space, /* in: space id */
2912
ulint n_ext, /* in: number of extents to reserve */
2913
ulint alloc_type,/* in: FSP_NORMAL, FSP_UNDO, or FSP_CLEANING */
2914
mtr_t* mtr) /* in: mtr */
2976
2916
fsp_header_t* space_header;
2977
2917
rw_lock_t* latch;
3165
/********************************************************************//**
3105
/************************************************************************
3166
3106
Marks a page used. The page must reside within the extents of the given
3170
3110
fseg_mark_page_used(
3171
3111
/*================*/
3172
fseg_inode_t* seg_inode,/*!< in: segment inode */
3173
ulint space, /*!< in: space id */
3174
ulint zip_size,/*!< in: compressed page size in bytes
3112
fseg_inode_t* seg_inode,/* in: segment inode */
3113
ulint space, /* in: space id */
3114
ulint zip_size,/* in: compressed page size in bytes
3175
3115
or 0 for uncompressed pages */
3176
ulint page, /*!< in: page offset */
3177
mtr_t* mtr) /*!< in: mtr */
3116
ulint page, /* in: page offset */
3117
mtr_t* mtr) /* in: mtr */
3180
3120
ulint not_full_n_used;
3182
3122
ut_ad(seg_inode && mtr);
3183
3123
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
3184
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
3185
== FSEG_MAGIC_N_VALUE);
3187
3125
descr = xdes_get_descriptor(space, zip_size, page, mtr);
3225
/**********************************************************************//**
3163
/**************************************************************************
3226
3164
Frees a single page of a segment. */
3229
3167
fseg_free_page_low(
3230
3168
/*===============*/
3231
fseg_inode_t* seg_inode, /*!< in: segment inode */
3232
ulint space, /*!< in: space id */
3233
ulint zip_size,/*!< in: compressed page size in bytes
3169
fseg_inode_t* seg_inode, /* in: segment inode */
3170
ulint space, /* in: space id */
3171
ulint zip_size,/* in: compressed page size in bytes
3234
3172
or 0 for uncompressed pages */
3235
ulint page, /*!< in: page offset */
3236
mtr_t* mtr) /*!< in: mtr handle */
3173
ulint page, /* in: page offset */
3174
mtr_t* mtr) /* in: mtr handle */
3239
3177
ulint not_full_n_used;
3245
3183
ut_ad(seg_inode && mtr);
3299
3238
/* If we get here, the page is in some extent of the segment */
3301
descr_id = mach_read_from_8(descr + XDES_ID);
3302
seg_id = mach_read_from_8(seg_inode + FSEG_ID);
3240
descr_id = mtr_read_dulint(descr + XDES_ID, mtr);
3241
seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
3304
3243
fprintf(stderr,
3305
3244
"InnoDB: InnoDB is freeing space %lu page %lu,\n"
3306
"InnoDB: which belongs to descr seg %llu\n"
3307
"InnoDB: segment %llu.\n",
3245
"InnoDB: which belongs to descr seg %lu %lu\n"
3246
"InnoDB: segment %lu %lu.\n",
3308
3247
(ulong) space, (ulong) page,
3248
(ulong) ut_dulint_get_high(descr_id),
3249
(ulong) ut_dulint_get_low(descr_id),
3250
(ulong) ut_dulint_get_high(seg_id),
3251
(ulong) ut_dulint_get_low(seg_id));
3312
if (UNIV_UNLIKELY(descr_id != seg_id)) {
3253
if (0 != ut_dulint_cmp(descr_id, seg_id)) {
3313
3254
fputs("InnoDB: Dump of the tablespace extent descriptor: ",
3315
3256
ut_print_buf(stderr, descr, 40);
3393
/**********************************************************************//**
3336
/**************************************************************************
3394
3337
Frees an extent of a segment to the space free list. */
3397
3340
fseg_free_extent(
3398
3341
/*=============*/
3399
fseg_inode_t* seg_inode, /*!< in: segment inode */
3400
ulint space, /*!< in: space id */
3401
ulint zip_size,/*!< in: compressed page size in bytes
3342
fseg_inode_t* seg_inode, /* in: segment inode */
3343
ulint space, /* in: space id */
3344
ulint zip_size,/* in: compressed page size in bytes
3402
3345
or 0 for uncompressed pages */
3403
ulint page, /*!< in: a page in the extent */
3404
mtr_t* mtr) /*!< in: mtr handle */
3346
ulint page, /* in: a page in the extent */
3347
mtr_t* mtr) /* in: mtr handle */
3406
3349
ulint first_page_in_extent;
3465
/**********************************************************************//**
3407
/**************************************************************************
3466
3408
Frees part of a segment. This function can be used to free a segment by
3467
3409
repeatedly calling this function in different mini-transactions. Doing
3468
3410
the freeing in a single mini-transaction might result in too big a
3470
@return TRUE if freeing completed */
3411
mini-transaction. */
3473
3414
fseg_free_step(
3474
3415
/*===========*/
3475
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
3416
/* out: TRUE if freeing completed */
3417
fseg_header_t* header, /* in, own: segment header; NOTE: if the header
3476
3418
resides on the first page of the frag list
3477
3419
of the segment, this pointer becomes obsolete
3478
3420
after the last freeing step */
3479
mtr_t* mtr) /*!< in: mtr */
3421
mtr_t* mtr) /* in: mtr */
3554
/**********************************************************************//**
3490
/**************************************************************************
3555
3491
Frees part of a segment. Differs from fseg_free_step because this function
3556
leaves the header page unfreed.
3557
@return TRUE if freeing completed, except the header page */
3492
leaves the header page unfreed. */
3560
3495
fseg_free_step_not_header(
3561
3496
/*======================*/
3562
fseg_header_t* header, /*!< in: segment header which must reside on
3497
/* out: TRUE if freeing completed, except the
3499
fseg_header_t* header, /* in: segment header which must reside on
3563
3500
the first fragment page of the segment */
3564
mtr_t* mtr) /*!< in: mtr */
3501
mtr_t* mtr) /* in: mtr */
3619
/**********************************************************************//**
3556
/***********************************************************************
3557
Frees a segment. The freeing is performed in several mini-transactions,
3558
so that there is no danger of bufferfixing too many buffer pages. */
3563
ulint space, /* in: space id */
3564
ulint zip_size,/* in: compressed page size in bytes
3565
or 0 for uncompressed pages */
3566
ulint page_no,/* in: page number where the segment header is
3568
ulint offset) /* in: byte offset of the segment header on that
3573
fseg_header_t* header;
3576
addr.page = page_no;
3577
addr.boffset = offset;
3582
header = fut_get_ptr(space, zip_size, addr, RW_X_LATCH, &mtr);
3584
finished = fseg_free_step(header, &mtr);
3595
/**************************************************************************
3620
3596
Returns the first extent descriptor for a segment. We think of the extent
3621
3597
lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
3623
@return the first extent descriptor, or NULL if none */
3626
3601
fseg_get_first_extent(
3627
3602
/*==================*/
3628
fseg_inode_t* inode, /*!< in: segment inode */
3629
ulint space, /*!< in: space id */
3630
ulint zip_size,/*!< in: compressed page size in bytes
3603
/* out: the first extent descriptor, or NULL if
3605
fseg_inode_t* inode, /* in: segment inode */
3606
ulint space, /* in: space id */
3607
ulint zip_size,/* in: compressed page size in bytes
3631
3608
or 0 for uncompressed pages */
3632
mtr_t* mtr) /*!< in: mtr */
3609
mtr_t* mtr) /* in: mtr */
3634
3611
fil_addr_t first;
3835
3817
n_full = flst_get_len(inode + FSEG_FULL, mtr);
3837
3819
fprintf(stderr,
3838
"SEGMENT id %llu space %lu; page %lu;"
3820
"SEGMENT id %lu %lu space %lu; page %lu;"
3839
3821
" res %lu used %lu; full ext %lu\n"
3840
3822
"fragm pages %lu; free extents %lu;"
3841
3823
" not full extents %lu: pages %lu\n",
3824
(ulong) seg_id_high, (ulong) seg_id_low,
3843
3825
(ulong) space, (ulong) page_no,
3844
3826
(ulong) reserved, (ulong) used, (ulong) n_full,
3845
3827
(ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
3846
3828
(ulong) n_used);
3847
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
3850
3831
#ifdef UNIV_BTR_PRINT
3851
/*******************************************************************//**
3832
/***********************************************************************
3852
3833
Writes info of a segment. */
3857
fseg_header_t* header, /*!< in: segment header */
3858
mtr_t* mtr) /*!< in: mtr */
3838
fseg_header_t* header, /* in: segment header */
3839
mtr_t* mtr) /* in: mtr */
3860
3841
fseg_inode_t* inode;
4180
4165
n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
4181
4166
n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
4183
seg_id = mach_read_from_8(header + FSP_SEG_ID);
4168
d_var = mtr_read_dulint(header + FSP_SEG_ID, &mtr);
4170
seg_id_low = ut_dulint_get_low(d_var);
4171
seg_id_high = ut_dulint_get_high(d_var);
4185
4173
fprintf(stderr,
4186
4174
"FILE SPACE INFO: id %lu\n"
4187
4175
"size %lu, free limit %lu, free extents %lu\n"
4188
4176
"not full frag extents %lu: used pages %lu,"
4189
4177
" full frag extents %lu\n"
4190
"first seg id not used %llu\n",
4178
"first seg id not used %lu %lu\n",
4192
4180
(ulong) size, (ulong) free_limit, (ulong) n_free,
4193
4181
(ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
4182
(ulong) seg_id_high, (ulong) seg_id_low);
4196
4184
mtr_commit(&mtr);